-
-
Notifications
You must be signed in to change notification settings - Fork 699
[BLOCKED][WIP] Don't instantiate unittest templates in libraries #8124
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -292,10 +292,10 @@ extern (C++) final class Module : Package | |
| extern (C++) static __gshared Dsymbols deferred3; // deferred Dsymbol's needing semantic3() run on them | ||
| extern (C++) static __gshared uint dprogress; // progress resolving the deferred list | ||
| /** | ||
| * A callback function that is called once an imported module is | ||
| * parsed. If the callback returns true, then it tells the | ||
| * frontend that the driver intends on compiling the import. | ||
| */ | ||
| A callback function that is called when a module is loaded as soon as its | ||
| module declaration has been parsed. If the callback returns true, then it tells the | ||
| frontend that the driver intends on compiling the import. | ||
| */ | ||
| extern (C++) static __gshared bool function(Module mod) onImport; | ||
|
|
||
| static void _init() | ||
|
|
@@ -370,12 +370,10 @@ extern (C++) final class Module : Package | |
| int searchCacheFlags; // cached flags | ||
|
|
||
| /** | ||
| * A root module is one that will be compiled all the way to | ||
| * object code. This field holds the root module that caused | ||
| * this module to be loaded. If this module is a root module, | ||
| * then it will be set to `this`. This is used to determine | ||
| * ownership of template instantiation. | ||
| */ | ||
| This field holds the root module that caused this module | ||
| to be loaded. If this module is a root module, then it will | ||
| be set to `this`. | ||
| */ | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unless it's no longer true, I'd keep the part of the comment that says "This is used to determine the ownership of templaet instantiation".
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The information was just moved to the |
||
| Module importedFrom; | ||
|
|
||
| Dsymbols* decldefs; // top level declarations for this Module | ||
|
|
@@ -515,41 +513,6 @@ extern (C++) final class Module : Package | |
| message("import %s", buf.peekString()); | ||
| } | ||
| m = m.parse(); | ||
|
|
||
| // Call onImport here because if the module is going to be compiled then we | ||
| // need to determine it early because it affects semantic analysis. This is | ||
| // being done after parsing the module so the full module name can be taken | ||
| // from whatever was declared in the file. | ||
|
|
||
| //!!!!!!!!!!!!!!!!!!!!!!! | ||
| // Workaround for bug in dmd version 2.068.2 platform Darwin_64_32. | ||
| // This is the compiler version that the autotester uses, and this code | ||
| // has been carefully crafted using trial and error to prevent a seg fault | ||
| // bug that occurs with that version of the compiler. Note, this segfault | ||
| // does not occur on the next version of dmd, namely, version 2.069.0. If | ||
| // the autotester upgrades to that version, then this workaround can be removed. | ||
| //!!!!!!!!!!!!!!!!!!!!!!! | ||
| version(OSX) | ||
| { | ||
| if (!m.isRoot() && onImport) | ||
| { | ||
| auto onImportResult = onImport(m); | ||
| if(onImportResult) | ||
| { | ||
| m.importedFrom = m; | ||
| assert(m.isRoot()); | ||
| } | ||
| } | ||
| } | ||
| else | ||
| { | ||
| if (!m.isRoot() && onImport && onImport(m)) | ||
| { | ||
| m.importedFrom = m; | ||
| assert(m.isRoot()); | ||
| } | ||
| } | ||
|
|
||
| Target.loadModule(m); | ||
| return m; | ||
| } | ||
|
|
@@ -853,7 +816,6 @@ extern (C++) final class Module : Package | |
| scope p = new Parser!ASTCodegen(this, buf[0 .. buflen], docfile !is null); | ||
| p.nextToken(); | ||
| members = p.parseModule(); | ||
| md = p.md; | ||
| numlines = p.scanloc.linnum; | ||
| if (p.errors) | ||
| ++global.errors; | ||
|
|
@@ -1288,11 +1250,35 @@ extern (C++) final class Module : Package | |
| return false; | ||
| } | ||
|
|
||
| bool isRoot() | ||
| /** | ||
| A root module is one that will be compiled to object code. This is used to | ||
| determine ownership of template instantiation and when to compile unittests. | ||
| Returns: | ||
| true if this is a root module | ||
| */ | ||
| final bool isRoot() const | ||
| { | ||
| return this.importedFrom == this; | ||
| } | ||
|
|
||
| /** | ||
| Called by the parser after the module declaration has been determined. | ||
| */ | ||
| final void afterModuleDeclaration(ModuleDeclaration* md) | ||
| { | ||
| this.md = md; | ||
|
|
||
| // Call onImport here because if the module is going to be compiled then we | ||
| // need to determine it early because it affects whether unittests will be parsed | ||
| // and semantic analysis. This is being done right after parsing the module delclaration | ||
| // so the full module name can be taken from whatever was declared in the file. | ||
| if (!isRoot() && onImport && onImport(this)) | ||
| { | ||
| importedFrom = this; | ||
| assert(isRoot()); | ||
| } | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could move
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does the module need to be fully parsed before calling that, or does it just need the module declaration parsed, or does it not need anything to be parsed?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wait...I see from the comment it says "post parsing". Which means it shouldn't be called in this function since this function is called in the middle of parsing (right after parsing the module declaration).
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might be good to rename this function to something like |
||
| } | ||
|
|
||
| // true if the module source file is directly | ||
| // listed in command line. | ||
| bool isCoreModule(Identifier ident) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6360,8 +6360,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.useUnitTests || | ||
| global.params.debuglevel) | ||
| if (global.params.debuglevel) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did you test the linked bug after making this change? Doesn't look like the CI gets so far along to run it itself.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is being tested and is passing on the autotester. It's not until the "test phobos" stage that we get linker errors due to DIP 1000 bugs.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @ibuclaw the original bug only had to do with |
||
| { | ||
| // Prefer instantiations from root modules, to maximize link-ability. | ||
| if (minst.isRoot()) | ||
|
|
@@ -7354,7 +7353,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol | |
| { | ||
| Module mi = minst; // instantiated . inserted module | ||
|
|
||
| if (global.params.useUnitTests || global.params.debuglevel) | ||
| if (global.params.debuglevel) | ||
| { | ||
| // Turn all non-root instances to speculative | ||
| if (mi && !mi.isRoot()) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| if [ "$2" == "HAS" ]; then | ||
| GREP_OPTION= | ||
| elif [ "$2" == "DOES_NOT_HAVE" ]; then | ||
| GREP_OPTION=-v | ||
| else | ||
| echo Unknown option "$2" | ||
| exit 1 | ||
| fi | ||
|
|
||
| if [ ${OS} != "linux" ]; then | ||
| echo Skipping checkbin $2 $3 because os $OS is not linux | ||
| exit 0 | ||
| fi | ||
|
|
||
| objdump -t "$1" | grep -q $GREP_OPTION "$3" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| module printVersionUnittest; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the next module is
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. meh, not a big deal, kind of a long name |
||
|
|
||
| version(unittest) | ||
| { | ||
| pragma(msg, "version unittest"); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| module printingUnittest; | ||
|
|
||
| unittest | ||
| { | ||
| import core.stdc.stdio; | ||
| printf("unittesting printingUnittest\n"); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| import printingUnittest; | ||
| void main() | ||
| { | ||
| // have to print something so grep works | ||
| import core.stdc.stdio; printf("done\n"); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| import printVersionUnittest; | ||
| void main() | ||
| { | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| obj_file=${OUTPUT_BASE}/tempobj${OBJ} | ||
| exe_file=${OUTPUT_BASE}/tempexe${EXE} | ||
|
|
||
| # Compile both modules, make sure unittest compiles/runs | ||
| unittest_output="unittesting printingUnittest" | ||
| $DMD -m${MODEL} -of=${exe_file} -I=${EXTRA_FILES} -unittest ${EXTRA_FILES}/printingUnittest.d ${EXTRA_FILES}/selectiveUnittests.d | ||
| ${exe_file} | grep -q "${unittest_output}" | ||
| ./runnable/extra-files/check_bin.sh ${exe_file} HAS __unittest | ||
|
|
||
| # Precompile the module and make sure it's unittest doesn't get compiled/run | ||
| $DMD -m${MODEL} -c -of=${obj_file} ${EXTRA_FILES}/printingUnittest.d | ||
| ./runnable/extra-files/check_bin.sh ${exe_file} DOES_NOT_HAVE __unittest | ||
|
|
||
| rm -f ${exe_file} | ||
| $DMD -m${MODEL} -of=${exe_file} -I=${EXTRA_FILES} -unittest ${obj_file} ${EXTRA_FILES}/selectiveUnittests.d | ||
| ${exe_file} | grep -q -v "${unittest_output}" | ||
|
|
||
| # Make sure that version(unittest) still get analyzed | ||
| unittest_output="version unittest" | ||
| $DMD -m${MODEL} -I=${EXTRA_FILES} -o- -unittest ${EXTRA_FILES}/printVersionUnittest.d ${EXTRA_FILES}/selectiveUnittests2.d 2>&1 | grep -q "${unittest_output}" | ||
|
|
||
| # Precompile the module and make sure version(unittest) is still enabled | ||
| $DMD -m${MODEL} -c -of=${obj_file} ${EXTRA_FILES}/printVersionUnittest.d | ||
| $DMD -m${MODEL} -I=${EXTRA_FILES} -o- -unittest ${obj_file} ${EXTRA_FILES}/selectiveUnittests2.d 2>&1 | grep -q "${unittest_output}" | ||
|
|
||
| rm -f ${obj_file} | ||
| rm -f ${exe_file} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When does isRoot return false for a module such that its unittests don't compile?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isRoot will return false if the module isn't "taken" to object code (see comment). This will happen if the module is not passed on the command line and is not included as a "compiled import"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess I'm just asking because this looks pretty constant (final, returns true). What is the type of AST class that represents an import module?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I'm seeing that this is duplicated in
dmodule.d, but with a different implementation (one that makes sense). I'm not sure what theastbase.dfile does, but it sure seems like it's doing something different thandmodule.d. What is this for?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was just looking through the comments and saw that your question wasn't answered. The module class you are looking at is missing ALOT of information, it's just as STUB as far as I know probably meant to hold a future refactored version of the current
Moduleclass indmodule.d.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had already figured it out. it seems it's there for when you want to instantiate the parser only, and not actually compile anything. Perhaps if you aren't generating object code.