[clang] Limit the maximum level of fold-expr expansion.

Introduce a new diagnostic, and respect the bracket-depth (256) by default.

Differential Revision: https://reviews.llvm.org/D86936
This commit is contained in:
Haojian Wu 2020-09-08 15:34:52 +02:00
parent 156b127945
commit 9c9974c3cc
3 changed files with 25 additions and 0 deletions

View File

@ -5092,6 +5092,9 @@ def err_fold_expression_empty : Error<
"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">;

View File

@ -28,6 +28,7 @@
#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"
@ -13193,6 +13194,18 @@ TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) {
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());

View File

@ -0,0 +1,9 @@
// 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}}