diff options
| author | Tim Foley <tfoleyNV@users.noreply.github.com> | 2020-02-05 13:26:39 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-02-05 13:26:39 -0800 |
| commit | b42b865ac7ce144561fa17743616e550eeae7102 (patch) | |
| tree | 3c322ee542a2d496218d38aad8fdcbd58ddffe7b /source/slang/slang-check-decl.cpp | |
| parent | 122126c006e53bd48064f220104d425b8bf91ddf (diff) | |
Improve behavior when undefined identifier is a contextual keyword (#1200)
The HLSL language has keywords with very common names like `triangle`, and Slang doesn't want to preclude users from using such names for their variables/functions/etc.
In addition, Slang adds new keywords on top of HLSL (like `extension`) and we don't want those to prevent us from compiling existing code.
As a result, almost all keywords in Slang are contextual keywords, and they can be shadowed by user varaibles.
The down-side to making all keywords contextual is that in a case like this:
```
int test() { return triangle; }
```
The identifier `triangle` is *not* undefined as far as lookup (it is defined as a modifier keyword), so the existing "undefined identifier" logic gets bypassed, and instead we ran into an internal compiler error trying to construct an expression that refers to a modifier keyword.
Fortunately, the internal compiler error in that case was overkill, and the compiler already had defensive logic to produce an expression with an error type if it couldn't figure out what the type of a declaration reference should be.
The main fix here is thus to emit an "undefined identifier" error instead of an internal compiler error at the point where we see an attempt to reference a declaration that shouldn't be available in an expression context.
In order to improve the quality of the diagnostic, the code for constructing declaration references was updated to pass along a source location to be used in error messages.
Diffstat (limited to 'source/slang/slang-check-decl.cpp')
| -rw-r--r-- | source/slang/slang-check-decl.cpp | 27 |
1 files changed, 21 insertions, 6 deletions
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp index 027ddc70f..7c8322fa7 100644 --- a/source/slang/slang-check-decl.cpp +++ b/source/slang/slang-check-decl.cpp @@ -252,7 +252,8 @@ namespace Slang SemanticsVisitor* sema, DiagnosticSink* sink, DeclRef<Decl> declRef, - RefPtr<Type>* outTypeResult) + RefPtr<Type>* outTypeResult, + SourceLoc loc) { if( sema ) { @@ -386,17 +387,30 @@ namespace Slang } if( sink ) { - sink->diagnose(declRef, Diagnostics::unimplemented, "cannot form reference to this kind of declaration"); + // The compiler is trying to form a reference to a declaration + // that doesn't appear to be usable as an expression or type. + // + // In practice, this arises when user code has an undefined-identifier + // error, but the name that was undefined in context also matches + // a contextual keyword. Rather than confuse the user with the + // details of contextual keywords in the compiler, we will diagnose + // this as an undefined identifier. + // + // TODO: This code could break if we ever go down this path with + // an identifier that doesn't have a name. + // + sink->diagnose(loc, Diagnostics::undefinedIdentifier2, declRef.GetName()); } return QualType(session->getErrorType()); } QualType getTypeForDeclRef( Session* session, - DeclRef<Decl> declRef) + DeclRef<Decl> declRef, + SourceLoc loc) { RefPtr<Type> typeResult; - return getTypeForDeclRef(session, nullptr, nullptr, declRef, &typeResult); + return getTypeForDeclRef(session, nullptr, nullptr, declRef, &typeResult, loc); } DeclRef<ExtensionDecl> ApplyExtensionToType( @@ -2832,7 +2846,7 @@ namespace Slang return extDeclRef; } - QualType SemanticsVisitor::GetTypeForDeclRef(DeclRef<Decl> declRef) + QualType SemanticsVisitor::GetTypeForDeclRef(DeclRef<Decl> declRef, SourceLoc loc) { RefPtr<Type> typeResult; return getTypeForDeclRef( @@ -2840,7 +2854,8 @@ namespace Slang this, getSink(), declRef, - &typeResult); + &typeResult, + loc); } void SemanticsVisitor::importModuleIntoScope(Scope* scope, ModuleDecl* moduleDecl) |
