@@ -58,6 +58,7 @@ along with GCC; see the file COPYING3. If not see
#include "target.h"
#include "cgraph.h"
#include "wide-int.h"
+#include "demangle.h"
/* Debugging support. */
@@ -66,6 +67,14 @@ along with GCC; see the file COPYING3. If not see
#define DEBUG_MANGLE 0
#endif
+/* If ENABLE_CHECKING, we try to demangle what we mangle in order to
+ catch nasty demangler crashes early. But by default, we don't
+ actually make sure the result is sane. Define this to enable such
+ extra validation. */
+#ifndef EXTRA_DEMANGLE_CHECKING
+#define EXTRA_DEMANGLE_CHECKING 1
+#endif
+
/* Macros for tracing the write_* functions. */
#if DEBUG_MANGLE
# define MANGLE_TRACE(FN, INPUT) \
@@ -104,6 +113,9 @@ typedef struct GTY(()) globals {
/* True if the mangling will be different in a future version of the
ABI. */
bool need_abi_warning;
+
+ /* True if we mangled a type. */
+ bool type;
} globals;
static GTY (()) globals G;
@@ -3345,6 +3357,7 @@ start_mangling (const tree entity)
{
G.entity = entity;
G.need_abi_warning = false;
+ G.type = false;
obstack_free (&name_obstack, name_base);
mangle_obstack = &name_obstack;
name_base = obstack_alloc (&name_obstack, 0);
@@ -3367,6 +3380,48 @@ finish_mangling_internal (const bool warn)
/* Null-terminate the string. */
write_char ('\0');
+
+#if ENABLE_CHECKING || EXTRA_DEMANGLE_CHECKING
+ /* Make sure we can demangle what we just generated. */
+ {
+ const char *mangled_str;
+ char *str;
+ int dmgl_opts;
+ int mangled_p ATTRIBUTE_UNUSED;
+
+ dmgl_opts = (G.type
+ ? DMGL_TYPES
+ : DMGL_VERBOSE | DMGL_ANSI | DMGL_PARAMS);
+
+ mangled_str = (const char *) obstack_base (mangle_obstack);
+ str = cplus_demangle_v3 (mangled_str, dmgl_opts);
+
+#if EXTRA_DEMANGLE_CHECKING
+ /* XXX The above catches potential demangler crashes. And,
+ ideally, we'd also abort if demangling fails. However, we
+ can't do that by default because the demangler isn't able to
+ demangle all symbols we generate. Some failures might be
+ demangler bugs, others unknown mangler bugs, and others known
+ mangler bugs fixed with a higher -fabi-version that the
+ demangler doesn't have a workaround for. */
+ mangled_p = (G.type
+ || (mangled_str[0] == '_' && mangled_str[1] == 'Z')
+ || (strncmp (mangled_str, "_GLOBAL_", 8) == 0
+ && (mangled_str[8] == '.'
+ || mangled_str[8] == '_'
+ || mangled_str[8] == '$')
+ && (mangled_str[9] == 'D' || mangled_str[9] == 'I')
+ && mangled_str[10] == '_'));
+ if ((str != NULL) != mangled_p)
+ internal_error ("mangler/demangler failure for %s: %s",
+ G.type ? "type" :"fn",
+ mangled_str);
+
+#endif
+
+ free (str);
+ }
+#endif
}
@@ -3438,7 +3493,10 @@ mangle_decl_string (const tree decl)
start_mangling (decl);
if (TREE_CODE (decl) == TYPE_DECL)
- write_type (TREE_TYPE (decl));
+ {
+ G.type = true;
+ write_type (TREE_TYPE (decl));
+ }
else
write_mangled_name (decl, true);
@@ -3535,6 +3593,7 @@ mangle_type_string (const tree type)
const char *result;
start_mangling (type);
+ G.type = true;
write_type (type);
result = finish_mangling (/*warn=*/false);
if (DEBUG_MANGLE)