Author: rsmith Date: Mon May 13 01:31:14 2019 New Revision: 360563 URL: http://llvm.org/viewvc/llvm-project?rev=360563&view=rev Log: PR41845: Detect and reject mismatched inner/outer pack expansion sizes in fold expressions rather than crashing.
Modified: cfe/trunk/include/clang/AST/ExprCXX.h cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp cfe/trunk/lib/Sema/TreeTransform.h cfe/trunk/lib/Serialization/ASTReaderStmt.cpp cfe/trunk/lib/Serialization/ASTWriterStmt.cpp cfe/trunk/test/SemaTemplate/cxx1z-fold-expressions.cpp Modified: cfe/trunk/include/clang/AST/ExprCXX.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=360563&r1=360562&r2=360563&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/ExprCXX.h (original) +++ cfe/trunk/include/clang/AST/ExprCXX.h Mon May 13 01:31:14 2019 @@ -4436,18 +4436,21 @@ class CXXFoldExpr : public Expr { SourceLocation LParenLoc; SourceLocation EllipsisLoc; SourceLocation RParenLoc; + // When 0, the number of expansions is not known. Otherwise, this is one more + // than the number of expansions. + unsigned NumExpansions; Stmt *SubExprs[2]; BinaryOperatorKind Opcode; public: CXXFoldExpr(QualType T, SourceLocation LParenLoc, Expr *LHS, BinaryOperatorKind Opcode, SourceLocation EllipsisLoc, Expr *RHS, - SourceLocation RParenLoc) + SourceLocation RParenLoc, Optional<unsigned> NumExpansions) : Expr(CXXFoldExprClass, T, VK_RValue, OK_Ordinary, /*Dependent*/ true, true, true, /*ContainsUnexpandedParameterPack*/ false), LParenLoc(LParenLoc), EllipsisLoc(EllipsisLoc), RParenLoc(RParenLoc), - Opcode(Opcode) { + NumExpansions(NumExpansions ? *NumExpansions + 1 : 0), Opcode(Opcode) { SubExprs[0] = LHS; SubExprs[1] = RHS; } @@ -4474,6 +4477,12 @@ public: SourceLocation getEllipsisLoc() const { return EllipsisLoc; } BinaryOperatorKind getOperator() const { return Opcode; } + Optional<unsigned> getNumExpansions() const { + if (NumExpansions) + return NumExpansions - 1; + return None; + } + SourceLocation getBeginLoc() const LLVM_READONLY { return LParenLoc; } SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=360563&r1=360562&r2=360563&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Mon May 13 01:31:14 2019 @@ -5204,7 +5204,8 @@ public: ExprResult BuildCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS, BinaryOperatorKind Operator, SourceLocation EllipsisLoc, Expr *RHS, - SourceLocation RParenLoc); + SourceLocation RParenLoc, + Optional<unsigned> NumExpansions); ExprResult BuildEmptyCXXFoldExpr(SourceLocation EllipsisLoc, BinaryOperatorKind Operator); Modified: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp?rev=360563&r1=360562&r2=360563&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp Mon May 13 01:31:14 2019 @@ -1176,15 +1176,18 @@ ExprResult Sema::ActOnCXXFoldExpr(Source } BinaryOperatorKind Opc = ConvertTokenKindToBinaryOpcode(Operator); - return BuildCXXFoldExpr(LParenLoc, LHS, Opc, EllipsisLoc, RHS, RParenLoc); + return BuildCXXFoldExpr(LParenLoc, LHS, Opc, EllipsisLoc, RHS, RParenLoc, + None); } ExprResult Sema::BuildCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS, BinaryOperatorKind Operator, SourceLocation EllipsisLoc, Expr *RHS, - SourceLocation RParenLoc) { + SourceLocation RParenLoc, + Optional<unsigned> NumExpansions) { return new (Context) CXXFoldExpr(Context.DependentTy, LParenLoc, LHS, - Operator, EllipsisLoc, RHS, RParenLoc); + Operator, EllipsisLoc, RHS, RParenLoc, + NumExpansions); } ExprResult Sema::BuildEmptyCXXFoldExpr(SourceLocation EllipsisLoc, Modified: cfe/trunk/lib/Sema/TreeTransform.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=360563&r1=360562&r2=360563&view=diff ============================================================================== --- cfe/trunk/lib/Sema/TreeTransform.h (original) +++ cfe/trunk/lib/Sema/TreeTransform.h Mon May 13 01:31:14 2019 @@ -3254,9 +3254,10 @@ public: ExprResult RebuildCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS, BinaryOperatorKind Operator, SourceLocation EllipsisLoc, Expr *RHS, - SourceLocation RParenLoc) { + SourceLocation RParenLoc, + Optional<unsigned> NumExpansions) { return getSema().BuildCXXFoldExpr(LParenLoc, LHS, Operator, EllipsisLoc, - RHS, RParenLoc); + RHS, RParenLoc, NumExpansions); } /// Build an empty C++1z fold-expression with the given operator. @@ -11823,7 +11824,8 @@ TreeTransform<Derived>::TransformCXXFold // be expanded. bool Expand = true; bool RetainExpansion = false; - Optional<unsigned> NumExpansions; + Optional<unsigned> OrigNumExpansions = E->getNumExpansions(), + NumExpansions = OrigNumExpansions; if (getDerived().TryExpandParameterPacks(E->getEllipsisLoc(), Pattern->getSourceRange(), Unexpanded, @@ -11852,7 +11854,7 @@ TreeTransform<Derived>::TransformCXXFold return getDerived().RebuildCXXFoldExpr( E->getBeginLoc(), LHS.get(), E->getOperator(), E->getEllipsisLoc(), - RHS.get(), E->getEndLoc()); + RHS.get(), E->getEndLoc(), NumExpansions); } // The transform has determined that we should perform an elementwise @@ -11873,7 +11875,7 @@ TreeTransform<Derived>::TransformCXXFold Result = getDerived().RebuildCXXFoldExpr( E->getBeginLoc(), Out.get(), E->getOperator(), E->getEllipsisLoc(), - Result.get(), E->getEndLoc()); + Result.get(), E->getEndLoc(), OrigNumExpansions); if (Result.isInvalid()) return true; } @@ -11890,7 +11892,8 @@ TreeTransform<Derived>::TransformCXXFold Result = getDerived().RebuildCXXFoldExpr( E->getBeginLoc(), LeftFold ? Result.get() : Out.get(), E->getOperator(), E->getEllipsisLoc(), - LeftFold ? Out.get() : Result.get(), E->getEndLoc()); + LeftFold ? Out.get() : Result.get(), E->getEndLoc(), + OrigNumExpansions); } else if (Result.isUsable()) { // We've got down to a single element; build a binary operator. Result = getDerived().RebuildBinaryOperator( @@ -11915,7 +11918,7 @@ TreeTransform<Derived>::TransformCXXFold Result = getDerived().RebuildCXXFoldExpr( E->getBeginLoc(), Result.get(), E->getOperator(), E->getEllipsisLoc(), - Out.get(), E->getEndLoc()); + Out.get(), E->getEndLoc(), OrigNumExpansions); if (Result.isInvalid()) return true; } Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=360563&r1=360562&r2=360563&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Mon May 13 01:31:14 2019 @@ -1810,6 +1810,7 @@ void ASTStmtReader::VisitCXXFoldExpr(CXX E->LParenLoc = ReadSourceLocation(); E->EllipsisLoc = ReadSourceLocation(); E->RParenLoc = ReadSourceLocation(); + E->NumExpansions = Record.readInt(); E->SubExprs[0] = Record.readSubExpr(); E->SubExprs[1] = Record.readSubExpr(); E->Opcode = (BinaryOperatorKind)Record.readInt(); Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=360563&r1=360562&r2=360563&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original) +++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Mon May 13 01:31:14 2019 @@ -1780,6 +1780,7 @@ void ASTStmtWriter::VisitCXXFoldExpr(CXX Record.AddSourceLocation(E->LParenLoc); Record.AddSourceLocation(E->EllipsisLoc); Record.AddSourceLocation(E->RParenLoc); + Record.push_back(E->NumExpansions); Record.AddStmt(E->SubExprs[0]); Record.AddStmt(E->SubExprs[1]); Record.push_back(E->Opcode); Modified: cfe/trunk/test/SemaTemplate/cxx1z-fold-expressions.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/cxx1z-fold-expressions.cpp?rev=360563&r1=360562&r2=360563&view=diff ============================================================================== --- cfe/trunk/test/SemaTemplate/cxx1z-fold-expressions.cpp (original) +++ cfe/trunk/test/SemaTemplate/cxx1z-fold-expressions.cpp Mon May 13 01:31:14 2019 @@ -92,3 +92,13 @@ template<typename ...T> constexpr auto s template<typename ...T> constexpr auto binary_conditional1(T ...t) { return (t ?: ...); } // expected-error {{expected expression}} template<typename ...T> constexpr auto binary_conditional2(T ...t) { return (... ?: t); } // expected-error {{expected expression}} template<typename ...T> constexpr auto binary_conditional3(T ...t) { return (t ?: ... ?: 0); } // expected-error {{expected expression}} + +namespace PR41845 { + template <int I> struct Constant {}; + + template <int... Is> struct Sum { + template <int... Js> using type = Constant<((Is + Js) + ... + 0)>; // expected-error {{pack expansion contains parameter pack 'Js' that has a different length (1 vs. 2) from outer parameter packs}} + }; + + Sum<1>::type<1, 2> x; // expected-note {{instantiation of}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits