"with no fallback value">;
def err_fold_expression_bad_operand : Error<
"expression not permitted as operand of fold expression">;
+def err_fold_expression_limit_exceeded: Error<
+ "instantiating fold expression with %0 arguments exceeded expression nesting "
+ "limit of %1">, DefaultFatal, NoSFINAE;
def err_unexpected_typedef : Error<
"unexpected type name %0: expected expression">;
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/AST/StmtOpenMP.h"
+#include "clang/Basic/DiagnosticParse.h"
#include "clang/Basic/OpenMPKinds.h"
#include "clang/Sema/Designator.h"
#include "clang/Sema/Lookup.h"
E->getEllipsisLoc(), RHS.get(), E->getEndLoc(), NumExpansions);
}
+ // Formally a fold expression expands to nested parenthesized expressions.
+ // Enforce this limit to avoid creating trees so deep we can't safely traverse
+ // them.
+ if (NumExpansions && SemaRef.getLangOpts().BracketDepth < NumExpansions) {
+ SemaRef.Diag(E->getEllipsisLoc(),
+ clang::diag::err_fold_expression_limit_exceeded)
+ << *NumExpansions << SemaRef.getLangOpts().BracketDepth
+ << E->getSourceRange();
+ SemaRef.Diag(E->getEllipsisLoc(), diag::note_bracket_depth);
+ return ExprError();
+ }
+
// The transform has determined that we should perform an elementwise
// expansion of the pattern. Do so.
ExprResult Result = getDerived().TransformExpr(E->getInit());
--- /dev/null
+// RUN: %clang_cc1 -fsyntax-only -fbracket-depth 2 -verify -std=c++17 %s
+
+template <class T, T... V> struct seq {
+ constexpr bool zero() { return (true && ... && (V == 0)); }; // expected-error {{instantiating fold expression with 3 arguments exceeded expression nesting limit of 2}} \
+ expected-note {{use -fbracket-depth}}
+};
+constexpr unsigned N = 3;
+auto x = __make_integer_seq<seq, int, N>{};
+static_assert(!x.zero(), ""); // expected-note {{in instantiation of member function}}