[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 10: Expansion Limit) (PR #169689)

2026-06-01 Thread via llvm-branch-commits

Sirraide wrote:

> > Iirc when I was testing this it did 1 million expansions w/o hitting any 
> > existing limits; that was w/ an empty expansion statement but that already 
> > took a few seconds.
> 
> That's fine - the limits are there to avoid overwhelming the compiler, not 
> because something might be slow

I’m more worried about it taking even longer and someone mistakenly thinking 
that we have a bug in Clang or that the compiler is hanging when the bug would 
really be in user code in this case; iirc @AaronBallman has said in the past 
that the `constexpr` steps limit exists for a similar reason, so I thought it’d 
make sense to implement something similar for this.

(side note: I don’t believe 1 million expansions would ever not be a bug 
candidly...)

https://github.com/llvm/llvm-project/pull/169689
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 10: Expansion Limit) (PR #169689)

2026-06-01 Thread Corentin Jabot via llvm-branch-commits

cor3ntin wrote:

> Iirc when I was testing this it did 1 million expansions w/o hitting any 
> existing limits; that was w/ an empty expansion statement but that already 
> took a few seconds.

That's fine - the limits are there to avoid overwhelming  the compiler, not 
because something might be slow

https://github.com/llvm/llvm-project/pull/169689
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 10: Expansion Limit) (PR #169689)

2026-05-29 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169689

>From a45da7e323957753a53ae50176782d6520032ad7 Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:41:45 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 10)

---
 .../clang/Basic/DiagnosticSemaKinds.td|  4 +
 clang/include/clang/Basic/LangOptions.def |  1 +
 clang/include/clang/Options/Options.td|  4 +
 clang/lib/Driver/ToolChains/Clang.cpp |  1 +
 clang/lib/Sema/SemaExpand.cpp | 18 +
 .../SemaCXX/cxx2c-expansion-stmts-limit.cpp   | 73 +++
 .../SemaCXX/cxx2c-fexpansion-statements.cpp   |  9 +++
 7 files changed, 110 insertions(+)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-limit.cpp
 create mode 100644 clang/test/SemaCXX/cxx2c-fexpansion-statements.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index d954715da1f2f..70422ba1de723 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -167,6 +167,10 @@ def note_constexpr_assert_failed : Note<
   "assertion failed during evaluation of constant expression">;
 def err_expansion_size_expr_not_ice : Error<
   "expansion statement size is not a constant expression">;
+def err_expansion_too_big : Error<
+  "expansion statement size %0 exceeds maximum configured size %1">;
+def note_use_fexpansion_limit : Note<
+  "use -fexpansion-limit=N to adjust this limit">;
 def err_iterating_expansion_stmt_unsupported : Error<
   "iterating expansion statements are currently not supported">;
 
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index dd4c5a653d38b..7da7851085130 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -386,6 +386,7 @@ LANGOPT(ConstexprCallDepth, 32, 512, Benign,
 "maximum constexpr call depth")
 LANGOPT(ConstexprStepLimit, 32, 1048576, Benign,
 "maximum constexpr evaluation steps")
+LANGOPT(MaxTemplateForExpansions, 32, 16384, Benign, "maximum template for 
expansions")
 LANGOPT(EnableNewConstInterp, 1, 0, Benign,
 "enable the experimental new constant interpreter")
 LANGOPT(BracketDepth, 32, 256, Benign,
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 412683fd968b0..6819a2b582b89 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -2159,6 +2159,10 @@ def fconstexpr_steps_EQ : Joined<["-"], 
"fconstexpr-steps=">, Group,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Set the maximum number of steps in constexpr function evaluation 
(0 = no limit)">,
   MarshallingInfoInt, "1048576">;
+def fexpansion_limit_EQ : Joined<["-"], "fexpansion-limit=">, Group,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Set the maximum number of times a single expansion statement may 
be expanded (0 = no limit)">,
+  MarshallingInfoInt, "256">;
 def fexperimental_new_constant_interpreter : Flag<["-"], 
"fexperimental-new-constant-interpreter">, Group,
   HelpText<"Enable the experimental new constant interpreter">,
   Visibility<[ClangOption, CC1Option]>,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 86b0a705c7fe9..e7b16101943ae 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6563,6 +6563,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_fexpansion_limit_EQ);
 
   Args.AddLastArg(CmdArgs, options::OPT_fexperimental_library);
 
diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp
index 40d780e79866c..8cc25b9a01679 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -42,6 +42,18 @@ struct IterableExpansionStmtData {
 };
 } // namespace
 
+static bool CheckExpansionSize(Sema &S, uint64_t NumInstantiations,
+   SourceLocation Loc) {
+  unsigned Max = S.LangOpts.MaxTemplateForExpansions;
+  if (Max != 0 && NumInstantiations > Max) {
+S.Diag(Loc, diag::err_expansion_too_big) << NumInstantiations << Max;
+S.Diag(Loc, diag::note_use_fexpansion_limit);
+return true;
+  }
+
+  return false;
+}
+
 // Build a 'DeclRefExpr' designating the template parameter that is used as
 // the expansion index
 static DeclRefExpr *BuildIndexDRE(Sema &S, CXXExpansionStmtDecl *ESD) {
@@ -248,6 +260,9 @@ static StmtResult BuildDestructuringDecompositionDecl(
 return StmtError();
   }
 
+  if (CheckExpansionSize(S, *Arity, ColonLoc))
+return StmtError();
+
   QualType AutoRRef = S.Cont

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 10: Expansion Limit) (PR #169689)

2026-05-07 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169689

>From b83e5e8e24c1844a1fd50893bbc7dfdec9969480 Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:41:45 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 10)

---
 .../clang/Basic/DiagnosticSemaKinds.td|  4 ++
 clang/include/clang/Basic/LangOptions.def |  1 +
 clang/include/clang/Options/Options.td|  4 ++
 clang/lib/Driver/ToolChains/Clang.cpp |  1 +
 clang/lib/Sema/SemaExpand.cpp | 18 +
 .../SemaCXX/cxx2c-expansion-stmts-limit.cpp   | 69 +++
 .../SemaCXX/cxx2c-fexpansion-statements.cpp   |  9 +++
 7 files changed, 106 insertions(+)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-limit.cpp
 create mode 100644 clang/test/SemaCXX/cxx2c-fexpansion-statements.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 59ff2571b1445..19af396628fa1 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -167,6 +167,10 @@ def note_constexpr_assert_failed : Note<
   "assertion failed during evaluation of constant expression">;
 def err_expansion_size_expr_not_ice : Error<
   "expansion statement size is not a constant expression">;
+def err_expansion_too_big : Error<
+  "expansion statement size %0 exceeds maximum configured size %1">;
+def note_use_fexpansion_limit : Note<
+  "use -fexpansion-limit=N to adjust this limit">;
 
 def note_iterating_expansion_stmt_iterator_requires_minus : Note<
   "while attempting to construct 'begin - begin' with iterator type %0">;
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index dd4c5a653d38b..7da7851085130 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -386,6 +386,7 @@ LANGOPT(ConstexprCallDepth, 32, 512, Benign,
 "maximum constexpr call depth")
 LANGOPT(ConstexprStepLimit, 32, 1048576, Benign,
 "maximum constexpr evaluation steps")
+LANGOPT(MaxTemplateForExpansions, 32, 16384, Benign, "maximum template for 
expansions")
 LANGOPT(EnableNewConstInterp, 1, 0, Benign,
 "enable the experimental new constant interpreter")
 LANGOPT(BracketDepth, 32, 256, Benign,
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 412683fd968b0..6819a2b582b89 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -2159,6 +2159,10 @@ def fconstexpr_steps_EQ : Joined<["-"], 
"fconstexpr-steps=">, Group,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Set the maximum number of steps in constexpr function evaluation 
(0 = no limit)">,
   MarshallingInfoInt, "1048576">;
+def fexpansion_limit_EQ : Joined<["-"], "fexpansion-limit=">, Group,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Set the maximum number of times a single expansion statement may 
be expanded (0 = no limit)">,
+  MarshallingInfoInt, "256">;
 def fexperimental_new_constant_interpreter : Flag<["-"], 
"fexperimental-new-constant-interpreter">, Group,
   HelpText<"Enable the experimental new constant interpreter">,
   Visibility<[ClangOption, CC1Option]>,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 86b0a705c7fe9..e7b16101943ae 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6563,6 +6563,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_fexpansion_limit_EQ);
 
   Args.AddLastArg(CmdArgs, options::OPT_fexperimental_library);
 
diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp
index fc72d90283c1d..c93bf9fe0cefd 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -42,6 +42,18 @@ struct IterableExpansionStmtData {
 };
 } // namespace
 
+static bool CheckExpansionSize(Sema &S, uint64_t NumInstantiations,
+   SourceLocation Loc) {
+  unsigned Max = S.LangOpts.MaxTemplateForExpansions;
+  if (Max != 0 && NumInstantiations > Max) {
+S.Diag(Loc, diag::err_expansion_too_big) << NumInstantiations << Max;
+S.Diag(Loc, diag::note_use_fexpansion_limit);
+return true;
+  }
+
+  return false;
+}
+
 // Build a 'DeclRefExpr' designating the template parameter that is used as
 // the expansion index
 static DeclRefExpr *BuildIndexDRE(Sema &S, CXXExpansionStmtDecl *ESD) {
@@ -297,6 +309,9 @@ static StmtResult BuildDestructuringDecompositionDecl(
 return StmtError();
   }
 
+  if (CheckExpansionSize(S, *Arity, ColonLoc))
+return StmtError();
+
   Qua

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 10: Expansion Limit) (PR #169689)

2026-05-07 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169689

>From b83e5e8e24c1844a1fd50893bbc7dfdec9969480 Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:41:45 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 10)

---
 .../clang/Basic/DiagnosticSemaKinds.td|  4 ++
 clang/include/clang/Basic/LangOptions.def |  1 +
 clang/include/clang/Options/Options.td|  4 ++
 clang/lib/Driver/ToolChains/Clang.cpp |  1 +
 clang/lib/Sema/SemaExpand.cpp | 18 +
 .../SemaCXX/cxx2c-expansion-stmts-limit.cpp   | 69 +++
 .../SemaCXX/cxx2c-fexpansion-statements.cpp   |  9 +++
 7 files changed, 106 insertions(+)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-limit.cpp
 create mode 100644 clang/test/SemaCXX/cxx2c-fexpansion-statements.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 59ff2571b1445..19af396628fa1 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -167,6 +167,10 @@ def note_constexpr_assert_failed : Note<
   "assertion failed during evaluation of constant expression">;
 def err_expansion_size_expr_not_ice : Error<
   "expansion statement size is not a constant expression">;
+def err_expansion_too_big : Error<
+  "expansion statement size %0 exceeds maximum configured size %1">;
+def note_use_fexpansion_limit : Note<
+  "use -fexpansion-limit=N to adjust this limit">;
 
 def note_iterating_expansion_stmt_iterator_requires_minus : Note<
   "while attempting to construct 'begin - begin' with iterator type %0">;
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index dd4c5a653d38b..7da7851085130 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -386,6 +386,7 @@ LANGOPT(ConstexprCallDepth, 32, 512, Benign,
 "maximum constexpr call depth")
 LANGOPT(ConstexprStepLimit, 32, 1048576, Benign,
 "maximum constexpr evaluation steps")
+LANGOPT(MaxTemplateForExpansions, 32, 16384, Benign, "maximum template for 
expansions")
 LANGOPT(EnableNewConstInterp, 1, 0, Benign,
 "enable the experimental new constant interpreter")
 LANGOPT(BracketDepth, 32, 256, Benign,
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 412683fd968b0..6819a2b582b89 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -2159,6 +2159,10 @@ def fconstexpr_steps_EQ : Joined<["-"], 
"fconstexpr-steps=">, Group,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Set the maximum number of steps in constexpr function evaluation 
(0 = no limit)">,
   MarshallingInfoInt, "1048576">;
+def fexpansion_limit_EQ : Joined<["-"], "fexpansion-limit=">, Group,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Set the maximum number of times a single expansion statement may 
be expanded (0 = no limit)">,
+  MarshallingInfoInt, "256">;
 def fexperimental_new_constant_interpreter : Flag<["-"], 
"fexperimental-new-constant-interpreter">, Group,
   HelpText<"Enable the experimental new constant interpreter">,
   Visibility<[ClangOption, CC1Option]>,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 86b0a705c7fe9..e7b16101943ae 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6563,6 +6563,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_fexpansion_limit_EQ);
 
   Args.AddLastArg(CmdArgs, options::OPT_fexperimental_library);
 
diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp
index fc72d90283c1d..c93bf9fe0cefd 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -42,6 +42,18 @@ struct IterableExpansionStmtData {
 };
 } // namespace
 
+static bool CheckExpansionSize(Sema &S, uint64_t NumInstantiations,
+   SourceLocation Loc) {
+  unsigned Max = S.LangOpts.MaxTemplateForExpansions;
+  if (Max != 0 && NumInstantiations > Max) {
+S.Diag(Loc, diag::err_expansion_too_big) << NumInstantiations << Max;
+S.Diag(Loc, diag::note_use_fexpansion_limit);
+return true;
+  }
+
+  return false;
+}
+
 // Build a 'DeclRefExpr' designating the template parameter that is used as
 // the expansion index
 static DeclRefExpr *BuildIndexDRE(Sema &S, CXXExpansionStmtDecl *ESD) {
@@ -297,6 +309,9 @@ static StmtResult BuildDestructuringDecompositionDecl(
 return StmtError();
   }
 
+  if (CheckExpansionSize(S, *Arity, ColonLoc))
+return StmtError();
+
   Qua

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 10: Expansion Limit) (PR #169689)

2026-05-04 Thread via llvm-branch-commits

Sirraide wrote:

> Is an actual performance concern here?
> 
> Unlike recursive things it's bound to terminate, and it's not adding 
> recursion in itself - the limit from the compiler perspective is the number 
> of instantiations / objects in the declaration context.
> 
> I expect people will want to iterate over the member of `::` or `::std` and 
> expect that to somehow work.
> 
> So i think this is fine for now but we will probably have to adjust with use 
> cases

Iirc when I was testing this it did 1 million expansions w/o hitting any 
existing limits; that was w/ an empty expansion statement but that already took 
a few seconds.

https://github.com/llvm/llvm-project/pull/169689
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 10: Expansion Limit) (PR #169689)

2026-05-04 Thread Corentin Jabot via llvm-branch-commits

https://github.com/cor3ntin commented:

Is an actual performance concern here?

Unlike recursive things it's bound to terminate, and it's not adding recursion 
in itself  - the limit from the compiler perspective is the number of 
instantiations / objects in the declaration context.

I expect people will want to iterate over the member of `::` or `::std` and 
expect that to somehow work.

So i think this is fine for now but we will probably have to adjust with use 
cases

https://github.com/llvm/llvm-project/pull/169689
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 10: Expansion Limit) (PR #169689)

2026-03-31 Thread via llvm-branch-commits

Sirraide wrote:

> > Perhaps we should look at some other imp limits that reflection might 
> > observe (field limit/arg limit/etc?), and see what number would cover all 
> > of those?
> 
> field/argument limits is a good idea; I’ll look at those

The limit for parameters in a function definition is 256 and for data members 
in a class it’s 16384;  I went w/ the latter since it’s a reasonable number I 
think

https://github.com/llvm/llvm-project/pull/169689
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 10: Expansion Limit) (PR #169689)

2026-03-31 Thread Erich Keane via llvm-branch-commits

erichkeane wrote:

> > How did we derive the 'max' limit default? Experimentally, based on another 
> > limit, or in implimits?
> 
> I candidly didn’t derive it at all when I first implemented this. I just 
> picked 256 as a placeholder value and was hoping that we could discuss this 
> and figure out what a reasonable limit should be 👀
> 
> > 1 million instantiations takes about 3 seconds provided the body of the 
> > expansion statement is empty
> 
> Apparently, I did run some testing locally though, so maybe 1 million (or the 
> closest power of 2, i.e. `1 << 20`) would be a good value?

Perhaps not that high :)  I could definitely see something like 1024 being 
reasonable, but I otherwise lack much of a preference. 256 feels a little 
small, but it isn't clear to me what a reason size will be, particularly with 
reflection.

Perhaps we should look at some other imp limits that reflection might observe 
(field limit/arg limit/etc?), and see what number would cover all of those? 

https://github.com/llvm/llvm-project/pull/169689
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 10: Expansion Limit) (PR #169689)

2026-03-24 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169689

>From cc3c4ef806dd4fb2a7f129cd874fe381817e0225 Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:41:45 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 10)

---
 .../clang/Basic/DiagnosticSemaKinds.td|  4 ++
 clang/include/clang/Basic/LangOptions.def |  1 +
 clang/include/clang/Options/Options.td|  4 ++
 clang/lib/Driver/ToolChains/Clang.cpp |  1 +
 clang/lib/Sema/SemaExpand.cpp | 18 +
 .../SemaCXX/cxx2c-expansion-stmts-limit.cpp   | 69 +++
 .../SemaCXX/cxx2c-fexpansion-statements.cpp   |  9 +++
 7 files changed, 106 insertions(+)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-limit.cpp
 create mode 100644 clang/test/SemaCXX/cxx2c-fexpansion-statements.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index ee53b489fce35..04eacce5e06ff 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -167,6 +167,10 @@ def note_constexpr_assert_failed : Note<
   "assertion failed during evaluation of constant expression">;
 def err_expansion_size_expr_not_ice : Error<
   "expansion size is not a constant expression">;
+def err_expansion_too_big : Error<
+  "expansion size %0 exceeds maximum configured size %1">;
+def note_use_fexpansion_limit : Note<
+  "use -fexpansion-limit=N to adjust this limit">;
 
 def note_iterating_expansion_stmt_iterator_requires_minus : Note<
   "while attempting to construct 'begin - begin' with iterator type %0">;
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 2c93e60b48cc5..64359db337f73 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -382,6 +382,7 @@ LANGOPT(ConstexprCallDepth, 32, 512, Benign,
 "maximum constexpr call depth")
 LANGOPT(ConstexprStepLimit, 32, 1048576, Benign,
 "maximum constexpr evaluation steps")
+LANGOPT(MaxTemplateForExpansions, 32, 256, Benign, "maximum template for 
expansions")
 LANGOPT(EnableNewConstInterp, 1, 0, Benign,
 "enable the experimental new constant interpreter")
 LANGOPT(BracketDepth, 32, 256, Benign,
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 6fc52384a6d1d..a4d80caff91f7 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -2139,6 +2139,10 @@ def fconstexpr_steps_EQ : Joined<["-"], 
"fconstexpr-steps=">, Group,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Set the maximum number of steps in constexpr function evaluation 
(0 = no limit)">,
   MarshallingInfoInt, "1048576">;
+def fexpansion_limit_EQ : Joined<["-"], "fexpansion-limit=">, Group,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Set the maximum number of times a single expansion statement may 
be expanded (0 = no limit)">,
+  MarshallingInfoInt, "256">;
 def fexperimental_new_constant_interpreter : Flag<["-"], 
"fexperimental-new-constant-interpreter">, Group,
   HelpText<"Enable the experimental new constant interpreter">,
   Visibility<[ClangOption, CC1Option]>,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 3b852528d92c4..a7bf52950435e 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6525,6 +6525,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_fexpansion_limit_EQ);
 
   Args.AddLastArg(CmdArgs, options::OPT_fexperimental_library);
 
diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp
index 27878377f934f..19caa88789cf0 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -43,6 +43,18 @@ struct IterableExpansionStmtData {
 };
 } // namespace
 
+static bool CheckExpansionSize(Sema &S, uint64_t NumInstantiations,
+   SourceLocation Loc) {
+  unsigned Max = S.LangOpts.MaxTemplateForExpansions;
+  if (Max != 0 && NumInstantiations > Max) {
+S.Diag(Loc, diag::err_expansion_too_big) << NumInstantiations << Max;
+S.Diag(Loc, diag::note_use_fexpansion_limit);
+return true;
+  }
+
+  return false;
+}
+
 // Build a 'DeclRefExpr' designating the template parameter '__N'.
 static DeclRefExpr *BuildIndexDRE(Sema &S, CXXExpansionStmtDecl *ESD) {
   return S.BuildDeclRefExpr(ESD->getIndexTemplateParm(),
@@ -298,6 +310,9 @@ static StmtResult BuildDestructuringDecompositionDecl(
 return StmtError();
   }
 
+  if (CheckExpansionSize(S, *Arity, ColonLoc))
+return StmtError();
+
   

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 10: Expansion Limit) (PR #169689)

2026-03-24 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169689

>From cc3c4ef806dd4fb2a7f129cd874fe381817e0225 Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:41:45 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 10)

---
 .../clang/Basic/DiagnosticSemaKinds.td|  4 ++
 clang/include/clang/Basic/LangOptions.def |  1 +
 clang/include/clang/Options/Options.td|  4 ++
 clang/lib/Driver/ToolChains/Clang.cpp |  1 +
 clang/lib/Sema/SemaExpand.cpp | 18 +
 .../SemaCXX/cxx2c-expansion-stmts-limit.cpp   | 69 +++
 .../SemaCXX/cxx2c-fexpansion-statements.cpp   |  9 +++
 7 files changed, 106 insertions(+)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-limit.cpp
 create mode 100644 clang/test/SemaCXX/cxx2c-fexpansion-statements.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index ee53b489fce35..04eacce5e06ff 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -167,6 +167,10 @@ def note_constexpr_assert_failed : Note<
   "assertion failed during evaluation of constant expression">;
 def err_expansion_size_expr_not_ice : Error<
   "expansion size is not a constant expression">;
+def err_expansion_too_big : Error<
+  "expansion size %0 exceeds maximum configured size %1">;
+def note_use_fexpansion_limit : Note<
+  "use -fexpansion-limit=N to adjust this limit">;
 
 def note_iterating_expansion_stmt_iterator_requires_minus : Note<
   "while attempting to construct 'begin - begin' with iterator type %0">;
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 2c93e60b48cc5..64359db337f73 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -382,6 +382,7 @@ LANGOPT(ConstexprCallDepth, 32, 512, Benign,
 "maximum constexpr call depth")
 LANGOPT(ConstexprStepLimit, 32, 1048576, Benign,
 "maximum constexpr evaluation steps")
+LANGOPT(MaxTemplateForExpansions, 32, 256, Benign, "maximum template for 
expansions")
 LANGOPT(EnableNewConstInterp, 1, 0, Benign,
 "enable the experimental new constant interpreter")
 LANGOPT(BracketDepth, 32, 256, Benign,
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 6fc52384a6d1d..a4d80caff91f7 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -2139,6 +2139,10 @@ def fconstexpr_steps_EQ : Joined<["-"], 
"fconstexpr-steps=">, Group,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Set the maximum number of steps in constexpr function evaluation 
(0 = no limit)">,
   MarshallingInfoInt, "1048576">;
+def fexpansion_limit_EQ : Joined<["-"], "fexpansion-limit=">, Group,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Set the maximum number of times a single expansion statement may 
be expanded (0 = no limit)">,
+  MarshallingInfoInt, "256">;
 def fexperimental_new_constant_interpreter : Flag<["-"], 
"fexperimental-new-constant-interpreter">, Group,
   HelpText<"Enable the experimental new constant interpreter">,
   Visibility<[ClangOption, CC1Option]>,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 3b852528d92c4..a7bf52950435e 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6525,6 +6525,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_fexpansion_limit_EQ);
 
   Args.AddLastArg(CmdArgs, options::OPT_fexperimental_library);
 
diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp
index 27878377f934f..19caa88789cf0 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -43,6 +43,18 @@ struct IterableExpansionStmtData {
 };
 } // namespace
 
+static bool CheckExpansionSize(Sema &S, uint64_t NumInstantiations,
+   SourceLocation Loc) {
+  unsigned Max = S.LangOpts.MaxTemplateForExpansions;
+  if (Max != 0 && NumInstantiations > Max) {
+S.Diag(Loc, diag::err_expansion_too_big) << NumInstantiations << Max;
+S.Diag(Loc, diag::note_use_fexpansion_limit);
+return true;
+  }
+
+  return false;
+}
+
 // Build a 'DeclRefExpr' designating the template parameter '__N'.
 static DeclRefExpr *BuildIndexDRE(Sema &S, CXXExpansionStmtDecl *ESD) {
   return S.BuildDeclRefExpr(ESD->getIndexTemplateParm(),
@@ -298,6 +310,9 @@ static StmtResult BuildDestructuringDecompositionDecl(
 return StmtError();
   }
 
+  if (CheckExpansionSize(S, *Arity, ColonLoc))
+return StmtError();
+
   

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 10: Expansion Limit) (PR #169689)

2026-03-18 Thread via llvm-branch-commits

github-actions[bot] wrote:


# :penguin: Linux x64 Test Results

* 87004 tests passed
* 1328 tests skipped
* 1 test failed

## Failed Tests
(click on a test name to see its output)

### Clang

Clang.SemaTemplate/GH176155.cpp

```
Exit Code: 1

Command Output (stdout):
--
# RUN: at line 1
/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang -cc1 
-internal-isystem 
/home/gha/actions-runner/_work/llvm-project/llvm-project/build/lib/clang/23/include
 -nostdsysteminc -std=c++20 -fsyntax-only -verify 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
# executed command: 
/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang -cc1 
-internal-isystem 
/home/gha/actions-runner/_work/llvm-project/llvm-project/build/lib/clang/23/include
 -nostdsysteminc -std=c++20 -fsyntax-only -verify 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
# .---command stderr
# | error: 'expected-error' diagnostics expected but not seen: 
# |   File 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
 Line 11 (directive at 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp:12):
 variable 'i' cannot be implicitly captured in a lambda with no capture-default 
specified
# |   File 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
 Line 11 (directive at 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp:15):
 variable 'i' cannot be implicitly captured in a lambda with no capture-default 
specified
# | error: 'expected-note' diagnostics expected but not seen: 
# |   File 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
 Line 5 (directive at 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp:6):
 while substituting into a lambda expression here
# |   File 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
 Line 5 (directive at 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp:7):
 capture 'i' by value
# |   File 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
 Line 5 (directive at 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp:7):
 capture 'i' by value
# |   File 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
 Line 5 (directive at 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp:8):
 capture 'i' by reference
# |   File 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
 Line 5 (directive at 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp:8):
 capture 'i' by reference
# |   File 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
 Line 5 (directive at 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp:9):
 default capture by value
# |   File 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
 Line 5 (directive at 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp:9):
 default capture by value
# |   File 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
 Line 5 (directive at 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp:10):
 default capture by reference
# |   File 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
 Line 5 (directive at 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp:10):
 default capture by reference
# |   File 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
 Line 11 (directive at 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp:13):
 'i' declared here
# |   File 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
 Line 5 (directive at 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp:14):
 lambda expression begins here
# |   File 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
 Line 11 (directive at 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp:16):
 'i' declared here
# |   File 
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/SemaTemplate/GH176155.cpp
 Line 5 (directive at 
/home/gha/actions-runner/_work/llvm-project/llv

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 10: Expansion Limit) (PR #169689)

2026-03-18 Thread via llvm-branch-commits

github-actions[bot] wrote:


# :window: Windows x64 Test Results

* 53296 tests passed
* 1029 tests skipped
* 1 test failed

## Failed Tests
(click on a test name to see its output)

### Clang

Clang.SemaTemplate/GH176155.cpp

```
Exit Code: 1

Command Output (stdout):
--
# RUN: at line 1
c:\_work\llvm-project\llvm-project\build\bin\clang.exe -cc1 -internal-isystem 
C:\_work\llvm-project\llvm-project\build\lib\clang\23\include -nostdsysteminc 
-std=c++20 -fsyntax-only -verify 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp
# executed command: 'c:\_work\llvm-project\llvm-project\build\bin\clang.exe' 
-cc1 -internal-isystem 
'C:\_work\llvm-project\llvm-project\build\lib\clang\23\include' -nostdsysteminc 
-std=c++20 -fsyntax-only -verify 
'C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp'
# .---command stderr
# | error: 'expected-error' diagnostics expected but not seen: 
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 11 
(directive at 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp:12): 
variable 'i' cannot be implicitly captured in a lambda with no capture-default 
specified
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 11 
(directive at 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp:15): 
variable 'i' cannot be implicitly captured in a lambda with no capture-default 
specified
# | error: 'expected-note' diagnostics expected but not seen: 
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 5 
(directive at 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp:6): 
while substituting into a lambda expression here
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 5 
(directive at 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp:7): 
capture 'i' by value
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 5 
(directive at 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp:7): 
capture 'i' by value
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 5 
(directive at 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp:8): 
capture 'i' by reference
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 5 
(directive at 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp:8): 
capture 'i' by reference
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 5 
(directive at 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp:9): 
default capture by value
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 5 
(directive at 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp:9): 
default capture by value
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 5 
(directive at 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp:10): 
default capture by reference
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 5 
(directive at 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp:10): 
default capture by reference
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 11 
(directive at 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp:13): 
'i' declared here
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 5 
(directive at 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp:14): 
lambda expression begins here
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 11 
(directive at 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp:16): 
'i' declared here
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 5 
(directive at 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp:17): 
lambda expression begins here
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 
23: in instantiation of default argument for 'f' required here
# |   File 
C:\_work\llvm-project\llvm-project\clang\test\SemaTemplate\GH176155.cpp Line 
26: while substituting deduced template arguments into function template 'f'
# | 17 errors generated.
# `-
# error: command failed with exit status: 1

--

```


If these failures are unrelated to your changes (for example tests are broken 
or flaky at HEAD), please open an issue at 
https://github.com/llvm/llvm-project/issues and add the `infrastructure` label.

https://github.com/llvm/llvm-project/pull/169689
__

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 10: Expansion Limit) (PR #169689)

2026-03-18 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169689

>From 82dc239df882b70017dde8de3dedebdeabe50c50 Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:41:45 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 10)

---
 .../clang/Basic/DiagnosticSemaKinds.td|  4 ++
 clang/include/clang/Basic/LangOptions.def |  1 +
 clang/include/clang/Options/Options.td|  4 ++
 clang/lib/Driver/ToolChains/Clang.cpp |  1 +
 clang/lib/Sema/SemaExpand.cpp | 18 +
 .../SemaCXX/cxx2c-expansion-stmts-limit.cpp   | 69 +++
 .../SemaCXX/cxx2c-fexpansion-statements.cpp   |  9 +++
 7 files changed, 106 insertions(+)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-limit.cpp
 create mode 100644 clang/test/SemaCXX/cxx2c-fexpansion-statements.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index ee53b489fce35..04eacce5e06ff 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -167,6 +167,10 @@ def note_constexpr_assert_failed : Note<
   "assertion failed during evaluation of constant expression">;
 def err_expansion_size_expr_not_ice : Error<
   "expansion size is not a constant expression">;
+def err_expansion_too_big : Error<
+  "expansion size %0 exceeds maximum configured size %1">;
+def note_use_fexpansion_limit : Note<
+  "use -fexpansion-limit=N to adjust this limit">;
 
 def note_iterating_expansion_stmt_iterator_requires_minus : Note<
   "while attempting to construct 'begin - begin' with iterator type %0">;
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 2c93e60b48cc5..64359db337f73 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -382,6 +382,7 @@ LANGOPT(ConstexprCallDepth, 32, 512, Benign,
 "maximum constexpr call depth")
 LANGOPT(ConstexprStepLimit, 32, 1048576, Benign,
 "maximum constexpr evaluation steps")
+LANGOPT(MaxTemplateForExpansions, 32, 256, Benign, "maximum template for 
expansions")
 LANGOPT(EnableNewConstInterp, 1, 0, Benign,
 "enable the experimental new constant interpreter")
 LANGOPT(BracketDepth, 32, 256, Benign,
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 6fc52384a6d1d..a4d80caff91f7 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -2139,6 +2139,10 @@ def fconstexpr_steps_EQ : Joined<["-"], 
"fconstexpr-steps=">, Group,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Set the maximum number of steps in constexpr function evaluation 
(0 = no limit)">,
   MarshallingInfoInt, "1048576">;
+def fexpansion_limit_EQ : Joined<["-"], "fexpansion-limit=">, Group,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Set the maximum number of times a single expansion statement may 
be expanded (0 = no limit)">,
+  MarshallingInfoInt, "256">;
 def fexperimental_new_constant_interpreter : Flag<["-"], 
"fexperimental-new-constant-interpreter">, Group,
   HelpText<"Enable the experimental new constant interpreter">,
   Visibility<[ClangOption, CC1Option]>,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 3b852528d92c4..a7bf52950435e 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6525,6 +6525,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_fexpansion_limit_EQ);
 
   Args.AddLastArg(CmdArgs, options::OPT_fexperimental_library);
 
diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp
index 231f6e657e55e..0d66c9ec1de6b 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -44,6 +44,18 @@ struct IterableExpansionStmtData {
 };
 } // namespace
 
+static bool CheckExpansionSize(Sema &S, uint64_t NumInstantiations,
+   SourceLocation Loc) {
+  unsigned Max = S.LangOpts.MaxTemplateForExpansions;
+  if (Max != 0 && NumInstantiations > Max) {
+S.Diag(Loc, diag::err_expansion_too_big) << NumInstantiations << Max;
+S.Diag(Loc, diag::note_use_fexpansion_limit);
+return true;
+  }
+
+  return false;
+}
+
 // Build a 'DeclRefExpr' designating the template parameter '__N'.
 static DeclRefExpr *BuildIndexDRE(Sema &S, CXXExpansionStmtDecl *ESD) {
   return S.BuildDeclRefExpr(ESD->getIndexTemplateParm(),
@@ -306,6 +318,9 @@ static StmtResult BuildDestructuringDecompositionDecl(
 return StmtError();
   }
 
+  if (CheckExpansionSize(S, *Arity, ColonLoc))
+return StmtError();
+
   

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 10: Expansion Limit) (PR #169689)

2025-12-05 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169689

>From 4fa5064b267bca9100fe2ab9678df253cdfcdf4f Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:41:45 +0100
Subject: [PATCH 1/2] [Clang] [C++26] Expansion Statements (Part 10)

---
 .../clang/Basic/DiagnosticSemaKinds.td|  4 ++
 clang/include/clang/Basic/LangOptions.def |  1 +
 clang/include/clang/Options/Options.td|  4 ++
 clang/lib/Driver/ToolChains/Clang.cpp |  1 +
 clang/lib/Sema/SemaExpand.cpp | 18 +
 .../SemaCXX/cxx2c-expansion-stmts-limit.cpp   | 68 +++
 .../SemaCXX/cxx2c-fexpansion-statements.cpp   |  9 +++
 7 files changed, 105 insertions(+)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-limit.cpp
 create mode 100644 clang/test/SemaCXX/cxx2c-fexpansion-statements.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 6994cd88fba21..71e4a178fe21d 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -167,6 +167,10 @@ def note_constexpr_assert_failed : Note<
   "assertion failed during evaluation of constant expression">;
 def err_expansion_size_expr_not_ice : Error<
   "expansion size is not a constant expression">;
+def err_expansion_too_big : Error<
+  "expansion size %0 exceeds maximum configured size %1">;
+def note_use_fexpansion_limit : Note<
+  "use -fexpansion-limit=N to adjust this limit">;
 
 // Semantic analysis of constant literals.
 def ext_predef_outside_function : Warning<
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 40fc66ea12e34..315cb4dc5e1cf 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -377,6 +377,7 @@ LANGOPT(ConstexprCallDepth, 32, 512, Benign,
 "maximum constexpr call depth")
 LANGOPT(ConstexprStepLimit, 32, 1048576, Benign,
 "maximum constexpr evaluation steps")
+LANGOPT(MaxTemplateForExpansions, 32, 256, Benign, "maximum template for 
expansions")
 LANGOPT(EnableNewConstInterp, 1, 0, Benign,
 "enable the experimental new constant interpreter")
 LANGOPT(BracketDepth, 32, 256, Benign,
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index c6841937c8d39..8af98ec6afb50 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -2064,6 +2064,10 @@ def fconstexpr_steps_EQ : Joined<["-"], 
"fconstexpr-steps=">, Group,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Set the maximum number of steps in constexpr function evaluation 
(0 = no limit)">,
   MarshallingInfoInt, "1048576">;
+def fexpansion_limit_EQ : Joined<["-"], "fexpansion-limit=">, Group,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Set the maximum number of times a single expansion statement may 
be expanded (0 = no limit)">,
+  MarshallingInfoInt, "256">;
 def fexperimental_new_constant_interpreter : Flag<["-"], 
"fexperimental-new-constant-interpreter">, Group,
   HelpText<"Enable the experimental new constant interpreter">,
   Visibility<[ClangOption, CC1Option]>,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 0380568412e62..331a388eac573 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6369,6 +6369,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_fexpansion_limit_EQ);
 
   Args.AddLastArg(CmdArgs, options::OPT_fexperimental_library);
 
diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp
index 6fa1ad9856783..8ca2b074acbea 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -44,6 +44,18 @@ struct IterableExpansionStmtData {
 };
 } // namespace
 
+static bool CheckExpansionSize(Sema &S, uint64_t NumInstantiations,
+   SourceLocation Loc) {
+  unsigned Max = S.LangOpts.MaxTemplateForExpansions;
+  if (Max != 0 && NumInstantiations > Max) {
+S.Diag(Loc, diag::err_expansion_too_big) << NumInstantiations << Max;
+S.Diag(Loc, diag::note_use_fexpansion_limit);
+return true;
+  }
+
+  return false;
+}
+
 // Build a 'DeclRefExpr' designating the template parameter '__N'.
 static DeclRefExpr *BuildIndexDRE(Sema &S, CXXExpansionStmtDecl *ESD) {
   return S.BuildDeclRefExpr(ESD->getIndexTemplateParm(),
@@ -245,6 +257,9 @@ static StmtResult BuildDestructuringDecompositionDecl(
 return StmtError();
   }
 
+  if (CheckExpansionSize(S, *Arity, ColonLoc))
+return StmtError();
+
   QualType AutoRRef = S.Context.getAutoRRefDeductTyp

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 10: Expansion Limit) (PR #169689)

2025-12-05 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169689

>From 4fa5064b267bca9100fe2ab9678df253cdfcdf4f Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:41:45 +0100
Subject: [PATCH 1/2] [Clang] [C++26] Expansion Statements (Part 10)

---
 .../clang/Basic/DiagnosticSemaKinds.td|  4 ++
 clang/include/clang/Basic/LangOptions.def |  1 +
 clang/include/clang/Options/Options.td|  4 ++
 clang/lib/Driver/ToolChains/Clang.cpp |  1 +
 clang/lib/Sema/SemaExpand.cpp | 18 +
 .../SemaCXX/cxx2c-expansion-stmts-limit.cpp   | 68 +++
 .../SemaCXX/cxx2c-fexpansion-statements.cpp   |  9 +++
 7 files changed, 105 insertions(+)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-limit.cpp
 create mode 100644 clang/test/SemaCXX/cxx2c-fexpansion-statements.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 6994cd88fba21..71e4a178fe21d 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -167,6 +167,10 @@ def note_constexpr_assert_failed : Note<
   "assertion failed during evaluation of constant expression">;
 def err_expansion_size_expr_not_ice : Error<
   "expansion size is not a constant expression">;
+def err_expansion_too_big : Error<
+  "expansion size %0 exceeds maximum configured size %1">;
+def note_use_fexpansion_limit : Note<
+  "use -fexpansion-limit=N to adjust this limit">;
 
 // Semantic analysis of constant literals.
 def ext_predef_outside_function : Warning<
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 40fc66ea12e34..315cb4dc5e1cf 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -377,6 +377,7 @@ LANGOPT(ConstexprCallDepth, 32, 512, Benign,
 "maximum constexpr call depth")
 LANGOPT(ConstexprStepLimit, 32, 1048576, Benign,
 "maximum constexpr evaluation steps")
+LANGOPT(MaxTemplateForExpansions, 32, 256, Benign, "maximum template for 
expansions")
 LANGOPT(EnableNewConstInterp, 1, 0, Benign,
 "enable the experimental new constant interpreter")
 LANGOPT(BracketDepth, 32, 256, Benign,
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index c6841937c8d39..8af98ec6afb50 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -2064,6 +2064,10 @@ def fconstexpr_steps_EQ : Joined<["-"], 
"fconstexpr-steps=">, Group,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Set the maximum number of steps in constexpr function evaluation 
(0 = no limit)">,
   MarshallingInfoInt, "1048576">;
+def fexpansion_limit_EQ : Joined<["-"], "fexpansion-limit=">, Group,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Set the maximum number of times a single expansion statement may 
be expanded (0 = no limit)">,
+  MarshallingInfoInt, "256">;
 def fexperimental_new_constant_interpreter : Flag<["-"], 
"fexperimental-new-constant-interpreter">, Group,
   HelpText<"Enable the experimental new constant interpreter">,
   Visibility<[ClangOption, CC1Option]>,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 0380568412e62..331a388eac573 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6369,6 +6369,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_fexpansion_limit_EQ);
 
   Args.AddLastArg(CmdArgs, options::OPT_fexperimental_library);
 
diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp
index 6fa1ad9856783..8ca2b074acbea 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -44,6 +44,18 @@ struct IterableExpansionStmtData {
 };
 } // namespace
 
+static bool CheckExpansionSize(Sema &S, uint64_t NumInstantiations,
+   SourceLocation Loc) {
+  unsigned Max = S.LangOpts.MaxTemplateForExpansions;
+  if (Max != 0 && NumInstantiations > Max) {
+S.Diag(Loc, diag::err_expansion_too_big) << NumInstantiations << Max;
+S.Diag(Loc, diag::note_use_fexpansion_limit);
+return true;
+  }
+
+  return false;
+}
+
 // Build a 'DeclRefExpr' designating the template parameter '__N'.
 static DeclRefExpr *BuildIndexDRE(Sema &S, CXXExpansionStmtDecl *ESD) {
   return S.BuildDeclRefExpr(ESD->getIndexTemplateParm(),
@@ -245,6 +257,9 @@ static StmtResult BuildDestructuringDecompositionDecl(
 return StmtError();
   }
 
+  if (CheckExpansionSize(S, *Arity, ColonLoc))
+return StmtError();
+
   QualType AutoRRef = S.Context.getAutoRRefDeductTyp

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 10: Expansion Limit) (PR #169689)

2025-12-03 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169689

>From e2a41057242421f63f0c3ef200bd447a1288409d Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:41:45 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 10)

---
 .../clang/Basic/DiagnosticSemaKinds.td|  4 ++
 clang/include/clang/Basic/LangOptions.def |  1 +
 clang/include/clang/Options/Options.td|  4 ++
 clang/lib/Driver/ToolChains/Clang.cpp |  1 +
 clang/lib/Sema/SemaExpand.cpp | 18 +
 .../SemaCXX/cxx2c-expansion-stmts-limit.cpp   | 68 +++
 .../SemaCXX/cxx2c-fexpansion-statements.cpp   |  9 +++
 7 files changed, 105 insertions(+)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-limit.cpp
 create mode 100644 clang/test/SemaCXX/cxx2c-fexpansion-statements.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index bf6d017e845fc..7b0e9be0484b9 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -167,6 +167,10 @@ def note_constexpr_assert_failed : Note<
   "assertion failed during evaluation of constant expression">;
 def err_expansion_size_expr_not_ice : Error<
   "expansion size is not a constant expression">;
+def err_expansion_too_big : Error<
+  "expansion size %0 exceeds maximum configured size %1">;
+def note_use_fexpansion_limit : Note<
+  "use -fexpansion-limit=N to adjust this limit">;
 
 // Semantic analysis of constant literals.
 def ext_predef_outside_function : Warning<
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 40fc66ea12e34..315cb4dc5e1cf 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -377,6 +377,7 @@ LANGOPT(ConstexprCallDepth, 32, 512, Benign,
 "maximum constexpr call depth")
 LANGOPT(ConstexprStepLimit, 32, 1048576, Benign,
 "maximum constexpr evaluation steps")
+LANGOPT(MaxTemplateForExpansions, 32, 256, Benign, "maximum template for 
expansions")
 LANGOPT(EnableNewConstInterp, 1, 0, Benign,
 "enable the experimental new constant interpreter")
 LANGOPT(BracketDepth, 32, 256, Benign,
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 0e88656c5e1bc..86867b4814eeb 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -2054,6 +2054,10 @@ def fconstexpr_steps_EQ : Joined<["-"], 
"fconstexpr-steps=">, Group,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Set the maximum number of steps in constexpr function evaluation 
(0 = no limit)">,
   MarshallingInfoInt, "1048576">;
+def fexpansion_limit_EQ : Joined<["-"], "fexpansion-limit=">, Group,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Set the maximum number of times a single expansion statement may 
be expanded (0 = no limit)">,
+  MarshallingInfoInt, "256">;
 def fexperimental_new_constant_interpreter : Flag<["-"], 
"fexperimental-new-constant-interpreter">, Group,
   HelpText<"Enable the experimental new constant interpreter">,
   Visibility<[ClangOption, CC1Option]>,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index c5d40c9825fab..649d4c3e4ca97 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6358,6 +6358,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_fexpansion_limit_EQ);
 
   Args.AddLastArg(CmdArgs, options::OPT_fexperimental_library);
 
diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp
index 6fa1ad9856783..8ca2b074acbea 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -44,6 +44,18 @@ struct IterableExpansionStmtData {
 };
 } // namespace
 
+static bool CheckExpansionSize(Sema &S, uint64_t NumInstantiations,
+   SourceLocation Loc) {
+  unsigned Max = S.LangOpts.MaxTemplateForExpansions;
+  if (Max != 0 && NumInstantiations > Max) {
+S.Diag(Loc, diag::err_expansion_too_big) << NumInstantiations << Max;
+S.Diag(Loc, diag::note_use_fexpansion_limit);
+return true;
+  }
+
+  return false;
+}
+
 // Build a 'DeclRefExpr' designating the template parameter '__N'.
 static DeclRefExpr *BuildIndexDRE(Sema &S, CXXExpansionStmtDecl *ESD) {
   return S.BuildDeclRefExpr(ESD->getIndexTemplateParm(),
@@ -245,6 +257,9 @@ static StmtResult BuildDestructuringDecompositionDecl(
 return StmtError();
   }
 
+  if (CheckExpansionSize(S, *Arity, ColonLoc))
+return StmtError();
+
   QualType AutoRRef = S.Context.getAutoRRefDeductType();

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 10: Expansion Limit) (PR #169689)

2025-12-03 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169689

>From e2a41057242421f63f0c3ef200bd447a1288409d Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:41:45 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 10)

---
 .../clang/Basic/DiagnosticSemaKinds.td|  4 ++
 clang/include/clang/Basic/LangOptions.def |  1 +
 clang/include/clang/Options/Options.td|  4 ++
 clang/lib/Driver/ToolChains/Clang.cpp |  1 +
 clang/lib/Sema/SemaExpand.cpp | 18 +
 .../SemaCXX/cxx2c-expansion-stmts-limit.cpp   | 68 +++
 .../SemaCXX/cxx2c-fexpansion-statements.cpp   |  9 +++
 7 files changed, 105 insertions(+)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-limit.cpp
 create mode 100644 clang/test/SemaCXX/cxx2c-fexpansion-statements.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index bf6d017e845fc..7b0e9be0484b9 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -167,6 +167,10 @@ def note_constexpr_assert_failed : Note<
   "assertion failed during evaluation of constant expression">;
 def err_expansion_size_expr_not_ice : Error<
   "expansion size is not a constant expression">;
+def err_expansion_too_big : Error<
+  "expansion size %0 exceeds maximum configured size %1">;
+def note_use_fexpansion_limit : Note<
+  "use -fexpansion-limit=N to adjust this limit">;
 
 // Semantic analysis of constant literals.
 def ext_predef_outside_function : Warning<
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 40fc66ea12e34..315cb4dc5e1cf 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -377,6 +377,7 @@ LANGOPT(ConstexprCallDepth, 32, 512, Benign,
 "maximum constexpr call depth")
 LANGOPT(ConstexprStepLimit, 32, 1048576, Benign,
 "maximum constexpr evaluation steps")
+LANGOPT(MaxTemplateForExpansions, 32, 256, Benign, "maximum template for 
expansions")
 LANGOPT(EnableNewConstInterp, 1, 0, Benign,
 "enable the experimental new constant interpreter")
 LANGOPT(BracketDepth, 32, 256, Benign,
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 0e88656c5e1bc..86867b4814eeb 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -2054,6 +2054,10 @@ def fconstexpr_steps_EQ : Joined<["-"], 
"fconstexpr-steps=">, Group,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Set the maximum number of steps in constexpr function evaluation 
(0 = no limit)">,
   MarshallingInfoInt, "1048576">;
+def fexpansion_limit_EQ : Joined<["-"], "fexpansion-limit=">, Group,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Set the maximum number of times a single expansion statement may 
be expanded (0 = no limit)">,
+  MarshallingInfoInt, "256">;
 def fexperimental_new_constant_interpreter : Flag<["-"], 
"fexperimental-new-constant-interpreter">, Group,
   HelpText<"Enable the experimental new constant interpreter">,
   Visibility<[ClangOption, CC1Option]>,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index c5d40c9825fab..649d4c3e4ca97 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6358,6 +6358,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_fexpansion_limit_EQ);
 
   Args.AddLastArg(CmdArgs, options::OPT_fexperimental_library);
 
diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp
index 6fa1ad9856783..8ca2b074acbea 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -44,6 +44,18 @@ struct IterableExpansionStmtData {
 };
 } // namespace
 
+static bool CheckExpansionSize(Sema &S, uint64_t NumInstantiations,
+   SourceLocation Loc) {
+  unsigned Max = S.LangOpts.MaxTemplateForExpansions;
+  if (Max != 0 && NumInstantiations > Max) {
+S.Diag(Loc, diag::err_expansion_too_big) << NumInstantiations << Max;
+S.Diag(Loc, diag::note_use_fexpansion_limit);
+return true;
+  }
+
+  return false;
+}
+
 // Build a 'DeclRefExpr' designating the template parameter '__N'.
 static DeclRefExpr *BuildIndexDRE(Sema &S, CXXExpansionStmtDecl *ESD) {
   return S.BuildDeclRefExpr(ESD->getIndexTemplateParm(),
@@ -245,6 +257,9 @@ static StmtResult BuildDestructuringDecompositionDecl(
 return StmtError();
   }
 
+  if (CheckExpansionSize(S, *Arity, ColonLoc))
+return StmtError();
+
   QualType AutoRRef = S.Context.getAutoRRefDeductType();

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 10: Expansion Limit) (PR #169689)

2025-12-02 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169689

>From 8e22321c5540419bde23f07f64164cf6685d0f64 Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:41:45 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 10)

---
 .../clang/Basic/DiagnosticSemaKinds.td|  4 ++
 clang/include/clang/Basic/LangOptions.def |  1 +
 clang/include/clang/Options/Options.td|  4 ++
 clang/lib/Driver/ToolChains/Clang.cpp |  1 +
 clang/lib/Sema/SemaExpand.cpp | 18 +
 .../SemaCXX/cxx2c-expansion-stmts-limit.cpp   | 68 +++
 .../SemaCXX/cxx2c-fexpansion-statements.cpp   |  9 +++
 7 files changed, 105 insertions(+)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-limit.cpp
 create mode 100644 clang/test/SemaCXX/cxx2c-fexpansion-statements.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index bf6d017e845fc..7b0e9be0484b9 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -167,6 +167,10 @@ def note_constexpr_assert_failed : Note<
   "assertion failed during evaluation of constant expression">;
 def err_expansion_size_expr_not_ice : Error<
   "expansion size is not a constant expression">;
+def err_expansion_too_big : Error<
+  "expansion size %0 exceeds maximum configured size %1">;
+def note_use_fexpansion_limit : Note<
+  "use -fexpansion-limit=N to adjust this limit">;
 
 // Semantic analysis of constant literals.
 def ext_predef_outside_function : Warning<
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 40fc66ea12e34..315cb4dc5e1cf 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -377,6 +377,7 @@ LANGOPT(ConstexprCallDepth, 32, 512, Benign,
 "maximum constexpr call depth")
 LANGOPT(ConstexprStepLimit, 32, 1048576, Benign,
 "maximum constexpr evaluation steps")
+LANGOPT(MaxTemplateForExpansions, 32, 256, Benign, "maximum template for 
expansions")
 LANGOPT(EnableNewConstInterp, 1, 0, Benign,
 "enable the experimental new constant interpreter")
 LANGOPT(BracketDepth, 32, 256, Benign,
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 0e88656c5e1bc..86867b4814eeb 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -2054,6 +2054,10 @@ def fconstexpr_steps_EQ : Joined<["-"], 
"fconstexpr-steps=">, Group,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Set the maximum number of steps in constexpr function evaluation 
(0 = no limit)">,
   MarshallingInfoInt, "1048576">;
+def fexpansion_limit_EQ : Joined<["-"], "fexpansion-limit=">, Group,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Set the maximum number of times a single expansion statement may 
be expanded (0 = no limit)">,
+  MarshallingInfoInt, "256">;
 def fexperimental_new_constant_interpreter : Flag<["-"], 
"fexperimental-new-constant-interpreter">, Group,
   HelpText<"Enable the experimental new constant interpreter">,
   Visibility<[ClangOption, CC1Option]>,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index c5d40c9825fab..649d4c3e4ca97 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6358,6 +6358,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_fexpansion_limit_EQ);
 
   Args.AddLastArg(CmdArgs, options::OPT_fexperimental_library);
 
diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp
index 532797c68b534..cb284cf08a03b 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -44,6 +44,18 @@ struct IterableExpansionStmtData {
 };
 } // namespace
 
+static bool CheckExpansionSize(Sema &S, uint64_t NumInstantiations,
+   SourceLocation Loc) {
+  unsigned Max = S.LangOpts.MaxTemplateForExpansions;
+  if (Max != 0 && NumInstantiations > Max) {
+S.Diag(Loc, diag::err_expansion_too_big) << NumInstantiations << Max;
+S.Diag(Loc, diag::note_use_fexpansion_limit);
+return true;
+  }
+
+  return false;
+}
+
 // Build a 'DeclRefExpr' designating the template parameter '__N'.
 static DeclRefExpr *BuildIndexDRE(Sema &S, CXXExpansionStmtDecl *ESD) {
   return S.BuildDeclRefExpr(ESD->getIndexTemplateParm(),
@@ -216,6 +228,9 @@ static StmtResult BuildDestructuringCXXExpansionStmt(
 return StmtError();
   }
 
+  if (CheckExpansionSize(S, *Arity, ColonLoc))
+return StmtError();
+
   QualType AutoRRef = S.Context.getAutoRRefDeductType();

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 10: Expansion Limit) (PR #169689)

2025-12-02 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169689

>From 8e22321c5540419bde23f07f64164cf6685d0f64 Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:41:45 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 10)

---
 .../clang/Basic/DiagnosticSemaKinds.td|  4 ++
 clang/include/clang/Basic/LangOptions.def |  1 +
 clang/include/clang/Options/Options.td|  4 ++
 clang/lib/Driver/ToolChains/Clang.cpp |  1 +
 clang/lib/Sema/SemaExpand.cpp | 18 +
 .../SemaCXX/cxx2c-expansion-stmts-limit.cpp   | 68 +++
 .../SemaCXX/cxx2c-fexpansion-statements.cpp   |  9 +++
 7 files changed, 105 insertions(+)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-limit.cpp
 create mode 100644 clang/test/SemaCXX/cxx2c-fexpansion-statements.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index bf6d017e845fc..7b0e9be0484b9 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -167,6 +167,10 @@ def note_constexpr_assert_failed : Note<
   "assertion failed during evaluation of constant expression">;
 def err_expansion_size_expr_not_ice : Error<
   "expansion size is not a constant expression">;
+def err_expansion_too_big : Error<
+  "expansion size %0 exceeds maximum configured size %1">;
+def note_use_fexpansion_limit : Note<
+  "use -fexpansion-limit=N to adjust this limit">;
 
 // Semantic analysis of constant literals.
 def ext_predef_outside_function : Warning<
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 40fc66ea12e34..315cb4dc5e1cf 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -377,6 +377,7 @@ LANGOPT(ConstexprCallDepth, 32, 512, Benign,
 "maximum constexpr call depth")
 LANGOPT(ConstexprStepLimit, 32, 1048576, Benign,
 "maximum constexpr evaluation steps")
+LANGOPT(MaxTemplateForExpansions, 32, 256, Benign, "maximum template for 
expansions")
 LANGOPT(EnableNewConstInterp, 1, 0, Benign,
 "enable the experimental new constant interpreter")
 LANGOPT(BracketDepth, 32, 256, Benign,
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 0e88656c5e1bc..86867b4814eeb 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -2054,6 +2054,10 @@ def fconstexpr_steps_EQ : Joined<["-"], 
"fconstexpr-steps=">, Group,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Set the maximum number of steps in constexpr function evaluation 
(0 = no limit)">,
   MarshallingInfoInt, "1048576">;
+def fexpansion_limit_EQ : Joined<["-"], "fexpansion-limit=">, Group,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Set the maximum number of times a single expansion statement may 
be expanded (0 = no limit)">,
+  MarshallingInfoInt, "256">;
 def fexperimental_new_constant_interpreter : Flag<["-"], 
"fexperimental-new-constant-interpreter">, Group,
   HelpText<"Enable the experimental new constant interpreter">,
   Visibility<[ClangOption, CC1Option]>,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index c5d40c9825fab..649d4c3e4ca97 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6358,6 +6358,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_fexpansion_limit_EQ);
 
   Args.AddLastArg(CmdArgs, options::OPT_fexperimental_library);
 
diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp
index 532797c68b534..cb284cf08a03b 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -44,6 +44,18 @@ struct IterableExpansionStmtData {
 };
 } // namespace
 
+static bool CheckExpansionSize(Sema &S, uint64_t NumInstantiations,
+   SourceLocation Loc) {
+  unsigned Max = S.LangOpts.MaxTemplateForExpansions;
+  if (Max != 0 && NumInstantiations > Max) {
+S.Diag(Loc, diag::err_expansion_too_big) << NumInstantiations << Max;
+S.Diag(Loc, diag::note_use_fexpansion_limit);
+return true;
+  }
+
+  return false;
+}
+
 // Build a 'DeclRefExpr' designating the template parameter '__N'.
 static DeclRefExpr *BuildIndexDRE(Sema &S, CXXExpansionStmtDecl *ESD) {
   return S.BuildDeclRefExpr(ESD->getIndexTemplateParm(),
@@ -216,6 +228,9 @@ static StmtResult BuildDestructuringCXXExpansionStmt(
 return StmtError();
   }
 
+  if (CheckExpansionSize(S, *Arity, ColonLoc))
+return StmtError();
+
   QualType AutoRRef = S.Context.getAutoRRefDeductType();

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 10: Expansion Limit) (PR #169689)

2025-12-01 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169689

>From 6b112812d9df5a60984a352906b9a18db40e2a1e Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:41:45 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 10)

---
 .../clang/Basic/DiagnosticSemaKinds.td|  4 ++
 clang/include/clang/Basic/LangOptions.def |  1 +
 clang/include/clang/Options/Options.td|  4 ++
 clang/lib/Driver/ToolChains/Clang.cpp |  1 +
 clang/lib/Sema/SemaExpand.cpp | 18 +
 .../SemaCXX/cxx2c-expansion-stmts-limit.cpp   | 68 +++
 .../SemaCXX/cxx2c-fexpansion-statements.cpp   |  9 +++
 7 files changed, 105 insertions(+)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-limit.cpp
 create mode 100644 clang/test/SemaCXX/cxx2c-fexpansion-statements.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 5115c175849e1..222d587b48a0b 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -169,6 +169,10 @@ def err_expansion_size_expr_not_ice : Error<
   "expansion size is not a constant expression">;
 def err_expansion_size_negative : Error<
   "expansion size must not be negative (was %0)">;
+def err_expansion_too_big : Error<
+  "expansion size %0 exceeds maximum configured size %1">;
+def note_use_fexpansion_limit : Note<
+  "use -fexpansion-limit=N to adjust this limit">;
 
 // Semantic analysis of constant literals.
 def ext_predef_outside_function : Warning<
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 40fc66ea12e34..315cb4dc5e1cf 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -377,6 +377,7 @@ LANGOPT(ConstexprCallDepth, 32, 512, Benign,
 "maximum constexpr call depth")
 LANGOPT(ConstexprStepLimit, 32, 1048576, Benign,
 "maximum constexpr evaluation steps")
+LANGOPT(MaxTemplateForExpansions, 32, 256, Benign, "maximum template for 
expansions")
 LANGOPT(EnableNewConstInterp, 1, 0, Benign,
 "enable the experimental new constant interpreter")
 LANGOPT(BracketDepth, 32, 256, Benign,
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 0e88656c5e1bc..86867b4814eeb 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -2054,6 +2054,10 @@ def fconstexpr_steps_EQ : Joined<["-"], 
"fconstexpr-steps=">, Group,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Set the maximum number of steps in constexpr function evaluation 
(0 = no limit)">,
   MarshallingInfoInt, "1048576">;
+def fexpansion_limit_EQ : Joined<["-"], "fexpansion-limit=">, Group,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Set the maximum number of times a single expansion statement may 
be expanded (0 = no limit)">,
+  MarshallingInfoInt, "256">;
 def fexperimental_new_constant_interpreter : Flag<["-"], 
"fexperimental-new-constant-interpreter">, Group,
   HelpText<"Enable the experimental new constant interpreter">,
   Visibility<[ClangOption, CC1Option]>,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index c5d40c9825fab..649d4c3e4ca97 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6358,6 +6358,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_fexpansion_limit_EQ);
 
   Args.AddLastArg(CmdArgs, options::OPT_fexperimental_library);
 
diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp
index fcc951503deb9..ad481df7e7d6a 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -43,6 +43,18 @@ struct IterableExpansionStmtData {
 };
 } // namespace
 
+static bool CheckExpansionSize(Sema &S, uint64_t NumInstantiations,
+   SourceLocation Loc) {
+  unsigned Max = S.LangOpts.MaxTemplateForExpansions;
+  if (Max != 0 && NumInstantiations > Max) {
+S.Diag(Loc, diag::err_expansion_too_big) << NumInstantiations << Max;
+S.Diag(Loc, diag::note_use_fexpansion_limit);
+return true;
+  }
+
+  return false;
+}
+
 // Build a 'DeclRefExpr' designating the template parameter '__N'.
 static DeclRefExpr *BuildIndexDRE(Sema &S, CXXExpansionStmtDecl *ESD) {
   return S.BuildDeclRefExpr(ESD->getIndexTemplateParm(),
@@ -198,6 +210,9 @@ static StmtResult BuildDestructuringCXXExpansionStmt(
 return StmtError();
   }
 
+  if (CheckExpansionSize(S, *Arity, ColonLoc))
+return StmtError();
+
   QualType AutoRRef = S.Context.getAutoRRefDeductType();
   SmallVecto

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 10: Expansion Limit) (PR #169689)

2025-12-01 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169689

>From 6b112812d9df5a60984a352906b9a18db40e2a1e Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:41:45 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 10)

---
 .../clang/Basic/DiagnosticSemaKinds.td|  4 ++
 clang/include/clang/Basic/LangOptions.def |  1 +
 clang/include/clang/Options/Options.td|  4 ++
 clang/lib/Driver/ToolChains/Clang.cpp |  1 +
 clang/lib/Sema/SemaExpand.cpp | 18 +
 .../SemaCXX/cxx2c-expansion-stmts-limit.cpp   | 68 +++
 .../SemaCXX/cxx2c-fexpansion-statements.cpp   |  9 +++
 7 files changed, 105 insertions(+)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-limit.cpp
 create mode 100644 clang/test/SemaCXX/cxx2c-fexpansion-statements.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 5115c175849e1..222d587b48a0b 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -169,6 +169,10 @@ def err_expansion_size_expr_not_ice : Error<
   "expansion size is not a constant expression">;
 def err_expansion_size_negative : Error<
   "expansion size must not be negative (was %0)">;
+def err_expansion_too_big : Error<
+  "expansion size %0 exceeds maximum configured size %1">;
+def note_use_fexpansion_limit : Note<
+  "use -fexpansion-limit=N to adjust this limit">;
 
 // Semantic analysis of constant literals.
 def ext_predef_outside_function : Warning<
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 40fc66ea12e34..315cb4dc5e1cf 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -377,6 +377,7 @@ LANGOPT(ConstexprCallDepth, 32, 512, Benign,
 "maximum constexpr call depth")
 LANGOPT(ConstexprStepLimit, 32, 1048576, Benign,
 "maximum constexpr evaluation steps")
+LANGOPT(MaxTemplateForExpansions, 32, 256, Benign, "maximum template for 
expansions")
 LANGOPT(EnableNewConstInterp, 1, 0, Benign,
 "enable the experimental new constant interpreter")
 LANGOPT(BracketDepth, 32, 256, Benign,
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 0e88656c5e1bc..86867b4814eeb 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -2054,6 +2054,10 @@ def fconstexpr_steps_EQ : Joined<["-"], 
"fconstexpr-steps=">, Group,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Set the maximum number of steps in constexpr function evaluation 
(0 = no limit)">,
   MarshallingInfoInt, "1048576">;
+def fexpansion_limit_EQ : Joined<["-"], "fexpansion-limit=">, Group,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Set the maximum number of times a single expansion statement may 
be expanded (0 = no limit)">,
+  MarshallingInfoInt, "256">;
 def fexperimental_new_constant_interpreter : Flag<["-"], 
"fexperimental-new-constant-interpreter">, Group,
   HelpText<"Enable the experimental new constant interpreter">,
   Visibility<[ClangOption, CC1Option]>,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index c5d40c9825fab..649d4c3e4ca97 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6358,6 +6358,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_fexpansion_limit_EQ);
 
   Args.AddLastArg(CmdArgs, options::OPT_fexperimental_library);
 
diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp
index fcc951503deb9..ad481df7e7d6a 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -43,6 +43,18 @@ struct IterableExpansionStmtData {
 };
 } // namespace
 
+static bool CheckExpansionSize(Sema &S, uint64_t NumInstantiations,
+   SourceLocation Loc) {
+  unsigned Max = S.LangOpts.MaxTemplateForExpansions;
+  if (Max != 0 && NumInstantiations > Max) {
+S.Diag(Loc, diag::err_expansion_too_big) << NumInstantiations << Max;
+S.Diag(Loc, diag::note_use_fexpansion_limit);
+return true;
+  }
+
+  return false;
+}
+
 // Build a 'DeclRefExpr' designating the template parameter '__N'.
 static DeclRefExpr *BuildIndexDRE(Sema &S, CXXExpansionStmtDecl *ESD) {
   return S.BuildDeclRefExpr(ESD->getIndexTemplateParm(),
@@ -198,6 +210,9 @@ static StmtResult BuildDestructuringCXXExpansionStmt(
 return StmtError();
   }
 
+  if (CheckExpansionSize(S, *Arity, ColonLoc))
+return StmtError();
+
   QualType AutoRRef = S.Context.getAutoRRefDeductType();
   SmallVecto

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 10: Expansion Limit) (PR #169689)

2025-11-28 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169689

>From 9a24859aeed9d3ad198d2d57b34c96b653d0fa0f Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:41:45 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 10)

---
 .../clang/Basic/DiagnosticSemaKinds.td|  4 ++
 clang/include/clang/Basic/LangOptions.def |  1 +
 clang/include/clang/Options/Options.td|  4 ++
 clang/lib/Driver/ToolChains/Clang.cpp |  1 +
 clang/lib/Sema/SemaExpand.cpp | 18 +
 .../SemaCXX/cxx2c-expansion-stmts-limit.cpp   | 68 +++
 .../SemaCXX/cxx2c-fexpansion-statements.cpp   |  9 +++
 7 files changed, 105 insertions(+)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-limit.cpp
 create mode 100644 clang/test/SemaCXX/cxx2c-fexpansion-statements.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 5115c175849e1..222d587b48a0b 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -169,6 +169,10 @@ def err_expansion_size_expr_not_ice : Error<
   "expansion size is not a constant expression">;
 def err_expansion_size_negative : Error<
   "expansion size must not be negative (was %0)">;
+def err_expansion_too_big : Error<
+  "expansion size %0 exceeds maximum configured size %1">;
+def note_use_fexpansion_limit : Note<
+  "use -fexpansion-limit=N to adjust this limit">;
 
 // Semantic analysis of constant literals.
 def ext_predef_outside_function : Warning<
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 40fc66ea12e34..315cb4dc5e1cf 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -377,6 +377,7 @@ LANGOPT(ConstexprCallDepth, 32, 512, Benign,
 "maximum constexpr call depth")
 LANGOPT(ConstexprStepLimit, 32, 1048576, Benign,
 "maximum constexpr evaluation steps")
+LANGOPT(MaxTemplateForExpansions, 32, 256, Benign, "maximum template for 
expansions")
 LANGOPT(EnableNewConstInterp, 1, 0, Benign,
 "enable the experimental new constant interpreter")
 LANGOPT(BracketDepth, 32, 256, Benign,
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 0e88656c5e1bc..86867b4814eeb 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -2054,6 +2054,10 @@ def fconstexpr_steps_EQ : Joined<["-"], 
"fconstexpr-steps=">, Group,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Set the maximum number of steps in constexpr function evaluation 
(0 = no limit)">,
   MarshallingInfoInt, "1048576">;
+def fexpansion_limit_EQ : Joined<["-"], "fexpansion-limit=">, Group,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Set the maximum number of times a single expansion statement may 
be expanded (0 = no limit)">,
+  MarshallingInfoInt, "256">;
 def fexperimental_new_constant_interpreter : Flag<["-"], 
"fexperimental-new-constant-interpreter">, Group,
   HelpText<"Enable the experimental new constant interpreter">,
   Visibility<[ClangOption, CC1Option]>,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index c5d40c9825fab..649d4c3e4ca97 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6358,6 +6358,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_fexpansion_limit_EQ);
 
   Args.AddLastArg(CmdArgs, options::OPT_fexperimental_library);
 
diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp
index fcc951503deb9..ad481df7e7d6a 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -43,6 +43,18 @@ struct IterableExpansionStmtData {
 };
 } // namespace
 
+static bool CheckExpansionSize(Sema &S, uint64_t NumInstantiations,
+   SourceLocation Loc) {
+  unsigned Max = S.LangOpts.MaxTemplateForExpansions;
+  if (Max != 0 && NumInstantiations > Max) {
+S.Diag(Loc, diag::err_expansion_too_big) << NumInstantiations << Max;
+S.Diag(Loc, diag::note_use_fexpansion_limit);
+return true;
+  }
+
+  return false;
+}
+
 // Build a 'DeclRefExpr' designating the template parameter '__N'.
 static DeclRefExpr *BuildIndexDRE(Sema &S, CXXExpansionStmtDecl *ESD) {
   return S.BuildDeclRefExpr(ESD->getIndexTemplateParm(),
@@ -198,6 +210,9 @@ static StmtResult BuildDestructuringCXXExpansionStmt(
 return StmtError();
   }
 
+  if (CheckExpansionSize(S, *Arity, ColonLoc))
+return StmtError();
+
   QualType AutoRRef = S.Context.getAutoRRefDeductType();
   SmallVecto

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 10: Expansion Limit) (PR #169689)

2025-11-28 Thread via llvm-branch-commits

https://github.com/Sirraide ready_for_review 
https://github.com/llvm/llvm-project/pull/169689
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 10: Expansion Limit) (PR #169689)

2025-11-28 Thread via llvm-branch-commits

https://github.com/Sirraide edited 
https://github.com/llvm/llvm-project/pull/169689
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 10: Expansion Limit) (PR #169689)

2025-11-28 Thread via llvm-branch-commits

llvmbot wrote:




@llvm/pr-subscribers-clang-codegen

Author: None (Sirraide)


Changes



---
Full diff: https://github.com/llvm/llvm-project/pull/169689.diff


7 Files Affected:

- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+4) 
- (modified) clang/include/clang/Basic/LangOptions.def (+1) 
- (modified) clang/include/clang/Options/Options.td (+4) 
- (modified) clang/lib/Driver/ToolChains/Clang.cpp (+1) 
- (modified) clang/lib/Sema/SemaExpand.cpp (+18) 
- (added) clang/test/SemaCXX/cxx2c-expansion-stmts-limit.cpp (+68) 
- (added) clang/test/SemaCXX/cxx2c-fexpansion-statements.cpp (+9) 


``diff
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 5115c175849e1..222d587b48a0b 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -169,6 +169,10 @@ def err_expansion_size_expr_not_ice : Error<
   "expansion size is not a constant expression">;
 def err_expansion_size_negative : Error<
   "expansion size must not be negative (was %0)">;
+def err_expansion_too_big : Error<
+  "expansion size %0 exceeds maximum configured size %1">;
+def note_use_fexpansion_limit : Note<
+  "use -fexpansion-limit=N to adjust this limit">;
 
 // Semantic analysis of constant literals.
 def ext_predef_outside_function : Warning<
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 40fc66ea12e34..315cb4dc5e1cf 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -377,6 +377,7 @@ LANGOPT(ConstexprCallDepth, 32, 512, Benign,
 "maximum constexpr call depth")
 LANGOPT(ConstexprStepLimit, 32, 1048576, Benign,
 "maximum constexpr evaluation steps")
+LANGOPT(MaxTemplateForExpansions, 32, 256, Benign, "maximum template for 
expansions")
 LANGOPT(EnableNewConstInterp, 1, 0, Benign,
 "enable the experimental new constant interpreter")
 LANGOPT(BracketDepth, 32, 256, Benign,
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 0e88656c5e1bc..86867b4814eeb 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -2054,6 +2054,10 @@ def fconstexpr_steps_EQ : Joined<["-"], 
"fconstexpr-steps=">, Group,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Set the maximum number of steps in constexpr function evaluation 
(0 = no limit)">,
   MarshallingInfoInt, "1048576">;
+def fexpansion_limit_EQ : Joined<["-"], "fexpansion-limit=">, Group,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Set the maximum number of times a single expansion statement may 
be expanded (0 = no limit)">,
+  MarshallingInfoInt, "256">;
 def fexperimental_new_constant_interpreter : Flag<["-"], 
"fexperimental-new-constant-interpreter">, Group,
   HelpText<"Enable the experimental new constant interpreter">,
   Visibility<[ClangOption, CC1Option]>,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index c5d40c9825fab..649d4c3e4ca97 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6358,6 +6358,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_fexpansion_limit_EQ);
 
   Args.AddLastArg(CmdArgs, options::OPT_fexperimental_library);
 
diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp
index fcc951503deb9..ad481df7e7d6a 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -43,6 +43,18 @@ struct IterableExpansionStmtData {
 };
 } // namespace
 
+static bool CheckExpansionSize(Sema &S, uint64_t NumInstantiations,
+   SourceLocation Loc) {
+  unsigned Max = S.LangOpts.MaxTemplateForExpansions;
+  if (Max != 0 && NumInstantiations > Max) {
+S.Diag(Loc, diag::err_expansion_too_big) << NumInstantiations << Max;
+S.Diag(Loc, diag::note_use_fexpansion_limit);
+return true;
+  }
+
+  return false;
+}
+
 // Build a 'DeclRefExpr' designating the template parameter '__N'.
 static DeclRefExpr *BuildIndexDRE(Sema &S, CXXExpansionStmtDecl *ESD) {
   return S.BuildDeclRefExpr(ESD->getIndexTemplateParm(),
@@ -198,6 +210,9 @@ static StmtResult BuildDestructuringCXXExpansionStmt(
 return StmtError();
   }
 
+  if (CheckExpansionSize(S, *Arity, ColonLoc))
+return StmtError();
+
   QualType AutoRRef = S.Context.getAutoRRefDeductType();
   SmallVector Bindings;
   for (unsigned I = 0; I < *Arity; ++I)
@@ -399,6 +414,9 @@ StmtResult Sema::FinishCXXExpansionStmt(Stmt *Exp, Stmt 
*Body) {
   if (!NumInstantiations)
 return StmtError();
 
+  if (CheckExpansionSize(*this, *NumInstant

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 10: Expansion Limit) (PR #169689)

2025-11-28 Thread via llvm-branch-commits

https://github.com/Sirraide edited 
https://github.com/llvm/llvm-project/pull/169689
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits