summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/slang/slang-ast-decl.cpp2
-rw-r--r--source/slang/slang-ast-decl.h1
-rw-r--r--source/slang/slang-check-conformance.cpp13
-rw-r--r--source/slang/slang-check-decl.cpp21
-rw-r--r--source/slang/slang-diagnostic-defs.h10
-rw-r--r--tests/diagnostics/array-of-struct-with-parameterblock.slang44
-rw-r--r--tests/diagnostics/array-of-struct-with-unbounded.slang20
-rw-r--r--tests/diagnostics/array-of-unbounded-arrays.slang13
-rw-r--r--tests/diagnostics/array-parameterblock-array-in-struct.slang22
-rw-r--r--tests/diagnostics/array-parameterblock-deeply-nested.slang20
-rw-r--r--tests/diagnostics/array-parameterblock-direct.slang (renamed from tests/diagnostics/array-parameterblock.slang)7
-rw-r--r--tests/diagnostics/array-parameterblock-nested.slang26
-rw-r--r--tests/diagnostics/array-parameterblock-struct.slang21
-rw-r--r--tests/diagnostics/nested-struct-with-unbounded.slang31
-rw-r--r--tests/diagnostics/structured-buffer-parameterblock.slang43
-rw-r--r--tests/diagnostics/structuredbuffer-with-unbounded.slang20
-rw-r--r--tests/diagnostics/unbounded-array-nonaddressable.slang46
17 files changed, 351 insertions, 9 deletions
diff --git a/source/slang/slang-ast-decl.cpp b/source/slang/slang-ast-decl.cpp
index 1e2d11600..817230984 100644
--- a/source/slang/slang-ast-decl.cpp
+++ b/source/slang/slang-ast-decl.cpp
@@ -493,7 +493,7 @@ InterfaceDecl* ThisTypeConstraintDecl::getInterfaceDecl()
void AggTypeDecl::addTag(TypeTag tag)
{
- typeTags = (TypeTag)((int)tag | (int)tag);
+ typeTags = (TypeTag)((int)typeTags | (int)tag);
}
bool AggTypeDecl::hasTag(TypeTag tag)
diff --git a/source/slang/slang-ast-decl.h b/source/slang/slang-ast-decl.h
index 1a850da0d..0bda6fc79 100644
--- a/source/slang/slang-ast-decl.h
+++ b/source/slang/slang-ast-decl.h
@@ -377,6 +377,7 @@ enum class TypeTag
Incomplete = 2,
LinkTimeSized = 4,
Opaque = 8,
+ NonAddressable = 16,
};
// Declaration of a type that represents some sort of aggregate
diff --git a/source/slang/slang-check-conformance.cpp b/source/slang/slang-check-conformance.cpp
index ba1b8ea55..40ab66e95 100644
--- a/source/slang/slang-check-conformance.cpp
+++ b/source/slang/slang-check-conformance.cpp
@@ -348,7 +348,11 @@ TypeTag SemanticsVisitor::getTypeTags(Type* type)
typeTag = (TypeTag)((int)typeTag | (int)TypeTag::LinkTimeSized);
}
if (!sized)
- typeTag = (TypeTag)((int)typeTag | (int)TypeTag::Unsized);
+ {
+ // Unbounded arrays are both Unsized and NonAddressable
+ typeTag =
+ (TypeTag)((int)typeTag | (int)TypeTag::Unsized | (int)TypeTag::NonAddressable);
+ }
return typeTag;
}
@@ -356,6 +360,11 @@ TypeTag SemanticsVisitor::getTypeTags(Type* type)
{
return getTypeTags(modifiedType->getBase());
}
+ if (as<ParameterBlockType>(type))
+ {
+ // ParameterBlock types are non-addressable
+ return TypeTag::NonAddressable;
+ }
if (auto parameterGroupType = as<UniformParameterGroupType>(type))
{
auto elementTags = getTypeTags(parameterGroupType->getElementType());
@@ -372,7 +381,9 @@ TypeTag SemanticsVisitor::getTypeTags(Type* type)
else if (auto declRefType = as<DeclRefType>(type))
{
if (auto aggTypeDecl = as<AggTypeDecl>(declRefType->getDeclRef()))
+ {
return aggTypeDecl.getDecl()->typeTags;
+ }
}
return TypeTag::None;
}
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp
index 867c1daad..1ba8c62f3 100644
--- a/source/slang/slang-check-decl.cpp
+++ b/source/slang/slang-check-decl.cpp
@@ -2703,6 +2703,9 @@ void SemanticsDeclBodyVisitor::checkVarDeclCommon(VarDeclBase* varDecl)
{
DiagnoseIsAllowedInitExpr(varDecl, getSink());
+ // Check for arrays of non-addressable types
+ validateArrayElementTypeForVariable(varDecl);
+
// if zero initialize is true, set everything to a default
if (getOptionSet().hasOption(CompilerOptionName::ZeroInitialize) && !varDecl->initExpr &&
as<VarDecl>(varDecl))
@@ -2840,6 +2843,7 @@ void SemanticsDeclBodyVisitor::checkVarDeclCommon(VarDeclBase* varDecl)
}
TypeTag varTypeTags = getTypeTags(varDecl->getType());
+
auto parentDecl = as<AggTypeDecl>(getParentDecl(varDecl));
if (parentDecl)
{
@@ -10389,9 +10393,12 @@ void SemanticsVisitor::validateArrayElementTypeForVariable(VarDeclBase* varDecl)
return;
const auto elementType = arrayType->getElementType();
- if (as<ParameterBlockType>(elementType))
+
+ // Check if the element type has the NonAddressable tag
+ TypeTag elementTags = getTypeTags(elementType);
+ if ((int)elementTags & (int)TypeTag::NonAddressable)
{
- getSink()->diagnose(varDecl, Diagnostics::disallowedArrayOfParameterBlock);
+ getSink()->diagnose(varDecl, Diagnostics::disallowedArrayOfNonAddressableType, elementType);
return;
}
}
@@ -14738,6 +14745,16 @@ void validateStructuredBufferElementType(SemanticsVisitor* visitor, VarDeclBase*
Diagnostics::recursiveTypesFoundInStructuredBuffer,
elementType);
}
+
+ // Check if the element type is NonAddressable
+ TypeTag elementTags = visitor->getTypeTags(elementType);
+ if ((int)elementTags & (int)TypeTag::NonAddressable)
+ {
+ visitor->getSink()->diagnose(
+ varDecl->loc,
+ Diagnostics::nonAddressableTypeInStructuredBuffer,
+ elementType);
+ }
}
void diagnoseMissingCapabilityProvenance(
diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h
index 840192a50..20d15a2ef 100644
--- a/source/slang/slang-diagnostic-defs.h
+++ b/source/slang/slang-diagnostic-defs.h
@@ -661,8 +661,14 @@ DIAGNOSTIC(30025, Error, invalidArraySize, "array size must be non-negative.")
DIAGNOSTIC(
30027,
Error,
- disallowedArrayOfParameterBlock,
- "Arrays of ParameterBlock are not allowed")
+ disallowedArrayOfNonAddressableType,
+ "Arrays of non-addressable type '$0' are not allowed")
+
+DIAGNOSTIC(
+ 30028,
+ Error,
+ nonAddressableTypeInStructuredBuffer,
+ "'$0' is non-addressable and cannot be used in StructuredBuffer")
DIAGNOSTIC(
30029,
Error,
diff --git a/tests/diagnostics/array-of-struct-with-parameterblock.slang b/tests/diagnostics/array-of-struct-with-parameterblock.slang
new file mode 100644
index 000000000..07ca3a50f
--- /dev/null
+++ b/tests/diagnostics/array-of-struct-with-parameterblock.slang
@@ -0,0 +1,44 @@
+// Test that arrays of structs containing ParameterBlocks are properly diagnosed
+// with error 30027 instead of causing a compiler crash
+
+//TEST:SIMPLE(filecheck=CHECK): -target spirv
+
+// A struct that contains a ParameterBlock member
+struct MyStruct
+{
+ ParameterBlock<IMyInterface> pb;
+ int data;
+}
+
+interface IMyInterface
+{
+ int getValue();
+}
+
+[shader("compute")]
+[numthreads(1, 1, 1)]
+void computeMain()
+{
+ // CHECK: ([[# @LINE+1]]): error 30027:
+ MyStruct arr[2];
+
+ // Also test with dynamic arrays
+ // CHECK: ([[# @LINE+1]]): error 30027:
+ MyStruct dynamicArr[];
+}
+
+// Test nested structs as well
+struct OuterStruct
+{
+ MyStruct inner;
+ float value;
+}
+
+[shader("compute")]
+[numthreads(1, 1, 1)]
+void computeMain2()
+{
+ // Nested struct containing ParameterBlock should also trigger the error
+ // CHECK: ([[# @LINE+1]]): error 30027:
+ OuterStruct nestedArr[3];
+}
diff --git a/tests/diagnostics/array-of-struct-with-unbounded.slang b/tests/diagnostics/array-of-struct-with-unbounded.slang
new file mode 100644
index 000000000..f3deda494
--- /dev/null
+++ b/tests/diagnostics/array-of-struct-with-unbounded.slang
@@ -0,0 +1,20 @@
+// Test that arrays of structs containing unbounded arrays are not allowed
+
+//TEST:SIMPLE(filecheck=CHECK): -target spirv -allow-glsl -stage compute -entry computeMain
+
+// Struct containing unbounded array (must be last member)
+struct StructWithUnbounded
+{
+ float value;
+ int data[]; // Unbounded array must be last member
+}
+
+// Array of struct containing unbounded array - should error (struct is NonAddressable)
+//CHECK: ([[# @LINE+1]]): error 30027
+StructWithUnbounded myArray[2];
+
+[numthreads(1, 1, 1)]
+void computeMain()
+{
+ // Empty - we're just testing the declarations
+} \ No newline at end of file
diff --git a/tests/diagnostics/array-of-unbounded-arrays.slang b/tests/diagnostics/array-of-unbounded-arrays.slang
new file mode 100644
index 000000000..0a5c42ce0
--- /dev/null
+++ b/tests/diagnostics/array-of-unbounded-arrays.slang
@@ -0,0 +1,13 @@
+// Test that arrays of unbounded arrays are not allowed
+
+//TEST:SIMPLE(filecheck=CHECK): -target spirv -allow-glsl -stage compute -entry computeMain
+
+// Array of unbounded arrays - should error (unbounded arrays are NonAddressable)
+//CHECK: ([[# @LINE+1]]): error 30027
+int arrayOfUnbounded[3][];
+
+[numthreads(1, 1, 1)]
+void computeMain()
+{
+ // Empty - we're just testing the declaration
+} \ No newline at end of file
diff --git a/tests/diagnostics/array-parameterblock-array-in-struct.slang b/tests/diagnostics/array-parameterblock-array-in-struct.slang
new file mode 100644
index 000000000..832c90925
--- /dev/null
+++ b/tests/diagnostics/array-parameterblock-array-in-struct.slang
@@ -0,0 +1,22 @@
+// Test that structs containing arrays of ParameterBlocks are also NonAddressable
+// and therefore cannot be used in arrays
+
+//TEST:SIMPLE(filecheck=CHECK): -target spirv -allow-glsl -stage compute -entry computeMain
+//TEST_DISABLED:SIMPLE(filecheck=CHECK): -target glsl -allow-glsl -stage compute -entry computeMain
+
+// Test case: struct containing array of ParameterBlock
+struct StructWithParameterBlockArray
+{
+ ParameterBlock<Texture2D> blocks[2]; // Array of ParameterBlocks
+ int value;
+}
+
+// This should trigger error 30027 - arrays of NonAddressable types are not allowed
+//CHECK: ([[# @LINE+1]]): error 30027
+StructWithParameterBlockArray myArray[3]; // Array of struct containing ParameterBlock array
+
+[numthreads(1, 1, 1)]
+void computeMain()
+{
+ // Empty - we're just testing the declaration
+} \ No newline at end of file
diff --git a/tests/diagnostics/array-parameterblock-deeply-nested.slang b/tests/diagnostics/array-parameterblock-deeply-nested.slang
new file mode 100644
index 000000000..86dcf913b
--- /dev/null
+++ b/tests/diagnostics/array-parameterblock-deeply-nested.slang
@@ -0,0 +1,20 @@
+//DIAGNOSTIC_TEST:SIMPLE(filecheck=CHECK):
+
+// Test: Array of deeply nested struct containing ParameterBlock - should error
+
+struct DeeplyNested
+{
+ struct Inner
+ {
+ ParameterBlock<int> deepPB;
+ }
+ Inner inner;
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+}
+
+//CHECK: ([[# @LINE+1]]): error 30027
+uniform DeeplyNested arrayOfDeeplyNested[4]; \ No newline at end of file
diff --git a/tests/diagnostics/array-parameterblock.slang b/tests/diagnostics/array-parameterblock-direct.slang
index 566694e37..b94aa4f60 100644
--- a/tests/diagnostics/array-parameterblock.slang
+++ b/tests/diagnostics/array-parameterblock-direct.slang
@@ -1,10 +1,11 @@
//DIAGNOSTIC_TEST:SIMPLE(filecheck=CHECK):
+// Test: Direct array of ParameterBlock - should error
+
[numthreads(4, 1, 1)]
void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
{
}
-
-//CHECK: ([[# @LINE+1]]): error 30027
-uniform ParameterBlock<float> qs[2];
+//CHECK: ([[# @LINE+1]]): error 30027
+uniform ParameterBlock<float> qs[2]; \ No newline at end of file
diff --git a/tests/diagnostics/array-parameterblock-nested.slang b/tests/diagnostics/array-parameterblock-nested.slang
new file mode 100644
index 000000000..f2c30ea88
--- /dev/null
+++ b/tests/diagnostics/array-parameterblock-nested.slang
@@ -0,0 +1,26 @@
+//DIAGNOSTIC_TEST:SIMPLE(filecheck=CHECK):
+
+// Test: Array of nested struct containing ParameterBlock - should error
+
+struct Inner
+{
+ ParameterBlock<float> pb;
+}
+
+struct NestedStruct
+{
+ Inner nested;
+ float value;
+}
+
+RWStructuredBuffer<float> outputBuffer;
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ // Force usage of the array to prevent optimization
+ outputBuffer[dispatchThreadID.x] = arrayOfNestedStruct[dispatchThreadID.x % 2].nested.pb;
+}
+
+//CHECK: ([[# @LINE+1]]): error 30027
+uniform NestedStruct arrayOfNestedStruct[2]; \ No newline at end of file
diff --git a/tests/diagnostics/array-parameterblock-struct.slang b/tests/diagnostics/array-parameterblock-struct.slang
new file mode 100644
index 000000000..5723ce709
--- /dev/null
+++ b/tests/diagnostics/array-parameterblock-struct.slang
@@ -0,0 +1,21 @@
+//DIAGNOSTIC_TEST:SIMPLE(filecheck=CHECK):
+
+// Test: Array of struct containing ParameterBlock - should error
+
+struct StructWithParameterBlock
+{
+ ParameterBlock<float> pb;
+ int other;
+}
+
+RWStructuredBuffer<float> outputBuffer;
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ // Force usage of the array to prevent optimization
+ outputBuffer[dispatchThreadID.x] = arrayOfStructWithPB[dispatchThreadID.x % 3].pb;
+}
+
+//CHECK: ([[# @LINE+1]]): error 30027
+uniform StructWithParameterBlock arrayOfStructWithPB[3]; \ No newline at end of file
diff --git a/tests/diagnostics/nested-struct-with-unbounded.slang b/tests/diagnostics/nested-struct-with-unbounded.slang
new file mode 100644
index 000000000..4271ad9ab
--- /dev/null
+++ b/tests/diagnostics/nested-struct-with-unbounded.slang
@@ -0,0 +1,31 @@
+// Test that arrays and StructuredBuffers of nested structs with unbounded arrays are not allowed
+
+//TEST:SIMPLE(filecheck=CHECK): -target spirv -allow-glsl -stage compute -entry computeMain
+
+// Struct containing unbounded array (must be last member)
+struct StructWithUnbounded
+{
+ float value;
+ int data[]; // Unbounded array must be last member
+}
+
+// Nested case
+struct NestedUnbounded
+{
+ int id;
+ StructWithUnbounded nested; // Struct with unbounded array member
+}
+
+// Array of nested struct - should error
+//CHECK: ([[# @LINE+1]]): error 30027
+NestedUnbounded nestedArray[5];
+
+// StructuredBuffer of nested struct - should error
+//CHECK: ([[# @LINE+1]]): error 30028
+StructuredBuffer<NestedUnbounded> nestedBuffer;
+
+[numthreads(1, 1, 1)]
+void computeMain()
+{
+ // Empty - we're just testing the declarations
+} \ No newline at end of file
diff --git a/tests/diagnostics/structured-buffer-parameterblock.slang b/tests/diagnostics/structured-buffer-parameterblock.slang
new file mode 100644
index 000000000..1fd2b52c8
--- /dev/null
+++ b/tests/diagnostics/structured-buffer-parameterblock.slang
@@ -0,0 +1,43 @@
+// Test that StructuredBuffer of ParameterBlock (NonAddressable type) is not allowed
+
+//TEST:SIMPLE(filecheck=CHECK): -target spirv -allow-glsl -stage compute -entry computeMain
+
+// Direct ParameterBlock in StructuredBuffer - should error
+//CHECK: ([[# @LINE+1]]): error 30028
+StructuredBuffer<ParameterBlock<Texture2D>> myBuffer1;
+
+// Struct containing ParameterBlock in StructuredBuffer - should error
+struct StructWithParameterBlock
+{
+ ParameterBlock<Texture2D> block;
+ int value;
+}
+
+//CHECK: ([[# @LINE+1]]): error 30028
+StructuredBuffer<StructWithParameterBlock> myBuffer2;
+
+// Nested struct containing ParameterBlock - should error
+struct NestedStruct
+{
+ StructWithParameterBlock nested;
+ float data;
+}
+
+//CHECK: ([[# @LINE+1]]): error 30028
+StructuredBuffer<NestedStruct> myBuffer3;
+
+// Struct containing array of ParameterBlock - should error
+struct StructWithParameterBlockArray
+{
+ ParameterBlock<Texture2D> blocks[2];
+ int value;
+}
+
+//CHECK: ([[# @LINE+1]]): error 30028
+StructuredBuffer<StructWithParameterBlockArray> myBuffer4;
+
+[numthreads(1, 1, 1)]
+void computeMain()
+{
+ // Empty - we're just testing the declarations
+} \ No newline at end of file
diff --git a/tests/diagnostics/structuredbuffer-with-unbounded.slang b/tests/diagnostics/structuredbuffer-with-unbounded.slang
new file mode 100644
index 000000000..7c2a3bd47
--- /dev/null
+++ b/tests/diagnostics/structuredbuffer-with-unbounded.slang
@@ -0,0 +1,20 @@
+// Test that StructuredBuffer of struct with unbounded array is not allowed
+
+//TEST:SIMPLE(filecheck=CHECK): -target spirv -allow-glsl -stage compute -entry computeMain
+
+// Struct containing unbounded array (must be last member)
+struct StructWithUnbounded
+{
+ float value;
+ int data[]; // Unbounded array must be last member
+}
+
+// StructuredBuffer of struct with unbounded array - should error
+//CHECK: ([[# @LINE+1]]): error 30028
+StructuredBuffer<StructWithUnbounded> myBuffer;
+
+[numthreads(1, 1, 1)]
+void computeMain()
+{
+ // Empty - we're just testing the declarations
+} \ No newline at end of file
diff --git a/tests/diagnostics/unbounded-array-nonaddressable.slang b/tests/diagnostics/unbounded-array-nonaddressable.slang
new file mode 100644
index 000000000..19a870594
--- /dev/null
+++ b/tests/diagnostics/unbounded-array-nonaddressable.slang
@@ -0,0 +1,46 @@
+// Test that unbounded arrays are NonAddressable and cannot be used in arrays
+
+//TEST:SIMPLE(filecheck=CHECK): -target spirv -allow-glsl -stage compute -entry computeMain
+
+// Unbounded array itself is fine
+int unboundedArray[];
+
+// Array of unbounded arrays - should error (unbounded arrays are NonAddressable)
+//CHECK: ([[# @LINE+1]]): error 30027
+int arrayOfUnbounded[3][];
+
+// Struct containing unbounded array (must be last member)
+struct StructWithUnbounded
+{
+ float value;
+ int data[]; // Unbounded array must be last member
+}
+
+// Array of struct containing unbounded array - should error (struct is NonAddressable)
+//CHECK: ([[# @LINE+1]]): error 30027
+StructWithUnbounded myArray[2];
+
+// StructuredBuffer of struct with unbounded array - should error
+//CHECK: ([[# @LINE+1]]): error 30028
+StructuredBuffer<StructWithUnbounded> myBuffer;
+
+// Nested case
+struct NestedUnbounded
+{
+ int id;
+ StructWithUnbounded nested; // Struct with unbounded array member
+}
+
+// Array of nested struct - should error
+//CHECK: ([[# @LINE+1]]): error 30027
+NestedUnbounded nestedArray[5];
+
+// StructuredBuffer of nested struct - should error
+//CHECK: ([[# @LINE+1]]): error 30028
+StructuredBuffer<NestedUnbounded> nestedBuffer;
+
+[numthreads(1, 1, 1)]
+void computeMain()
+{
+ // Empty - we're just testing the declarations
+} \ No newline at end of file