diff options
Diffstat (limited to 'source/slang/slang-check-decl.cpp')
| -rw-r--r-- | source/slang/slang-check-decl.cpp | 74 |
1 files changed, 34 insertions, 40 deletions
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp index 6c414b292..6d579e1fb 100644 --- a/source/slang/slang-check-decl.cpp +++ b/source/slang/slang-check-decl.cpp @@ -21,8 +21,8 @@ namespace Slang : public SemanticsDeclVisitorBase , public DeclVisitor<SemanticsDeclModifiersVisitor> { - SemanticsDeclModifiersVisitor(SharedSemanticsContext* shared) - : SemanticsDeclVisitorBase(shared) + SemanticsDeclModifiersVisitor(SemanticsContext const& outer) + : SemanticsDeclVisitorBase(outer) {} void visitDeclGroup(DeclGroup*) {} @@ -37,8 +37,8 @@ namespace Slang : public SemanticsDeclVisitorBase , public DeclVisitor<SemanticsDeclHeaderVisitor> { - SemanticsDeclHeaderVisitor(SharedSemanticsContext* shared) - : SemanticsDeclVisitorBase(shared) + SemanticsDeclHeaderVisitor(SemanticsContext const& outer) + : SemanticsDeclVisitorBase(outer) {} void visitDecl(Decl*) {} @@ -106,8 +106,8 @@ namespace Slang : public SemanticsDeclVisitorBase , public DeclVisitor<SemanticsDeclRedeclarationVisitor> { - SemanticsDeclRedeclarationVisitor(SharedSemanticsContext* shared) - : SemanticsDeclVisitorBase(shared) + SemanticsDeclRedeclarationVisitor(SemanticsContext const& outer) + : SemanticsDeclVisitorBase(outer) {} void visitDecl(Decl*) {} @@ -127,8 +127,8 @@ namespace Slang : public SemanticsDeclVisitorBase , public DeclVisitor<SemanticsDeclBasesVisitor> { - SemanticsDeclBasesVisitor(SharedSemanticsContext* shared) - : SemanticsDeclVisitorBase(shared) + SemanticsDeclBasesVisitor(SemanticsContext const& outer) + : SemanticsDeclVisitorBase(outer) {} void visitDecl(Decl*) {} @@ -161,8 +161,8 @@ namespace Slang : public SemanticsDeclVisitorBase , public DeclVisitor<SemanticsDeclBodyVisitor> { - SemanticsDeclBodyVisitor(SharedSemanticsContext* shared) - : SemanticsDeclVisitorBase(shared) + SemanticsDeclBodyVisitor(SemanticsContext const& outer) + : SemanticsDeclVisitorBase(outer) {} void visitDecl(Decl*) {} @@ -668,7 +668,7 @@ namespace Slang /// This call does *not* handle updating the state of `decl`; the /// caller takes responsibility for doing so. /// - static void _dispatchDeclCheckingVisitor(Decl* decl, DeclCheckState state, SharedSemanticsContext* shared); + static void _dispatchDeclCheckingVisitor(Decl* decl, DeclCheckState state, SemanticsContext const& shared); // Make sure a declaration has been checked, so we can refer to it. // Note that this may lead to us recursively invoking checking, @@ -729,7 +729,12 @@ namespace Slang // We now dispatch an appropriate visitor based on `nextState`. // - _dispatchDeclCheckingVisitor(decl, nextState, getShared()); + // Note that we always dispatch the visitor in a "fresh" semantic-checking + // context, so that the state at the point where a declaration is *referenced* + // cannot affect the state in which the declaration is *checked*. + // + SemanticsContext subContext(getShared()); + _dispatchDeclCheckingVisitor(decl, nextState, subContext); // In the common case, the visitor will have done the necessary // checking, but will *not* have updated the `checkState` on @@ -1177,8 +1182,8 @@ namespace Slang : public SemanticsDeclVisitorBase , public DeclVisitor<SemanticsDeclConformancesVisitor> { - SemanticsDeclConformancesVisitor(SharedSemanticsContext* shared) - : SemanticsDeclVisitorBase(shared) + SemanticsDeclConformancesVisitor(SemanticsContext const& outer) + : SemanticsDeclVisitorBase(outer) {} void visitDecl(Decl*) {} @@ -2088,31 +2093,24 @@ namespace Slang // to the user as some kind of overload-resolution failure. // // In order to protect the user from whatever errors might - // occur, we will swap out the current diagnostic sink for - // a temporary one. + // occur, we will perform the checking in the context of + // a temporary diagnostic sink. // - DiagnosticSink* savedSink = m_shared->m_sink; - DiagnosticSink tempSink(savedSink->getSourceManager(), nullptr); - m_shared->m_sink = &tempSink; + DiagnosticSink tempSink(getSourceManager(), nullptr); + SemanticsVisitor subVisitor(withSink(&tempSink)); // With our temporary diagnostic sink soaking up any messages // from overload resolution, we can now try to resolve // the call to see what happens. // - auto checkedCall = ResolveInvoke(synCall); + auto checkedCall = subVisitor.ResolveInvoke(synCall); // Of course, it is possible that the call went through fine, // but the result isn't of the type we expect/require, // so we also need to coerce the result of the call to // the expected type. // - auto coercedCall = coerce(resultType, checkedCall); - - // Once we are done making our semantic checks, we can - // restore the original sink, so that subsequent operations - // report diagnostics as usual. - // - m_shared->m_sink = savedSink; + auto coercedCall = subVisitor.coerce(resultType, checkedCall); // If our overload resolution or type coercion failed, // then we have not been able to synthesize a witness @@ -2380,9 +2378,8 @@ namespace Slang // `SemanticsVisitor` so that code can push/pop the emission // of diagnostics more easily. // - DiagnosticSink* savedSink = m_shared->m_sink; - DiagnosticSink tempSink(savedSink->getSourceManager(), nullptr); - m_shared->m_sink = &tempSink; + DiagnosticSink tempSink(getSourceManager(), nullptr); + SemanticsVisitor subVisitor(withSink(&tempSink)); // We start by constructing an expression that represents // `this.name` where `name` is the name of the required @@ -2415,7 +2412,7 @@ namespace Slang // general-purpose language features is unlikely to be as efficient // as special-case logic. // - auto synMemberRef = createLookupResultExpr( + auto synMemberRef = subVisitor.createLookupResultExpr( requiredMemberDeclRef.getName(), lookupResult, synThis, @@ -2434,7 +2431,7 @@ namespace Slang // which involves coercing the member access `this.name` to // the expected type of the property. // - auto coercedMemberRef = coerce(propertyType, synMemberRef); + auto coercedMemberRef = subVisitor.coerce(propertyType, synMemberRef); auto synReturn = m_astBuilder->create<ReturnStmt>(); synReturn->expression = coercedMemberRef; @@ -2461,7 +2458,7 @@ namespace Slang synAssign->left = synMemberRef; synAssign->right = synArgs[0]; - auto synCheckedAssign = checkAssignWithCheckedOperands(synAssign); + auto synCheckedAssign = subVisitor.checkAssignWithCheckedOperands(synAssign); auto synExprStmt = m_astBuilder->create<ExpressionStmt>(); synExprStmt->expression = synCheckedAssign; @@ -2477,10 +2474,8 @@ namespace Slang return false; } - // We restore the semantic checking state that was in place before - // we checked the synthesized accessor body, and then bail out - // if we ran into any errors (meaning that the synthesized accessor - // is not usable). + // We bail out if we ran into any errors (meaning that the synthesized + // accessor is not usable). // // TODO: If there were *warnings* emitted to the sink, it would probably // be good to show those warnings to the user, since they might indicate @@ -2488,7 +2483,6 @@ namespace Slang // satisfying an `int` property requirement, but the user would probably // want to be warned when they do such a thing. // - m_shared->m_sink = savedSink; if(tempSink.getErrorCount() != 0) return false; @@ -5046,7 +5040,7 @@ namespace Slang name, decl->moduleNameAndLoc.loc, getSink(), - m_shared->m_environmentModules); + getShared()->m_environmentModules); // If we didn't find a matching module, then bail out if (!importedModule) @@ -5324,7 +5318,7 @@ namespace Slang } - static void _dispatchDeclCheckingVisitor(Decl* decl, DeclCheckState state, SharedSemanticsContext* shared) + static void _dispatchDeclCheckingVisitor(Decl* decl, DeclCheckState state, SemanticsContext const& shared) { switch(state) { |
