From 8a136a201bdf68d54f850b2d0bf6ea77d42b60aa Mon Sep 17 00:00:00 2001 From: Alexandru Militaru Date: Tue, 17 Mar 2020 13:12:08 +0200 Subject: [PATCH 1/8] Added -unittest=rootonly and -unittest=first flags --- src/dmd/cond.d | 5 +++++ src/dmd/dmodule.d | 3 ++- src/dmd/dsymbolsem.d | 2 +- src/dmd/globals.d | 2 ++ src/dmd/globals.h | 2 ++ src/dmd/glue.d | 3 ++- src/dmd/inline.d | 5 +++-- src/dmd/mars.d | 8 +++++++- src/dmd/parse.d | 10 ++++++---- src/dmd/traits.d | 2 +- 10 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/dmd/cond.d b/src/dmd/cond.d index b8bfd38abe6e..eaa9ec37c123 100644 --- a/src/dmd/cond.d +++ b/src/dmd/cond.d @@ -796,7 +796,12 @@ extern (C++) final class VersionCondition : DVCondition definedInModule = true; } else if (findCondition(global.versionids, ident)) + { inc = Include.yes; + if ((ident == Id._unittest && !mod.isRoot() && global.params.UnittestRootOnly) + || (ident == Id._unittest && !mod.rootChief && global.params.UnittestFirstRootOnly)) + inc = Include.no; + } else { if (!mod.versionidsNot) diff --git a/src/dmd/dmodule.d b/src/dmd/dmodule.d index 24a32262d637..3a64a20723aa 100644 --- a/src/dmd/dmodule.d +++ b/src/dmd/dmodule.d @@ -427,6 +427,7 @@ extern (C++) final class Module : Package Strings contentImportedFiles; // array of files whose content was imported int needmoduleinfo; int selfimports; // 0: don't know, 1: does not, 2: does + bool rootChief; // first root module in the command line /************************************* * Return true if module imports itself. @@ -1002,7 +1003,7 @@ extern (C++) final class Module : Package { scope p = new Parser!AST(this, buf, cast(bool) docfile); p.nextToken(); - members = p.parseModule(); + members = p.parseModule(isRoot(), rootChief); md = p.md; numlines = p.scanloc.linnum; } diff --git a/src/dmd/dsymbolsem.d b/src/dmd/dsymbolsem.d index 37a066a2fd05..83a383cb1b9e 100644 --- a/src/dmd/dsymbolsem.d +++ b/src/dmd/dsymbolsem.d @@ -4527,7 +4527,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor return; } - if (global.params.useUnitTests) + if (global.params.useUnitTests || global.params.UnittestRootOnly || global.params.UnittestFirstRootOnly) { if (!utd.type) utd.type = new TypeFunction(ParameterList(), Type.tvoid, LINK.d, utd.storage_class); diff --git a/src/dmd/globals.d b/src/dmd/globals.d index 5adb13b8b724..90e74f007e9b 100644 --- a/src/dmd/globals.d +++ b/src/dmd/globals.d @@ -147,6 +147,8 @@ extern (C++) struct Param DiagnosticReporting useDeprecated = DiagnosticReporting.inform; // how use of deprecated features are handled bool stackstomp; // add stack stomping code bool useUnitTests; // generate unittest code + bool UnittestRootOnly; // generate unittest code only for root modules + bool UnittestFirstRootOnly; // generate unittest code only for the first root module bool useInline = false; // inline expand functions bool useDIP25; // implement http://wiki.dlang.org/DIP25 bool noDIP25; // revert to pre-DIP25 behavior diff --git a/src/dmd/globals.h b/src/dmd/globals.h index d2f8a65defa0..6127e34b1320 100644 --- a/src/dmd/globals.h +++ b/src/dmd/globals.h @@ -126,6 +126,8 @@ struct Param Diagnostic useDeprecated; bool stackstomp; // add stack stomping code bool useUnitTests; // generate unittest code + bool UnittestRootOnly; // generate unittest code only for root modules + bool UnittestFirstRootOnly; // generate unittest code only for the first root module bool useInline; // inline expand functions bool useDIP25; // implement http://wiki.dlang.org/DIP25 bool noDIP25; // revert to pre-DIP25 behavior diff --git a/src/dmd/glue.d b/src/dmd/glue.d index 308e7c495dcc..2156d2217634 100644 --- a/src/dmd/glue.d +++ b/src/dmd/glue.d @@ -739,7 +739,8 @@ void FuncDeclaration_toObjFile(FuncDeclaration fd, bool multiobj) return; UnitTestDeclaration ud = fd.isUnitTestDeclaration(); - if (ud && !global.params.useUnitTests) + if (ud && !global.params.useUnitTests && !global.params.UnittestRootOnly + && !global.params.UnittestFirstRootOnly) return; if (multiobj && !fd.isStaticDtorDeclaration() && !fd.isStaticCtorDeclaration() && !fd.isCrtCtorDtor) diff --git a/src/dmd/inline.d b/src/dmd/inline.d index 6f7ae2c94aa4..920df414e8bd 100644 --- a/src/dmd/inline.d +++ b/src/dmd/inline.d @@ -1543,8 +1543,9 @@ public: { printf("FuncDeclaration.inlineScan('%s')\n", fd.toPrettyChars()); } - if (fd.isUnitTestDeclaration() && !global.params.useUnitTests || - fd.flags & FUNCFLAG.inlineScanned) + if (fd.isUnitTestDeclaration() && (!global.params.useUnitTests && !global.params.UnittestRootOnly + && !global.params.UnittestFirstRootOnly) + || fd.flags & FUNCFLAG.inlineScanned) return; if (fd.fbody && !fd.naked) { diff --git a/src/dmd/mars.d b/src/dmd/mars.d index 0f7aa4fb0e1e..f7400f4e1a4d 100644 --- a/src/dmd/mars.d +++ b/src/dmd/mars.d @@ -1284,7 +1284,7 @@ void addDefaultVersionIdentifiers(const ref Param params) VersionCondition.addPredefinedGlobalIdent("D_Coverage"); if (params.pic != PIC.fixed) VersionCondition.addPredefinedGlobalIdent(params.pic == PIC.pic ? "D_PIC" : "D_PIE"); - if (params.useUnitTests) + if (params.useUnitTests || params.UnittestRootOnly || params.UnittestFirstRootOnly) VersionCondition.addPredefinedGlobalIdent("unittest"); if (params.useAssert == CHECKENABLE.on) VersionCondition.addPredefinedGlobalIdent("assert"); @@ -2257,6 +2257,10 @@ bool parseCommandLine(const ref Strings arguments, const size_t argc, ref Param } else if (arg == "-unittest") params.useUnitTests = true; + else if (arg == "-unittest=rootonly") + params.UnittestRootOnly = true; + else if (arg == "-unittest=first") + params.UnittestFirstRootOnly = true; else if (p[1] == 'I') // https://dlang.org/dmd.html#switch-I { if (!params.imppath) @@ -2701,10 +2705,12 @@ Modules createModules(ref Strings files, ref Strings libmodules) auto id = Identifier.idPool(name); auto m = new Module(files[i].toDString, id, global.params.doDocComments, global.params.doHdrGeneration); modules.push(m); + m.rootChief = false; if (firstmodule) { global.params.objfiles.push(m.objfile.toChars()); firstmodule = false; + m.rootChief = true; } } return modules; diff --git a/src/dmd/parse.d b/src/dmd/parse.d index 4a95a1087fac..e7a64291cedb 100644 --- a/src/dmd/parse.d +++ b/src/dmd/parse.d @@ -327,7 +327,7 @@ final class Parser(AST) : Lexer //nextToken(); // start up the scanner } - AST.Dsymbols* parseModule() + AST.Dsymbols* parseModule(bool rootModule = false, bool rootChief = false) { const comment = token.blockComment; bool isdeprecated = false; @@ -428,7 +428,7 @@ final class Parser(AST) : Lexer addComment(mod, comment); } - decldefs = parseDeclDefs(0, &lastDecl); + decldefs = parseDeclDefs(0, &lastDecl, null, rootModule, rootChief); if (token.value != TOK.endOfFile) { error(token.loc, "unrecognized declaration"); @@ -472,7 +472,7 @@ final class Parser(AST) : Lexer return true; } - AST.Dsymbols* parseDeclDefs(int once, AST.Dsymbol* pLastDecl = null, PrefixAttributes!AST* pAttrs = null) + AST.Dsymbols* parseDeclDefs(int once, AST.Dsymbol* pLastDecl = null, PrefixAttributes!AST* pAttrs = null, bool rootModule= false, bool rootChief = false) { AST.Dsymbol lastDecl = null; // used to link unittest to its previous declaration if (!pLastDecl) @@ -622,7 +622,9 @@ final class Parser(AST) : Lexer goto Lerror; case TOK.unittest_: - if (global.params.useUnitTests || global.params.doDocComments || global.params.doHdrGeneration) + if ((global.params.useUnitTests || global.params.doDocComments || global.params.doHdrGeneration) || + (global.params.UnittestRootOnly && rootModule) || + (global.params.UnittestFirstRootOnly && rootChief)) { s = parseUnitTest(pAttrs); if (*pLastDecl) diff --git a/src/dmd/traits.d b/src/dmd/traits.d index 3a8bc876a2ed..aa098e25b0cb 100644 --- a/src/dmd/traits.d +++ b/src/dmd/traits.d @@ -1797,7 +1797,7 @@ Lnext: } auto exps = new Expressions(); - if (global.params.useUnitTests) + if (global.params.useUnitTests || global.params.UnittestRootOnly || global.params.UnittestFirstRootOnly) { bool[void*] uniqueUnitTests; From 9c7b5b2143900364685773ce48bbbcfacddba8c3 Mon Sep 17 00:00:00 2001 From: Alexandru Militaru Date: Tue, 24 Mar 2020 09:21:47 +0200 Subject: [PATCH 2/8] make -unittest=rootonly default; do not turn off version (unittest) --- src/dmd/cond.d | 3 --- src/dmd/mars.d | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/dmd/cond.d b/src/dmd/cond.d index eaa9ec37c123..ca86c1f59eb7 100644 --- a/src/dmd/cond.d +++ b/src/dmd/cond.d @@ -798,9 +798,6 @@ extern (C++) final class VersionCondition : DVCondition else if (findCondition(global.versionids, ident)) { inc = Include.yes; - if ((ident == Id._unittest && !mod.isRoot() && global.params.UnittestRootOnly) - || (ident == Id._unittest && !mod.rootChief && global.params.UnittestFirstRootOnly)) - inc = Include.no; } else { diff --git a/src/dmd/mars.d b/src/dmd/mars.d index f7400f4e1a4d..a6c1781cc358 100644 --- a/src/dmd/mars.d +++ b/src/dmd/mars.d @@ -2256,7 +2256,7 @@ bool parseCommandLine(const ref Strings arguments, const size_t argc, ref Param goto Lerror; } else if (arg == "-unittest") - params.useUnitTests = true; + params.UnittestRootOnly = true; else if (arg == "-unittest=rootonly") params.UnittestRootOnly = true; else if (arg == "-unittest=first") From 2adb80924aff71e382061d1c2e406efb19e140d2 Mon Sep 17 00:00:00 2001 From: Alexandru Militaru Date: Wed, 25 Mar 2020 16:32:48 +0200 Subject: [PATCH 3/8] fix bugs --- src/dmd/dmodule.d | 2 +- src/dmd/dsymbolsem.d | 2 +- src/dmd/dtemplate.d | 11 +++++++++-- src/dmd/globals.d | 12 +++++++++--- src/dmd/globals.h | 12 +++++++++--- src/dmd/glue.d | 3 +-- src/dmd/inline.d | 5 ++--- src/dmd/mars.d | 10 +++++----- src/dmd/module.h | 1 + src/dmd/parse.d | 13 +++++++------ src/dmd/traits.d | 2 +- 11 files changed, 46 insertions(+), 27 deletions(-) diff --git a/src/dmd/dmodule.d b/src/dmd/dmodule.d index 3a64a20723aa..e2ae4010ced7 100644 --- a/src/dmd/dmodule.d +++ b/src/dmd/dmodule.d @@ -1003,7 +1003,7 @@ extern (C++) final class Module : Package { scope p = new Parser!AST(this, buf, cast(bool) docfile); p.nextToken(); - members = p.parseModule(isRoot(), rootChief); + members = p.parseModule(); md = p.md; numlines = p.scanloc.linnum; } diff --git a/src/dmd/dsymbolsem.d b/src/dmd/dsymbolsem.d index 83a383cb1b9e..3b7d01384bc1 100644 --- a/src/dmd/dsymbolsem.d +++ b/src/dmd/dsymbolsem.d @@ -4527,7 +4527,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor return; } - if (global.params.useUnitTests || global.params.UnittestRootOnly || global.params.UnittestFirstRootOnly) + if (global.params.unittestMode != UnittestMode.disabled) { if (!utd.type) utd.type = new TypeFunction(ParameterList(), Type.tvoid, LINK.d, utd.storage_class); diff --git a/src/dmd/dtemplate.d b/src/dmd/dtemplate.d index 49cb9f6d1d8e..561c8922d780 100644 --- a/src/dmd/dtemplate.d +++ b/src/dmd/dtemplate.d @@ -6141,7 +6141,14 @@ extern (C++) class TemplateInstance : ScopeDsymbol return false; } - if (global.params.useUnitTests) + /* The issue is that if the importee is compiled with a different -debug + * setting than the importer, the importer may believe it exists + * in the compiled importee when it does not, when the instantiation + * is behind a conditional debug declaration. + */ + // workaround for https://issues.dlang.org/show_bug.cgi?id=11239 + if (global.params.unittestMode == UnittestMode.standard || + global.params.debuglevel) { // Prefer instantiations from root modules, to maximize link-ability. if (minst.isRoot()) @@ -7139,7 +7146,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol { Module mi = minst; // instantiated . inserted module - if (global.params.useUnitTests || global.params.debuglevel) + if (global.params.unittestMode == UnittestMode.standard || global.params.debuglevel) { // Turn all non-root instances to speculative if (mi && !mi.isRoot()) diff --git a/src/dmd/globals.d b/src/dmd/globals.d index 90e74f007e9b..bf6dd1a347cf 100644 --- a/src/dmd/globals.d +++ b/src/dmd/globals.d @@ -110,6 +110,14 @@ enum CppStdRevision : uint cpp17 = 201703 } +enum UnittestMode +{ + disabled, + standard, + rootOnly, + firstOnly +} + // Put command line switches in here extern (C++) struct Param { @@ -146,9 +154,7 @@ extern (C++) struct Param bool mscoff = false; // for Win32: write MsCoff object files instead of OMF DiagnosticReporting useDeprecated = DiagnosticReporting.inform; // how use of deprecated features are handled bool stackstomp; // add stack stomping code - bool useUnitTests; // generate unittest code - bool UnittestRootOnly; // generate unittest code only for root modules - bool UnittestFirstRootOnly; // generate unittest code only for the first root module + UnittestMode unittestMode; bool useInline = false; // inline expand functions bool useDIP25; // implement http://wiki.dlang.org/DIP25 bool noDIP25; // revert to pre-DIP25 behavior diff --git a/src/dmd/globals.h b/src/dmd/globals.h index 6127e34b1320..3e5433b8c5e3 100644 --- a/src/dmd/globals.h +++ b/src/dmd/globals.h @@ -89,6 +89,14 @@ enum CppStdRevision CppStdRevisionCpp17 = 201703 }; +enum UnittestMode +{ + disabled, + standard, + rootOnly, + firstOnly +}; + // Put command line switches in here struct Param { @@ -125,9 +133,7 @@ struct Param bool mscoff; // for Win32: write COFF object files instead of OMF Diagnostic useDeprecated; bool stackstomp; // add stack stomping code - bool useUnitTests; // generate unittest code - bool UnittestRootOnly; // generate unittest code only for root modules - bool UnittestFirstRootOnly; // generate unittest code only for the first root module + UnittestMode unittestMode; bool useInline; // inline expand functions bool useDIP25; // implement http://wiki.dlang.org/DIP25 bool noDIP25; // revert to pre-DIP25 behavior diff --git a/src/dmd/glue.d b/src/dmd/glue.d index 2156d2217634..4addcb54fce6 100644 --- a/src/dmd/glue.d +++ b/src/dmd/glue.d @@ -739,8 +739,7 @@ void FuncDeclaration_toObjFile(FuncDeclaration fd, bool multiobj) return; UnitTestDeclaration ud = fd.isUnitTestDeclaration(); - if (ud && !global.params.useUnitTests && !global.params.UnittestRootOnly - && !global.params.UnittestFirstRootOnly) + if (ud && global.params.unittestMode == UnittestMode.disabled) return; if (multiobj && !fd.isStaticDtorDeclaration() && !fd.isStaticCtorDeclaration() && !fd.isCrtCtorDtor) diff --git a/src/dmd/inline.d b/src/dmd/inline.d index 920df414e8bd..e44b9fbcea6c 100644 --- a/src/dmd/inline.d +++ b/src/dmd/inline.d @@ -1543,9 +1543,8 @@ public: { printf("FuncDeclaration.inlineScan('%s')\n", fd.toPrettyChars()); } - if (fd.isUnitTestDeclaration() && (!global.params.useUnitTests && !global.params.UnittestRootOnly - && !global.params.UnittestFirstRootOnly) - || fd.flags & FUNCFLAG.inlineScanned) + if (fd.isUnitTestDeclaration() && (global.params.unittestMode == UnittestMode.disabled + || fd.flags & FUNCFLAG.inlineScanned)) return; if (fd.fbody && !fd.naked) { diff --git a/src/dmd/mars.d b/src/dmd/mars.d index a6c1781cc358..9f188224cbaa 100644 --- a/src/dmd/mars.d +++ b/src/dmd/mars.d @@ -1284,7 +1284,7 @@ void addDefaultVersionIdentifiers(const ref Param params) VersionCondition.addPredefinedGlobalIdent("D_Coverage"); if (params.pic != PIC.fixed) VersionCondition.addPredefinedGlobalIdent(params.pic == PIC.pic ? "D_PIC" : "D_PIE"); - if (params.useUnitTests || params.UnittestRootOnly || params.UnittestFirstRootOnly) + if (params.unittestMode != UnittestMode.disabled) VersionCondition.addPredefinedGlobalIdent("unittest"); if (params.useAssert == CHECKENABLE.on) VersionCondition.addPredefinedGlobalIdent("assert"); @@ -2256,11 +2256,11 @@ bool parseCommandLine(const ref Strings arguments, const size_t argc, ref Param goto Lerror; } else if (arg == "-unittest") - params.UnittestRootOnly = true; + params.unittestMode = UnittestMode.rootOnly; else if (arg == "-unittest=rootonly") - params.UnittestRootOnly = true; + params.unittestMode = UnittestMode.rootOnly; else if (arg == "-unittest=first") - params.UnittestFirstRootOnly = true; + params.unittestMode = UnittestMode.firstOnly; else if (p[1] == 'I') // https://dlang.org/dmd.html#switch-I { if (!params.imppath) @@ -2480,7 +2480,7 @@ private void reconcileCommands(ref Param params, size_t numSrcFiles) params.useArrayBounds = params.boundscheck; } - if (params.useUnitTests) + if (params.unittestMode != UnittestMode.disabled) { if (params.useAssert == CHECKENABLE._default) params.useAssert = CHECKENABLE.on; diff --git a/src/dmd/module.h b/src/dmd/module.h index fa5da1062c11..1aa6fd77bd90 100644 --- a/src/dmd/module.h +++ b/src/dmd/module.h @@ -82,6 +82,7 @@ class Module : public Package int needmoduleinfo; int selfimports; // 0: don't know, 1: does not, 2: does bool selfImports(); // returns true if module imports itself + bool rootChief; int rootimports; // 0: don't know, 1: does not, 2: does bool rootImports(); // returns true if module imports root module diff --git a/src/dmd/parse.d b/src/dmd/parse.d index e7a64291cedb..ae2fe7dfa751 100644 --- a/src/dmd/parse.d +++ b/src/dmd/parse.d @@ -327,7 +327,7 @@ final class Parser(AST) : Lexer //nextToken(); // start up the scanner } - AST.Dsymbols* parseModule(bool rootModule = false, bool rootChief = false) + AST.Dsymbols* parseModule() { const comment = token.blockComment; bool isdeprecated = false; @@ -428,7 +428,7 @@ final class Parser(AST) : Lexer addComment(mod, comment); } - decldefs = parseDeclDefs(0, &lastDecl, null, rootModule, rootChief); + decldefs = parseDeclDefs(0, &lastDecl); if (token.value != TOK.endOfFile) { error(token.loc, "unrecognized declaration"); @@ -472,7 +472,7 @@ final class Parser(AST) : Lexer return true; } - AST.Dsymbols* parseDeclDefs(int once, AST.Dsymbol* pLastDecl = null, PrefixAttributes!AST* pAttrs = null, bool rootModule= false, bool rootChief = false) + AST.Dsymbols* parseDeclDefs(int once, AST.Dsymbol* pLastDecl = null, PrefixAttributes!AST* pAttrs = null) { AST.Dsymbol lastDecl = null; // used to link unittest to its previous declaration if (!pLastDecl) @@ -622,9 +622,10 @@ final class Parser(AST) : Lexer goto Lerror; case TOK.unittest_: - if ((global.params.useUnitTests || global.params.doDocComments || global.params.doHdrGeneration) || - (global.params.UnittestRootOnly && rootModule) || - (global.params.UnittestFirstRootOnly && rootChief)) + if ((global.params.unittestMode == UnittestMode.standard + || global.params.doDocComments || global.params.doHdrGeneration) || + (global.params.unittestMode == UnittestMode.rootOnly && mod.isRoot()) || + (global.params.unittestMode == UnittestMode.firstOnly && mod.rootChief)) { s = parseUnitTest(pAttrs); if (*pLastDecl) diff --git a/src/dmd/traits.d b/src/dmd/traits.d index aa098e25b0cb..7add1928ae74 100644 --- a/src/dmd/traits.d +++ b/src/dmd/traits.d @@ -1797,7 +1797,7 @@ Lnext: } auto exps = new Expressions(); - if (global.params.useUnitTests || global.params.UnittestRootOnly || global.params.UnittestFirstRootOnly) + if (global.params.unittestMode != UnittestMode.disabled) { bool[void*] uniqueUnitTests; From edca48e91f2ad8a8e5e33ba9a7bc228b277828b0 Mon Sep 17 00:00:00 2001 From: Alexandru Militaru Date: Wed, 25 Mar 2020 20:32:19 +0200 Subject: [PATCH 4/8] fix avg.d --- test/dub_package/avg.d | 2 +- test/dub_package/impvisitor.d | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/dub_package/avg.d b/test/dub_package/avg.d index 363a391da5cf..07211b1b4881 100755 --- a/test/dub_package/avg.d +++ b/test/dub_package/avg.d @@ -52,7 +52,7 @@ void main() global._init(); global.params.isLinux = true; global.params.is64bit = (size_t.sizeof == 8); - global.params.useUnitTests = true; + global.params.unittestMode = UnittestMode.rootOnly; ASTBase.Type._init(); auto id = Identifier.idPool(fname); diff --git a/test/dub_package/impvisitor.d b/test/dub_package/impvisitor.d index b42069430650..93fbf229483d 100755 --- a/test/dub_package/impvisitor.d +++ b/test/dub_package/impvisitor.d @@ -100,7 +100,7 @@ void main() global._init(); global.params.isLinux = true; global.params.is64bit = (size_t.sizeof == 8); - global.params.useUnitTests = true; + global.params.unittestMode = UnittestMode.rootOnly; ASTBase.Type._init(); auto id = Identifier.idPool(fn); From b44c98ff869bff46028b86aa547524fd3364ebca Mon Sep 17 00:00:00 2001 From: Alexandru Militaru Date: Thu, 26 Mar 2020 18:43:13 +0200 Subject: [PATCH 5/8] fix missing fields from ASTBase.Module --- src/dmd/astbase.d | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/dmd/astbase.d b/src/dmd/astbase.d index df42d3e35314..4c163abb137a 100644 --- a/src/dmd/astbase.d +++ b/src/dmd/astbase.d @@ -1485,12 +1485,21 @@ struct ASTBase const FileName srcfile; const(char)* arg; + bool rootModule; + bool rootChief; - extern (D) this(const(char)* filename, Identifier ident, int doDocComment, int doHdrGen) + extern (D) this(const(char)* filename, Identifier ident, int doDocComment, int doHdrGen, bool rootModule = false, bool rootChief = false) { super(ident); this.arg = filename; srcfile = FileName(FileName.defaultExt(filename.toDString, global.mars_ext)); + this.rootModule = rootModule; + this.rootChief = rootChief; + } + + bool isRoot() + { + return rootModule; } override void accept(Visitor v) From c1b6e4d19b47eecd34dc46210cfbcffbfd6b427c Mon Sep 17 00:00:00 2001 From: Alexandru Militaru Date: Sat, 18 Apr 2020 09:05:19 +0300 Subject: [PATCH 6/8] simplify changes --- src/dmd/astbase.d | 3 +-- src/dmd/cond.d | 2 -- src/dmd/dmodule.d | 1 - src/dmd/dsymbolsem.d | 2 +- src/dmd/dtemplate.d | 5 ++--- src/dmd/globals.d | 10 +--------- src/dmd/globals.h | 10 +--------- src/dmd/glue.d | 2 +- src/dmd/inline.d | 4 ++-- src/dmd/mars.d | 12 +++--------- src/dmd/module.h | 1 - src/dmd/parse.d | 6 ++---- src/dmd/traits.d | 2 +- test/dub_package/avg.d | 2 +- test/dub_package/impvisitor.d | 2 +- 15 files changed, 17 insertions(+), 47 deletions(-) diff --git a/src/dmd/astbase.d b/src/dmd/astbase.d index 4c163abb137a..24292dc6a60f 100644 --- a/src/dmd/astbase.d +++ b/src/dmd/astbase.d @@ -1488,13 +1488,12 @@ struct ASTBase bool rootModule; bool rootChief; - extern (D) this(const(char)* filename, Identifier ident, int doDocComment, int doHdrGen, bool rootModule = false, bool rootChief = false) + extern (D) this(const(char)* filename, Identifier ident, int doDocComment, int doHdrGen, bool rootModule = false) { super(ident); this.arg = filename; srcfile = FileName(FileName.defaultExt(filename.toDString, global.mars_ext)); this.rootModule = rootModule; - this.rootChief = rootChief; } bool isRoot() diff --git a/src/dmd/cond.d b/src/dmd/cond.d index ca86c1f59eb7..b8bfd38abe6e 100644 --- a/src/dmd/cond.d +++ b/src/dmd/cond.d @@ -796,9 +796,7 @@ extern (C++) final class VersionCondition : DVCondition definedInModule = true; } else if (findCondition(global.versionids, ident)) - { inc = Include.yes; - } else { if (!mod.versionidsNot) diff --git a/src/dmd/dmodule.d b/src/dmd/dmodule.d index e2ae4010ced7..24a32262d637 100644 --- a/src/dmd/dmodule.d +++ b/src/dmd/dmodule.d @@ -427,7 +427,6 @@ extern (C++) final class Module : Package Strings contentImportedFiles; // array of files whose content was imported int needmoduleinfo; int selfimports; // 0: don't know, 1: does not, 2: does - bool rootChief; // first root module in the command line /************************************* * Return true if module imports itself. diff --git a/src/dmd/dsymbolsem.d b/src/dmd/dsymbolsem.d index 3b7d01384bc1..37a066a2fd05 100644 --- a/src/dmd/dsymbolsem.d +++ b/src/dmd/dsymbolsem.d @@ -4527,7 +4527,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor return; } - if (global.params.unittestMode != UnittestMode.disabled) + if (global.params.useUnitTests) { if (!utd.type) utd.type = new TypeFunction(ParameterList(), Type.tvoid, LINK.d, utd.storage_class); diff --git a/src/dmd/dtemplate.d b/src/dmd/dtemplate.d index 561c8922d780..d8bb743f0b26 100644 --- a/src/dmd/dtemplate.d +++ b/src/dmd/dtemplate.d @@ -6147,8 +6147,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol * is behind a conditional debug declaration. */ // workaround for https://issues.dlang.org/show_bug.cgi?id=11239 - if (global.params.unittestMode == UnittestMode.standard || - global.params.debuglevel) + if (global.params.useUnitTests) { // Prefer instantiations from root modules, to maximize link-ability. if (minst.isRoot()) @@ -7146,7 +7145,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol { Module mi = minst; // instantiated . inserted module - if (global.params.unittestMode == UnittestMode.standard || global.params.debuglevel) + if (global.params.useUnitTests) { // Turn all non-root instances to speculative if (mi && !mi.isRoot()) diff --git a/src/dmd/globals.d b/src/dmd/globals.d index bf6dd1a347cf..5adb13b8b724 100644 --- a/src/dmd/globals.d +++ b/src/dmd/globals.d @@ -110,14 +110,6 @@ enum CppStdRevision : uint cpp17 = 201703 } -enum UnittestMode -{ - disabled, - standard, - rootOnly, - firstOnly -} - // Put command line switches in here extern (C++) struct Param { @@ -154,7 +146,7 @@ extern (C++) struct Param bool mscoff = false; // for Win32: write MsCoff object files instead of OMF DiagnosticReporting useDeprecated = DiagnosticReporting.inform; // how use of deprecated features are handled bool stackstomp; // add stack stomping code - UnittestMode unittestMode; + bool useUnitTests; // generate unittest code bool useInline = false; // inline expand functions bool useDIP25; // implement http://wiki.dlang.org/DIP25 bool noDIP25; // revert to pre-DIP25 behavior diff --git a/src/dmd/globals.h b/src/dmd/globals.h index 3e5433b8c5e3..d2f8a65defa0 100644 --- a/src/dmd/globals.h +++ b/src/dmd/globals.h @@ -89,14 +89,6 @@ enum CppStdRevision CppStdRevisionCpp17 = 201703 }; -enum UnittestMode -{ - disabled, - standard, - rootOnly, - firstOnly -}; - // Put command line switches in here struct Param { @@ -133,7 +125,7 @@ struct Param bool mscoff; // for Win32: write COFF object files instead of OMF Diagnostic useDeprecated; bool stackstomp; // add stack stomping code - UnittestMode unittestMode; + bool useUnitTests; // generate unittest code bool useInline; // inline expand functions bool useDIP25; // implement http://wiki.dlang.org/DIP25 bool noDIP25; // revert to pre-DIP25 behavior diff --git a/src/dmd/glue.d b/src/dmd/glue.d index 4addcb54fce6..308e7c495dcc 100644 --- a/src/dmd/glue.d +++ b/src/dmd/glue.d @@ -739,7 +739,7 @@ void FuncDeclaration_toObjFile(FuncDeclaration fd, bool multiobj) return; UnitTestDeclaration ud = fd.isUnitTestDeclaration(); - if (ud && global.params.unittestMode == UnittestMode.disabled) + if (ud && !global.params.useUnitTests) return; if (multiobj && !fd.isStaticDtorDeclaration() && !fd.isStaticCtorDeclaration() && !fd.isCrtCtorDtor) diff --git a/src/dmd/inline.d b/src/dmd/inline.d index e44b9fbcea6c..6f7ae2c94aa4 100644 --- a/src/dmd/inline.d +++ b/src/dmd/inline.d @@ -1543,8 +1543,8 @@ public: { printf("FuncDeclaration.inlineScan('%s')\n", fd.toPrettyChars()); } - if (fd.isUnitTestDeclaration() && (global.params.unittestMode == UnittestMode.disabled - || fd.flags & FUNCFLAG.inlineScanned)) + if (fd.isUnitTestDeclaration() && !global.params.useUnitTests || + fd.flags & FUNCFLAG.inlineScanned) return; if (fd.fbody && !fd.naked) { diff --git a/src/dmd/mars.d b/src/dmd/mars.d index 9f188224cbaa..0f7aa4fb0e1e 100644 --- a/src/dmd/mars.d +++ b/src/dmd/mars.d @@ -1284,7 +1284,7 @@ void addDefaultVersionIdentifiers(const ref Param params) VersionCondition.addPredefinedGlobalIdent("D_Coverage"); if (params.pic != PIC.fixed) VersionCondition.addPredefinedGlobalIdent(params.pic == PIC.pic ? "D_PIC" : "D_PIE"); - if (params.unittestMode != UnittestMode.disabled) + if (params.useUnitTests) VersionCondition.addPredefinedGlobalIdent("unittest"); if (params.useAssert == CHECKENABLE.on) VersionCondition.addPredefinedGlobalIdent("assert"); @@ -2256,11 +2256,7 @@ bool parseCommandLine(const ref Strings arguments, const size_t argc, ref Param goto Lerror; } else if (arg == "-unittest") - params.unittestMode = UnittestMode.rootOnly; - else if (arg == "-unittest=rootonly") - params.unittestMode = UnittestMode.rootOnly; - else if (arg == "-unittest=first") - params.unittestMode = UnittestMode.firstOnly; + params.useUnitTests = true; else if (p[1] == 'I') // https://dlang.org/dmd.html#switch-I { if (!params.imppath) @@ -2480,7 +2476,7 @@ private void reconcileCommands(ref Param params, size_t numSrcFiles) params.useArrayBounds = params.boundscheck; } - if (params.unittestMode != UnittestMode.disabled) + if (params.useUnitTests) { if (params.useAssert == CHECKENABLE._default) params.useAssert = CHECKENABLE.on; @@ -2705,12 +2701,10 @@ Modules createModules(ref Strings files, ref Strings libmodules) auto id = Identifier.idPool(name); auto m = new Module(files[i].toDString, id, global.params.doDocComments, global.params.doHdrGeneration); modules.push(m); - m.rootChief = false; if (firstmodule) { global.params.objfiles.push(m.objfile.toChars()); firstmodule = false; - m.rootChief = true; } } return modules; diff --git a/src/dmd/module.h b/src/dmd/module.h index 1aa6fd77bd90..fa5da1062c11 100644 --- a/src/dmd/module.h +++ b/src/dmd/module.h @@ -82,7 +82,6 @@ class Module : public Package int needmoduleinfo; int selfimports; // 0: don't know, 1: does not, 2: does bool selfImports(); // returns true if module imports itself - bool rootChief; int rootimports; // 0: don't know, 1: does not, 2: does bool rootImports(); // returns true if module imports root module diff --git a/src/dmd/parse.d b/src/dmd/parse.d index ae2fe7dfa751..0be553014b83 100644 --- a/src/dmd/parse.d +++ b/src/dmd/parse.d @@ -622,10 +622,8 @@ final class Parser(AST) : Lexer goto Lerror; case TOK.unittest_: - if ((global.params.unittestMode == UnittestMode.standard - || global.params.doDocComments || global.params.doHdrGeneration) || - (global.params.unittestMode == UnittestMode.rootOnly && mod.isRoot()) || - (global.params.unittestMode == UnittestMode.firstOnly && mod.rootChief)) + if (global.params.useUnitTests && mod.isRoot() + || global.params.doDocComments || global.params.doHdrGeneration) { s = parseUnitTest(pAttrs); if (*pLastDecl) diff --git a/src/dmd/traits.d b/src/dmd/traits.d index 7add1928ae74..3a8bc876a2ed 100644 --- a/src/dmd/traits.d +++ b/src/dmd/traits.d @@ -1797,7 +1797,7 @@ Lnext: } auto exps = new Expressions(); - if (global.params.unittestMode != UnittestMode.disabled) + if (global.params.useUnitTests) { bool[void*] uniqueUnitTests; diff --git a/test/dub_package/avg.d b/test/dub_package/avg.d index 07211b1b4881..363a391da5cf 100755 --- a/test/dub_package/avg.d +++ b/test/dub_package/avg.d @@ -52,7 +52,7 @@ void main() global._init(); global.params.isLinux = true; global.params.is64bit = (size_t.sizeof == 8); - global.params.unittestMode = UnittestMode.rootOnly; + global.params.useUnitTests = true; ASTBase.Type._init(); auto id = Identifier.idPool(fname); diff --git a/test/dub_package/impvisitor.d b/test/dub_package/impvisitor.d index 93fbf229483d..b42069430650 100755 --- a/test/dub_package/impvisitor.d +++ b/test/dub_package/impvisitor.d @@ -100,7 +100,7 @@ void main() global._init(); global.params.isLinux = true; global.params.is64bit = (size_t.sizeof == 8); - global.params.unittestMode = UnittestMode.rootOnly; + global.params.useUnitTests = true; ASTBase.Type._init(); auto id = Identifier.idPool(fn); From 224310df51d845642dad543e4dffd5cea6ed63e8 Mon Sep 17 00:00:00 2001 From: Alexandru Militaru Date: Sat, 18 Apr 2020 09:10:30 +0300 Subject: [PATCH 7/8] solve conflict --- src/dmd/astbase.d | 1 - src/dmd/dtemplate.d | 6 ------ 2 files changed, 7 deletions(-) diff --git a/src/dmd/astbase.d b/src/dmd/astbase.d index 24292dc6a60f..460ce857b24e 100644 --- a/src/dmd/astbase.d +++ b/src/dmd/astbase.d @@ -1486,7 +1486,6 @@ struct ASTBase const FileName srcfile; const(char)* arg; bool rootModule; - bool rootChief; extern (D) this(const(char)* filename, Identifier ident, int doDocComment, int doHdrGen, bool rootModule = false) { diff --git a/src/dmd/dtemplate.d b/src/dmd/dtemplate.d index d8bb743f0b26..9e7e4f842d35 100644 --- a/src/dmd/dtemplate.d +++ b/src/dmd/dtemplate.d @@ -6141,12 +6141,6 @@ extern (C++) class TemplateInstance : ScopeDsymbol return false; } - /* The issue is that if the importee is compiled with a different -debug - * setting than the importer, the importer may believe it exists - * in the compiled importee when it does not, when the instantiation - * is behind a conditional debug declaration. - */ - // workaround for https://issues.dlang.org/show_bug.cgi?id=11239 if (global.params.useUnitTests) { // Prefer instantiations from root modules, to maximize link-ability. From 4c47e124ca8476d36778f6c9c210fafce7f8b8ff Mon Sep 17 00:00:00 2001 From: Alexandru Militaru Date: Sat, 18 Apr 2020 10:21:52 +0300 Subject: [PATCH 8/8] remove unittest special case --- src/dmd/dtemplate.d | 43 ------------------------------------------- 1 file changed, 43 deletions(-) diff --git a/src/dmd/dtemplate.d b/src/dmd/dtemplate.d index 9e7e4f842d35..b905db489baf 100644 --- a/src/dmd/dtemplate.d +++ b/src/dmd/dtemplate.d @@ -6141,41 +6141,6 @@ extern (C++) class TemplateInstance : ScopeDsymbol return false; } - if (global.params.useUnitTests) - { - // Prefer instantiations from root modules, to maximize link-ability. - if (minst.isRoot()) - return true; - - TemplateInstance tnext = this.tnext; - TemplateInstance tinst = this.tinst; - this.tnext = null; - this.tinst = null; - - if (tinst && tinst.needsCodegen()) - { - minst = tinst.minst; // cache result - assert(minst); - assert(minst.isRoot() || minst.rootImports()); - return true; - } - if (tnext && tnext.needsCodegen()) - { - minst = tnext.minst; // cache result - assert(minst); - assert(minst.isRoot() || minst.rootImports()); - return true; - } - - // https://issues.dlang.org/show_bug.cgi?id=2500 case - if (minst.rootImports()) - return true; - - // Elide codegen because this is not included in root instances. - return false; - } - else - { // Prefer instantiations from non-root module, to minimize object code size. /* If a TemplateInstance is ever instantiated by non-root modules, @@ -6205,7 +6170,6 @@ extern (C++) class TemplateInstance : ScopeDsymbol // Do codegen because this is not included in non-root instances. return true; - } } /********************************************** @@ -7139,13 +7103,6 @@ extern (C++) class TemplateInstance : ScopeDsymbol { Module mi = minst; // instantiated . inserted module - if (global.params.useUnitTests) - { - // Turn all non-root instances to speculative - if (mi && !mi.isRoot()) - mi = null; - } - //printf("%s.appendToModuleMember() enclosing = %s mi = %s\n", // toPrettyChars(), // enclosing ? enclosing.toPrettyChars() : null,