https://github.com/maxmanolov updated 
https://github.com/llvm/llvm-project/pull/205503

>From 268c083e3fa791cb184989f6a733a0f3580fee85 Mon Sep 17 00:00:00 2001
From: Max Manolov <[email protected]>
Date: Wed, 24 Jun 2026 01:29:40 -0700
Subject: [PATCH 1/4] [clang][Sema] Avoid out-of-memory crash on huge
 designated initializer indices

---
 clang/docs/ReleaseNotes.md                |  1 +
 clang/lib/Sema/SemaInit.cpp               | 19 +++++++++++++++++++
 clang/test/Sema/designated-initializers.c | 19 +++++++++++++++++++
 3 files changed, 39 insertions(+)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 09ec3594ab31f..58c81474e294c 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -720,6 +720,7 @@ latest release, please see the [Clang Web 
Site](https://clang.llvm.org) or the
 - Fixed an assertion where we improperly handled implicit conversions to 
integral types from an atomic-type with a conversion function. (#GH201770)
 - Fixed assertion failures involving code completion with delayed default 
arguments and exception specifications. (#GH200879)
 - Fixed a regression where calling a function that takes a class-type 
parameter by value inside `decltype` of a concept could be incorrectly rejected 
when used as a non-type template argument. (#GH175831)
+- Clang now diagnoses inferred-size arrays with huge designated initializer 
indices instead of attempting to allocate an enormous initializer list and 
crashing with an out-of-memory error. (#GH205472)
 
 #### Bug Fixes to Compiler Builtins
 
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index dad9c8c972dd9..ba7aeac2dc9ee 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -39,6 +39,7 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/raw_ostream.h"
+#include <limits>
 
 using namespace clang;
 
@@ -3375,6 +3376,24 @@ InitListChecker::CheckDesignatedInitializer(const 
InitializedEntity &Entity,
     DesignatedEndIndex.setIsUnsigned(true);
   }
 
+  // The semantic form of an initializer list stores one pointer for every
+  // array element, including the elements omitted before a designator. Avoid
+  // creating an initializer list whose dense representation is too large for
+  // an unsigned-sized allocation.
+  constexpr unsigned MaxInitListElements =
+      std::numeric_limits<unsigned>::max() / sizeof(Stmt *);
+  if (DesignatedEndIndex.uge(MaxInitListElements)) {
+    if (!VerifyOnly) {
+      llvm::APSInt NumInits =
+          DesignatedEndIndex.extend(DesignatedEndIndex.getBitWidth() + 1);
+      ++NumInits;
+      SemaRef.Diag(IndexExpr->getBeginLoc(), diag::err_array_too_large)
+          << toString(NumInits, 10) << IndexExpr->getSourceRange();
+    }
+    ++Index;
+    return true;
+  }
+
   bool IsStringLiteralInitUpdate =
       StructuredList && StructuredList->isStringLiteralInit();
   if (IsStringLiteralInitUpdate && VerifyOnly) {
diff --git a/clang/test/Sema/designated-initializers.c 
b/clang/test/Sema/designated-initializers.c
index 11dc3a2308dee..179b8855fe1c8 100644
--- a/clang/test/Sema/designated-initializers.c
+++ b/clang/test/Sema/designated-initializers.c
@@ -4,6 +4,25 @@ int complete_array_from_init[] = { 1, 2, [10] = 5, 1, 2, [5] = 
2, 6 };
 
 int complete_array_from_init_check[((sizeof(complete_array_from_init) / 
sizeof(int)) == 13)? 1 : -1];
 
+int normal_sparse_designated_initializer[] = { [3] = 1 };
+typedef char normal_sparse_designated_initializer_size[
+    sizeof(normal_sparse_designated_initializer) / sizeof(int) == 4 ? 1 : -1];
+
+struct LargeDesignatedInitializerPoint {
+  int x, y;
+};
+
+void large_designated_initializer(void) {
+  static struct LargeDesignatedInitializerPoint pts[] = {
+      [0x80000000] = { .x = 10, .y = 20 }, // expected-error {{array is too 
large (2147483649 elements)}}
+      [0x80000001] = { .x = 30, .y = 40 }  // expected-error {{array is too 
large (2147483650 elements)}}
+  };
+}
+
+int large_fixed_designated_initializer[4] = {
+  [0x80000000] = 1, // expected-error {{array designator index (2147483648) 
exceeds array bounds (4)}}
+};
+
 int iarray[10] = {
   [0] = 1,
   [1 ... 5] = 2,

>From 30865329a0aa5d2c5dd745a745afa351e970a3e4 Mon Sep 17 00:00:00 2001
From: Max Manolov <[email protected]>
Date: Mon, 20 Jul 2026 14:43:32 -0700
Subject: [PATCH 2/4] Make initializer list element limit configurable

---
 clang/docs/ReleaseNotes.md                    |  6 ++++-
 clang/docs/UsersManual.rst                    |  8 ++++++
 clang/include/clang/Basic/LangOptions.def     |  2 ++
 clang/include/clang/Options/Options.td        |  6 +++++
 clang/lib/Driver/ToolChains/Clang.cpp         |  1 +
 clang/lib/Sema/SemaInit.cpp                   | 25 +++++++++++++------
 clang/test/Driver/max-init-list-elements.c    |  5 ++++
 .../test/Sema/designated-initializer-limit.c  | 24 ++++++++++++++++++
 clang/test/Sema/designated-initializers.c     |  2 ++
 9 files changed, 70 insertions(+), 9 deletions(-)
 create mode 100644 clang/test/Driver/max-init-list-elements.c
 create mode 100644 clang/test/Sema/designated-initializer-limit.c

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 58c81474e294c..f4481cf3729b3 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -720,7 +720,11 @@ latest release, please see the [Clang Web 
Site](https://clang.llvm.org) or the
 - Fixed an assertion where we improperly handled implicit conversions to 
integral types from an atomic-type with a conversion function. (#GH201770)
 - Fixed assertion failures involving code completion with delayed default 
arguments and exception specifications. (#GH200879)
 - Fixed a regression where calling a function that takes a class-type 
parameter by value inside `decltype` of a concept could be incorrectly rejected 
when used as a non-type template argument. (#GH175831)
-- Clang now diagnoses inferred-size arrays with huge designated initializer 
indices instead of attempting to allocate an enormous initializer list and 
crashing with an out-of-memory error. (#GH205472)
+- Clang now diagnoses inferred-size arrays with huge designated initializer
+  indices instead of attempting to allocate an enormous initializer list and
+  crashing with an out-of-memory error. The limit defaults to 1048576 dense
+  semantic initializer-list elements and can be adjusted with
+  `-fmax-init-list-elements=`. (#GH205472)
 
 #### Bug Fixes to Compiler Builtins
 
diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst
index 05a1ab7c2022a..5f0f5df6b8362 100644
--- a/clang/docs/UsersManual.rst
+++ b/clang/docs/UsersManual.rst
@@ -4241,6 +4241,14 @@ Controlling implementation limits
   Sets the limit for iterative calls to 'operator->' functions to N.  The
   default is 256.
 
+.. option:: -fmax-init-list-elements=N
+
+  Sets the maximum number of elements Clang may materialize for an array
+  initializer's dense semantic representation. An array designator with an
+  inclusive end index of N requires N + 1 elements. The default is 1048576.
+  The effective limit is also capped by a non-configurable internal
+  allocation-safety limit.
+
 .. _objc:
 
 Objective-C Language Features
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index d68784b7efbcd..77cb25fc70d50 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -389,6 +389,8 @@ LANGOPT(EnableNewConstInterp, 1, 
CLANG_USE_EXPERIMENTAL_CONST_INTERP, Benign,
         "enable the experimental new constant interpreter")
 LANGOPT(BracketDepth, 32, 256, Benign,
         "maximum bracket nesting depth")
+VALUE_LANGOPT(MaxInitListElements, 32, 1048576, Benign,
+              "maximum number of elements in a dense semantic initializer 
list")
 LANGOPT(NumLargeByValueCopy, 32, 0, Benign,
         "if non-zero, warn about parameter or return Warn if parameter/return 
value is larger in bytes than this setting. 0 is no check.")
 VALUE_LANGOPT(MSCompatibilityVersion, 32, 0, NotCompatible, "Microsoft Visual 
C/C++ Version")
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index c998446ac0a22..6897e2a6fec3a 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -1601,6 +1601,12 @@ def emit_sgf_symbol_labels_for_testing: Flag<["--"], 
"emit-sgf-symbol-labels-for
    Visibility<[CC1Option]>,
    MarshallingInfoFlag<FrontendOpts<"EmitSymbolGraphSymbolLabelsForTesting">>;
 def e : Separate<["-"], "e">, Flags<[LinkerInput]>, Group<Link_Group>;
+def fmax_init_list_elements_EQ :
+  Joined<["-"], "fmax-init-list-elements=">, Group<f_Group>,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Set the maximum number of elements Clang may materialize for an "
+           "array initializer's dense semantic representation">,
+  MarshallingInfoInt<LangOpts<"MaxInitListElements">, "1048576">;
 def fmax_tokens_EQ : Joined<["-"], "fmax-tokens=">, Group<f_Group>,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Max total number of preprocessed tokens for -Wmax-tokens.">,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index a3a3954bc464e..f0cb8b9060323 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6802,6 +6802,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
   Args.AddLastArg(CmdArgs, options::OPT_foperator_arrow_depth_EQ);
   Args.AddLastArg(CmdArgs, options::OPT_fconstexpr_depth_EQ);
   Args.AddLastArg(CmdArgs, options::OPT_fconstexpr_steps_EQ);
+  Args.AddLastArg(CmdArgs, options::OPT_fmax_init_list_elements_EQ);
 
   Args.AddLastArg(CmdArgs, options::OPT_fexperimental_library);
 
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index ba7aeac2dc9ee..cc6cbc9e12a4e 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -39,6 +39,7 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/raw_ostream.h"
+#include <algorithm>
 #include <limits>
 
 using namespace clang;
@@ -3377,16 +3378,24 @@ InitListChecker::CheckDesignatedInitializer(const 
InitializedEntity &Entity,
   }
 
   // The semantic form of an initializer list stores one pointer for every
-  // array element, including the elements omitted before a designator. Avoid
-  // creating an initializer list whose dense representation is too large for
-  // an unsigned-sized allocation.
-  constexpr unsigned MaxInitListElements =
+  // array element, including the elements omitted before a designator. Compute
+  // the required number of elements in a wider type so adding one cannot
+  // overflow.
+  llvm::APSInt NumInits = DesignatedEndIndex;
+  NumInits.setIsUnsigned(true);
+  NumInits = NumInits.extend(NumInits.getBitWidth() + 1);
+  ++NumInits;
+
+  // Keep a non-configurable ceiling so even an excessive command-line limit
+  // cannot request an initializer list too large for an unsigned-sized
+  // allocation.
+  constexpr unsigned MaxAllocatableInitListElements =
       std::numeric_limits<unsigned>::max() / sizeof(Stmt *);
-  if (DesignatedEndIndex.uge(MaxInitListElements)) {
+  const unsigned MaxInitListElements =
+      std::min(SemaRef.getLangOpts().MaxInitListElements,
+               MaxAllocatableInitListElements);
+  if (NumInits.ugt(MaxInitListElements)) {
     if (!VerifyOnly) {
-      llvm::APSInt NumInits =
-          DesignatedEndIndex.extend(DesignatedEndIndex.getBitWidth() + 1);
-      ++NumInits;
       SemaRef.Diag(IndexExpr->getBeginLoc(), diag::err_array_too_large)
           << toString(NumInits, 10) << IndexExpr->getSourceRange();
     }
diff --git a/clang/test/Driver/max-init-list-elements.c 
b/clang/test/Driver/max-init-list-elements.c
new file mode 100644
index 0000000000000..00fb749b6b0c4
--- /dev/null
+++ b/clang/test/Driver/max-init-list-elements.c
@@ -0,0 +1,5 @@
+// RUN: %clang -### -fsyntax-only -fmax-init-list-elements=4 %s 2>&1 | \
+// RUN:   FileCheck %s
+
+// CHECK: "-cc1"
+// CHECK-SAME: "-fmax-init-list-elements=4"
diff --git a/clang/test/Sema/designated-initializer-limit.c 
b/clang/test/Sema/designated-initializer-limit.c
new file mode 100644
index 0000000000000..c4f3f9cb8938e
--- /dev/null
+++ b/clang/test/Sema/designated-initializer-limit.c
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-unknown-unknown \
+// RUN:   -fmax-init-list-elements=4 %s
+
+int designated_at_limit[] = { [3] = 1 };
+_Static_assert(sizeof(designated_at_limit) / sizeof(int) == 4, "");
+
+int range_at_limit[] = { [1 ... 3] = 1 };
+_Static_assert(sizeof(range_at_limit) / sizeof(int) == 4, "");
+
+int designated_over_limit[] = {
+    [4] = 1, // expected-error {{array is too large (5 elements)}}
+};
+
+int range_over_limit[] = {
+    [1 ... 4] = 1, // expected-error {{array is too large (5 elements)}}
+};
+
+int fixed_over_limit[5] = {
+    [4] = 1, // expected-error {{array is too large (5 elements)}}
+};
+
+int fixed_out_of_bounds[4] = {
+    [4] = 1, // expected-error {{array designator index (4) exceeds array 
bounds (4)}}
+};
diff --git a/clang/test/Sema/designated-initializers.c 
b/clang/test/Sema/designated-initializers.c
index 179b8855fe1c8..5527c7229a697 100644
--- a/clang/test/Sema/designated-initializers.c
+++ b/clang/test/Sema/designated-initializers.c
@@ -1,4 +1,6 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-unknown-unknown %s
+// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-unknown-unknown \
+// RUN:   -fmax-init-list-elements=4294967295 %s
 
 int complete_array_from_init[] = { 1, 2, [10] = 5, 1, 2, [5] = 2, 6 };
 

>From da6f2c39791827b9e0b81bca4098746672c86cd5 Mon Sep 17 00:00:00 2001
From: Max Manolov <[email protected]>
Date: Thu, 30 Jul 2026 18:15:43 -0700
Subject: [PATCH 3/4] Remove initializer list allocation ceiling

---
 clang/lib/Sema/SemaInit.cpp               | 12 +-----------
 clang/test/Sema/designated-initializers.c |  3 ---
 2 files changed, 1 insertion(+), 14 deletions(-)

diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index cc6cbc9e12a4e..2264377f60d6a 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -39,8 +39,6 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <limits>
 
 using namespace clang;
 
@@ -3386,15 +3384,7 @@ InitListChecker::CheckDesignatedInitializer(const 
InitializedEntity &Entity,
   NumInits = NumInits.extend(NumInits.getBitWidth() + 1);
   ++NumInits;
 
-  // Keep a non-configurable ceiling so even an excessive command-line limit
-  // cannot request an initializer list too large for an unsigned-sized
-  // allocation.
-  constexpr unsigned MaxAllocatableInitListElements =
-      std::numeric_limits<unsigned>::max() / sizeof(Stmt *);
-  const unsigned MaxInitListElements =
-      std::min(SemaRef.getLangOpts().MaxInitListElements,
-               MaxAllocatableInitListElements);
-  if (NumInits.ugt(MaxInitListElements)) {
+  if (NumInits.ugt(SemaRef.getLangOpts().MaxInitListElements)) {
     if (!VerifyOnly) {
       SemaRef.Diag(IndexExpr->getBeginLoc(), diag::err_array_too_large)
           << toString(NumInits, 10) << IndexExpr->getSourceRange();
diff --git a/clang/test/Sema/designated-initializers.c 
b/clang/test/Sema/designated-initializers.c
index 5527c7229a697..0e06e0390a880 100644
--- a/clang/test/Sema/designated-initializers.c
+++ b/clang/test/Sema/designated-initializers.c
@@ -1,7 +1,4 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-unknown-unknown %s
-// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-unknown-unknown \
-// RUN:   -fmax-init-list-elements=4294967295 %s
-
 int complete_array_from_init[] = { 1, 2, [10] = 5, 1, 2, [5] = 2, 6 };
 
 int complete_array_from_init_check[((sizeof(complete_array_from_init) / 
sizeof(int)) == 13)? 1 : -1];

>From ee1eacba2105ee8d3f6f0a49094b19c5a0de1d28 Mon Sep 17 00:00:00 2001
From: Max Manolov <[email protected]>
Date: Thu, 30 Jul 2026 18:15:58 -0700
Subject: [PATCH 4/4] Update initializer list limit documentation

---
 clang/docs/ReleaseNotes.md | 6 +-----
 clang/docs/UsersManual.rst | 2 --
 2 files changed, 1 insertion(+), 7 deletions(-)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index f4481cf3729b3..598195a05fb75 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -720,11 +720,7 @@ latest release, please see the [Clang Web 
Site](https://clang.llvm.org) or the
 - Fixed an assertion where we improperly handled implicit conversions to 
integral types from an atomic-type with a conversion function. (#GH201770)
 - Fixed assertion failures involving code completion with delayed default 
arguments and exception specifications. (#GH200879)
 - Fixed a regression where calling a function that takes a class-type 
parameter by value inside `decltype` of a concept could be incorrectly rejected 
when used as a non-type template argument. (#GH175831)
-- Clang now diagnoses inferred-size arrays with huge designated initializer
-  indices instead of attempting to allocate an enormous initializer list and
-  crashing with an out-of-memory error. The limit defaults to 1048576 dense
-  semantic initializer-list elements and can be adjusted with
-  `-fmax-init-list-elements=`. (#GH205472)
+- Clang now diagnoses inferred-size arrays with huge designated initializer 
indices instead of attempting to allocate an enormous initializer list and 
crashing with an out-of-memory error. The limit defaults to 1048576 dense 
semantic initializer-list elements and can be adjusted with 
`-fmax-init-list-elements=`. (#GH205472)
 
 #### Bug Fixes to Compiler Builtins
 
diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst
index 5f0f5df6b8362..9f58b724db84e 100644
--- a/clang/docs/UsersManual.rst
+++ b/clang/docs/UsersManual.rst
@@ -4246,8 +4246,6 @@ Controlling implementation limits
   Sets the maximum number of elements Clang may materialize for an array
   initializer's dense semantic representation. An array designator with an
   inclusive end index of N requires N + 1 elements. The default is 1048576.
-  The effective limit is also capped by a non-configurable internal
-  allocation-safety limit.
 
 .. _objc:
 

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to