* mangle.c (write_unnamed_type_name): Implement.
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 3 Oct 2009 00:46:49 +0000 (00:46 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 3 Oct 2009 00:46:49 +0000 (00:46 +0000)
(local_class_index): Split out from...
(discriminator_for_local_entity): ...here.
(nested_anon_class_index): New.
* cp-tree.h (TYPE_FUNCTION_SCOPE_P): New.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@152429 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/mangle.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/abi/mangle32.C [new file with mode: 0644]

index 91a6ad6..0fea912 100644 (file)
@@ -1,3 +1,11 @@
+2009-10-02  Jason Merrill  <jason@redhat.com>
+
+       * mangle.c (write_unnamed_type_name): Implement.
+       (local_class_index): Split out from...
+       (discriminator_for_local_entity): ...here.
+       (nested_anon_class_index): New.
+       * cp-tree.h (TYPE_FUNCTION_SCOPE_P): New.
+
 2009-10-02  Janis Johnson  <janis187@us.ibm.com>
 
        * call.c (convert_arg_to_ellipsis): Avoid promoting decimal32
index fc00176..8a18575 100644 (file)
@@ -2249,6 +2249,9 @@ struct GTY(()) lang_decl {
   (DECL_CONTEXT (NODE) \
    && TREE_CODE (DECL_CONTEXT (NODE)) == FUNCTION_DECL)
 
+#define TYPE_FUNCTION_SCOPE_P(NODE) \
+  (TYPE_CONTEXT (NODE) && TREE_CODE (TYPE_CONTEXT (NODE)) == FUNCTION_DECL)
+
 /* 1 iff VAR_DECL node NODE is a type-info decl.  This flag is set for
    both the primary typeinfo object and the associated NTBS name.  */
 #define DECL_TINFO_P(NODE) TREE_LANG_FLAG_4 (VAR_DECL_CHECK (NODE))
index 1e08465..d96a929 100644 (file)
@@ -217,6 +217,7 @@ static void write_discriminator (const int);
 static void write_local_name (tree, const tree, const tree);
 static void dump_substitution_candidates (void);
 static tree mangle_decl_string (const tree);
+static int local_class_index (tree);
 
 /* Control functions.  */
 
@@ -1204,8 +1205,7 @@ write_unqualified_name (const tree decl)
       tree type = TREE_TYPE (decl);
 
       if (TREE_CODE (decl) == TYPE_DECL
-          && TYPE_ANONYMOUS_P (type)
-          && !ANON_UNION_TYPE_P (type))
+          && TYPE_ANONYMOUS_P (type))
         write_unnamed_type_name (type);
       else if (TREE_CODE (decl) == TYPE_DECL
                && LAMBDA_TYPE_P (type))
@@ -1252,14 +1252,48 @@ write_compact_number (int num)
   write_char ('_');
 }
 
+/* Return how many unnamed types precede TYPE in its enclosing class.  */
+
+static int
+nested_anon_class_index (tree type)
+{
+  int index = 0;
+  tree member = TYPE_FIELDS (TYPE_CONTEXT (type));
+  for (; member; member = TREE_CHAIN (member))
+    if (DECL_IMPLICIT_TYPEDEF_P (member))
+      {
+       tree memtype = TREE_TYPE (member);
+       if (memtype == type)
+         return index;
+       else if (TYPE_ANONYMOUS_P (memtype))
+         ++index;
+      }
+
+  gcc_unreachable ();
+}
+
+/* <unnamed-type-name> ::= Ut [ <nonnegative number> ] _ */
+
 static void
 write_unnamed_type_name (const tree type __attribute__ ((__unused__)))
 {
+  int discriminator;
   MANGLE_TRACE_TREE ("unnamed-type-name", type);
 
+  if (TYPE_FUNCTION_SCOPE_P (type))
+    discriminator = local_class_index (type);
+  else if (TYPE_CLASS_SCOPE_P (type))
+    discriminator = nested_anon_class_index (type);
+  else
+    {
+      gcc_assert (no_linkage_check (type, /*relaxed_p=*/true));
+      /* Just use the old mangling at namespace scope.  */
+      write_source_name (TYPE_IDENTIFIER (type));
+      return;
+    }
+
   write_string ("Ut");
-  /* TODO: Implement discriminators for unnamed-types.  */
-  write_char ('_');
+  write_compact_number (discriminator);
 }
 
 /* <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
@@ -1539,6 +1573,29 @@ write_special_name_destructor (const tree dtor)
     }
 }
 
+/* Scan the vector of local classes and return how many others with the
+   same name (or same no name) and context precede ENTITY.  */
+
+static int
+local_class_index (tree entity)
+{
+  int ix, discriminator = 0;
+  tree name = (TYPE_ANONYMOUS_P (entity) ? NULL_TREE
+              : TYPE_IDENTIFIER (entity));
+  tree ctx = TYPE_CONTEXT (entity);
+  for (ix = 0; ; ix++)
+    {
+      tree type = VEC_index (tree, local_classes, ix);
+      if (type == entity)
+       return discriminator;
+      if (TYPE_CONTEXT (type) == ctx
+         && (name ? TYPE_IDENTIFIER (type) == name
+             : TYPE_ANONYMOUS_P (type)))
+       ++discriminator;
+    }
+  gcc_unreachable ();
+}
+
 /* Return the discriminator for ENTITY appearing inside
    FUNCTION.  The discriminator is the lexical ordinal of VAR among
    entities with the same name in the same FUNCTION.  */
@@ -1546,15 +1603,17 @@ write_special_name_destructor (const tree dtor)
 static int
 discriminator_for_local_entity (tree entity)
 {
-  /* Assume this is the only local entity with this name.  */
-  int discriminator = 0;
-
-  if (DECL_DISCRIMINATOR_P (entity) && DECL_LANG_SPECIFIC (entity))
-    discriminator = DECL_DISCRIMINATOR (entity);
+  if (DECL_DISCRIMINATOR_P (entity))
+    {
+      if (DECL_LANG_SPECIFIC (entity))
+       return DECL_DISCRIMINATOR (entity);
+      else
+       /* The first entity with a particular name doesn't get
+          DECL_LANG_SPECIFIC/DECL_DISCRIMINATOR.  */
+       return 0;
+    }
   else if (TREE_CODE (entity) == TYPE_DECL)
     {
-      int ix;
-
       /* Scan the list of local classes.  */
       entity = TREE_TYPE (entity);
 
@@ -1562,18 +1621,10 @@ discriminator_for_local_entity (tree entity)
       if (LAMBDA_TYPE_P (entity) || TYPE_ANONYMOUS_P (entity))
        return 0;
 
-      for (ix = 0; ; ix++)
-       {
-         tree type = VEC_index (tree, local_classes, ix);
-         if (type == entity)
-           break;
-         if (TYPE_IDENTIFIER (type) == TYPE_IDENTIFIER (entity)
-             && TYPE_CONTEXT (type) == TYPE_CONTEXT (entity))
-           ++discriminator;
-       }
+      return local_class_index (entity);
     }
-
-  return discriminator;
+  else
+    gcc_unreachable ();
 }
 
 /* Return the discriminator for STRING, a string literal used inside
index e40e71d..ef98be2 100644 (file)
@@ -1,3 +1,7 @@
+2009-10-02  Jason Merrill  <jason@redhat.com>
+
+       * g++.dg/abi/mangle32.C: New.
+
 2009-10-02  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gnat.dg/atomic2.adb: New test.
diff --git a/gcc/testsuite/g++.dg/abi/mangle32.C b/gcc/testsuite/g++.dg/abi/mangle32.C
new file mode 100644 (file)
index 0000000..de02887
--- /dev/null
@@ -0,0 +1,41 @@
+// Testcase for mangling of unnamed types.
+
+// namespace-scope unnamed types have no linkage, so we only test that they
+// are distinct.
+typedef struct { } *A;
+typedef struct { } *B;
+
+void f(A) { }
+void f(B) { }
+
+struct C
+{
+  typedef struct { }* D;
+  typedef enum { }* E;
+};
+
+// { dg-final { scan-assembler "_Z2g1PN1CUt_E" } }
+void g1(C::D) { }
+// { dg-final { scan-assembler "_Z2g2PN1CUt0_E" } }
+void g2(C::E) { }
+
+template <class T>
+void h1(T t) { }
+
+template <class T>
+void h2(T t) { }
+
+inline void j()
+{
+  typedef enum { }* F;
+// { dg-final { scan-assembler "_Z2h1IPZ1jvEUt_EvT_" } }
+  h1(F());
+  typedef struct { }* G;
+// { dg-final { scan-assembler "_Z2h2IPZ1jvEUt0_EvT_" } }
+  h2(G());
+}
+
+int main()
+{
+  j();
+}