diff options
author | Jason Merrill <jason@redhat.com> | 2009-10-02 20:46:49 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2009-10-02 20:46:49 -0400 |
commit | 3930dbe9d6c9849e32ce39d7ff585348d4716329 (patch) | |
tree | dce6c2dc62ee375a25c6ec2937c1971bb4daf712 /gcc | |
parent | b2eb5a67b218756fb956146cc72b69f2cf475f5c (diff) | |
download | gcc-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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 3 | ||||
-rw-r--r-- | gcc/cp/mangle.c | 95 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/abi/mangle32.C | 41 |
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(); +} |