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>
* call.c (convert_arg_to_ellipsis): Avoid promoting decimal32
......
......@@ -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))
......
......@@ -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
......
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.
......
// 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