summaryrefslogtreecommitdiff
path: root/source/slang/slang.cpp
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2018-04-20 17:54:39 -0700
committerGitHub <noreply@github.com>2018-04-20 17:54:39 -0700
commit163d3068e332703cc499446fff37230a7c68e8f2 (patch)
treea1d0b9507ab01c908811603d8cde47736bdbe3ef /source/slang/slang.cpp
parent2f782d403ae5729b6c93fbe92577ee01f7a8d608 (diff)
Better diagnostics when compilation is aborted (#517)
* Improve messages when compilation is aborted. Make sure to include the information from any `Slang::Exception` that was thrown, so that the poor user can at least point us at our own message string from an assertion failure. This doesn't provide them line-number information in their code or the Slang codebase, so there is still work to be done in making the compiler more friendly about this stuff. * When aborting compilation, try to note what source location we were working on This is handled by having exception handlers on the stack at key bottleneck points in semantic checking and IR generation, which can then emit a diagnostic to note what we were working on when things failed. This is not intended to be an indiciation to the user that their code is at fault for a compiler crash (it is always our fault), but might give them a chance to work around whatever bug is blocking them.
Diffstat (limited to 'source/slang/slang.cpp')
-rw-r--r--source/slang/slang.cpp50
1 files changed, 39 insertions, 11 deletions
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index dbd48753b..9e740d5f5 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -9,6 +9,9 @@
#include "syntax-visitors.h"
#include "../slang/type-layout.h"
+// Used to print exception type names in internal-compiler-error messages
+#include <typeinfo>
+
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
@@ -724,6 +727,23 @@ Decl * CompileRequest::lookupGlobalDecl(Name * name)
return resultDecl;
}
+void CompileRequest::noteInternalErrorLoc(SourceLoc const& loc)
+{
+ // Don't consider invalid source locations.
+ if(!loc.isValid())
+ return;
+
+ // If this is the first source location being noted,
+ // then emit a message to help the user isolate what
+ // code might have confused the compiler.
+ if(internalErrorLocsNoted == 0)
+ {
+ mSink.diagnose(loc, Diagnostics::noteLocationOfInternalError);
+ }
+ internalErrorLocsNoted++;
+}
+
+
RefPtr<ModuleDecl> findOrImportModule(
CompileRequest* request,
Name* name,
@@ -1111,27 +1131,35 @@ SLANG_API int spCompile(
//
// TODO: Consider supporting Windows "Structured Exception Handling"
// so that we can also recover from a wider class of crashes.
+ int anyErrors = 1;
try
{
- int anyErrors = req->executeActions();
- return anyErrors;
+ anyErrors = req->executeActions();
}
catch (Slang::AbortCompilationException&)
{
- // This should only be thrown if we already emitted a fatal error
- // message, so there is no reason to print something else.
- //
- // We still need to copy the diagnostic output into the variable
- // that the user will query via the API.
- req->mDiagnosticOutput = req->mSink.outputBuffer.ProduceString();
- return 1;
+ // This situation indicates a fatal (but not necesarily internal) error
+ // that forced compilation to terminate. There should already have been
+ // a diagnositc produced, so we don't need to add one here.
+ }
+ catch (Slang::Exception& e)
+ {
+ // The compiler failed due to an internal error that was detected.
+ // We will print out information on the exception to help out the user
+ // in either filing a bug, or locating what in their code created
+ // a problem.
+ req->mSink.diagnose(Slang::SourceLoc(), Slang::Diagnostics::compilationAbortedDueToException, typeid(e).name(), e.Message);
}
catch (...)
{
+ // The compiler failed due to some exception that wasn't a sublass of
+ // `Exception`, so something really fishy is going on. We want to
+ // let the user know that we messed up, so they know to blame Slang
+ // and not some other component in their system.
req->mSink.diagnose(Slang::SourceLoc(), Slang::Diagnostics::compilationAborted);
- req->mDiagnosticOutput = req->mSink.outputBuffer.ProduceString();
- return 1;
}
+ req->mDiagnosticOutput = req->mSink.outputBuffer.ProduceString();
+ return anyErrors;
#else
// When debugging, we probably don't want to filter out any errors, since
// we are probably trying to root-cause and *fix* those errors.