diff options
| author | ArielG-NV <159081215+ArielG-NV@users.noreply.github.com> | 2024-07-02 13:35:49 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-07-02 13:35:49 -0400 |
| commit | d5d03d1510f45f5ed7864031244713d87fc82b87 (patch) | |
| tree | e0391686ca3b06406e497c4e7e7f90172355e4cf /source/slang/slang-check-decl.cpp | |
| parent | bd01bd3f4b8eecbfb924b8eb4090694e44e8166c (diff) | |
Emit errors when invalid capabilities are used (#4510)
* Fix invalid capabilities being allowed
fixes: #4506
fixes: #4508
1. As per #4506, no longer allow invalid `[require(...)]`
2. As per #4508, no longer allow mismatch between `case` and `require` of a calling function
3. Fixes incorrect hlsl.meta capabilities
4. Added a ref to the parent function/decl for when erroring with capabilities to help debug meta.slang files for when weird source locations are generated.
* rename vars and copy lambdas by value
* fix some more capabilities
* incorrect capabilities on a texture test
* push capabilities fix
note: seperated capabilities for glsl,spirv,cuda,hlsl since not all functions support all targets (source of capability error)
* fix cmd line arg by using `xslang` to passthrough to slangc
* let auto-infer run for certain capabilities to reduce simple mistakes
---------
Co-authored-by: Jay Kwak <82421531+jkwak-work@users.noreply.github.com>
Diffstat (limited to 'source/slang/slang-check-decl.cpp')
| -rw-r--r-- | source/slang/slang-check-decl.cpp | 98 |
1 files changed, 68 insertions, 30 deletions
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp index 74d08f8e5..c3074bc55 100644 --- a/source/slang/slang-check-decl.cpp +++ b/source/slang/slang-check-decl.cpp @@ -10095,6 +10095,11 @@ namespace Slang } } + static void _propagateSeeDefinitionOf(SemanticsVisitor* visitor, Decl* funcDecl, DiagnosticCategory diagnosticCategory) + { + maybeDiagnose(visitor->getSink(), visitor->getOptionSet(), diagnosticCategory, funcDecl, Diagnostics::seeDefinitionOf, funcDecl); + } + static void _propagateRequirement(SemanticsVisitor* visitor, CapabilitySet& resultCaps, SyntaxNode* userNode, SyntaxNode* referencedNode, const CapabilitySet& nodeCaps, SourceLoc referenceLoc) { auto referencedDecl = as<Decl>(referencedNode); @@ -10178,20 +10183,22 @@ namespace Slang CapabilitySet getStatementCapabilityUsage(SemanticsVisitor* visitor, Stmt* stmt); - template<typename ProcessFunc> + template<typename ProcessFunc, typename ParentDiagnosticFunc> struct CapabilityDeclReferenceVisitor - : public SemanticsDeclReferenceVisitor<CapabilityDeclReferenceVisitor<ProcessFunc>> + : public SemanticsDeclReferenceVisitor<CapabilityDeclReferenceVisitor<ProcessFunc, ParentDiagnosticFunc>> { - typedef SemanticsDeclReferenceVisitor<CapabilityDeclReferenceVisitor<ProcessFunc>> Base; + typedef SemanticsDeclReferenceVisitor<CapabilityDeclReferenceVisitor<ProcessFunc, ParentDiagnosticFunc>> Base; - const ProcessFunc& handleReferenceFunc; + const ProcessFunc handleProcessFunc; + const ParentDiagnosticFunc handleParentDiagnosticFunc; RequireCapabilityAttribute* maybeRequireCapability; SemanticsContext& outerContext; - CapabilityDeclReferenceVisitor(const ProcessFunc& processFunc, RequireCapabilityAttribute* maybeRequireCapability, SemanticsContext& outer) - : handleReferenceFunc(processFunc) + CapabilityDeclReferenceVisitor(const ProcessFunc& processFunc, const ParentDiagnosticFunc& parentDiagnosticFunc, RequireCapabilityAttribute* maybeRequireCapability, SemanticsContext& outer) + : handleProcessFunc(processFunc) + , handleParentDiagnosticFunc(parentDiagnosticFunc) , maybeRequireCapability(maybeRequireCapability) , outerContext(outer) - , SemanticsDeclReferenceVisitor<CapabilityDeclReferenceVisitor<ProcessFunc>>(outer) + , SemanticsDeclReferenceVisitor<CapabilityDeclReferenceVisitor<ProcessFunc, ParentDiagnosticFunc>>(outer) { } virtual void processReferencedDecl(Decl* decl) override @@ -10199,16 +10206,16 @@ namespace Slang SourceLoc loc = SourceLoc(); if (Base::sourceLocStack.getCount()) loc = Base::sourceLocStack.getLast(); - handleReferenceFunc(decl, decl->inferredCapabilityRequirements, loc); + handleProcessFunc(decl, decl->inferredCapabilityRequirements, loc); } virtual void processDeclModifiers(Decl* decl) override { if (decl) - handleReferenceFunc(decl, decl->inferredCapabilityRequirements, decl->loc); + handleProcessFunc(decl, decl->inferredCapabilityRequirements, decl->loc); } void visitDiscardStmt(DiscardStmt* stmt) { - handleReferenceFunc(stmt, CapabilitySet(CapabilityName::fragment), stmt->loc); + handleProcessFunc(stmt, CapabilitySet(CapabilityName::fragment), stmt->loc); } void visitTargetSwitchStmt(TargetSwitchStmt* stmt) { @@ -10247,6 +10254,19 @@ namespace Slang else { targetCap = CapabilitySet(CapabilityName(stmt->targetCases[targetCaseIndex]->capability)); + + if (maybeRequireCapability) + { + CapabilitySet testingForInvalid = maybeRequireCapability->capabilitySet; + // Ensure case statement is valid with parent `[require(...)]` + testingForInvalid.join(targetCap); + if (testingForInvalid.isInvalid()) + { + maybeDiagnose(Base::getSink(), outerContext.getOptionSet(), DiagnosticCategory::Capability, stmt->targetCases[targetCaseIndex]->loc, + Diagnostics::conflictingCapabilityDueToStatement, targetCap, maybeRequireCapability, maybeRequireCapability->capabilitySet); + handleParentDiagnosticFunc(DiagnosticCategory::Capability); + } + } } auto targetCase = stmt->targetCases[targetCaseIndex]; auto oldCap = targetCap; @@ -10255,22 +10275,23 @@ namespace Slang if (targetCap.isInvalid()) { maybeDiagnose(Base::getSink(), outerContext.getOptionSet(), DiagnosticCategory::Capability, targetCase->body->loc, Diagnostics::conflictingCapabilityDueToStatement, bodyCap, "target_switch", oldCap); + handleParentDiagnosticFunc(DiagnosticCategory::Capability); } set.unionWith(targetCap); } - handleReferenceFunc(stmt, set, stmt->loc); + handleProcessFunc(stmt, set, stmt->loc); } void visitRequireCapabilityDecl(RequireCapabilityDecl* decl) { - handleReferenceFunc(decl, decl->inferredCapabilityRequirements, decl->loc); + handleProcessFunc(decl, decl->inferredCapabilityRequirements, decl->loc); } }; - template<typename ProcessFunc> - void visitReferencedDecls(SemanticsContext& context, NodeBase* node, SourceLoc initialLoc, RequireCapabilityAttribute* maybeRequireCapability, const ProcessFunc& func) + template<typename ProcessFunc, typename ParentDiagnosticFunc> + void visitReferencedDecls(SemanticsContext& context, NodeBase* node, SourceLoc initialLoc, RequireCapabilityAttribute* maybeRequireCapability, const ProcessFunc& processFunc, const ParentDiagnosticFunc& parentDiagnosticFunc) { - CapabilityDeclReferenceVisitor<ProcessFunc> visitor(func, maybeRequireCapability, context); + CapabilityDeclReferenceVisitor<ProcessFunc, ParentDiagnosticFunc> visitor(processFunc, parentDiagnosticFunc, maybeRequireCapability, context); visitor.sourceLocStack.add(initialLoc); if (auto val = as<Val>(node)) @@ -10289,19 +10310,31 @@ namespace Slang return CapabilitySet(); CapabilitySet inferredRequirements; - visitReferencedDecls(*visitor, stmt, stmt->loc, nullptr, [&](SyntaxNode* node, const CapabilitySet& nodeCaps, SourceLoc refLoc) - { - _propagateRequirement(visitor, inferredRequirements, stmt, node, nodeCaps, refLoc); - }); + visitReferencedDecls(*visitor, stmt, stmt->loc, nullptr, + [&](SyntaxNode* node, const CapabilitySet& nodeCaps, SourceLoc refLoc) + { + _propagateRequirement(visitor, inferredRequirements, stmt, node, nodeCaps, refLoc); + }, + [](DiagnosticCategory category) + { + SLANG_UNUSED(category); + } + ); return inferredRequirements; } void SemanticsDeclCapabilityVisitor::checkVarDeclCommon(VarDeclBase* varDecl) { - visitReferencedDecls(*this, varDecl->type.type, varDecl->loc, varDecl->findModifier<RequireCapabilityAttribute>(), [this, varDecl](SyntaxNode* node, const CapabilitySet& nodeCaps, SourceLoc refLoc) - { - _propagateRequirement(this, varDecl->inferredCapabilityRequirements, varDecl, node, nodeCaps, refLoc); - }); + visitReferencedDecls(*this, varDecl->type.type, varDecl->loc, varDecl->findModifier<RequireCapabilityAttribute>(), + [this, varDecl](SyntaxNode* node, const CapabilitySet& nodeCaps, SourceLoc refLoc) + { + _propagateRequirement(this, varDecl->inferredCapabilityRequirements, varDecl, node, nodeCaps, refLoc); + }, + [this, varDecl](DiagnosticCategory category) + { + _propagateSeeDefinitionOf(this, varDecl, category); + } + ); } CapabilitySet SemanticsDeclCapabilityVisitor::getDeclaredCapabilitySet(Decl* decl) @@ -10351,8 +10384,8 @@ namespace Slang decl->inferredCapabilityRequirements = getDeclaredCapabilitySet(decl); } - template<typename ProcessFunc> - static inline void _dispatchCapabilitiesVisitorOfFunctionDecl(SemanticsVisitor* visitor, FunctionDeclBase* funcDecl, ProcessFunc propegateFuncForReferences) + template<typename ProcessFunc, typename ParentDiagnosticFunc> + static inline void _dispatchCapabilitiesVisitorOfFunctionDecl(SemanticsVisitor* visitor, FunctionDeclBase* funcDecl, const ProcessFunc& processFunc, const ParentDiagnosticFunc& parentDiagnosticFunc) { visitor->setParentFuncOfVisitor(funcDecl); @@ -10362,7 +10395,7 @@ namespace Slang _propagateRequirement(visitor, funcDecl->inferredCapabilityRequirements, funcDecl, member, member->inferredCapabilityRequirements, member->loc); } - visitReferencedDecls(*visitor, funcDecl->body, funcDecl->loc, funcDecl->findModifier<RequireCapabilityAttribute>(), propegateFuncForReferences); + visitReferencedDecls(*visitor, funcDecl->body, funcDecl->loc, funcDecl->findModifier<RequireCapabilityAttribute>(), processFunc, parentDiagnosticFunc); if (!isEffectivelyStatic(funcDecl)) { @@ -10378,10 +10411,15 @@ namespace Slang void SemanticsDeclCapabilityVisitor::visitFunctionDeclBase(FunctionDeclBase* funcDecl) { _dispatchCapabilitiesVisitorOfFunctionDecl(this, funcDecl, - [this, funcDecl](SyntaxNode* node, const CapabilitySet& nodeCaps, SourceLoc refLoc) - { - _propagateRequirement(this, funcDecl->inferredCapabilityRequirements, funcDecl, node, nodeCaps, refLoc); - }); + [this, funcDecl](SyntaxNode* node, const CapabilitySet& nodeCaps, SourceLoc refLoc) + { + _propagateRequirement(this, funcDecl->inferredCapabilityRequirements, funcDecl, node, nodeCaps, refLoc); + }, + [this, funcDecl](DiagnosticCategory category) + { + _propagateSeeDefinitionOf(this, funcDecl, category); + } + ); auto declaredCaps = getDeclaredCapabilitySet(funcDecl); |
