Stop being strict about validating the "clone" part of mangled names

Support for parsing mangled symbol names with a ".something" suffix
in the demangler was originally added because the compiler was using
that for function cloning, but since then the compiler has started
using ".something" suffixes in many other cases, such as function
renaming for ThinLTO and CFI. As a result, some symbols in binaries
built with these features would fail to demangle.

So instead of trying to validate what comes after the "." let's just
stop parsing when we see a ".", so that the symbols are demangled
correctly. This behavior is consistent with libc++.

PiperOrigin-RevId: 756054147
Change-Id: I01e9e97eee32bee05ba243b615ed26a36b59591d
diff --git a/absl/debugging/internal/demangle.cc b/absl/debugging/internal/demangle.cc
index dc15b8e..5f62ebb 100644
--- a/absl/debugging/internal/demangle.cc
+++ b/absl/debugging/internal/demangle.cc
@@ -484,36 +484,6 @@
 
 static bool IsDigit(char c) { return c >= '0' && c <= '9'; }
 
-// Returns true if "str" is a function clone suffix.  These suffixes are used
-// by GCC 4.5.x and later versions (and our locally-modified version of GCC
-// 4.4.x) to indicate functions which have been cloned during optimization.
-// We treat any sequence (.<alpha>+.<digit>+)+ as a function clone suffix.
-// Additionally, '_' is allowed along with the alphanumeric sequence.
-static bool IsFunctionCloneSuffix(const char *str) {
-  size_t i = 0;
-  while (str[i] != '\0') {
-    bool parsed = false;
-    // Consume a single [.<alpha> | _]*[.<digit>]* sequence.
-    if (str[i] == '.' && (IsAlpha(str[i + 1]) || str[i + 1] == '_')) {
-      parsed = true;
-      i += 2;
-      while (IsAlpha(str[i]) || str[i] == '_') {
-        ++i;
-      }
-    }
-    if (str[i] == '.' && IsDigit(str[i + 1])) {
-      parsed = true;
-      i += 2;
-      while (IsDigit(str[i])) {
-        ++i;
-      }
-    }
-    if (!parsed)
-      return false;
-  }
-  return true;  // Consumed everything in "str".
-}
-
 static bool EndsWith(State *state, const char chr) {
   return state->parse_state.out_cur_idx > 0 &&
          state->parse_state.out_cur_idx < state->out_end_idx &&
@@ -2932,7 +2902,7 @@
   if (ParseMangledName(state)) {
     if (RemainingInput(state)[0] != '\0') {
       // Drop trailing function clone suffix, if any.
-      if (IsFunctionCloneSuffix(RemainingInput(state))) {
+      if (RemainingInput(state)[0] == '.') {
         return true;
       }
       // Append trailing version suffix if any.
diff --git a/absl/debugging/internal/demangle_test.cc b/absl/debugging/internal/demangle_test.cc
index 9c8225a..2012184 100644
--- a/absl/debugging/internal/demangle_test.cc
+++ b/absl/debugging/internal/demangle_test.cc
@@ -556,14 +556,15 @@
   EXPECT_TRUE(Demangle("_ZL3Foov.part.9.165493.constprop.775.31805", tmp,
                        sizeof(tmp)));
   EXPECT_STREQ("Foo()", tmp);
-  // Invalid (. without anything else), should not demangle.
-  EXPECT_FALSE(Demangle("_ZL3Foov.", tmp, sizeof(tmp)));
-  // Invalid (. with mix of alpha and digits), should not demangle.
-  EXPECT_FALSE(Demangle("_ZL3Foov.abc123", tmp, sizeof(tmp)));
-  // Invalid (.clone. not followed by number), should not demangle.
-  EXPECT_FALSE(Demangle("_ZL3Foov.clone.", tmp, sizeof(tmp)));
-  // Invalid (.constprop. not followed by number), should not demangle.
-  EXPECT_FALSE(Demangle("_ZL3Foov.isra.2.constprop.", tmp, sizeof(tmp)));
+  // Other suffixes should demangle too.
+  EXPECT_TRUE(Demangle("_ZL3Foov.", tmp, sizeof(tmp)));
+  EXPECT_STREQ("Foo()", tmp);
+  EXPECT_TRUE(Demangle("_ZL3Foov.abc123", tmp, sizeof(tmp)));
+  EXPECT_STREQ("Foo()", tmp);
+  EXPECT_TRUE(Demangle("_ZL3Foov.clone.", tmp, sizeof(tmp)));
+  EXPECT_STREQ("Foo()", tmp);
+  EXPECT_TRUE(Demangle("_ZL3Foov.isra.2.constprop.", tmp, sizeof(tmp)));
+  EXPECT_STREQ("Foo()", tmp);
 }
 
 TEST(Demangle, Discriminators) {