diff --git a/src/glue.c b/src/glue.c index 557de080c250..fefe3696508d 100644 --- a/src/glue.c +++ b/src/glue.c @@ -131,7 +131,7 @@ void obj_write_deferred(Library *library) md->genobjfile(0); } - + /* Set object file name to be source name with sequence number, * as mangled symbol names get way too long. */ @@ -532,6 +532,7 @@ void FuncDeclaration::toObjFile(int multiobj) int has_arguments; //printf("FuncDeclaration::toObjFile(%p, %s.%s)\n", func, parent->toChars(), func->toChars()); + //if (type) printf("type = %s\n", func->type->toChars()); #if 0 //printf("line = %d\n",func->getWhere() / LINEINC); @@ -580,6 +581,17 @@ void FuncDeclaration::toObjFile(int multiobj) assert(semanticRun == PASSsemantic3done); semanticRun = PASSobj; + /* Skip generating code if this part of a TemplateInstance that is instantiated + * only by non-root modules (i.e. modules not listed on the command line). + */ + TemplateInstance *ti = inTemplateInstance(); + if (!global.params.useUnitTests && + ti && ti->instantiatingModule && !ti->instantiatingModule->root) + { + //printf("instantiated by %s %s\n", ti->instantiatingModule->toChars(), ti->toChars()); + return; + } + if (global.params.verbose) printf("function %s\n",func->toPrettyChars()); diff --git a/src/mars.c b/src/mars.c index d546fec0b8db..aae1e16cbb3a 100644 --- a/src/mars.c +++ b/src/mars.c @@ -1459,6 +1459,7 @@ Language changes listed by -transition=id:\n\ for (size_t filei = 0, modi = 0; filei < filecount; filei++, modi++) { m = modules[modi]; + m->root = TRUE; if (global.params.verbose) printf("parse %s\n", m->toChars()); if (!Module::rootModule) diff --git a/src/mtype.c b/src/mtype.c index d1e09833e882..303527419a6a 100644 --- a/src/mtype.c +++ b/src/mtype.c @@ -4680,6 +4680,7 @@ StructDeclaration *TypeAArray::getImpl() #endif // Instantiate on the root module of import dependency graph. Scope *scx = sc->push(sc->module->importedFrom); + scx->instantiatingModule = sc->module->importedFrom; ti->semantic(scx); ti->semantic2(scx); ti->semantic3(scx); diff --git a/src/scope.c b/src/scope.c index 1116ab335fc7..e8befc33e1e9 100644 --- a/src/scope.c +++ b/src/scope.c @@ -50,6 +50,7 @@ Scope::Scope() //printf("Scope::Scope() %p\n", this); this->module = NULL; + this->instantiatingModule = NULL; this->scopesym = NULL; this->sd = NULL; this->enclosing = NULL; @@ -88,6 +89,7 @@ Scope::Scope(Scope *enclosing) //printf("Scope::Scope(enclosing = %p) %p\n", enclosing, this); assert(!(enclosing->flags & SCOPEfree)); this->module = enclosing->module; + this->instantiatingModule = enclosing->instantiatingModule; this->func = enclosing->func; this->parent = enclosing->parent; this->scopesym = NULL; diff --git a/src/scope.h b/src/scope.h index 4c5241f1a3dc..864d9ab683d8 100644 --- a/src/scope.h +++ b/src/scope.h @@ -1,5 +1,5 @@ -// Copyright (c) 1999-2012 by Digital Mars +// Copyright (c) 1999-2013 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -65,6 +65,7 @@ struct Scope Scope *enclosing; // enclosing Scope Module *module; // Root module + Module *instantiatingModule; // top level module that started a chain of template instantiations ScopeDsymbol *scopesym; // current symbol ScopeDsymbol *sd; // if in static if, and declaring new symbols, // sd gets the addMember() diff --git a/src/struct.c b/src/struct.c index fae41613d89f..cb8a50753130 100644 --- a/src/struct.c +++ b/src/struct.c @@ -144,9 +144,10 @@ void AggregateDeclaration::semantic3(Scope *sc) Dsymbol *s = ti->toAlias(); Expression *e = new DsymbolExp(Loc(), s, 0); - Scope *sc = ti->tempdecl->scope->startCTFE(); - e = e->semantic(sc); - sc->endCTFE(); + Scope *sc2 = ti->tempdecl->scope->startCTFE(); + sc2->instantiatingModule = sc->instantiatingModule ? sc->instantiatingModule : sc->module; + e = e->semantic(sc2); + sc2->endCTFE(); e = e->ctfeInterpret(); getRTInfo = e; diff --git a/src/template.c b/src/template.c index acc254d4f7a6..ecd11c96ce47 100644 --- a/src/template.c +++ b/src/template.c @@ -807,7 +807,7 @@ void TemplateDeclaration::makeParamNamesVisibleInConstraint(Scope *paramscope, E * Return match level. */ -MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti, +MATCH TemplateDeclaration::matchWithInstance(Scope *sc, TemplateInstance *ti, Objects *dedtypes, Expressions *fargs, int flag) { MATCH m; size_t dedtypes_dim = dedtypes->dim; @@ -849,6 +849,7 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti, ScopeDsymbol *paramsym = new ScopeDsymbol(); paramsym->parent = scope->parent; Scope *paramscope = scope->push(paramsym); + paramscope->instantiatingModule = sc->instantiatingModule; paramscope->stc = 0; // Attempt type deduction @@ -1004,7 +1005,7 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti, * 0 td2 is more specialized than this */ -MATCH TemplateDeclaration::leastAsSpecialized(TemplateDeclaration *td2, Expressions *fargs) +MATCH TemplateDeclaration::leastAsSpecialized(Scope *sc, TemplateDeclaration *td2, Expressions *fargs) { /* This works by taking the template parameters to this template * declaration and feeding them to td2 as if it were a template @@ -1042,7 +1043,7 @@ MATCH TemplateDeclaration::leastAsSpecialized(TemplateDeclaration *td2, Expressi dedtypes.setDim(td2->parameters->dim); // Attempt a type deduction - MATCH m = td2->matchWithInstance(&ti, &dedtypes, fargs, 1); + MATCH m = td2->matchWithInstance(sc, &ti, &dedtypes, fargs, 1); if (m) { /* A non-variadic template is more specialized than a @@ -1127,6 +1128,12 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(FuncDeclaration *f, Loc l ScopeDsymbol *paramsym = new ScopeDsymbol(); paramsym->parent = scope->parent; Scope *paramscope = scope->push(paramsym); + + paramscope->instantiatingModule = sc->instantiatingModule; + Module *mi = sc->instantiatingModule ? sc->instantiatingModule : sc->module; + if (!sc->instantiatingModule || sc->instantiatingModule->root) + paramscope->instantiatingModule = mi; + paramscope->callsc = sc; paramscope->stc = 0; @@ -2348,7 +2355,7 @@ void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc, Objects dedtypes; dedtypes.setDim(td->parameters->dim); assert(td->semanticRun != PASSinit); - MATCH mta = td->matchWithInstance(ti, &dedtypes, fargs, 0); + MATCH mta = td->matchWithInstance(sc, ti, &dedtypes, fargs, 0); //printf("matchWithInstance = %d\n", mta); if (!mta || mta < ta_last) // no match or less match return 0; @@ -2433,8 +2440,8 @@ void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc, if (td_best) { // Disambiguate by picking the most specialized TemplateDeclaration - MATCH c1 = td->leastAsSpecialized(td_best, fargs); - MATCH c2 = td_best->leastAsSpecialized(td, fargs); + MATCH c1 = td->leastAsSpecialized(sc, td_best, fargs); + MATCH c2 = td_best->leastAsSpecialized(sc, td, fargs); //printf("1: c1 = %d, c2 = %d\n", c1, c2); if (c1 > c2) goto Ltd; if (c1 < c2) goto Ltd_best; @@ -2621,7 +2628,7 @@ FuncDeclaration *TemplateDeclaration::doHeaderInstantiation(Scope *sc, ti->tinst = sc->tinst; { ti->tdtypes.setDim(parameters->dim); - if (!matchWithInstance(ti, &ti->tdtypes, fargs, 2)) + if (!matchWithInstance(sc, ti, &ti->tdtypes, fargs, 2)) return NULL; } @@ -2640,6 +2647,7 @@ FuncDeclaration *TemplateDeclaration::doHeaderInstantiation(Scope *sc, ti->argsym = new ScopeDsymbol(); ti->argsym->parent = scope->parent; scope = scope->push(ti->argsym); + scope->instantiatingModule = sc->instantiatingModule; bool hasttp = false; @@ -5154,6 +5162,7 @@ TemplateInstance::TemplateInstance(Loc loc, Identifier *ident) this->name = ident; this->tiargs = NULL; this->tempdecl = NULL; + this->instantiatingModule = NULL; this->inst = NULL; this->tinst = NULL; this->argsym = NULL; @@ -5183,6 +5192,7 @@ TemplateInstance::TemplateInstance(Loc loc, TemplateDeclaration *td, Objects *ti this->name = td->ident; this->tiargs = tiargs; this->tempdecl = td; + this->instantiatingModule = NULL; this->inst = NULL; this->tinst = NULL; this->argsym = NULL; @@ -5329,6 +5339,28 @@ void TemplateInstance::trySemantic3(Scope *sc2) void TemplateInstance::semantic(Scope *sc, Expressions *fargs) { //printf("TemplateInstance::semantic('%s', this=%p, gag = %d, sc = %p)\n", toChars(), this, global.gag, sc); +#if 0 + for (Dsymbol *s = this; s; s = s->parent) + { + printf("\t%s\n", s->toChars()); + } + printf("Scope\n"); + for (Scope *scx = sc; scx; scx = scx->enclosing) + { + printf("\t%s parent %s instantiatingModule %p\n", scx->module ? scx->module->toChars() : "null", scx->parent ? scx->parent->toChars() : "null", scx->instantiatingModule); + } +#endif + + Module *mi = sc->instantiatingModule ? sc->instantiatingModule : sc->module; + + /* If a TemplateInstance is ever instantiated by non-root modules, + * we do not have to generate code for it, + * because it will be generated when the non-root module is compiled. + */ + if (!instantiatingModule || instantiatingModule->root) + instantiatingModule = mi; + //printf("mi = %s\n", mi->toChars()); + #if LOG printf("\n+TemplateInstance::semantic('%s', this=%p)\n", toChars(), this); #endif @@ -5414,6 +5446,8 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) #if LOG printf("\tit's a match with instance %p, %d\n", inst, inst->semanticRun); #endif + if (!inst->instantiatingModule || inst->instantiatingModule->root) + inst->instantiatingModule = mi; return; } L1: ; @@ -5579,6 +5613,8 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) argsym = new ScopeDsymbol(); argsym->parent = scope->parent; scope = scope->push(argsym); + if (!scope->instantiatingModule || scope->instantiatingModule->root) + scope->instantiatingModule = mi; // scope->stc = 0; // Declare each template parameter as an alias for the argument type @@ -6234,7 +6270,7 @@ bool TemplateInstance::findBestMatch(Scope *sc, Expressions *fargs) assert(tempdecl->scope); // Deduce tdtypes tdtypes.setDim(tempdecl->parameters->dim); - if (!tempdecl->matchWithInstance(this, &tdtypes, fargs, 2)) + if (!tempdecl->matchWithInstance(sc, this, &tdtypes, fargs, 2)) { error("incompatible arguments for template instantiation"); return false; @@ -6250,6 +6286,7 @@ bool TemplateInstance::findBestMatch(Scope *sc, Expressions *fargs) struct ParamBest { // context + Scope *sc; TemplateInstance *ti; Objects dedtypes; // result @@ -6283,7 +6320,7 @@ bool TemplateInstance::findBestMatch(Scope *sc, Expressions *fargs) dedtypes.setDim(td->parameters->dim); dedtypes.zero(); assert(td->semanticRun != PASSinit); - MATCH m = td->matchWithInstance(ti, &dedtypes, ti->fargs, 0); + MATCH m = td->matchWithInstance(sc, ti, &dedtypes, ti->fargs, 0); //printf("matchWithInstance = %d\n", m); if (!m) // no match at all return 0; @@ -6293,8 +6330,8 @@ bool TemplateInstance::findBestMatch(Scope *sc, Expressions *fargs) { // Disambiguate by picking the most specialized TemplateDeclaration - MATCH c1 = td->leastAsSpecialized(td_best, ti->fargs); - MATCH c2 = td_best->leastAsSpecialized(td, ti->fargs); + MATCH c1 = td->leastAsSpecialized(sc, td_best, ti->fargs); + MATCH c2 = td_best->leastAsSpecialized(sc, td, ti->fargs); //printf("c1 = %d, c2 = %d\n", c1, c2); if (c1 > c2) goto Ltd; if (c1 < c2) goto Ltd_best; @@ -6320,6 +6357,7 @@ bool TemplateInstance::findBestMatch(Scope *sc, Expressions *fargs) ParamBest p; // context p.ti = this; + p.sc = sc; /* Since there can be multiple TemplateDeclaration's with the same * name, look for the best match. @@ -6713,6 +6751,7 @@ bool TemplateInstance::needsTypeInference(Scope *sc, int flag) struct ParamNeedsInf { // context + Scope *sc; TemplateInstance *ti; int flag; // result @@ -6809,7 +6848,7 @@ bool TemplateInstance::needsTypeInference(Scope *sc, int flag) dedtypes.setDim(td->parameters->dim); dedtypes.zero(); assert(td->semanticRun != PASSinit); - MATCH m = td->matchWithInstance(ti, &dedtypes, NULL, 0); + MATCH m = td->matchWithInstance(sc, ti, &dedtypes, NULL, 0); if (m == MATCHnomatch) return 0; } @@ -6826,6 +6865,7 @@ bool TemplateInstance::needsTypeInference(Scope *sc, int flag) ParamNeedsInf p; // context p.ti = this; + p.sc = sc; p.flag = flag; // result p.count = 0; @@ -6854,6 +6894,7 @@ void TemplateInstance::semantic2(Scope *sc) sc = tempdecl->scope; assert(sc); sc = sc->push(argsym); + sc->instantiatingModule = instantiatingModule; sc = sc->push(this); sc->tinst = this; for (size_t i = 0; i < members->dim; i++) @@ -6885,6 +6926,7 @@ void TemplateInstance::semantic3(Scope *sc) { sc = tempdecl->scope; sc = sc->push(argsym); + sc->instantiatingModule = instantiatingModule; sc = sc->push(this); sc->tinst = this; int needGagging = (speculative && !global.gag); @@ -7585,6 +7627,7 @@ void TemplateMixin::semantic3(Scope *sc) if (members) { sc = sc->push(argsym); + sc->instantiatingModule = instantiatingModule; sc = sc->push(this); for (size_t i = 0; i < members->dim; i++) { diff --git a/src/template.h b/src/template.h index 1e4ba83ed732..21140e2c722f 100644 --- a/src/template.h +++ b/src/template.h @@ -95,8 +95,8 @@ class TemplateDeclaration : public ScopeDsymbol PROT prot(); // void toDocBuffer(OutBuffer *buf); - MATCH matchWithInstance(TemplateInstance *ti, Objects *atypes, Expressions *fargs, int flag); - MATCH leastAsSpecialized(TemplateDeclaration *td2, Expressions *fargs); + MATCH matchWithInstance(Scope *sc, TemplateInstance *ti, Objects *atypes, Expressions *fargs, int flag); + MATCH leastAsSpecialized(Scope *sc, TemplateDeclaration *td2, Expressions *fargs); MATCH deduceFunctionTemplateMatch(FuncDeclaration *f, Loc loc, Scope *sc, Objects *tiargs, Type *tthis, Expressions *fargs, Objects *dedargs); RootObject *declareParameter(Scope *sc, TemplateParameter *tp, RootObject *o); @@ -319,6 +319,7 @@ class TemplateInstance : public ScopeDsymbol Dsymbol *enclosing; // if referencing local symbols, this is the context hash_t hash; // cached result of hashCode() Expressions *fargs; // for function template, these are the function arguments + Module *instantiatingModule; // the top module that instantiated this instance #ifdef IN_GCC /* On some targets, it is necessary to know whether a symbol will be emitted in the output or not before the symbol diff --git a/test/runnable/imports/test10441b.d b/test/runnable/imports/test10441b.d new file mode 100644 index 000000000000..1f9318caa31b --- /dev/null +++ b/test/runnable/imports/test10441b.d @@ -0,0 +1,9 @@ + +public import test10441c; + +auto foo()() + if (boo(1)) +{ + return 1; +} + diff --git a/test/runnable/imports/test10441c.d b/test/runnable/imports/test10441c.d new file mode 100644 index 000000000000..fa9686a6682a --- /dev/null +++ b/test/runnable/imports/test10441c.d @@ -0,0 +1,6 @@ + +auto boo(T)(T t) +{ + return 1; +} + diff --git a/test/runnable/test10441.d b/test/runnable/test10441.d new file mode 100644 index 000000000000..6dc24eac0ff7 --- /dev/null +++ b/test/runnable/test10441.d @@ -0,0 +1,10 @@ +// EXTRA_SOURCES: imports/test10441b.d imports/test10441c.d + +import test10441b; + +void main() +{ + boo(1); + foo(); +} +