d: Fix ICE force_type_die, at dwarf2out.c using nested types
In functions whose return type is instantiated from a nested template, make sure that all members of the instance are emitted before finishing the outer function, otherwise they will be removed during the prune_unused_types pass. gcc/d/ChangeLog: 2019-03-21 Iain Buclaw <ibuclaw@gdcproject.org> PR d/89017 * d-codegen.cc (d_decl_context): Skip over template instances when finding the context. * decl.cc (DeclVisitor::visit(TemplateDeclaration)): New override. (build_type_decl): Include parameters in name of template types. gcc/testsuite/ChangeLog: 2019-03-21 Iain Buclaw <ibuclaw@gdcproject.org> PR d/89017 * gdc.dg/pr89017.d: New test. From-SVN: r269828
This commit is contained in:
parent
5d2df818b7
commit
9dddefefdf
@ -1,3 +1,11 @@
|
||||
2019-03-21 Iain Buclaw <ibuclaw@gdcproject.org>
|
||||
|
||||
PR d/89017
|
||||
* d-codegen.cc (d_decl_context): Skip over template instances when
|
||||
finding the context.
|
||||
* decl.cc (DeclVisitor::visit(TemplateDeclaration)): New override.
|
||||
(build_type_decl): Include parameters in name of template types.
|
||||
|
||||
2019-03-13 Iain Buclaw <ibuclaw@gdcproject.org>
|
||||
|
||||
PR d/88957
|
||||
|
@ -67,7 +67,7 @@ d_decl_context (Dsymbol *dsym)
|
||||
Dsymbol *parent = dsym;
|
||||
Declaration *decl = dsym->isDeclaration ();
|
||||
|
||||
while ((parent = parent->toParent ()))
|
||||
while ((parent = parent->toParent2 ()))
|
||||
{
|
||||
/* We've reached the top-level module namespace.
|
||||
Set DECL_CONTEXT as the NAMESPACE_DECL of the enclosing module,
|
||||
@ -101,11 +101,6 @@ d_decl_context (Dsymbol *dsym)
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
/* Instantiated types are given the context of their template. */
|
||||
TemplateInstance *ti = parent->isTemplateInstance ();
|
||||
if (ti != NULL && decl == NULL)
|
||||
parent = ti->tempdecl;
|
||||
}
|
||||
|
||||
return NULL_TREE;
|
||||
|
@ -255,6 +255,40 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/* Templates are D's approach to generic programming. They have no members
|
||||
that can be emitted, however if the template is nested and used as a
|
||||
voldemort type, then it's members must be compiled before the parent
|
||||
function finishes. */
|
||||
|
||||
void visit (TemplateDeclaration *d)
|
||||
{
|
||||
/* Type cannot be directly named outside of the scope it's declared in, so
|
||||
the only way it can be escaped is if the function has auto return. */
|
||||
FuncDeclaration *fd = d_function_chain ? d_function_chain->function : NULL;
|
||||
|
||||
if (!fd || !fd->isAuto ())
|
||||
return;
|
||||
|
||||
/* Check if the function returns an instantiated type that may contain
|
||||
nested members. Only applies to classes or structs. */
|
||||
Type *tb = fd->type->nextOf ()->baseElemOf ();
|
||||
|
||||
while (tb->ty == Tarray || tb->ty == Tpointer)
|
||||
tb = tb->nextOf ()->baseElemOf ();
|
||||
|
||||
TemplateInstance *ti = NULL;
|
||||
|
||||
if (tb->ty == Tstruct)
|
||||
ti = ((TypeStruct *) tb)->sym->isInstantiated ();
|
||||
else if (tb->ty == Tclass)
|
||||
ti = ((TypeClass *) tb)->sym->isInstantiated ();
|
||||
|
||||
/* Return type is instantiated from this template declaration, walk over
|
||||
all members of the instance. */
|
||||
if (ti && ti->tempdecl == d)
|
||||
ti->accept (this);
|
||||
}
|
||||
|
||||
/* Walk over all members in the instantiated template. */
|
||||
|
||||
void visit (TemplateInstance *d)
|
||||
@ -2228,8 +2262,13 @@ build_type_decl (tree type, Dsymbol *dsym)
|
||||
|
||||
gcc_assert (!POINTER_TYPE_P (type));
|
||||
|
||||
/* If a templated type, use the template instance name, as that includes all
|
||||
template parameters. */
|
||||
const char *name = dsym->parent->isTemplateInstance ()
|
||||
? ((TemplateInstance *) dsym->parent)->toChars () : dsym->ident->toChars ();
|
||||
|
||||
tree decl = build_decl (make_location_t (dsym->loc), TYPE_DECL,
|
||||
get_identifier (dsym->ident->toChars ()), type);
|
||||
get_identifier (name), type);
|
||||
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (mangle_decl (dsym)));
|
||||
TREE_PUBLIC (decl) = 1;
|
||||
DECL_ARTIFICIAL (decl) = 1;
|
||||
|
@ -1,3 +1,8 @@
|
||||
2019-03-21 Iain Buclaw <ibuclaw@gdcproject.org>
|
||||
|
||||
PR d/89017
|
||||
* gdc.dg/pr89017.d: New test.
|
||||
|
||||
2019-03-20 Janus Weil <janus@gcc.gnu.org>
|
||||
|
||||
PR fortran/71861
|
||||
|
49
gcc/testsuite/gdc.dg/pr89017.d
Normal file
49
gcc/testsuite/gdc.dg/pr89017.d
Normal file
@ -0,0 +1,49 @@
|
||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89017
|
||||
// { dg-do compile }
|
||||
|
||||
enum Type
|
||||
{
|
||||
Struct,
|
||||
Class,
|
||||
Pointer,
|
||||
Array,
|
||||
}
|
||||
|
||||
auto f89017(Type type)()
|
||||
{
|
||||
static if (type == Type.Class)
|
||||
{
|
||||
class C(S)
|
||||
{
|
||||
struct S
|
||||
{
|
||||
void fn(){}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
struct C(S)
|
||||
{
|
||||
struct S
|
||||
{
|
||||
void fn(){}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static if (type == Type.Struct)
|
||||
return C!Type();
|
||||
static if (type == Type.Class || type == Type.Pointer)
|
||||
return new C!Type();
|
||||
static if (type == Type.Array)
|
||||
return new C!Type[2];
|
||||
}
|
||||
|
||||
void test89017()
|
||||
{
|
||||
f89017!(Type.Class);
|
||||
f89017!(Type.Struct);
|
||||
f89017!(Type.Pointer);
|
||||
f89017!(Type.Array);
|
||||
}
|
Loading…
Reference in New Issue
Block a user