aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2009-10-02 20:46:49 -0400
committerJason Merrill <jason@gcc.gnu.org>2009-10-02 20:46:49 -0400
commit3930dbe9d6c9849e32ce39d7ff585348d4716329 (patch)
treedce6c2dc62ee375a25c6ec2937c1971bb4daf712
parentb2eb5a67b218756fb956146cc72b69f2cf475f5c (diff)
downloadgcc-3930dbe9d6c9849e32ce39d7ff585348d4716329.zip
gcc-3930dbe9d6c9849e32ce39d7ff585348d4716329.tar.gz
gcc-3930dbe9d6c9849e32ce39d7ff585348d4716329.tar.bz2
mangle.c (write_unnamed_type_name): Implement.
* 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. From-SVN: r152429
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/cp-tree.h3
-rw-r--r--gcc/cp/mangle.c95
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/abi/mangle32.C41
5 files changed, 129 insertions, 22 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 91a6ad6..0fea912 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index fc00176..8a18575 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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))
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 1e08465..d96a929 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index e40e71d..ef98be2 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..de02887
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/mangle32.C
@@ -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();
+}