summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/slang/core.meta.slang4
-rw-r--r--source/slang/core.meta.slang.h4
-rw-r--r--source/slang/slang-check.cpp18
-rw-r--r--source/slang/slang-diagnostic-defs.h1
-rw-r--r--source/slang/slang-diagnostics.cpp27
-rw-r--r--source/slang/slang-diagnostics.h2
-rw-r--r--source/slang/slang-modifier-defs.h4
-rw-r--r--source/slang/slang-parameter-binding.cpp42
-rw-r--r--tests/diagnostics/overlapping-bindings.slang17
-rw-r--r--tests/diagnostics/overlapping-bindings.slang.expected7
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 = {
+}