Commit 3930dbe9 by Jason Merrill Committed by Jason Merrill

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
parent b2eb5a67
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> 2009-10-02 Janis Johnson <janis187@us.ibm.com>
* call.c (convert_arg_to_ellipsis): Avoid promoting decimal32 * call.c (convert_arg_to_ellipsis): Avoid promoting decimal32
......
...@@ -2249,6 +2249,9 @@ struct GTY(()) lang_decl { ...@@ -2249,6 +2249,9 @@ struct GTY(()) lang_decl {
(DECL_CONTEXT (NODE) \ (DECL_CONTEXT (NODE) \
&& TREE_CODE (DECL_CONTEXT (NODE)) == FUNCTION_DECL) && 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 /* 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. */ both the primary typeinfo object and the associated NTBS name. */
#define DECL_TINFO_P(NODE) TREE_LANG_FLAG_4 (VAR_DECL_CHECK (NODE)) #define DECL_TINFO_P(NODE) TREE_LANG_FLAG_4 (VAR_DECL_CHECK (NODE))
......
...@@ -217,6 +217,7 @@ static void write_discriminator (const int); ...@@ -217,6 +217,7 @@ static void write_discriminator (const int);
static void write_local_name (tree, const tree, const tree); static void write_local_name (tree, const tree, const tree);
static void dump_substitution_candidates (void); static void dump_substitution_candidates (void);
static tree mangle_decl_string (const tree); static tree mangle_decl_string (const tree);
static int local_class_index (tree);
/* Control functions. */ /* Control functions. */
...@@ -1204,8 +1205,7 @@ write_unqualified_name (const tree decl) ...@@ -1204,8 +1205,7 @@ write_unqualified_name (const tree decl)
tree type = TREE_TYPE (decl); tree type = TREE_TYPE (decl);
if (TREE_CODE (decl) == TYPE_DECL if (TREE_CODE (decl) == TYPE_DECL
&& TYPE_ANONYMOUS_P (type) && TYPE_ANONYMOUS_P (type))
&& !ANON_UNION_TYPE_P (type))
write_unnamed_type_name (type); write_unnamed_type_name (type);
else if (TREE_CODE (decl) == TYPE_DECL else if (TREE_CODE (decl) == TYPE_DECL
&& LAMBDA_TYPE_P (type)) && LAMBDA_TYPE_P (type))
...@@ -1252,14 +1252,48 @@ write_compact_number (int num) ...@@ -1252,14 +1252,48 @@ write_compact_number (int num)
write_char ('_'); 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 static void
write_unnamed_type_name (const tree type __attribute__ ((__unused__))) write_unnamed_type_name (const tree type __attribute__ ((__unused__)))
{ {
int discriminator;
MANGLE_TRACE_TREE ("unnamed-type-name", type); 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"); write_string ("Ut");
/* TODO: Implement discriminators for unnamed-types. */ write_compact_number (discriminator);
write_char ('_');
} }
/* <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _ /* <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
...@@ -1539,6 +1573,29 @@ write_special_name_destructor (const tree dtor) ...@@ -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 /* Return the discriminator for ENTITY appearing inside
FUNCTION. The discriminator is the lexical ordinal of VAR among FUNCTION. The discriminator is the lexical ordinal of VAR among
entities with the same name in the same FUNCTION. */ entities with the same name in the same FUNCTION. */
...@@ -1546,15 +1603,17 @@ write_special_name_destructor (const tree dtor) ...@@ -1546,15 +1603,17 @@ write_special_name_destructor (const tree dtor)
static int static int
discriminator_for_local_entity (tree entity) discriminator_for_local_entity (tree entity)
{ {
/* Assume this is the only local entity with this name. */ if (DECL_DISCRIMINATOR_P (entity))
int discriminator = 0; {
if (DECL_LANG_SPECIFIC (entity))
if (DECL_DISCRIMINATOR_P (entity) && DECL_LANG_SPECIFIC (entity)) return DECL_DISCRIMINATOR (entity);
discriminator = 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) else if (TREE_CODE (entity) == TYPE_DECL)
{ {
int ix;
/* Scan the list of local classes. */ /* Scan the list of local classes. */
entity = TREE_TYPE (entity); entity = TREE_TYPE (entity);
...@@ -1562,18 +1621,10 @@ discriminator_for_local_entity (tree entity) ...@@ -1562,18 +1621,10 @@ discriminator_for_local_entity (tree entity)
if (LAMBDA_TYPE_P (entity) || TYPE_ANONYMOUS_P (entity)) if (LAMBDA_TYPE_P (entity) || TYPE_ANONYMOUS_P (entity))
return 0; return 0;
for (ix = 0; ; ix++) return local_class_index (entity);
{
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;
} }
} else
gcc_unreachable ();
return discriminator;
} }
/* Return the discriminator for STRING, a string literal used inside /* Return the discriminator for STRING, a string literal used inside
......
2009-10-02 Jason Merrill <jason@redhat.com>
* g++.dg/abi/mangle32.C: New.
2009-10-02 Eric Botcazou <ebotcazou@adacore.com> 2009-10-02 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/atomic2.adb: New test. * gnat.dg/atomic2.adb: New test.
......
// 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();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment