diff options
| author | T. Foley <tfoleyNV@users.noreply.github.com> | 2021-06-06 09:27:19 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-06-06 12:27:19 -0400 |
| commit | 688d5fa6eb2c7f5281e50ace1401737479911ebc (patch) | |
| tree | ffe07e09b6ec8e558bff9ed3e92e056dbdefbc42 | |
| parent | 58d7af37f45f88130641188b1e39b00569acd575 (diff) | |
Include a "stack trace" with nested-import errors (#1872)
* Include a "stack trace" with nested-import errors
When errors occur in nested `#include` files it is often helpful to have a "stack trace" / traceback of the `#include` chain that led from a root translation unit to the file with an error.
This change implements a similar feature for `import`s.
It is worth noting that `import`s don't really *require* this kind of compiler support the way `#include`s do because the intention is that the meaning of an `import`ed file does not depend on the order or nesting of `import`s. As such, when trying to *fix* an error in an `import`ed file, you usually don't care how it came to be `import`ed into your shaders.
The use case here is somebody adapting a large body of Slang code to use in a different codebase, such that they have certain `.slang` files they don't actually intend to have compile correctly, and they want to be able to diagnose how they came to include those files when/if they cause problems.
The actual feature implementation is pretty simple because we already track a stack of active `import`s so that we can detect and diagnose recursive `import`s. This change simply changes the disagnostics when there is an error in imported code so that instead of just noting the inner-most `import` site it lists all the `import` sites that were active at the time.
The change includes a test case to confirm that the behavior works (at least for the case of a parse error).
* fixup: test outputs
Co-authored-by: Yong He <yonghe@outlook.com>
Co-authored-by: jsmall-nvidia <jsmall@nvidia.com>
10 files changed, 75 insertions, 9 deletions
diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h index 0742859f1..0ee63fd09 100755 --- a/source/slang/slang-compiler.h +++ b/source/slang/slang-compiler.h @@ -1519,10 +1519,14 @@ namespace Slang { public: ModuleBeingImportedRAII( - Linkage* linkage, - Module* module) + Linkage* linkage, + Module* module, + Name* name, + SourceLoc const& importLoc) : linkage(linkage) , module(module) + , name(name) + , importLoc(importLoc) { next = linkage->m_modulesBeingImported; linkage->m_modulesBeingImported = this; @@ -1535,15 +1539,21 @@ namespace Slang Linkage* linkage; Module* module; + Name* name; + SourceLoc importLoc; ModuleBeingImportedRAII* next; }; // Any modules currently being imported will be listed here - ModuleBeingImportedRAII* m_modulesBeingImported = nullptr; + ModuleBeingImportedRAII*m_modulesBeingImported = nullptr; /// Is the given module in the middle of being imported? bool isBeingImported(Module* module); + /// Diagnose that an error occured in the process of importing a module + void _diagnoseErrorInImportedModule( + DiagnosticSink* sink); + List<Type*> m_specializedTypes; }; diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h index 4c10ff5d5..8f94c47af 100644 --- a/source/slang/slang-diagnostic-defs.h +++ b/source/slang/slang-diagnostic-defs.h @@ -433,7 +433,8 @@ DIAGNOSTIC(38027, Error, mismatchExistentialSlotArgCount, "expected $0 existenti DIAGNOSTIC(38029, Error,typeArgumentDoesNotConformToInterface, "type argument '$0' does not conform to the required interface '$1'") DIAGNOSTIC(38200, Error, recursiveModuleImport, "module `$0` recursively imports itself") -DIAGNOSTIC(39999, Fatal, errorInImportedModule, "error in imported module, compilation ceased.") +DIAGNOSTIC(39999, Error, errorInImportedModule, "import of module '$0' failed because of a compilation error") +DIAGNOSTIC(39999, Fatal, complationCeased, "compilation ceased") // 39xxx - Type layout and parameter binding. diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index 9d2d766b9..f8af39fcb 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -2397,6 +2397,15 @@ Module* Linkage::loadModule(String const& name) sink); } +void Linkage::_diagnoseErrorInImportedModule( + DiagnosticSink* sink) +{ + for(auto info = m_modulesBeingImported; info; info = info->next) + { + sink->diagnose(info->importLoc, Diagnostics::errorInImportedModule, info->name); + } + sink->diagnose(SourceLoc(), Diagnostics::complationCeased); +} RefPtr<Module> Linkage::loadModule( Name* name, @@ -2418,7 +2427,9 @@ RefPtr<Module> Linkage::loadModule( ModuleBeingImportedRAII moduleBeingImported( this, - module); + module, + name, + srcLoc); // Create with the 'friendly' name SourceFile* sourceFile = getSourceManager()->createSourceFileWithBlob(filePathInfo, sourceBlob); @@ -2431,7 +2442,7 @@ RefPtr<Module> Linkage::loadModule( if( errorCountAfter != errorCountBefore ) { - sink->diagnose(srcLoc, Diagnostics::errorInImportedModule); + _diagnoseErrorInImportedModule(sink); } if (errorCountAfter) { @@ -2449,7 +2460,7 @@ RefPtr<Module> Linkage::loadModule( if (errorCountAfter != errorCountBefore) { - sink->diagnose(srcLoc, Diagnostics::errorInImportedModule); + _diagnoseErrorInImportedModule(sink); // Something went wrong during the parsing, so we should bail out. return nullptr; } diff --git a/tests/bugs/import-with-error.slang.expected b/tests/bugs/import-with-error.slang.expected index 86f34fc9f..8dbe7efbc 100644 --- a/tests/bugs/import-with-error.slang.expected +++ b/tests/bugs/import-with-error.slang.expected @@ -3,9 +3,10 @@ standard error = { tests/bugs/import-with-error-extra.slang(10): error 30015: undefined identifier 'b'. int a = b; ^ -tests/bugs/import-with-error.slang(6): fatal error 39999: error in imported module, compilation ceased. +tests/bugs/import-with-error.slang(6): error 39999: import of module 'import_with_error_extra' failed because of a compilation error import import_with_error_extra; ^~~~~~~~~~~~~~~~~~~~~~~ +(0): fatal error 39999: compilation ceased } standard output = { } diff --git a/tests/diagnostics/recursive-import.slang.expected b/tests/diagnostics/recursive-import.slang.expected index 1127b3191..4829bd91e 100644 --- a/tests/diagnostics/recursive-import.slang.expected +++ b/tests/diagnostics/recursive-import.slang.expected @@ -3,9 +3,13 @@ standard error = { tests/diagnostics/recursive-import.slang(6): error 38200: module `recursive_import_extra` recursively imports itself import recursive_import_extra; ^~~~~~~~~~~~~~~~~~~~~~ -tests/diagnostics/recursive-import-extra.slang(6): fatal error 39999: error in imported module, compilation ceased. +tests/diagnostics/recursive-import-extra.slang(6): error 39999: import of module 'recursive_import' failed because of a compilation error import recursive_import; ^~~~~~~~~~~~~~~~ +tests/diagnostics/recursive-import.slang(6): error 39999: import of module 'recursive_import_extra' failed because of a compilation error +import recursive_import_extra; + ^~~~~~~~~~~~~~~~~~~~~~ +(0): fatal error 39999: compilation ceased } standard output = { } diff --git a/tests/language-feature/modules/error-in-nested-import/a.slang b/tests/language-feature/modules/error-in-nested-import/a.slang new file mode 100644 index 000000000..331b19bbb --- /dev/null +++ b/tests/language-feature/modules/error-in-nested-import/a.slang @@ -0,0 +1,5 @@ +// a.slang +//TEST_IGNORE_FILE: + +import b; + diff --git a/tests/language-feature/modules/error-in-nested-import/b.slang b/tests/language-feature/modules/error-in-nested-import/b.slang new file mode 100644 index 000000000..1cfc37621 --- /dev/null +++ b/tests/language-feature/modules/error-in-nested-import/b.slang @@ -0,0 +1,5 @@ +// b.slang +//TEST_IGNORE_FILE: + +import c; + diff --git a/tests/language-feature/modules/error-in-nested-import/c.slang b/tests/language-feature/modules/error-in-nested-import/c.slang new file mode 100644 index 000000000..60feab7a1 --- /dev/null +++ b/tests/language-feature/modules/error-in-nested-import/c.slang @@ -0,0 +1,4 @@ +// c.slang +//TEST_IGNORE_FILE: + +int a(; diff --git a/tests/language-feature/modules/error-in-nested-import/error-in-nested-import.slang b/tests/language-feature/modules/error-in-nested-import/error-in-nested-import.slang new file mode 100644 index 000000000..2efa69121 --- /dev/null +++ b/tests/language-feature/modules/error-in-nested-import/error-in-nested-import.slang @@ -0,0 +1,7 @@ +// error-in-nested-import.slang +//DIAGNOSTIC_TEST:SIMPLE: + +import a; + +int main() +{}
\ No newline at end of file diff --git a/tests/language-feature/modules/error-in-nested-import/error-in-nested-import.slang.expected b/tests/language-feature/modules/error-in-nested-import/error-in-nested-import.slang.expected new file mode 100644 index 000000000..d5c621ecd --- /dev/null +++ b/tests/language-feature/modules/error-in-nested-import/error-in-nested-import.slang.expected @@ -0,0 +1,18 @@ +result code = -1 +standard error = { +tests/language-feature/modules/error-in-nested-import/c.slang(4): error 20001: unexpected ';', expected identifier +int a(; + ^ +tests/language-feature/modules/error-in-nested-import/b.slang(4): error 39999: import of module 'c' failed because of a compilation error +import c; + ^ +tests/language-feature/modules/error-in-nested-import/a.slang(4): error 39999: import of module 'b' failed because of a compilation error +import b; + ^ +tests/language-feature/modules/error-in-nested-import/error-in-nested-import.slang(4): error 39999: import of module 'a' failed because of a compilation error +import a; + ^ +(0): fatal error 39999: compilation ceased +} +standard output = { +} |
