https://github.com/akash-manna-sky created 
https://github.com/llvm/llvm-project/pull/219817

Fixes #213855

When an array type is formed while its element type is still incomplete, 
`BuildArrayType` can only check the element count; the element size isn't known 
yet. That's what happens with `S<Size> A[Size]` here: `S<4294967173>` is an 
uninstantiated specialization when the field type is built and only gets 
instantiated afterwards, and nothing rechecked the array after that. A ~2^67 
byte array type survived as a valid field, and the first size query (the `this` 
alignment check while defining the implicit default constructor) tripped the 
overflow assertion in `getTypeInfoImpl`. The narrowing and parse errors in the 
report are incidental — `SS<4294967173u>` alone crashes, and so does the 
non-template version with a forward-declared element type that's defined later.

`RequireCompleteType` is where Sema goes before computing a size, and it's also 
where the element type gets instantiated in the template case, so the check now 
lives there too: once a constant array type is complete, its total size is 
checked against the same limit `BuildArrayType` uses and rejected with the same 
"array is too large" error, which leaves the field or variable invalid so no 
constructor or layout code ever sees it. Uninitialized variable definitions 
only required the base element type to be complete, so they now require the 
whole array type as well, matching what initialized ones already did.

LLM tools were used for this contribution. I've reviewed, built, and tested the 
change myself before pushing to GitHub.


>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

Reply via email to