summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArielG-NV <159081215+ArielG-NV@users.noreply.github.com>2025-05-16 10:44:44 -0700
committerGitHub <noreply@github.com>2025-05-16 10:44:44 -0700
commit0651ffb6489282f0f902ec5f630821a7b9d848bb (patch)
tree28b27f1b5cc19520b4c54c046a260710d3e7fdd6
parent8683b85c0494db99feb08b6efcdc26dfe006729f (diff)
Enforce rule that `export`/`extern` (non cpp) must be `const` (#7113)
* Enforce rule that `export`/`extern` (non cpp) must be `const` fixes: #5570 Problem: 1. we allow non-const-link-time-var to be linked to a const-link-time-var. 2. problem is that: module use site has const var, so, we emit OpStore %Ptr %Const in IR, this is expected, this is good. We fail because we in reality have a OpStore %Ptr %Var (fails since we need a OpLoad in-between) in IR since the module with our link-time-variable-value is a regular variable. 3. We loose the float_litteral talked about inside the github issue since, we technically don't use our variable "VAL" (we never OpLoad from it), so spirv-opt removes the float_litteral, this is a byproduct of the actual issue. Solution: * `export`/`extern` variables must always be `const`. This excludes `__extern_cpp` since `cpp` does not exhibit this issue and works differently. * format code * changel logic and tests to only ensure `static const` with `export`/`extern` * changing the rules: only reqirement is that if we have const we must have static * remove a spirrious change made * fix merge --------- Co-authored-by: slangbot <186143334+slangbot@users.noreply.github.com> Co-authored-by: Yong He <yonghe@outlook.com>
-rw-r--r--source/slang/slang-check-decl.cpp25
-rw-r--r--source/slang/slang-diagnostic-defs.h7
-rw-r--r--tests/language-feature/constants/link-time-vardecl-must-be-static-const-or-neither.slang32
3 files changed, 63 insertions, 1 deletions
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp
index 79482ea6e..daa761d3d 100644
--- a/source/slang/slang-check-decl.cpp
+++ b/source/slang/slang-check-decl.cpp
@@ -42,6 +42,31 @@ struct SemanticsDeclModifiersVisitor : public SemanticsDeclVisitorBase,
void visitDeclGroup(DeclGroup*) {}
+ void visitVarDecl(VarDecl* decl)
+ {
+ visitDecl(decl);
+
+ // Export'd/Extern'd variables must be `const`, otherwise we may have a mismatch
+ // causing errors.
+ bool hasConst = false;
+ bool hasExportOrExtern = false;
+ bool hasStatic = 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<HLSLStaticModifier>(m))
+ hasStatic = true;
+ }
+ if (hasExportOrExtern && hasConst != hasStatic)
+ getSink()->diagnose(
+ decl,
+ Diagnostics::ExternAndExportVarDeclMustBeConst,
+ decl->getName());
+ }
+
void visitDecl(Decl* decl) { checkModifiers(decl); }
void visitStructDecl(StructDecl* structDecl);
diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h
index 6bedcfe3e..cafd61062 100644
--- a/source/slang/slang-diagnostic-defs.h
+++ b/source/slang/slang-diagnostic-defs.h
@@ -1366,13 +1366,18 @@ DIAGNOSTIC(
Error,
variableCannotBePushAndSpecializationConstant,
"'$0' cannot be a push constant and a specialization constant at the same time")
-
DIAGNOSTIC(31221, Error, invalidHLSLRegisterName, "invalid HLSL register name '$0'.")
DIAGNOSTIC(
31222,
Error,
invalidHLSLRegisterNameForType,
"invalid HLSL register name '$0' for type '$1'.")
+DIAGNOSTIC(
+ 31223,
+ Error,
+ ExternAndExportVarDeclMustBeConst,
+ "extern and export variables must be static const: '$0'")
+
// Enums
DIAGNOSTIC(32000, Error, invalidEnumTagType, "invalid tag type for 'enum': '$0'")
diff --git a/tests/language-feature/constants/link-time-vardecl-must-be-static-const-or-neither.slang b/tests/language-feature/constants/link-time-vardecl-must-be-static-const-or-neither.slang
new file mode 100644
index 000000000..a1ae810e1
--- /dev/null
+++ b/tests/language-feature/constants/link-time-vardecl-must-be-static-const-or-neither.slang
@@ -0,0 +1,32 @@
+//TEST:SIMPLE(filecheck=CHECK_PASS): -target spirv -entry computeMain -stage compute -DUSE_EXTERN
+//TEST:SIMPLE(filecheck=CHECK_PASS): -target spirv -entry computeMain -stage compute
+//TEST:SIMPLE(filecheck=CHECK_PASS): -target spirv -entry computeMain -stage compute -DUSE_EXTERN -DUSE_CONST -DUSE_STATIC
+//TEST:SIMPLE(filecheck=CHECK_PASS): -target spirv -entry computeMain -stage compute -DUSE_CONST -DUSE_STATIC
+//CHECK_PASS-NOT: error 31223
+
+//TEST:SIMPLE(filecheck=CHECK_FAIL): -target spirv -entry computeMain -stage compute -DUSE_EXTERN -DUSE_CONST
+//TEST:SIMPLE(filecheck=CHECK_FAIL): -target spirv -entry computeMain -stage compute -DUSE_CONST
+//TEST:SIMPLE(filecheck=CHECK_FAIL): -target spirv -entry computeMain -stage compute -DUSE_EXTERN -DUSE_STATIC
+//TEST:SIMPLE(filecheck=CHECK_FAIL): -target spirv -entry computeMain -stage compute -DUSE_STATIC
+//CHECK_FAIL: error 31223
+
+
+#ifdef USE_CONST
+const
+#endif
+#ifdef USE_STATIC
+static
+#endif
+#ifdef USE_EXTERN
+extern int num;
+#else
+export int num = 10;
+#endif
+
+RWStructuredBuffer<float> outputBuffer;
+
+[numthreads(1,1,1)]
+void computeMain()
+{
+ outputBuffer[0] = num;
+}