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 <[email protected]> Date: Wed, 14 Jan 2026 17:45:29 -0800 Subject: [PATCH 1/3] 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@+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@+1{{too few initializers in list for type 'int[][2]' (expected 2 but found 0)}} + int a[][2] = {}; + + // Incomplete middle dimension + // expected-error@+1{{array has incomplete element type 'int[][3]'}} + int b[2][][3] = {}; + + // Incomplete inner dimension + // expected-error@+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@+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@+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@+1{{base class 'Base' has a flexible array member}} +struct Derived : Base { + int d; +}; + +export void fn_derived() { + // expected-error@+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@+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@+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 <[email protected]> Date: Wed, 14 Jan 2026 18:26:18 -0800 Subject: [PATCH 2/3] 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)">; >From db6199f2d7fd2e9fa13373a621dfabe6c59d54a6 Mon Sep 17 00:00:00 2001 From: Joshua Batista <[email protected]> Date: Fri, 16 Jan 2026 16:06:44 -0800 Subject: [PATCH 3/3] fix comment grammar / phrasing --- clang/lib/Sema/SemaHLSL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 831b7c83d12e8..4d31e26d56e6b 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -4809,7 +4809,7 @@ bool SemaHLSL::transformInitList(const InitializedEntity &Entity, return false; } - // Only after validating legality do we infer size + // We infer size after validating legality. // 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 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
