llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-codegen

Author: None (Sirraide)

<details>
<summary>Changes</summary>



---
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<f_Group>,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Set the maximum number of steps in constexpr function evaluation 
(0 = no limit)">,
   MarshallingInfoInt<LangOpts<"ConstexprStepLimit">, "1048576">;
+def fexpansion_limit_EQ : Joined<["-"], "fexpansion-limit=">, Group<f_Group>,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Set the maximum number of times a single expansion statement may 
be expanded (0 = no limit)">,
+  MarshallingInfoInt<LangOpts<"MaxTemplateForExpansions">, "256">;
 def fexperimental_new_constant_interpreter : Flag<["-"], 
"fexperimental-new-constant-interpreter">, Group<f_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<BindingDecl *> 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, *NumInstantiations, Expansion->getColonLoc()))
+    return StmtError();
+
   // Collect shared statements.
   SmallVector<Stmt *, 1> Shared;
   if (Expansion->getInit())
diff --git a/clang/test/SemaCXX/cxx2c-expansion-stmts-limit.cpp 
b/clang/test/SemaCXX/cxx2c-expansion-stmts-limit.cpp
new file mode 100644
index 0000000000000..8411d6987565c
--- /dev/null
+++ b/clang/test/SemaCXX/cxx2c-expansion-stmts-limit.cpp
@@ -0,0 +1,68 @@
+// RUN: %clang_cc1 %s -std=c++2c -fsyntax-only -fexpansion-limit=32 -verify
+
+void g(int);
+
+template <__SIZE_TYPE__ size>
+struct String {
+  char data[size];
+
+  template <__SIZE_TYPE__ n>
+  constexpr String(const char (&str)[n]) { __builtin_memcpy(data, str, n); }
+
+  constexpr const char* begin() const { return data; }
+  constexpr const char* end() const { return data + size - 1; }
+};
+
+template <__SIZE_TYPE__ n>
+String(const char (&str)[n]) -> String<n>;
+
+template <typename T, __SIZE_TYPE__ size>
+struct Array {
+  T data[size]{};
+  constexpr const T* begin() const { return data; }
+  constexpr const T* end() const { return data + size; }
+};
+
+void expansion_size() {
+  static constexpr Array<int, 32> almost_too_big;
+  template for (auto x : almost_too_big) g(x);
+  template for (constexpr auto x : almost_too_big) g(x);
+
+  static constexpr Array<int, 33> too_big;
+  template for (auto x : too_big) g(x); // expected-error {{expansion size 33 
exceeds maximum configured size 32}} expected-note {{use -fexpansion-limit=N to 
adjust this limit}}
+  template for (constexpr auto x : too_big) g(x); // expected-error 
{{expansion size 33 exceeds maximum configured size 32}} expected-note {{use 
-fexpansion-limit=N to adjust this limit}}
+
+  static constexpr String 
big{"1234567890123456789012345678901234567890234567890"};
+  template for (auto x : big) g(x); // expected-error {{expansion size 49 
exceeds maximum configured size 32}} expected-note {{use -fexpansion-limit=N to 
adjust this limit}}
+  template for (constexpr auto x : big) g(x); // expected-error {{expansion 
size 49 exceeds maximum configured size 32}} expected-note {{use 
-fexpansion-limit=N to adjust this limit}}
+
+  template for (auto x : {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+    11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+    21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+    31, 32}) g(x);
+  template for (constexpr auto x : {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+    11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+    21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+    31, 32}) g(x);
+
+  template for (auto x : {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, // expected-error 
{{expansion size 33 exceeds maximum configured size 32}} expected-note {{use 
-fexpansion-limit=N to adjust this limit}}
+    11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+    21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+    31, 32, 33}) g(x);
+  template for (constexpr auto x : {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, // 
expected-error {{expansion size 33 exceeds maximum configured size 32}} 
expected-note {{use -fexpansion-limit=N to adjust this limit}}
+    11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+    21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+    31, 32, 33}) g(x);
+
+  int huge[1'000'000'000];
+  template for (auto x : huge) {} // expected-error {{expansion size 
1000000000 exceeds maximum configured size 32}} expected-note {{use 
-fexpansion-limit=N to adjust this limit}}
+}
+
+void array_too_big() {
+  int ok[32];
+  int too_big[33];
+
+  template for (auto x : ok) {}
+  template for (auto x : too_big) {} // expected-error {{expansion size 33 
exceeds maximum configured size 32}} \
+                                        expected-note {{use 
-fexpansion-limit=N to adjust this limit}}
+}
diff --git a/clang/test/SemaCXX/cxx2c-fexpansion-statements.cpp 
b/clang/test/SemaCXX/cxx2c-fexpansion-statements.cpp
new file mode 100644
index 0000000000000..2c80c392e400d
--- /dev/null
+++ b/clang/test/SemaCXX/cxx2c-fexpansion-statements.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 %s -std=c++2c -fsyntax-only -fexpansion-limit=0 -verify
+// expected-no-diagnostics
+
+// Test that passing =0 disables the limit.
+
+void big() {
+  int ok[500];
+  template for (auto x : ok) {}
+}

``````````

</details>


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

Reply via email to