summaryrefslogtreecommitdiffstats
path: root/source/slang
diff options
context:
space:
mode:
authorEllie Hermaszewska <ellieh@nvidia.com>2025-10-13 23:14:45 +0900
committerGitHub <noreply@github.com>2025-10-13 22:14:45 +0800
commit96df31a9fa53e3d897a2b7c4eef021f37f421c91 (patch)
tree46cfb983265ce63b619da3b18004d2c163371d2c /source/slang
parentf5a3a6dc6a98d22964154f809f9e0dcae30ab67f (diff)
Fix segfault on arrays of structs containing parameter blocks (#8555)
Closes https://github.com/shader-slang/slang/issues/8154 However there is further design work to do on implementing the "NonAddressableType" suggestion
Diffstat (limited to 'source/slang')
-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
5 files changed, 41 insertions, 6 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,