]> gcc.gnu.org Git - gcc.git/commitdiff
mangle.c (mangle_type_string_for_rtti): Rename to be clearer.
authorJason Merrill <jason@redhat.com>
Wed, 22 Jul 2009 23:03:22 +0000 (19:03 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 22 Jul 2009 23:03:22 +0000 (19:03 -0400)
* mangle.c (mangle_type_string_for_rtti): Rename to be clearer.
(needs_fake_anon): New.
(write_name): Check it.
(write_nested_name): Add a fake anonymous namespace scope if true.
* name-lookup.c (get_anonymous_namespace_name): No longer static.
* rtti.c, cp-tree.h: Adjust.

* libsupc++/typeinfo (__GXX_MERGED_TYPEINFO_NAMES): Default to 0.

From-SVN: r149964

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/mangle.c
gcc/cp/name-lookup.c
gcc/cp/rtti.c
libstdc++-v3/ChangeLog
libstdc++-v3/libsupc++/typeinfo

index c86770ed2ef5d5483600886fd53f3bcf49e33c4f..85178863136be2886f170bf204ef0539b28e0203 100644 (file)
@@ -1,3 +1,12 @@
+2009-07-22  Jason Merrill  <jason@redhat.com>
+
+       * mangle.c (mangle_type_string_for_rtti): Rename to be clearer.
+       (needs_fake_anon): New.
+       (write_name): Check it.
+       (write_nested_name): Add a fake anonymous namespace scope if true.
+       * name-lookup.c (get_anonymous_namespace_name): No longer static.
+       * rtti.c, cp-tree.h: Adjust.
+
 2009-07-22  Richard Guenther  <rguenther@suse.de>
 
        PR c++/40799
index 6ad039ae3cf083c24bfb33a9b29d3e4748232798..2bc2d6214e48b19e00c38c8a4e178182a8bb7ed2 100644 (file)
@@ -4345,6 +4345,7 @@ extern tree type_promotes_to                      (tree);
 extern tree perform_qualification_conversions  (tree, tree);
 
 /* in name-lookup.c */
+extern tree get_anonymous_namespace_name       (void);
 extern tree pushdecl                           (tree);
 extern tree pushdecl_maybe_friend              (tree, bool);
 extern void maybe_push_cleanup_level           (tree);
@@ -5095,7 +5096,7 @@ extern tree merge_exception_specifiers            (tree, tree);
 /* in mangle.c */
 extern void init_mangle                                (void);
 extern void mangle_decl                                (tree);
-extern const char *mangle_type_string          (tree);
+extern const char *mangle_type_string_for_rtti (tree);
 extern tree mangle_typeinfo_for_type           (tree);
 extern tree mangle_typeinfo_string_for_type    (tree);
 extern tree mangle_vtbl_for_type               (tree);
index 1c79dcc31744f3d3c5729c2ab100b1df1c4113ac..bb046d23d5a4c946d332cdd2e50cc09170db8f25 100644 (file)
@@ -105,6 +105,10 @@ typedef struct GTY(()) globals {
 
 static GTY (()) globals G;
 
+/* Whether or not to pretend that a static function is in an anonymous
+   namespace.  */
+static bool fake_anon_scope;
+
 /* The obstack on which we build mangled names.  */
 static struct obstack *mangle_obstack;
 
@@ -726,6 +730,20 @@ write_encoding (const tree decl)
     }
 }
 
+/* Since we now use strcmp to compare typeinfos on all targets because of
+   the RTLD_LOCAL problem, we need to munge the typeinfo name used for
+   local classes of static functions to fix g++.dg/abi/local1.C.  We do
+   that by pretending that the function is in an anonymous namespace.  */
+
+static bool
+needs_fake_anon (const_tree decl)
+{
+  /* Pretend there's an anonymous namespace right around a static
+     function if we're mangling for RTTI.  */
+  return (fake_anon_scope && !TREE_PUBLIC (decl)
+         && TREE_CODE (decl) == FUNCTION_DECL);
+}
+
 /* <name> ::= <unscoped-name>
          ::= <unscoped-template-name> <template-args>
          ::= <nested-name>
@@ -749,18 +767,23 @@ write_name (tree decl, const int ignore_local_scope)
       /* In case this is a typedef, fish out the corresponding
         TYPE_DECL for the main variant.  */
       decl = TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (decl)));
-      context = TYPE_CONTEXT (TYPE_MAIN_VARIANT (TREE_TYPE (decl)));
+      context = CP_TYPE_CONTEXT (TYPE_MAIN_VARIANT (TREE_TYPE (decl)));
     }
   else
-    context = (DECL_CONTEXT (decl) == NULL) ? NULL : CP_DECL_CONTEXT (decl);
+    context = CP_DECL_CONTEXT (decl);
+
+  gcc_assert (context != NULL_TREE);
+
+  /* If we need a fake anonymous namespace, force the nested name path.  */
+  if (needs_fake_anon (decl) && context == global_namespace)
+    context = error_mark_node;
 
   /* A decl in :: or ::std scope is treated specially.  The former is
      mangled using <unscoped-name> or <unscoped-template-name>, the
      latter with a special substitution.  Also, a name that is
      directly in a local function scope is also mangled with
      <unscoped-name> rather than a full <nested-name>.  */
-  if (context == NULL
-      || context == global_namespace
+  if (context == global_namespace
       || DECL_NAMESPACE_STD_P (context)
       || (ignore_local_scope && TREE_CODE (context) == FUNCTION_DECL))
     {
@@ -778,6 +801,9 @@ write_name (tree decl, const int ignore_local_scope)
     }
   else
     {
+      if (context == error_mark_node)
+       context = global_namespace;
+
       /* Handle local names, unless we asked not to (that is, invoked
         under <local-name>, to handle only the part of the name under
         the local scope).  */
@@ -790,10 +816,10 @@ write_name (tree decl, const int ignore_local_scope)
             directly in that function's scope, either decl or one of
             its enclosing scopes.  */
          tree local_entity = decl;
-         while (context != NULL && context != global_namespace)
+         while (context != global_namespace)
            {
              /* Make sure we're always dealing with decls.  */
-             if (context != NULL && TYPE_P (context))
+             if (TYPE_P (context))
                context = TYPE_NAME (context);
              /* Is this a function?  */
              if (TREE_CODE (context) == FUNCTION_DECL)
@@ -837,7 +863,6 @@ write_unscoped_name (const tree decl)
       /* If not, it should be either in the global namespace, or directly
         in a local function scope.  */
       gcc_assert (context == global_namespace
-                 || context == NULL
                  || TREE_CODE (context) == FUNCTION_DECL);
 
       write_unqualified_name (decl);
@@ -909,6 +934,9 @@ write_nested_name (const tree decl)
     {
       /* No, just use <prefix>  */
       write_prefix (DECL_CONTEXT (decl));
+      if (needs_fake_anon (decl))
+       /* Pretend this static function is in an anonymous namespace.  */
+       write_source_name (get_anonymous_namespace_name ());
       write_unqualified_name (decl);
     }
   write_char ('E');
@@ -2817,15 +2845,18 @@ mangle_decl (const tree decl)
   SET_DECL_ASSEMBLER_NAME (decl, id);
 }
 
-/* Generate the mangled representation of TYPE.  */
+/* Generate the mangled representation of TYPE for the typeinfo name.  */
 
 const char *
-mangle_type_string (const tree type)
+mangle_type_string_for_rtti (const tree type)
 {
   const char *result;
 
   start_mangling (type);
+  /* Mangle in a fake anonymous namespace if necessary.  */
+  fake_anon_scope = true;
   write_type (type);
+  fake_anon_scope = false;
   result = finish_mangling (/*warn=*/false);
   if (DEBUG_MANGLE)
     fprintf (stderr, "mangle_type_string = '%s'\n\n", result);
index 7a8016ffa0bb9d1000ab2e07189fe384db0e81b0..c2d877907bcff525233e09d94fd41042c4b9680c 100644 (file)
@@ -62,19 +62,14 @@ static GTY(()) tree anonymous_namespace_name;
 
 /* Initialize anonymous_namespace_name if necessary, and return it.  */
 
-static tree
-get_anonymous_namespace_name(void)
+tree
+get_anonymous_namespace_name (void)
 {
   if (!anonymous_namespace_name)
     {
       /* The anonymous namespace has to have a unique name
         if typeinfo objects are being compared by name.  */
-      if (! flag_weak || ! SUPPORTS_ONE_ONLY)
-       anonymous_namespace_name = get_file_function_name ("N");
-      else
-       /* The demangler expects anonymous namespaces to be called
-          something starting with '_GLOBAL__N_'.  */
-       anonymous_namespace_name = get_identifier ("_GLOBAL__N_1");
+      anonymous_namespace_name = get_file_function_name ("N");
     }
   return anonymous_namespace_name;
 }
index 01bba3477df88db1c0105f3b1c39dbee31a54b7a..8dde479a6c485e3627c83789509921ad08c9568a 100644 (file)
@@ -356,7 +356,7 @@ tinfo_name (tree type)
   const char *name;
   tree name_string;
 
-  name = mangle_type_string (type);
+  name = mangle_type_string_for_rtti (type);
   name_string = fix_string_type (build_string (strlen (name) + 1, name));
   return name_string;
 }
index 2caf219164f0599c9aa30dd0716c5e78a64b0563..ad521da44eb2869f9b3a0ca80f6deaad1b1c5e79 100644 (file)
@@ -1,3 +1,7 @@
+2009-07-22  Jason Merrill  <jason@redhat.com>
+
+       * libsupc++/typeinfo (__GXX_MERGED_TYPEINFO_NAMES): Default to 0.
+
 2009-07-22  Paolo Carlini  <paolo.carlini@oracle.com>
 
        * include/std/valarray (valarray<>::operator=(const valarray<>&),
index eea38e70e4a153e17b4cdd226451886c98e5017a..4c470430deff29f162e11792579d98acfbdab1c4 100644 (file)
@@ -43,32 +43,29 @@ namespace __cxxabiv1
 } // namespace __cxxabiv1
 
 // Determine whether typeinfo names for the same type are merged (in which
-// case comparison can just compare pointers) or not (in which case
-// strings must be compared and g++.dg/abi/local1.C will fail), and
-// whether comparison is to be implemented inline or not.  By default we
-// use inline pointer comparison if weak symbols are available, and
-// out-of-line strcmp if not.  Out-of-line pointer comparison is used
-// where the object files are to be portable to multiple systems, some of
-// which may not be able to use pointer comparison, but the particular
-// system for which libstdc++ is being built can use pointer comparison;
-// in particular for most ARM EABI systems, where the ABI specifies
-// out-of-line comparison.  Inline strcmp is not currently supported.  The
-// compiler's target configuration can override the defaults by defining
-// __GXX_TYPEINFO_EQUALITY_INLINE to 1 or 0 to indicate whether or not
-// comparison is inline, and __GXX_MERGED_TYPEINFO_NAMES to 1 or 0 to
-// indicate whether or not pointer comparison can be used.
+// case comparison can just compare pointers) or not (in which case strings
+// must be compared), and whether comparison is to be implemented inline or
+// not.  We used to do inline pointer comparison by default if weak symbols
+// are available, but even with weak symbols sometimes names are not merged
+// when objects are loaded with RTLD_LOCAL, so now we always use strcmp by
+// default.  For ABI compatibility, we do the strcmp inline if weak symbols
+// are available, and out-of-line if not.  Out-of-line pointer comparison
+// is used where the object files are to be portable to multiple systems,
+// some of which may not be able to use pointer comparison, but the
+// particular system for which libstdc++ is being built can use pointer
+// comparison; in particular for most ARM EABI systems, where the ABI
+// specifies out-of-line comparison.  The compiler's target configuration
+// can override the defaults by defining __GXX_TYPEINFO_EQUALITY_INLINE to
+// 1 or 0 to indicate whether or not comparison is inline, and
+// __GXX_MERGED_TYPEINFO_NAMES to 1 or 0 to indicate whether or not pointer
+// comparison can be used.
 
 #ifndef __GXX_MERGED_TYPEINFO_NAMES
-  #if !__GXX_WEAK__
-    // If weak symbols are not supported, typeinfo names are not merged.
-    #define __GXX_MERGED_TYPEINFO_NAMES 0
-  #else
-    // On platforms that support weak symbols, typeinfo names are merged.
-    #define __GXX_MERGED_TYPEINFO_NAMES 1
-  #endif
+// By default, typeinfo names are not merged.
+#define __GXX_MERGED_TYPEINFO_NAMES 0
 #endif
 
-// By default follow the same rules as for __GXX_MERGED_TYPEINFO_NAMES.
+// By default follow the old inline rules to avoid ABI changes.
 #ifndef __GXX_TYPEINFO_EQUALITY_INLINE
   #if !__GXX_WEAK__
     #define __GXX_TYPEINFO_EQUALITY_INLINE 0
@@ -100,25 +97,35 @@ namespace std
     { return __name; }
 
 #if !__GXX_TYPEINFO_EQUALITY_INLINE
-    bool before(const type_info& __arg) const;
-
     // In old abi, or when weak symbols are not supported, there can
     // be multiple instances of a type_info object for one
     // type. Uniqueness must use the _name value, not object address.
+    bool before(const type_info& __arg) const;
     bool operator==(const type_info& __arg) const;
 #else
   #if !__GXX_MERGED_TYPEINFO_NAMES
-    #error "Inline implementation of type_info comparision requires merging of type_info objects"
-  #endif
     /** Returns true if @c *this precedes @c __arg in the implementation's
      *  collation order.  */
-    // In new abi we can rely on type_info's NTBS being unique,
+    // Even with the new abi, on systems that support dlopen
+    // we can run into cases where type_info names aren't merged,
+    // so we still need to do string comparison.
+    bool before(const type_info& __arg) const
+    { return __builtin_strcmp (__name, __arg.__name) < 0; }
+
+    bool operator==(const type_info& __arg) const
+    {
+      return ((__name == __arg.__name)
+             || __builtin_strcmp (__name, __arg.__name) == 0);
+    }
+  #else
+    // On some targets we can rely on type_info's NTBS being unique,
     // and therefore address comparisons are sufficient.
     bool before(const type_info& __arg) const
     { return __name < __arg.__name; }
 
     bool operator==(const type_info& __arg) const
     { return __name == __arg.__name; }
+  #endif
 #endif
     bool operator!=(const type_info& __arg) const
     { return !operator==(__arg); }
This page took 0.084156 seconds and 5 git commands to generate.