diff options
| -rw-r--r-- | source/slang/core.meta.slang | 4 | ||||
| -rw-r--r-- | source/slang/core.meta.slang.h | 4 | ||||
| -rw-r--r-- | source/slang/slang-check.cpp | 18 | ||||
| -rw-r--r-- | source/slang/slang-diagnostic-defs.h | 1 | ||||
| -rw-r--r-- | source/slang/slang-diagnostics.cpp | 27 | ||||
| -rw-r--r-- | source/slang/slang-diagnostics.h | 2 | ||||
| -rw-r--r-- | source/slang/slang-modifier-defs.h | 4 | ||||
| -rw-r--r-- | source/slang/slang-parameter-binding.cpp | 42 | ||||
| -rw-r--r-- | tests/diagnostics/overlapping-bindings.slang | 17 | ||||
| -rw-r--r-- | tests/diagnostics/overlapping-bindings.slang.expected | 7 |
10 files changed, 121 insertions, 5 deletions
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang index bc9c9b50a..f61f00d64 100644 --- a/source/slang/core.meta.slang +++ b/source/slang/core.meta.slang @@ -1314,3 +1314,7 @@ attribute_syntax [__AttributeUsage(target : _AttributeTargets)] : AttributeUsage __attributeTarget(VarDeclBase) attribute_syntax [format(format : String)] : FormatAttribute; + +__attributeTarget(Decl) +attribute_syntax [allow(diagnostic: String)] : AllowAttribute; + diff --git a/source/slang/core.meta.slang.h b/source/slang/core.meta.slang.h index 8362a2c4b..0e24dd711 100644 --- a/source/slang/core.meta.slang.h +++ b/source/slang/core.meta.slang.h @@ -1345,3 +1345,7 @@ SLANG_RAW("attribute_syntax [__AttributeUsage(target : _AttributeTargets)] : Att SLANG_RAW("\n") SLANG_RAW("__attributeTarget(VarDeclBase)\n") SLANG_RAW("attribute_syntax [format(format : String)] : FormatAttribute;\n") +SLANG_RAW("\n") +SLANG_RAW("__attributeTarget(Decl)\n") +SLANG_RAW("attribute_syntax [allow(diagnostic: String)] : AllowAttribute;\n") +SLANG_RAW("\n") diff --git a/source/slang/slang-check.cpp b/source/slang/slang-check.cpp index a8900986b..534642a1c 100644 --- a/source/slang/slang-check.cpp +++ b/source/slang/slang-check.cpp @@ -2934,6 +2934,24 @@ namespace Slang formatAttr->format = format; } + else if (auto allowAttr = as<AllowAttribute>(attr)) + { + SLANG_ASSERT(attr->args.getCount() == 1); + + String diagnosticName; + if(!checkLiteralStringVal(attr->args[0], &diagnosticName)) + { + return false; + } + + auto diagnosticInfo = findDiagnosticByName(diagnosticName.getUnownedSlice()); + if(!diagnosticInfo) + { + getSink()->diagnose(attr->args[0], Diagnostics::unknownDiagnosticName, diagnosticName); + } + + allowAttr->diagnostic = diagnosticInfo; + } else { if(attr->args.getCount() == 0) diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h index 04b7560d2..e8114dc95 100644 --- a/source/slang/slang-diagnostic-defs.h +++ b/source/slang/slang-diagnostic-defs.h @@ -269,6 +269,7 @@ DIAGNOSTIC(31006, Error, attributeFunctionNotFound, "Could not find function '$0 DIAGNOSTIC(31100, Error, unknownStageName, "unknown stage name '$0'") DIAGNOSTIC(31101, Error, unknownImageFormatName, "unknown image format '$0'") +DIAGNOSTIC(31101, Error, unknownDiagnosticName, "unknown diagnostic '$0'") DIAGNOSTIC(31120, Error, invalidAttributeTarget, "invalid syntax target for user defined attribute") diff --git a/source/slang/slang-diagnostics.cpp b/source/slang/slang-diagnostics.cpp index 4aabd3ab9..76b2fcffa 100644 --- a/source/slang/slang-diagnostics.cpp +++ b/source/slang/slang-diagnostics.cpp @@ -339,12 +339,37 @@ void DiagnosticSink::diagnoseRaw( } } - namespace Diagnostics { #define DIAGNOSTIC(id, severity, name, messageFormat) const DiagnosticInfo name = { id, Severity::severity, messageFormat }; #include "slang-diagnostic-defs.h" } +DiagnosticInfo const* findDiagnosticByName(UnownedStringSlice const& name) +{ + // TODO: We should eventually have a more formal system for associating individual + // diagnostics, or groups of diagnostics, with user-exposed names for use when + // enabling/disabling warnings (or turning warnings into errors, etc.). + // + // For now we build an ad hoc mapping from string names to corresponding single + // diagnostics (not groups). + // + static const struct + { + char const* name; + DiagnosticInfo const* diagnostic; + } kDiagnostics[] = + { + { "overlapping-bindings", &Diagnostics::parameterBindingsOverlap }, + }; + + for( auto& entry : kDiagnostics ) + { + if( name == entry.name ) + return entry.diagnostic; + } + return nullptr; +} + } // namespace Slang diff --git a/source/slang/slang-diagnostics.h b/source/slang/slang-diagnostics.h index 3d75c577d..9b70ef0d9 100644 --- a/source/slang/slang-diagnostics.h +++ b/source/slang/slang-diagnostics.h @@ -257,6 +257,8 @@ namespace Slang DiagnosticSink* m_sink = nullptr; }; + DiagnosticInfo const* findDiagnosticByName(UnownedStringSlice const& name); + namespace Diagnostics { #define DIAGNOSTIC(id, severity, name, messageFormat) extern const DiagnosticInfo name; diff --git a/source/slang/slang-modifier-defs.h b/source/slang/slang-modifier-defs.h index 2af1f0f8f..754e7e44a 100644 --- a/source/slang/slang-modifier-defs.h +++ b/source/slang/slang-modifier-defs.h @@ -461,3 +461,7 @@ END_SYNTAX_CLASS() SYNTAX_CLASS(FormatAttribute, Attribute) FIELD(ImageFormat, format) END_SYNTAX_CLASS() + +SYNTAX_CLASS(AllowAttribute, Attribute) + FIELD_INIT(DiagnosticInfo const*, diagnostic, nullptr) +END_SYNTAX_CLASS() diff --git a/source/slang/slang-parameter-binding.cpp b/source/slang/slang-parameter-binding.cpp index d5efc3515..dc99f55e2 100644 --- a/source/slang/slang-parameter-binding.cpp +++ b/source/slang/slang-parameter-binding.cpp @@ -784,6 +784,25 @@ static UInt allocateUnusedSpaces( return context->shared->usedSpaces.Allocate(nullptr, count); } +static bool shouldDisableDiagnostic( + Decl* decl, + DiagnosticInfo const& diagnosticInfo) +{ + for( auto dd = decl; dd; dd = dd->ParentDecl ) + { + for( auto modifier : dd->modifiers ) + { + auto allowAttr = as<AllowAttribute>(modifier); + if(!allowAttr) + continue; + + if(allowAttr->diagnostic == &diagnosticInfo) + return true; + } + } + return false; +} + static void addExplicitParameterBinding( ParameterBindingContext* context, RefPtr<ParameterInfo> parameterInfo, @@ -842,11 +861,26 @@ static void addExplicitParameterBinding( auto paramA = parameterInfo->varLayouts[0]->varDecl.getDecl(); auto paramB = overlappedVarLayout->varDecl.getDecl(); - getSink(context)->diagnose(paramA, Diagnostics::parameterBindingsOverlap, - getReflectionName(paramA), - getReflectionName(paramB)); + auto& diagnosticInfo = Diagnostics::parameterBindingsOverlap; + + // If *both* of the shader parameters declarations agree + // that overlapping bindings should be allowed, then we + // will not emit a diagnostic. Otherwise, we will warn + // the user because such overlapping bindings are likely + // to indicate a programming error. + // + if(shouldDisableDiagnostic(paramA, diagnosticInfo) + && shouldDisableDiagnostic(paramB, diagnosticInfo)) + { + } + else + { + getSink(context)->diagnose(paramA, diagnosticInfo, + getReflectionName(paramA), + getReflectionName(paramB)); - getSink(context)->diagnose(paramB, Diagnostics::seeDeclarationOf, getReflectionName(paramB)); + getSink(context)->diagnose(paramB, Diagnostics::seeDeclarationOf, getReflectionName(paramB)); + } } } } diff --git a/tests/diagnostics/overlapping-bindings.slang b/tests/diagnostics/overlapping-bindings.slang new file mode 100644 index 000000000..8df588d16 --- /dev/null +++ b/tests/diagnostics/overlapping-bindings.slang @@ -0,0 +1,17 @@ +// overlapping-bindings.slang + +//DIAGNOSTIC_TEST:SIMPLE:-target hlsl + +// Two parameters with the same `register: + +Texture2D a : register(t0); + +Texture2D b : register(t0); + +// Parameters marked to ignore overlap: + +[allow("overlapping-bindings")] +Texture2D c : register(t1); + +[allow("overlapping-bindings")] +Texture2D d : register(t1); diff --git a/tests/diagnostics/overlapping-bindings.slang.expected b/tests/diagnostics/overlapping-bindings.slang.expected new file mode 100644 index 000000000..80481eaf9 --- /dev/null +++ b/tests/diagnostics/overlapping-bindings.slang.expected @@ -0,0 +1,7 @@ +result code = 0 +standard error = { +tests/diagnostics/overlapping-bindings.slang(9): warning 39001: explicit binding for parameter 'b' overlaps with parameter 'a' +tests/diagnostics/overlapping-bindings.slang(7): note: see declaration of 'a' +} +standard output = { +} |
