https://github.com/akash-manna-sky updated https://github.com/llvm/llvm-project/pull/219817
>From 0173717b091555434bd5b96ced13cd1d638d0132 Mon Sep 17 00:00:00 2001 From: Akash Manna <[email protected]> Date: Sun, 30 Aug 2026 21:15:11 +0530 Subject: [PATCH] [clang][Sema] Recheck array size once the element type is complete BuildArrayType can only check the element count when the element type is still incomplete, e.g. an uninstantiated class template specialization, and nothing revalidated the array once the element type was completed. An array whose total size overflows could therefore end up as a valid field or variable, and the first size query asserted in ASTContext::getTypeInfoImpl. Perform the check in RequireCompleteType once a constant array type is complete, using the same limit and diagnostic as BuildArrayType, and require the whole array type rather than just the base element type to be complete for uninitialized variable definitions. Fixes #213855 --- clang/docs/ReleaseNotes.md | 6 +++++ clang/include/clang/Sema/Sema.h | 3 ++- clang/lib/Sema/SemaDecl.cpp | 7 ++++++ clang/lib/Sema/SemaType.cpp | 36 ++++++++++++++++++++++++++++ clang/test/SemaTemplate/GH213855.cpp | 33 +++++++++++++++++++++++++ 5 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 clang/test/SemaTemplate/GH213855.cpp diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index bdbabf2cd98d0..5de035d9a78a6 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -551,6 +551,12 @@ features cannot lower the translation-unit ABI level; inside a union caused the union to be treated as a polymorphic class. (#GH213854) +- Fixed an assertion failure when an array whose element type was still + incomplete when the array type was formed (for example, an array of a class + template specialization that is only instantiated later) turned out to be too + large once the element type was completed. Clang now diagnoses the oversized + array instead of asserting. (#GH213855) + #### Bug Fixes to AST Handling - Fixed a non-deterministic ordering of unused local typedefs that made diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 4650bd53775f7..05ad0eb1ab3e5 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -15601,7 +15601,8 @@ class Sema final : public SemaBase { /// this routine then attempts to perform class template /// instantiation. If instantiation fails, or if @p T is incomplete /// and cannot be completed, issues the diagnostic @p diag (giving it - /// the type @p T) and returns true. + /// the type @p T) and returns true. The same applies to an array type + /// that turns out to be too large once its element type is complete. /// /// @param Loc The location in the source that the incomplete type /// diagnostic should refer to. diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 07c6157ab8f31..7a1f79a64c841 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -14857,6 +14857,13 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) { Var->setInvalidDecl(); return; } + // Completing the element type may reveal that the array is too large. + if (Type->isConstantArrayType() && + RequireCompleteType(Var->getLocation(), Type, + diag::err_typecheck_decl_incomplete_type)) { + Var->setInvalidDecl(); + return; + } } else { return; } diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index ad9204b12524b..270cf22ba4369 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -9687,6 +9687,28 @@ static void assignInheritanceModel(Sema &S, CXXRecordDecl *RD) { } } +/// Return the (possibly nested) constant array type in \p T whose size cannot +/// be represented, if any. BuildArrayType can only check the element count if +/// the element type is still incomplete when the array type is formed. +static const ConstantArrayType *findArrayTypeTooLarge(const ASTContext &Context, + QualType T) { + const auto *CAT = dyn_cast<ConstantArrayType>(T.getCanonicalType()); + if (!CAT) + return nullptr; + + // Check nested arrays from the inside out. + QualType ElementType = CAT->getElementType(); + if (const ConstantArrayType *Inner = + findArrayTypeTooLarge(Context, ElementType)) + return Inner; + + if (ConstantArrayType::getNumAddressingBits(Context, ElementType, + CAT->getSize()) > + ConstantArrayType::getMaxSizeBits(Context)) + return CAT; + return nullptr; +} + bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser *Diagnoser) { @@ -9738,6 +9760,20 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, /*Recover*/ TreatAsComplete); return !TreatAsComplete; } + + // The element type may have been incomplete when the array type was + // formed, in which case BuildArrayType could not check the array's size. + if (T->isConstantArrayType() && !T->isDependentType() && + !T->isVariablyModifiedType() && !T->isUndeducedType()) { + if (const ConstantArrayType *CAT = findArrayTypeTooLarge(Context, T)) { + if (Diagnoser) + Diag(Loc, diag::err_array_too_large) + << toString(CAT->getSize(), 10, /*Signed=*/false, + /*formatAsCLiteral=*/false, /*UpperCase=*/false, + /*InsertSeparators=*/true); + return true; + } + } return false; } diff --git a/clang/test/SemaTemplate/GH213855.cpp b/clang/test/SemaTemplate/GH213855.cpp new file mode 100644 index 0000000000000..de4bea8b05907 --- /dev/null +++ b/clang/test/SemaTemplate/GH213855.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-linux-gnu %s + +// An array whose element type is incomplete when the array type is formed can +// only have its size checked once the element type is completed. + +namespace GH213855 { +template <unsigned Size> struct S : public CBdVfsImpl { // expected-error {{expected class name}} + double A[Size]; +}; +template <unsigned Size> struct SS { + S<Size> A[Size]; // expected-error {{array is too large (4'294'967'173 elements)}} +void foo() { SS<-123> ss; } // expected-error {{non-type template argument evaluates to -123, which cannot be narrowed to type 'unsigned int'}} \ + // expected-note {{in instantiation of template class 'GH213855::SS<4294967173>' requested here}} +}; +} // namespace GH213855 + +namespace array_variable { +template <unsigned Size> struct S { double A[Size]; }; +S<4294967173u> arr[4294967173u]; // expected-error {{array is too large (4'294'967'173 elements)}} +} // namespace array_variable + +namespace incomplete_element_type { +struct Incomplete; +extern Incomplete ok[2]; +extern Incomplete arr[4294967173]; +extern Incomplete arr2[2][4294967173]; +struct Incomplete { double A[4294967173]; }; +Incomplete arr3[4294967173]; // expected-error {{array is too large (4'294'967'173 elements)}} + +unsigned long n0 = sizeof(ok); +unsigned long n1 = sizeof(arr); // expected-error {{array is too large (4'294'967'173 elements)}} +unsigned long n2 = sizeof(arr2); // expected-error {{array is too large (4'294'967'173 elements)}} +} // namespace incomplete_element_type _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
