On Fri, 2009-08-21 at 15:25 -0700, Richard Henderson wrote:
> On 08/21/2009 02:37 PM, Jerry Quinn wrote:
> > OK, I've gotten almost this far and can bootstrap (the asterisk is
> > actually not the very first char and I have to figure that out).
> > However, in the referenced test case, both typeinfos are apparently
> > merged, thus returning the same pointer for their name strings, so
> > pointer comparison still wouldn't work.
> >
> > Therefore, I guess I'll need to do the following:
> >
> >>    You might also need to take steps to ensure that the typeinfo gets 
> >> emitted
> >> as non-COMDAT with local symbols, so that each object does indeed end up 
> >> with
> >> its own separate copy.
> >
> > Where should I look to do this?
> 
> First thing you should do is make sure you're emitting a VAR_DECL
> with the string contents, rather than a STRING_CST constant.  The
> later will be merged within an object file within the compiler.
> 
> Second, make sure the VAR_DECL for the typeinfo is no DECL_ONE_ONLY.
> That flag sets up COMDAT sections, which will be merged by the linker.

It looks like I"ve got a working patch now.  It bootstraps and has no
reqressions from make check, nor from make check in the libstdc++
directory.

Any thoughts?

Jerry


2009-08-22  Jerry Quinn  <jlqu...@optonline.net>

        * name-lookup.c (get_anonymous_namespace_name): Use fixed
        namespace "cxx_anon_ns".
        * mangle.c (write_nested_name): Insert '*' to mark fake anonymous
        namespace.
        (get_mangled_string_length): New function.
        (mangle_type_string_for_rtti): Put '*' at start of mangled namestring.
        * rtti.c (tinfo_base_init): Disable DECL_COMDAT for fake
        anonymous namespaces.

2009-08-22  Jerry Quinn  <jlqu...@optonline.net>

        * libsupc++/tinfo.cc (typeinfo::operator==): Compare names
        starting with '*' by pointer.
        * libsupc++/tinfo2.cc (typeinfo::before): Same.
        * libsupc++/typeinfo (typeinfo::operator==): Same.
        * libsupc++/typeinfo (typeinfo::before): Same.


Index: gcc/cp/rtti.c
===================================================================
--- gcc/cp/rtti.c       (revision 151008)
+++ gcc/cp/rtti.c       (working copy)
@@ -862,9 +862,12 @@
     DECL_TINFO_P (name_decl) = 1;
     set_linkage_according_to_type (target, name_decl);
     import_export_decl (name_decl);
+    /* Disable DECL_COMDAT if we have an anonymous namspace here. */
+    if (TREE_STRING_POINTER (name_string)[0] == '*')
+      DECL_COMDAT (name_decl) = 0;
     DECL_INITIAL (name_decl) = name_string;
     mark_used (name_decl);
     pushdecl_top_level_and_finish (name_decl, name_string);
 2009-08-21  Jakub Jelinek  <ja...@redhat.com>
 
        PR c++/41131
Index: gcc/cp/mangle.c
===================================================================
--- gcc/cp/mangle.c     (revision 151008)
+++ gcc/cp/mangle.c     (working copy)
@@ -935,8 +935,14 @@
       /* 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 ());
+       {
+         /* Add a * to mark fake anonymous namespaces in typeinfos as
+            compare-by-pointer.  This * is used to put another one at the
+            front when done building the string. */
+         write_char ('*');
+         /* Pretend this static function is in an anonymous namespace.  */
+         write_source_name (get_anonymous_namespace_name ());
+       }
       write_unqualified_name (decl);
     }
   write_char ('E');
@@ -2755,6 +2761,14 @@
   name_base = obstack_alloc (&name_obstack, 0);
 }
 
+/*  Returns the length of the mangled string array.  */
+
+static inline int
+get_mangled_string_length (void)
+{
+  return obstack_object_size (mangle_obstack);
+}
+
 /* Done with mangling. If WARN is true, and the name of G.entity will
    be mangled differently in a future version of the ABI, issue a
    warning.  */
@@ -2851,13 +2865,20 @@
 mangle_type_string_for_rtti (const tree type)
 {
   const char *result;
+  int result_len;
 
   start_mangling (type);
   /* Mangle in a fake anonymous namespace if necessary.  */
   fake_anon_scope = true;
+  /* Place marker to be removed if not dealing with a nested name.  */
+  write_char('*');
   write_type (type);
   fake_anon_scope = false;
+  result_len = get_mangled_string_length ();
   result = finish_mangling (/*warn=*/false);
+  /* Remove the marker if not needed.  */
+  if (!strchr(result + 1, '*'))
+    result++;
   if (DEBUG_MANGLE)
     fprintf (stderr, "mangle_type_string = '%s'\n\n", result);
   return result;
Index: gcc/cp/name-lookup.c
===================================================================
--- gcc/cp/name-lookup.c        (revision 151008)
+++ gcc/cp/name-lookup.c        (working copy)
@@ -69,7 +69,7 @@
     {
       /* The anonymous namespace has to have a unique name
         if typeinfo objects are being compared by name.  */
-      anonymous_namespace_name = get_file_function_name ("N");
+      anonymous_namespace_name = get_identifier ("cxx_anon_ns");
     }
   return anonymous_namespace_name;
 }
Index: libstdc++-v3/libsupc++/tinfo2.cc
===================================================================
--- libstdc++-v3/libsupc++/tinfo2.cc    (revision 151008)
+++ libstdc++-v3/libsupc++/tinfo2.cc    (working copy)
@@ -37,7 +37,9 @@
 #if __GXX_MERGED_TYPEINFO_NAMES
   return name () < arg.name ();
 #else
-  return __builtin_strcmp (name (), arg.name ()) < 0;
+  return (name ()[0] == '*' && arg.name()[0] == '*')
+    ? name () < arg.name ()
+    :  __builtin_strcmp (name (), arg.name ()) < 0;
 #endif
 }
 
Index: libstdc++-v3/libsupc++/typeinfo
===================================================================
--- libstdc++-v3/libsupc++/typeinfo     (revision 151008)
+++ libstdc++-v3/libsupc++/typeinfo     (working copy)
@@ -110,12 +110,15 @@
     // 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; }
+    { return (__name[0] == '*' && __arg.__name[0] == '*')
+       ? __name < __arg.__name
+       : __builtin_strcmp (__name, __arg.__name) < 0; }
 
     bool operator==(const type_info& __arg) const
     {
       return ((__name == __arg.__name)
-             || __builtin_strcmp (__name, __arg.__name) == 0);
+             || (__name[0] != '*' && __arg.__name[0] != '*' &&
+                 __builtin_strcmp (__name, __arg.__name) == 0));
     }
   #else
     // On some targets we can rely on type_info's NTBS being unique,
Index: libstdc++-v3/libsupc++/tinfo.cc
===================================================================
--- libstdc++-v3/libsupc++/tinfo.cc     (revision 151008)
+++ libstdc++-v3/libsupc++/tinfo.cc     (working copy)
@@ -41,7 +41,9 @@
 #if __GXX_MERGED_TYPEINFO_NAMES
   return name () == arg.name ();
 #else
-  return (&arg == this) || (__builtin_strcmp (name (), arg.name ()) ==
0);
+  return (&arg == this)
+    || (name ()[0] != '*' && arg.name ()[0] != '*'
+       && (__builtin_strcmp (name (), arg.name ()) == 0));
 #endif
 }
 




Reply via email to