Skip to content

Diagnose on initExpr of a global const decl #7711

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
Jul 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions source/slang/slang-check-decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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); }
Expand Down
6 changes: 6 additions & 0 deletions source/slang/slang-diagnostic-defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1502,6 +1502,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'")
Expand Down
49 changes: 49 additions & 0 deletions tests/diagnostics/global-const-uniform-with-init.slang
Original file line number Diff line number Diff line change
@@ -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);
}
2 changes: 1 addition & 1 deletion tests/diagnostics/global-uniform.slang
Original file line number Diff line number Diff line change
Expand Up @@ -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;
3 changes: 0 additions & 3 deletions tests/diagnostics/global-uniform.slang.expected
Original file line number Diff line number Diff line change
@@ -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;
^
Expand Down
Loading