summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2018-01-26 15:30:23 -0800
committerGitHub <noreply@github.com>2018-01-26 15:30:23 -0800
commit06f0effb848c6b938e03da8a61e44b3d032380e8 (patch)
treee575c83fa7a6b277edc069e4f82f910b74ad56db /source
parenta050f4a144d5ab36c93cd0a443767340301fb32e (diff)
Fix handling of errors in imported modules (#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.
Diffstat (limited to 'source')
-rw-r--r--source/slang/diagnostic-defs.h2
-rw-r--r--source/slang/slang.cpp36
2 files changed, 32 insertions, 6 deletions
diff --git a/source/slang/diagnostic-defs.h b/source/slang/diagnostic-defs.h
index bae501a3c..f8b09a196 100644
--- a/source/slang/diagnostic-defs.h
+++ b/source/slang/diagnostic-defs.h
@@ -257,6 +257,8 @@ DIAGNOSTIC(38102, Error, accessorMustBeInsideSubscriptOrProperty, "an accessor d
DIAGNOSTIC(38020, Error, mismatchEntryPointTypeArgument, "expecting $0 entry-point type arguments, provided $1.")
DIAGNOSTIC(38021, Error, typeArgumentDoesNotConformToInterface, "type argument `$1` for generic parameter `$0` does not conform to interface `$1`.")
+DIAGNOSTIC(38200, Error, recursiveModuleImport, "module `$0` recursively imports itself")
+
//
// 4xxxx - IL code generation.
//
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index e4bf251fc..773b1dd09 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -499,16 +499,31 @@ void CompileRequest::loadParsedModule(
Name* name,
String const& path)
{
+ // Note: we add the loaded module to our name->module listing
+ // before doing semantic checking, so that if it tries to
+ // recursively `import` itself, we can detect it.
+ RefPtr<LoadedModule> loadedModule = new LoadedModule();
+ mapPathToLoadedModule.Add(path, loadedModule);
+ mapNameToLoadedModules.Add(name, loadedModule);
+
+ int errorCountBefore = mSink.GetErrorCount();
checkTranslationUnit(translationUnit.Ptr());
+ int errorCountAfter = mSink.GetErrorCount();
RefPtr<ModuleDecl> moduleDecl = translationUnit->SyntaxNode;
-
- RefPtr<LoadedModule> loadedModule = new LoadedModule();
loadedModule->moduleDecl = moduleDecl;
- loadedModule->irModule = generateIRForTranslationUnit(translationUnit);
- mapPathToLoadedModule.Add(path, loadedModule);
- mapNameToLoadedModules.Add(name, loadedModule);
+ if (errorCountAfter != errorCountBefore)
+ {
+ // There must have been an error in the loaded module.
+ }
+ else
+ {
+ // If we didn't run into any errors, then try to generate
+ // IR code for the imported module.
+ loadedModule->irModule = generateIRForTranslationUnit(translationUnit);
+ }
+
loadedModulesList.Add(loadedModule);
}
@@ -591,7 +606,16 @@ RefPtr<ModuleDecl> CompileRequest::findOrImportModule(
// If so, return it.
RefPtr<LoadedModule> loadedModule;
if (mapNameToLoadedModules.TryGetValue(name, loadedModule))
- return loadedModule->moduleDecl;
+ {
+ if (!loadedModule)
+ return nullptr;
+
+ if (!loadedModule->moduleDecl)
+ {
+ // We seem to be in the middle of loading this module
+ mSink.diagnose(loc, Diagnostics::recursiveModuleImport, name);
+ }
+ }
// Derive a file name for the module, by taking the given
// identifier, replacing all occurences of `_` with `-`,