From 9c9974c3ccb6468cc83f759240293538cf123fcd Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Tue, 8 Sep 2020 15:34:52 +0200 Subject: [PATCH] [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 --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 3 +++ clang/lib/Sema/TreeTransform.h | 13 +++++++++++++ clang/test/SemaCXX/fold_expr_expansion_limit.cpp | 9 +++++++++ 3 files changed, 25 insertions(+) create mode 100644 clang/test/SemaCXX/fold_expr_expansion_limit.cpp diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index e1601da..ec0c0fd 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -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">; diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 4c8293f..6457b19 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -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::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()); diff --git a/clang/test/SemaCXX/fold_expr_expansion_limit.cpp b/clang/test/SemaCXX/fold_expr_expansion_limit.cpp new file mode 100644 index 0000000..600278d --- /dev/null +++ b/clang/test/SemaCXX/fold_expr_expansion_limit.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -fbracket-depth 2 -verify -std=c++17 %s + +template 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{}; +static_assert(!x.zero(), ""); // expected-note {{in instantiation of member function}} -- 2.7.4