Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 9050 - Too early instantiation of template structs #2851

Merged
merged 1 commit into from Nov 26, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/clone.c
Expand Up @@ -76,6 +76,7 @@ FuncDeclaration *AggregateDeclaration::hasIdentityOpAssign(Scope *sc)
unsigned oldspec = global.speculativeGag; // template opAssign fbody makes it.
global.speculativeGag = global.gag;
sc = sc->push();
sc->tinst = NULL;
sc->speculative = true;

for (size_t i = 0; i < 2; i++)
Expand Down Expand Up @@ -419,6 +420,7 @@ FuncDeclaration *AggregateDeclaration::hasIdentityOpEquals(Scope *sc)
unsigned oldspec = global.speculativeGag; // template opAssign fbody makes it.
global.speculativeGag = global.gag;
sc = sc->push();
sc->tinst = NULL;
sc->speculative = true;

for (size_t j = 0; j < 2; j++)
Expand Down
58 changes: 57 additions & 1 deletion src/template.c
Expand Up @@ -5198,6 +5198,7 @@ TemplateInstance::TemplateInstance(Loc loc, Identifier *ident)
this->instantiatingModule = NULL;
this->inst = NULL;
this->tinst = NULL;
this->deferred = NULL;
this->argsym = NULL;
this->aliasdecl = NULL;
this->semantictiargsdone = false;
Expand Down Expand Up @@ -5228,6 +5229,7 @@ TemplateInstance::TemplateInstance(Loc loc, TemplateDeclaration *td, Objects *ti
this->instantiatingModule = NULL;
this->inst = NULL;
this->tinst = NULL;
this->deferred = NULL;
this->argsym = NULL;
this->aliasdecl = NULL;
this->semantictiargsdone = true;
Expand Down Expand Up @@ -5773,9 +5775,63 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
semantic2(sc2);
}

if (sc->func)
if (sc->func && aliasdecl && aliasdecl->toAlias()->isFuncDeclaration())
{
/* Template function instantiation should run semantic3 immediately
* for attribute inference.
*/
//printf("function semantic3 %s inside %s\n", toChars(), sc->func->toChars());
trySemantic3(sc2);
}
else if (sc->func && !tinst)
{
/* If a template is instantiated inside function, the whole instantiation
* should be done at that position. But, immediate running semantic3 of
* dependent templates may cause unresolved forward reference (Bugzilla 9050).
* To avoid the issue, don't run semantic3 until semantic and semantic2 done.
*/
TemplateInstances deferred;
this->deferred = &deferred;

//printf("Run semantic3 on %s\n", toChars());
trySemantic3(sc2);

for (size_t i = 0; i < deferred.dim; i++)
{
//printf("+ run deferred semantic3 on %s\n", deferred[i]->toChars());
deferred[i]->semantic3(NULL);
}

this->deferred = NULL;
}
else if (tinst)
{
TemplateInstance *ti = tinst;
int nest = 0;
while (ti && !ti->deferred && ti->tinst)
{
ti = ti->tinst;
if (++nest > 500)
{
global.gag = 0; // ensure error message gets printed
error("recursive expansion");
fatal();
}
}
if (ti && ti->deferred)
{
//printf("deferred semantic3 of %p %s, ti = %s, ti->deferred = %p\n", this, toChars(), ti->toChars());
for (size_t i = 0; ; i++)
{
if (i == ti->deferred->dim)
{
ti->deferred->push(this);
break;
}
if ((*ti->deferred)[i] == this)
break;
}
}
}

Laftersemantic:
Expand Down
2 changes: 2 additions & 0 deletions src/template.h
Expand Up @@ -315,6 +315,8 @@ class TemplateInstance : public ScopeDsymbol
Expressions *fargs; // for function template, these are the function arguments
Module *instantiatingModule; // the top module that instantiated this instance

TemplateInstances* deferred;

TemplateInstance(Loc loc, Identifier *temp_id);
TemplateInstance(Loc loc, TemplateDeclaration *tempdecl, Objects *tiargs);
static Objects *arraySyntaxCopy(Objects *objs);
Expand Down
36 changes: 36 additions & 0 deletions test/runnable/template9.d
Expand Up @@ -1913,6 +1913,42 @@ void test9038()
check_data9038!(bar.f)(bar);
}

/**********************************/
// 9050

struct A9050(T) {}

struct B9050(T)
{
void f() { foo9050(A9050!int()); }
}

auto foo9050()(A9050!int base) pure
{
return B9050!int();
}

auto s9050 = foo9050(A9050!int());

/**********************************/
// 10936 (dup of 9050)

struct Vec10936(string s)
{
auto foo(string v)()
{
return Vec10936!(v)();
}

static void bar()
{
Vec10936!"" v;
auto p = v.foo!"sup";
}
}

Vec10936!"" v;

/**********************************/
// 9076

Expand Down