summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/slang/slang-check-decl.cpp20
-rw-r--r--source/slang/slang-diagnostic-defs.h6
-rw-r--r--tests/diagnostics/global-const-uniform-with-init.slang49
-rw-r--r--tests/diagnostics/global-uniform.slang2
-rw-r--r--tests/diagnostics/global-uniform.slang.expected3
5 files changed, 76 insertions, 4 deletions
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp
index 9853b0097..a3662702a 100644
--- a/source/slang/slang-check-decl.cpp
+++ b/source/slang/slang-check-decl.cpp
@@ -212,22 +212,42 @@ struct SemanticsDeclModifiersVisitor : public SemanticsDeclVisitorBase,
// Export'd/Extern'd variables must be `const`, otherwise we may have a mismatch
// causing errors.
bool hasConst = false;
+ bool hasUniform = false;
bool hasExportOrExtern = false;
bool hasStatic = false;
+ bool hasSpecializationConstant = false;
for (auto m : decl->modifiers)
{
if (as<ExternModifier>(m) || as<HLSLExportModifier>(m))
hasExportOrExtern = true;
else if (as<ConstModifier>(m))
hasConst = true;
+ else if (as<HLSLUniformModifier>(m))
+ hasUniform = true;
else if (as<HLSLStaticModifier>(m))
hasStatic = true;
+ else if (as<SpecializationConstantAttribute>(m) || as<VkConstantIdAttribute>(m))
+ hasSpecializationConstant = true;
}
if (hasExportOrExtern && hasConst != hasStatic)
getSink()->diagnose(
decl,
Diagnostics::ExternAndExportVarDeclMustBeConst,
decl->getName());
+
+
+ // Global const or uniform variables with initializers must be static
+ // In HLSL, const global variables without static are uniform parameters
+ // that cannot have default values
+ // Exception: specialization constants are allowed to have initializers
+ if (isGlobalDecl(decl) && (hasConst || hasUniform) && !hasStatic &&
+ !hasSpecializationConstant && decl->initExpr)
+ {
+ getSink()->diagnose(
+ decl,
+ Diagnostics::constGlobalVarWithInitRequiresStatic,
+ decl->getName());
+ }
}
void visitDecl(Decl* decl) { checkModifiers(decl); }
diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h
index c549ccca3..3d584679e 100644
--- a/source/slang/slang-diagnostic-defs.h
+++ b/source/slang/slang-diagnostic-defs.h
@@ -1508,6 +1508,12 @@ DIAGNOSTIC(
ExternAndExportVarDeclMustBeConst,
"extern and export variables must be static const: '$0'")
+DIAGNOSTIC(
+ 31224,
+ Error,
+ constGlobalVarWithInitRequiresStatic,
+ "global const variable with initializer must be declared static: '$0'")
+
// Enums
DIAGNOSTIC(32000, Error, invalidEnumTagType, "invalid tag type for 'enum': '$0'")
diff --git a/tests/diagnostics/global-const-uniform-with-init.slang b/tests/diagnostics/global-const-uniform-with-init.slang
new file mode 100644
index 000000000..352c309e3
--- /dev/null
+++ b/tests/diagnostics/global-const-uniform-with-init.slang
@@ -0,0 +1,49 @@
+//TEST:SIMPLE(filecheck=CHK): -target hlsl -entry main
+
+// Test for diagnostic 31224: global const/uniform variables with initializers must be static
+// Exception: specialization constants are allowed to have initializers without static
+// Test for diagnostic 31219: specialization constants cannot be declared static
+
+// These should trigger error 31224
+//CHK-DAG: ([[# @LINE + 1]]): error 31224: global const variable with initializer must be declared static: 'globalConstWithInit'
+const float globalConstWithInit = 1.0f;
+
+//CHK-DAG: ([[# @LINE + 1]]): error 31224: global const variable with initializer must be declared static: 'uniformWithInit'
+uniform float uniformWithInit = 2.0f;
+
+// These are valid and should not produce errors
+static const float staticConstWithInit = 3.0f; // OK - static const with init
+const float globalConstNoInit; // OK - const without init
+uniform float uniformNoInit; // OK - uniform without init
+
+// Specialization constants with initializers are allowed without static
+[SpecializationConstant]
+const int specConstInt = 42; // OK - specialization constant with init
+
+[vk::constant_id(5)]
+const float specConstFloat = 3.14f; // OK - vk constant id with init
+
+// These should trigger error 31219: static specialization constants are not allowed
+//CHK-DAG: ([[# @LINE + 2]]): error 31219: push or specialization constants cannot be 'static'.
+[SpecializationConstant]
+static const int staticSpecConstInt = 100;
+
+//CHK-DAG: ([[# @LINE + 2]]): error 31219: push or specialization constants cannot be 'static'.
+[vk::constant_id(7)]
+static const float staticSpecConstFloat = 2.71f;
+
+void functionScope()
+{
+ const float localConstWithInit = 4.0f; // OK - local const with init
+}
+
+struct MyStruct
+{
+ static const float memberStaticConst = 5.0f; // OK - member static const
+};
+
+[shader("vertex")]
+float4 main() : SV_Position
+{
+ return float4(staticConstWithInit, 0, 0, 1);
+} \ No newline at end of file
diff --git a/tests/diagnostics/global-uniform.slang b/tests/diagnostics/global-uniform.slang
index de4537115..1223f624c 100644
--- a/tests/diagnostics/global-uniform.slang
+++ b/tests/diagnostics/global-uniform.slang
@@ -7,7 +7,7 @@
uniform float a;
-const uint4 b = uint4(0,1,2,3);
+static const uint4 b = uint4(0,1,2,3);
struct C { float x; int y; };
C c;
diff --git a/tests/diagnostics/global-uniform.slang.expected b/tests/diagnostics/global-uniform.slang.expected
index 70877f4bd..3c9f3ba2a 100644
--- a/tests/diagnostics/global-uniform.slang.expected
+++ b/tests/diagnostics/global-uniform.slang.expected
@@ -1,8 +1,5 @@
result code = 0
standard error = {
-tests/diagnostics/global-uniform.slang(10): warning 39019: 'b' is implicitly a global shader parameter, not a global variable. If a global variable is intended, add the 'static' modifier. If a uniform shader parameter is intended, add the 'uniform' modifier to silence this warning.
-const uint4 b = uint4(0,1,2,3);
- ^
tests/diagnostics/global-uniform.slang(13): warning 39019: 'c' is implicitly a global shader parameter, not a global variable. If a global variable is intended, add the 'static' modifier. If a uniform shader parameter is intended, add the 'uniform' modifier to silence this warning.
C c;
^