[clang] [Sema][HLSL] Reject empty initializer lists for LHS containing an incomplete array. (PR #176075)
Joshua Batista via cfe-commits
cfe-commits at lists.llvm.org
Wed Jan 14 18:26:53 PST 2026
https://github.com/bob80905 updated https://github.com/llvm/llvm-project/pull/176075
>From e84cf41ea23932b04820304e7e91d677a87af68d Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Wed, 14 Jan 2026 17:45:29 -0800
Subject: [PATCH 1/2] first attempt
---
.../clang/Basic/DiagnosticSemaKinds.td | 2 +
clang/lib/Sema/SemaHLSL.cpp | 47 +++++++++
.../SemaHLSL/Language/EmptyInitializers.hlsl | 96 +++++++++++++++++++
3 files changed, 145 insertions(+)
create mode 100644 clang/test/SemaHLSL/Language/EmptyInitializers.hlsl
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 5cbbc7d130c99..1f7a7a3640e27 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -13354,6 +13354,8 @@ def err_hlsl_pointers_unsupported : Error<
"%select{pointers|references}0 are unsupported in HLSL">;
def err_hlsl_missing_resource_class : Error<"HLSL resource needs to have [[hlsl::resource_class()]] attribute">;
def err_hlsl_attribute_needs_intangible_type: Error<"attribute %0 can be used only on HLSL intangible type %1">;
+def err_hlsl_incomplete_array_non_resource : Error<
+ "incomplete array type %0 is only permitted for resource types in HLSL">;
def err_hlsl_incorrect_num_initializers: Error<
"too %select{few|many}0 initializers in list for type %1 "
"(expected %2 but found %3)">;
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index f15b274a65a53..831b7c83d12e8 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -4737,6 +4737,40 @@ class InitListTransformer {
};
} // namespace
+// Recursively detect any incomplete array anywhere in the type graph,
+// including arrays, struct fields, and base classes.
+static bool containsIncompleteArrayType(QualType Ty) {
+ Ty = Ty.getCanonicalType();
+
+ // Array types
+ if (const ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
+ if (isa<IncompleteArrayType>(AT))
+ return true;
+ return containsIncompleteArrayType(AT->getElementType());
+ }
+
+ // Record (struct/class) types
+ if (const auto *RT = Ty->getAs<RecordType>()) {
+ const RecordDecl *RD = RT->getDecl();
+
+ // Walk base classes (for C++ / HLSL structs with inheritance)
+ if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
+ for (const CXXBaseSpecifier &Base : CXXRD->bases()) {
+ if (containsIncompleteArrayType(Base.getType()))
+ return true;
+ }
+ }
+
+ // Walk fields
+ for (const FieldDecl *F : RD->fields()) {
+ if (containsIncompleteArrayType(F->getType()))
+ return true;
+ }
+ }
+
+ return false;
+}
+
bool SemaHLSL::transformInitList(const InitializedEntity &Entity,
InitListExpr *Init) {
// If the initializer is a scalar, just return it.
@@ -4763,6 +4797,19 @@ bool SemaHLSL::transformInitList(const InitializedEntity &Entity,
if (ExpectedSize == 0 && ActualSize == 0)
return true;
+ // Reject empty initializer if *any* incomplete array exists structurally
+ if (ActualSize == 0 && containsIncompleteArrayType(Entity.getType())) {
+ QualType InitTy = Entity.getType().getNonReferenceType();
+ if (InitTy.hasAddressSpace())
+ InitTy = SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);
+
+ SemaRef.Diag(Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
+ << /*TooManyOrFew=*/(int)(ExpectedSize < ActualSize) << InitTy
+ << /*ExpectedSize=*/ExpectedSize << /*ActualSize=*/ActualSize;
+ return false;
+ }
+
+ // Only after validating legality do we infer size
// For incomplete arrays it is completely arbitrary to choose whether we think
// the user intended fewer or more elements. This implementation assumes that
// the user intended more, and errors that there are too few initializers to
diff --git a/clang/test/SemaHLSL/Language/EmptyInitializers.hlsl b/clang/test/SemaHLSL/Language/EmptyInitializers.hlsl
new file mode 100644
index 0000000000000..8a3406e92843a
--- /dev/null
+++ b/clang/test/SemaHLSL/Language/EmptyInitializers.hlsl
@@ -0,0 +1,96 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - -fsyntax-only %s -verify
+
+//===----------------------------------------------------------------------===//
+// Baseline: struct with direct incomplete array
+//===----------------------------------------------------------------------===//
+struct S {
+ int a[];
+};
+
+export void fn(int A) {
+ // expected-error at +1{{too few initializers in list for type 'S' (expected 1 but found 0)}}
+ S s = {};
+}
+
+//===----------------------------------------------------------------------===//
+// Multidimensional arrays with at least one incomplete dimension
+//===----------------------------------------------------------------------===//
+export void fn_multi_arrays() {
+ // Incomplete outer dimension
+ // expected-error at +1{{too few initializers in list for type 'int[][2]' (expected 2 but found 0)}}
+ int a[][2] = {};
+
+ // Incomplete middle dimension
+ // expected-error at +1{{array has incomplete element type 'int[][3]'}}
+ int b[2][][3] = {};
+
+ // Incomplete inner dimension
+ // expected-error at +1{{array has incomplete element type 'int[]'}}
+ int c[2][3][] = {};
+}
+
+//===----------------------------------------------------------------------===//
+// Struct containing multidimensional incomplete arrays
+//===----------------------------------------------------------------------===//
+struct S2 {
+ int m[][4];
+};
+
+export void fn_struct_multi() {
+ // expected-error at +1{{too few initializers in list for type 'S2' (expected 1 but found 0)}}
+ S2 s = {};
+}
+
+//===----------------------------------------------------------------------===//
+// Nested structs with incomplete arrays
+//===----------------------------------------------------------------------===//
+struct Inner {
+ int x[];
+};
+
+struct Outer {
+ Inner I;
+};
+
+export void fn_nested_struct() {
+ // expected-error at +1{{too few initializers in list for type 'Outer' (expected 1 but found 0)}}
+ Outer o = {};
+}
+
+//===----------------------------------------------------------------------===//
+// Base-class inheritance containing incomplete arrays
+//===----------------------------------------------------------------------===//
+struct Base {
+ int b[];
+};
+
+// expected-error at +1{{base class 'Base' has a flexible array member}}
+struct Derived : Base {
+ int d;
+};
+
+export void fn_derived() {
+ // expected-error at +1{{too few initializers in list for type 'Derived' (expected 1 but found 0)}}
+ Derived d = {};
+}
+
+//===----------------------------------------------------------------------===//
+// Deep inheritance chain with incomplete array in base
+//===----------------------------------------------------------------------===//
+struct Base2 {
+ int x[];
+};
+
+// expected-error at +1{{base class 'Base2' has a flexible array member}}
+struct Mid : Base2 {
+ int y;
+};
+
+struct Final : Mid {
+ int z;
+};
+
+export void fn_deep_inheritance() {
+ // expected-error at +1{{too few initializers in list for type 'Final' (expected 2 but found 0)}}
+ Final f = {};
+}
>From de339fd9f15f6f89775beeae07c883ac64d99f9b Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Wed, 14 Jan 2026 18:26:18 -0800
Subject: [PATCH 2/2] remove unnecessary diagnostic
---
clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 --
1 file changed, 2 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 1f7a7a3640e27..5cbbc7d130c99 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -13354,8 +13354,6 @@ def err_hlsl_pointers_unsupported : Error<
"%select{pointers|references}0 are unsupported in HLSL">;
def err_hlsl_missing_resource_class : Error<"HLSL resource needs to have [[hlsl::resource_class()]] attribute">;
def err_hlsl_attribute_needs_intangible_type: Error<"attribute %0 can be used only on HLSL intangible type %1">;
-def err_hlsl_incomplete_array_non_resource : Error<
- "incomplete array type %0 is only permitted for resource types in HLSL">;
def err_hlsl_incorrect_num_initializers: Error<
"too %select{few|many}0 initializers in list for type %1 "
"(expected %2 but found %3)">;
More information about the cfe-commits
mailing list