Skip to content

Commit 06f0eff

Browse files
author
Tim Foley
authored
Fix handling of errors in imported modules (shader-slang#387)
* Fix handling of errors in imported modules - If a semantic error is detected in an imported module, then don't try to generate IR code for it - Also, if a module (transitively) imports itself, then report that as an error - The way I'm checking for this is a bit hacky (I'm adding the module to the map of loaded modules, but in an "unfinished" state, and then using that unfinished state to detect the import of a module already being imported). This isn't a 100% complete solution for any of the related problems, but it improves the user experience for the common case. * Remove #import test. The feature is slated to be removed, so it isn't worth fixing up this test case.
1 parent a050f4a commit 06f0eff

10 files changed

+78
-36
lines changed

source/slang/diagnostic-defs.h

+2
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,8 @@ DIAGNOSTIC(38102, Error, accessorMustBeInsideSubscriptOrProperty, "an accessor d
257257
DIAGNOSTIC(38020, Error, mismatchEntryPointTypeArgument, "expecting $0 entry-point type arguments, provided $1.")
258258
DIAGNOSTIC(38021, Error, typeArgumentDoesNotConformToInterface, "type argument `$1` for generic parameter `$0` does not conform to interface `$1`.")
259259

260+
DIAGNOSTIC(38200, Error, recursiveModuleImport, "module `$0` recursively imports itself")
261+
260262
//
261263
// 4xxxx - IL code generation.
262264
//

source/slang/slang.cpp

+30-6
Original file line numberDiff line numberDiff line change
@@ -499,16 +499,31 @@ void CompileRequest::loadParsedModule(
499499
Name* name,
500500
String const& path)
501501
{
502+
// Note: we add the loaded module to our name->module listing
503+
// before doing semantic checking, so that if it tries to
504+
// recursively `import` itself, we can detect it.
505+
RefPtr<LoadedModule> loadedModule = new LoadedModule();
506+
mapPathToLoadedModule.Add(path, loadedModule);
507+
mapNameToLoadedModules.Add(name, loadedModule);
508+
509+
int errorCountBefore = mSink.GetErrorCount();
502510
checkTranslationUnit(translationUnit.Ptr());
511+
int errorCountAfter = mSink.GetErrorCount();
503512

504513
RefPtr<ModuleDecl> moduleDecl = translationUnit->SyntaxNode;
505-
506-
RefPtr<LoadedModule> loadedModule = new LoadedModule();
507514
loadedModule->moduleDecl = moduleDecl;
508-
loadedModule->irModule = generateIRForTranslationUnit(translationUnit);
509515

510-
mapPathToLoadedModule.Add(path, loadedModule);
511-
mapNameToLoadedModules.Add(name, loadedModule);
516+
if (errorCountAfter != errorCountBefore)
517+
{
518+
// There must have been an error in the loaded module.
519+
}
520+
else
521+
{
522+
// If we didn't run into any errors, then try to generate
523+
// IR code for the imported module.
524+
loadedModule->irModule = generateIRForTranslationUnit(translationUnit);
525+
}
526+
512527
loadedModulesList.Add(loadedModule);
513528
}
514529

@@ -591,7 +606,16 @@ RefPtr<ModuleDecl> CompileRequest::findOrImportModule(
591606
// If so, return it.
592607
RefPtr<LoadedModule> loadedModule;
593608
if (mapNameToLoadedModules.TryGetValue(name, loadedModule))
594-
return loadedModule->moduleDecl;
609+
{
610+
if (!loadedModule)
611+
return nullptr;
612+
613+
if (!loadedModule->moduleDecl)
614+
{
615+
// We seem to be in the middle of loading this module
616+
mSink.diagnose(loc, Diagnostics::recursiveModuleImport, name);
617+
}
618+
}
595619

596620
// Derive a file name for the module, by taking the given
597621
// identifier, replacing all occurences of `_` with `-`,
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//TEST_IGNORE_FILE:
2+
3+
// This file exists to be imported.
4+
//
5+
// It contains a semantic error that should lead to compilation failure
6+
// in the module doing the importing.
7+
8+
void broken()
9+
{
10+
int a = b;
11+
}

tests/bugs/import-with-error.slang

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//TEST:SIMPLE:-use-ir
2+
3+
// Confirm that we correctly issue a diagnostic when
4+
// we `import` a module that has some errors in it.
5+
6+
import import_with_error_extra;
7+
8+
void main()
9+
{
10+
broken();
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
result code = -1
2+
standard error = {
3+
tests/bugs/import-with-error-extra.slang(10): error 30015: undefined identifier 'b'.
4+
}
5+
standard output = {
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
//TEST_IGNORE_FILE:
2+
3+
// This file creates an `import` loop with
4+
// `recursive-import.slang`
5+
6+
import recursive_import;
+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
//TEST:SIMPLE:
2+
3+
// A file that recursively imports itself
4+
// (including transitive cases) should be diagnosed.
5+
6+
import recursive_import_extra;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
result code = -1
2+
standard error = {
3+
tests/diagnostics/recursive-import.slang(6): error 38200: module `recursive_import_extra` recursively imports itself
4+
}
5+
standard output = {
6+
}

tests/preprocessor/import.hlsl

-18
This file was deleted.

tests/preprocessor/import.slang.h

-12
This file was deleted.

0 commit comments

Comments
 (0)