diff --git a/src/mars.c b/src/mars.c index f83b52be8390..f38c9e85285f 100644 --- a/src/mars.c +++ b/src/mars.c @@ -1510,6 +1510,7 @@ Language changes listed by -transition=id:\n\ printf("semantic3 %s\n", m->toChars()); m->semantic3(); } + Module::runDeferredSemantic3(); if (global.errors) fatal(); diff --git a/src/module.c b/src/module.c index f7057af769f1..4d6fda1960b8 100644 --- a/src/module.c +++ b/src/module.c @@ -34,6 +34,7 @@ DsymbolTable *Module::modules; Modules Module::amodules; Dsymbols Module::deferred; // deferred Dsymbol's needing semantic() run on them +Dsymbols Module::deferred3; unsigned Module::dprogress; const char *lookForSourceFile(const char *filename); @@ -994,6 +995,33 @@ void Module::runDeferredSemantic() //printf("-Module::runDeferredSemantic(), len = %d\n", deferred.dim); } +void Module::addDeferredSemantic3(Dsymbol *s) +{ + // Don't add it if it is already there + for (size_t i = 0; i < deferred3.dim; i++) + { + Dsymbol *sd = deferred3[i]; + if (sd == s) + return; + } + deferred3.push(s); +} + +void Module::runDeferredSemantic3() +{ + Dsymbols *a = &Module::deferred3; + for (size_t i = 0; i < a->dim; i++) + { + Dsymbol *s = (*a)[i]; + //printf("[%d] %s semantic3a\n", i, s->toPrettyChars()); + + s->semantic3(NULL); + + if (global.errors) + break; + } +} + /************************************ * Recursively look at every module this module imports, * return TRUE if it imports m. diff --git a/src/module.h b/src/module.h index 0d095463f146..f186d773af49 100644 --- a/src/module.h +++ b/src/module.h @@ -63,6 +63,7 @@ class Module : public Package static DsymbolTable *modules; // symbol table of all modules static Modules amodules; // array of all modules static Dsymbols deferred; // deferred Dsymbol's needing semantic() run on them + static Dsymbols deferred3; // deferred Dsymbol's needing semantic3() run on them static unsigned dprogress; // progress resolving the deferred list static void init(); @@ -143,8 +144,10 @@ class Module : public Package Dsymbol *search(Loc loc, Identifier *ident, int flags); Dsymbol *symtabInsert(Dsymbol *s); void deleteObjFile(); - void addDeferredSemantic(Dsymbol *s); + static void addDeferredSemantic(Dsymbol *s); static void runDeferredSemantic(); + static void addDeferredSemantic3(Dsymbol *s); + static void runDeferredSemantic3(); static void clearCache(); int imports(Module *m); diff --git a/src/template.c b/src/template.c index c7a758abdf1f..61d6f6717c7a 100644 --- a/src/template.c +++ b/src/template.c @@ -2184,8 +2184,8 @@ void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc, printf("\t%s %s\n", arg->type->toChars(), arg->toChars()); //printf("\tty = %d\n", arg->type->ty); } - printf("stc = %llx\n", dstart->scope->stc); - printf("match:t/f = %d/%d\n", ta_last, m->last); + //printf("stc = %llx\n", dstart->scope->stc); + //printf("match:t/f = %d/%d\n", ta_last, m->last); #endif struct ParamDeduce @@ -5450,7 +5450,6 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) // in target_symbol_list(_idx) so we can remove it later if we encounter // an error. #if 1 - int dosemantic3 = 0; Dsymbols *target_symbol_list = NULL; size_t target_symbol_list_idx; @@ -5482,13 +5481,22 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) } else { - Module *m = (enclosing ? sc : tempdecl->scope)->module->importedFrom; + Module *m = (enclosing ? sc : tempdecl->scope)->module; + if (m->importedFrom != m) + { + //if (tinst && tinst->objFileModule) + // m = tinst->objFileModule; + //else + m = m->importedFrom; + } //printf("\t2: adding to module %s instead of module %s\n", m->toChars(), sc->module->toChars()); a = m->members; + + /* Defer semantic3 running in order to avoid mutual forward reference. + * See test/runnable/test10736.d + */ if (m->semanticRun >= 3) - { - dosemantic3 = 1; - } + Module::addDeferredSemantic3(this); } for (size_t i = 0; 1; i++) { @@ -5685,14 +5693,15 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) * for initializers inside a function. */ // if (sc->parent->isFuncDeclaration()) - + { /* BUG 782: this has problems if the classes this depends on * are forward referenced. Find a way to defer semantic() * on this template. */ semantic2(sc2); + } - if (sc->func || dosemantic3) + if (sc->func) { trySemantic3(sc2); } diff --git a/test/runnable/imports/test10736a.d b/test/runnable/imports/test10736a.d new file mode 100644 index 000000000000..70563fd8c782 --- /dev/null +++ b/test/runnable/imports/test10736a.d @@ -0,0 +1,4 @@ +module imports.test10736a; + +version(A) import std.range; +else import imports.test10736c; diff --git a/test/runnable/imports/test10736b.d b/test/runnable/imports/test10736b.d new file mode 100644 index 000000000000..1aa49d837e59 --- /dev/null +++ b/test/runnable/imports/test10736b.d @@ -0,0 +1,13 @@ +module imports.test10736b; + +version(A) import std.range; +else import imports.test10736c; + +void main() +{ + int[] arr = [0, 1, 2, 3]; + auto x = chunks(arr, 4); // error + + import core.stdc.stdio; + printf("success\n"); +} diff --git a/test/runnable/imports/test10736c.d b/test/runnable/imports/test10736c.d new file mode 100644 index 000000000000..ca8a8e30a840 --- /dev/null +++ b/test/runnable/imports/test10736c.d @@ -0,0 +1,24 @@ +module imports.test10736c; + +struct Chunks(Source) +{ + this(Source source, size_t chunkSize) + { + _source = source; + _chunkSize = chunkSize; + } + + typeof(this) opSlice(size_t, size_t) + { + return chunks(_source, _chunkSize); + } + +private: + Source _source; + size_t _chunkSize; +} + +Chunks!Source chunks(Source)(Source source, size_t chunkSize) +{ + return typeof(return)(source, chunkSize); +} diff --git a/test/runnable/test10736.d b/test/runnable/test10736.d new file mode 100644 index 000000000000..55b6f539887f --- /dev/null +++ b/test/runnable/test10736.d @@ -0,0 +1,5 @@ +// EXTRA_SOURCES: imports/test10736a.d +// EXTRA_SOURCES: imports/test10736b.d + +import imports.test10736a; +import imports.test10736b;