diff --git a/compiler/src/dmd/aggregate.d b/compiler/src/dmd/aggregate.d index 982e914f9dd..a8f0359645d 100644 --- a/compiler/src/dmd/aggregate.d +++ b/compiler/src/dmd/aggregate.d @@ -25,7 +25,7 @@ import dmd.declaration; import dmd.dscope; import dmd.dstruct; import dmd.dsymbol; -import dmd.dsymbolsem : dsymbolSemantic, determineFields, search; +import dmd.dsymbolsem : dsymbolSemantic, determineFields, search, include; import dmd.dtemplate; import dmd.errors; import dmd.expression; diff --git a/compiler/src/dmd/attrib.d b/compiler/src/dmd/attrib.d index 0300c4f2056..23485d899ba 100644 --- a/compiler/src/dmd/attrib.d +++ b/compiler/src/dmd/attrib.d @@ -72,14 +72,6 @@ extern (C++) abstract class AttribDeclaration : Dsymbol this.decl = decl; } - Dsymbols* include(Scope* sc) - { - if (errors) - return null; - - return decl; - } - /**************************************** * Create a new scope if one or more given attributes * are different from the sc's. @@ -661,18 +653,6 @@ extern (C++) class ConditionalDeclaration : AttribDeclaration } } - // Decide if 'then' or 'else' code should be included - override Dsymbols* include(Scope* sc) - { - //printf("ConditionalDeclaration::include(sc = %p) scope = %p\n", sc, _scope); - - if (errors) - return null; - - assert(condition); - return condition.include(_scope ? _scope : sc) ? decl : elsedecl; - } - override final void addComment(const(char)* comment) { /* Because addComment is called by the parser, if we called @@ -701,8 +681,8 @@ extern (C++) class ConditionalDeclaration : AttribDeclaration extern (C++) final class StaticIfDeclaration : ConditionalDeclaration { ScopeDsymbol scopesym; /// enclosing symbol (e.g. module) where symbols will be inserted - private bool addisdone = false; /// true if members have been added to scope - private bool onStack = false; /// true if a call to `include` is currently active + public bool addisdone = false; /// true if members have been added to scope + public bool onStack = false; /// true if a call to `include` is currently active extern (D) this(const ref Loc loc, Condition condition, Dsymbols* decl, Dsymbols* elsedecl) @safe { @@ -716,42 +696,6 @@ extern (C++) final class StaticIfDeclaration : ConditionalDeclaration return new StaticIfDeclaration(loc, condition.syntaxCopy(), Dsymbol.arraySyntaxCopy(decl), Dsymbol.arraySyntaxCopy(elsedecl)); } - /**************************************** - * Different from other AttribDeclaration subclasses, include() call requires - * the completion of addMember and setScope phases. - */ - override Dsymbols* include(Scope* sc) - { - //printf("StaticIfDeclaration::include(sc = %p) scope = %p\n", sc, _scope); - - if (errors || onStack) - return null; - onStack = true; - scope(exit) onStack = false; - - if (sc && condition.inc == Include.notComputed) - { - assert(scopesym); // addMember is already done - assert(_scope); // setScope is already done - Dsymbols* d = ConditionalDeclaration.include(_scope); - if (d && !addisdone) - { - // Add members lazily. - d.foreachDsymbol( s => s.addMember(_scope, scopesym) ); - - // Set the member scopes lazily. - d.foreachDsymbol( s => s.setScope(_scope) ); - - addisdone = true; - } - return d; - } - else - { - return ConditionalDeclaration.include(sc); - } - } - override const(char)* kind() const { return "static if"; @@ -818,43 +762,6 @@ extern (C++) final class StaticForeachDeclaration : AttribDeclaration return false; } - override Dsymbols* include(Scope* sc) - { - if (errors || onStack) - return null; - if (cached) - { - assert(!onStack); - return cache; - } - onStack = true; - scope(exit) onStack = false; - - if (_scope) - { - sfe.prepare(_scope); // lower static foreach aggregate - } - if (!sfe.ready()) - { - return null; // TODO: ok? - } - - // expand static foreach - import dmd.statementsem: makeTupleForeach; - Dsymbols* d = makeTupleForeach(_scope, true, true, sfe.aggrfe, decl, sfe.needExpansion).decl; - if (d) // process generated declarations - { - // Add members lazily. - d.foreachDsymbol( s => s.addMember(_scope, scopesym) ); - - // Set the member scopes lazily. - d.foreachDsymbol( s => s.setScope(_scope) ); - } - cached = true; - cache = d; - return d; - } - override void addComment(const(char)* comment) { // do nothing @@ -921,7 +828,6 @@ extern(C++) final class ForwardingAttribDeclaration : AttribDeclaration } } - /*********************************************************** * Mixin declarations, like: * mixin("int x"); diff --git a/compiler/src/dmd/canthrow.d b/compiler/src/dmd/canthrow.d index 5738ae37afc..caf58a20634 100644 --- a/compiler/src/dmd/canthrow.d +++ b/compiler/src/dmd/canthrow.d @@ -20,6 +20,7 @@ import dmd.astenums; import dmd.blockexit : BE, checkThrow; import dmd.declaration; import dmd.dsymbol; +import dmd.dsymbolsem : include; import dmd.errorsink; import dmd.expression; import dmd.expressionsem : errorSupplementalInferredAttr; diff --git a/compiler/src/dmd/dmodule.d b/compiler/src/dmd/dmodule.d index 4e9e491cea1..5d566fe34bd 100644 --- a/compiler/src/dmd/dmodule.d +++ b/compiler/src/dmd/dmodule.d @@ -30,7 +30,7 @@ import dmd.dmacro; import dmd.doc; import dmd.dscope; import dmd.dsymbol; -import dmd.dsymbolsem : dsymbolSemantic, importAll, load; +import dmd.dsymbolsem : dsymbolSemantic, importAll, load, include; import dmd.errors; import dmd.errorsink; import dmd.expression; diff --git a/compiler/src/dmd/dsymbolsem.d b/compiler/src/dmd/dsymbolsem.d index e7e054930cc..6c0e1b269ad 100644 --- a/compiler/src/dmd/dsymbolsem.d +++ b/compiler/src/dmd/dsymbolsem.d @@ -7475,6 +7475,135 @@ private extern(C++) class NewScopeVisitor : Visitor sc = sc2; } } + + +extern(C++) Dsymbols* include(Dsymbol d, Scope* sc) +{ + scope icv = new IncludeVisitor(sc); + d.accept(icv); + return icv.symbols; +} + +extern(C++) class IncludeVisitor : Visitor +{ + alias visit = typeof(super).visit; + Scope* sc; + Dsymbols* symbols; + this(Scope* sc) + { + this.sc = sc; + this.symbols = symbols; + } + + override void visit(AttribDeclaration ad) + { + if (ad.errors) + { + symbols = null; + return; + } + symbols = ad.decl; + return; + } + +// Decide if 'then' or 'else' code should be included + override void visit(ConditionalDeclaration cdc) + { + //printf("ConditionalDeclaration::include(sc = %p) scope = %p\n", sc, _scope); + + if (cdc.errors) + { + symbols = null; + return; + } + assert(cdc.condition); + symbols = cdc.condition.include(cdc._scope ? cdc._scope : sc) ? cdc.decl : cdc.elsedecl; + return; + } + + override void visit(StaticIfDeclaration sif) + { + /**************************************** + * Different from other AttribDeclaration subclasses, include() call requires + * the completion of addMember and setScope phases. + */ + //printf("StaticIfDeclaration::include(sc = %p) scope = %p\n", sc, _scope); + if (sif.errors || sif.onStack) + { + symbols = null; + return; + } + sif.onStack = true; + scope(exit) sif.onStack = false; + + if (sc && sif.condition.inc == Include.notComputed) + { + assert(sif.scopesym); // addMember is already done + assert(sif._scope); // setScope is already done + Dsymbols* d = include(cast(ConditionalDeclaration)sif, sif._scope); + if (d && !sif.addisdone) + { + // Add members lazily. + d.foreachDsymbol( s => s.addMember(sif._scope, sif.scopesym) ); + + // Set the member scopes lazily. + d.foreachDsymbol( s => s.setScope(sif._scope) ); + + sif.addisdone = true; + } + symbols = d; + return; + } + else + { + visit(cast(ConditionalDeclaration)sif); + } + } + + override void visit(StaticForeachDeclaration sfd) + { + if (sfd.errors || sfd.onStack) + { + symbols = null; + return; + } + if (sfd.cached) + { + assert(!sfd.onStack); + symbols = sfd.cache; + return; + } + sfd.onStack = true; + scope(exit) sfd.onStack = false; + + if (sfd._scope) + { + sfd.sfe.prepare(sfd._scope); // lower static foreach aggregate + } + if (!sfd.sfe.ready()) + { + symbols = null;// TODO: ok? + return; + } + + // expand static foreach + import dmd.statementsem: makeTupleForeach; + Dsymbols* d = makeTupleForeach(sfd._scope, true, true, sfd.sfe.aggrfe, sfd.decl, sfd.sfe.needExpansion).decl; + if (d) // process generated declarations + { + // Add members lazily. + d.foreachDsymbol( s => s.addMember(sfd._scope, sfd.scopesym) ); + + // Set the member scopes lazily. + d.foreachDsymbol( s => s.setScope(sfd._scope) ); + } + sfd.cached = true; + sfd.cache = d; + symbols = d; + return; + } +} + /** * Called from a symbol's semantic to check if `gnuAbiTag` UDA * can be applied to them diff --git a/compiler/src/dmd/dtemplate.d b/compiler/src/dmd/dtemplate.d index 9db90dd4ec9..6b91c61410b 100644 --- a/compiler/src/dmd/dtemplate.d +++ b/compiler/src/dmd/dtemplate.d @@ -53,7 +53,7 @@ import dmd.dinterpret; import dmd.dmodule; import dmd.dscope; import dmd.dsymbol; -import dmd.dsymbolsem : dsymbolSemantic, checkDeprecated, aliasSemantic, search, search_correct, setScope, importAll; +import dmd.dsymbolsem : dsymbolSemantic, checkDeprecated, aliasSemantic, search, search_correct, setScope, importAll, include; import dmd.errors; import dmd.errorsink; import dmd.expression; diff --git a/compiler/src/dmd/e2ir.d b/compiler/src/dmd/e2ir.d index 430644f3fda..20b4652af43 100644 --- a/compiler/src/dmd/e2ir.d +++ b/compiler/src/dmd/e2ir.d @@ -37,6 +37,7 @@ import dmd.dmodule; import dmd.dscope; import dmd.dstruct; import dmd.dsymbol; +import dmd.dsymbolsem : include; import dmd.dtemplate; import dmd.expression; import dmd.expressionsem : fill; diff --git a/compiler/src/dmd/inline.d b/compiler/src/dmd/inline.d index b30cacb0a31..af14d555ed6 100644 --- a/compiler/src/dmd/inline.d +++ b/compiler/src/dmd/inline.d @@ -26,6 +26,7 @@ import dmd.dmodule; import dmd.dscope; import dmd.dstruct; import dmd.dsymbol; +import dmd.dsymbolsem : include; import dmd.dtemplate; import dmd.expression; import dmd.expressionsem : semanticTypeInfo; diff --git a/compiler/src/dmd/json.d b/compiler/src/dmd/json.d index f20b3d4b38a..021387d6f43 100644 --- a/compiler/src/dmd/json.d +++ b/compiler/src/dmd/json.d @@ -24,6 +24,7 @@ import dmd.denum; import dmd.dimport; import dmd.dmodule; import dmd.dsymbol; +import dmd.dsymbolsem : include; import dmd.dtemplate; import dmd.errors; import dmd.expression; diff --git a/compiler/src/dmd/pragmasem.d b/compiler/src/dmd/pragmasem.d index 405b7654ffa..f2f748500a6 100644 --- a/compiler/src/dmd/pragmasem.d +++ b/compiler/src/dmd/pragmasem.d @@ -21,6 +21,7 @@ import dmd.attrib; import dmd.dinterpret; import dmd.dscope; import dmd.dsymbol; +import dmd.dsymbolsem : include; import dmd.errors; import dmd.expression; import dmd.expressionsem; diff --git a/compiler/src/dmd/toobj.d b/compiler/src/dmd/toobj.d index 7e2a826020b..46cdae5d1a3 100644 --- a/compiler/src/dmd/toobj.d +++ b/compiler/src/dmd/toobj.d @@ -35,6 +35,7 @@ import dmd.dmodule; import dmd.dscope; import dmd.dstruct; import dmd.dsymbol; +import dmd.dsymbolsem : include; import dmd.dtemplate; import dmd.errors; import dmd.errorsink;