Hi, it looks like this broke check-clang-tools, see e.g. http://45.33.8.238/linux/24975/step_8.txt
Nico On Thu, Aug 6, 2020 at 7:57 PM Richard Smith via cfe-commits < cfe-commits@lists.llvm.org> wrote: > > Author: Richard Smith > Date: 2020-08-06T16:56:39-07:00 > New Revision: ed5a18fc0399dce994aa354a33e6f981f9828647 > > URL: > https://github.com/llvm/llvm-project/commit/ed5a18fc0399dce994aa354a33e6f981f9828647 > DIFF: > https://github.com/llvm/llvm-project/commit/ed5a18fc0399dce994aa354a33e6f981f9828647.diff > > LOG: PR30738: Implement two-phase name lookup for fold-expressions. > > Added: > > > Modified: > clang/include/clang/AST/ExprCXX.h > clang/include/clang/Sema/Sema.h > clang/lib/AST/ASTContext.cpp > clang/lib/Parse/ParseExpr.cpp > clang/lib/Sema/SemaDeclCXX.cpp > clang/lib/Sema/SemaExpr.cpp > clang/lib/Sema/SemaLookup.cpp > clang/lib/Sema/SemaOverload.cpp > clang/lib/Sema/SemaTemplate.cpp > clang/lib/Sema/SemaTemplateVariadic.cpp > clang/lib/Sema/TreeTransform.h > clang/lib/Serialization/ASTReaderStmt.cpp > clang/lib/Serialization/ASTWriterStmt.cpp > clang/test/AST/ast-dump-expr-json.cpp > clang/test/AST/ast-dump-expr.cpp > clang/test/SemaTemplate/cxx1z-fold-expressions.cpp > > Removed: > > > > > ################################################################################ > diff --git a/clang/include/clang/AST/ExprCXX.h > b/clang/include/clang/AST/ExprCXX.h > index 3f272c96a2d8..b53bb20f7ebc 100644 > --- a/clang/include/clang/AST/ExprCXX.h > +++ b/clang/include/clang/AST/ExprCXX.h > @@ -4519,31 +4519,38 @@ class CXXFoldExpr : public Expr { > friend class ASTStmtReader; > friend class ASTStmtWriter; > > + enum SubExpr { Callee, LHS, RHS, Count }; > + > 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]; > + Stmt *SubExprs[SubExpr::Count]; > BinaryOperatorKind Opcode; > > public: > - CXXFoldExpr(QualType T, SourceLocation LParenLoc, Expr *LHS, > - BinaryOperatorKind Opcode, SourceLocation EllipsisLoc, Expr > *RHS, > - SourceLocation RParenLoc, Optional<unsigned> NumExpansions) > + CXXFoldExpr(QualType T, UnresolvedLookupExpr *Callee, > + SourceLocation LParenLoc, Expr *LHS, BinaryOperatorKind > Opcode, > + SourceLocation EllipsisLoc, Expr *RHS, SourceLocation > RParenLoc, > + Optional<unsigned> NumExpansions) > : Expr(CXXFoldExprClass, T, VK_RValue, OK_Ordinary), > LParenLoc(LParenLoc), > EllipsisLoc(EllipsisLoc), RParenLoc(RParenLoc), > NumExpansions(NumExpansions ? *NumExpansions + 1 : 0), > Opcode(Opcode) { > - SubExprs[0] = LHS; > - SubExprs[1] = RHS; > + SubExprs[SubExpr::Callee] = Callee; > + SubExprs[SubExpr::LHS] = LHS; > + SubExprs[SubExpr::RHS] = RHS; > setDependence(computeDependence(this)); > } > > CXXFoldExpr(EmptyShell Empty) : Expr(CXXFoldExprClass, Empty) {} > > - Expr *getLHS() const { return static_cast<Expr*>(SubExprs[0]); } > - Expr *getRHS() const { return static_cast<Expr*>(SubExprs[1]); } > + UnresolvedLookupExpr *getCallee() const { > + return static_cast<UnresolvedLookupExpr *>(SubExprs[SubExpr::Callee]); > + } > + Expr *getLHS() const { return > static_cast<Expr*>(SubExprs[SubExpr::LHS]); } > + Expr *getRHS() const { return > static_cast<Expr*>(SubExprs[SubExpr::RHS]); } > > /// Does this produce a right-associated sequence of operators? > bool isRightFold() const { > @@ -4577,10 +4584,12 @@ class CXXFoldExpr : public Expr { > } > > // Iterators > - child_range children() { return child_range(SubExprs, SubExprs + 2); } > + child_range children() { > + return child_range(SubExprs, SubExprs + SubExpr::Count); > + } > > const_child_range children() const { > - return const_child_range(SubExprs, SubExprs + 2); > + return const_child_range(SubExprs, SubExprs + SubExpr::Count); > } > }; > > > diff --git a/clang/include/clang/Sema/Sema.h > b/clang/include/clang/Sema/Sema.h > index 7a83e0316618..b88e5578c114 100644 > --- a/clang/include/clang/Sema/Sema.h > +++ b/clang/include/clang/Sema/Sema.h > @@ -3556,6 +3556,12 @@ class Sema final { > OverloadCandidateSet *CandidateSet, > ExprResult *Result); > > + ExprResult CreateUnresolvedLookupExpr(CXXRecordDecl *NamingClass, > + NestedNameSpecifierLoc NNSLoc, > + DeclarationNameInfo DNI, > + const UnresolvedSetImpl &Fns, > + bool PerformADL = true); > + > ExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc, > UnaryOperatorKind Opc, > const UnresolvedSetImpl &Fns, > @@ -3822,7 +3828,6 @@ class Sema final { > bool LookupInSuper(LookupResult &R, CXXRecordDecl *Class); > > void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, > - QualType T1, QualType T2, > UnresolvedSetImpl &Functions); > > LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation > IdentLoc, > @@ -5166,6 +5171,8 @@ class Sema final { > BinaryOperatorKind Opc, Expr *LHSExpr, Expr > *RHSExpr); > ExprResult CreateBuiltinBinOp(SourceLocation OpLoc, BinaryOperatorKind > Opc, > Expr *LHSExpr, Expr *RHSExpr); > + void LookupBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc, > + UnresolvedSetImpl &Functions); > > void DiagnoseCommaOperator(const Expr *LHS, SourceLocation Loc); > > @@ -5846,11 +5853,12 @@ class Sema final { > SourceLocation RParenLoc); > > /// Handle a C++1z fold-expression: ( expr op ... op expr ). > - ExprResult ActOnCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS, > + ExprResult ActOnCXXFoldExpr(Scope *S, SourceLocation LParenLoc, Expr > *LHS, > tok::TokenKind Operator, > SourceLocation EllipsisLoc, Expr *RHS, > SourceLocation RParenLoc); > - ExprResult BuildCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS, > + ExprResult BuildCXXFoldExpr(UnresolvedLookupExpr *Callee, > + SourceLocation LParenLoc, Expr *LHS, > BinaryOperatorKind Operator, > SourceLocation EllipsisLoc, Expr *RHS, > SourceLocation RParenLoc, > > diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp > index 04a4c5482db7..61e39dc176a9 100644 > --- a/clang/lib/AST/ASTContext.cpp > +++ b/clang/lib/AST/ASTContext.cpp > @@ -753,10 +753,10 @@ canonicalizeImmediatelyDeclaredConstraint(const > ASTContext &C, Expr *IDC, > CSE->isInstantiationDependent(), > CSE->containsUnexpandedParameterPack()); > > if (auto *OrigFold = dyn_cast<CXXFoldExpr>(IDC)) > - NewIDC = new (C) CXXFoldExpr(OrigFold->getType(), SourceLocation(), > NewIDC, > - BinaryOperatorKind::BO_LAnd, > - SourceLocation(), /*RHS=*/nullptr, > - SourceLocation(), > /*NumExpansions=*/None); > + NewIDC = new (C) CXXFoldExpr( > + OrigFold->getType(), /*Callee*/nullptr, SourceLocation(), NewIDC, > + BinaryOperatorKind::BO_LAnd, SourceLocation(), /*RHS=*/nullptr, > + SourceLocation(), /*NumExpansions=*/None); > return NewIDC; > } > > > diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp > index 4f662f00e1df..a6d64cbb7507 100644 > --- a/clang/lib/Parse/ParseExpr.cpp > +++ b/clang/lib/Parse/ParseExpr.cpp > @@ -3324,8 +3324,9 @@ ExprResult Parser::ParseFoldExpression(ExprResult > LHS, > : diag::ext_fold_expression); > > T.consumeClose(); > - return Actions.ActOnCXXFoldExpr(T.getOpenLocation(), LHS.get(), Kind, > - EllipsisLoc, RHS.get(), > T.getCloseLocation()); > + return Actions.ActOnCXXFoldExpr(getCurScope(), T.getOpenLocation(), > LHS.get(), > + Kind, EllipsisLoc, RHS.get(), > + T.getCloseLocation()); > } > > /// ParseExpressionList - Used for C/C++ (argument-)expression-list. > > diff --git a/clang/lib/Sema/SemaDeclCXX.cpp > b/clang/lib/Sema/SemaDeclCXX.cpp > index 22bf35dbd0cb..7a0adc2694ac 100644 > --- a/clang/lib/Sema/SemaDeclCXX.cpp > +++ b/clang/lib/Sema/SemaDeclCXX.cpp > @@ -8212,7 +8212,7 @@ static void > lookupOperatorsForDefaultedComparison(Sema &Self, Scope *S, > UnresolvedSetImpl > &Operators, > OverloadedOperatorKind > Op) { > auto Lookup = [&](OverloadedOperatorKind OO) { > - Self.LookupOverloadedOperatorName(OO, S, QualType(), QualType(), > Operators); > + Self.LookupOverloadedOperatorName(OO, S, Operators); > }; > > // Every defaulted operator looks up itself. > > diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp > index eec057b303e0..4931cf46cffd 100644 > --- a/clang/lib/Sema/SemaExpr.cpp > +++ b/clang/lib/Sema/SemaExpr.cpp > @@ -14177,6 +14177,19 @@ ExprResult Sema::ActOnBinOp(Scope *S, > SourceLocation TokLoc, > return BuildBinOp(S, TokLoc, Opc, LHSExpr, RHSExpr); > } > > +void Sema::LookupBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind > Opc, > + UnresolvedSetImpl &Functions) { > + OverloadedOperatorKind OverOp = > BinaryOperator::getOverloadedOperator(Opc); > + if (OverOp != OO_None && OverOp != OO_Equal) > + LookupOverloadedOperatorName(OverOp, S, Functions); > + > + // In C++20 onwards, we may have a second operator to look up. > + if (getLangOpts().CPlusPlus20) { > + if (OverloadedOperatorKind ExtraOp = > getRewrittenOverloadedOperator(OverOp)) > + LookupOverloadedOperatorName(ExtraOp, S, Functions); > + } > +} > + > /// Build an overloaded binary operator expression in the given scope. > static ExprResult BuildOverloadedBinOp(Sema &S, Scope *Sc, SourceLocation > OpLoc, > BinaryOperatorKind Opc, > @@ -14196,23 +14209,9 @@ static ExprResult BuildOverloadedBinOp(Sema &S, > Scope *Sc, SourceLocation OpLoc, > break; > } > > - // Find all of the overloaded operators visible from this > - // point. We perform both an operator-name lookup from the local > - // scope and an argument-dependent lookup based on the types of > - // the arguments. > + // Find all of the overloaded operators visible from this point. > UnresolvedSet<16> Functions; > - OverloadedOperatorKind OverOp > - = BinaryOperator::getOverloadedOperator(Opc); > - if (Sc && OverOp != OO_None && OverOp != OO_Equal) > - S.LookupOverloadedOperatorName(OverOp, Sc, LHS->getType(), > - RHS->getType(), Functions); > - > - // In C++20 onwards, we may have a second operator to look up. > - if (S.getLangOpts().CPlusPlus20) { > - if (OverloadedOperatorKind ExtraOp = > getRewrittenOverloadedOperator(OverOp)) > - S.LookupOverloadedOperatorName(ExtraOp, Sc, LHS->getType(), > - RHS->getType(), Functions); > - } > + S.LookupBinOp(Sc, OpLoc, Opc, Functions); > > // Build the (potentially-overloaded, potentially-dependent) > // binary operation. > @@ -14628,15 +14627,11 @@ ExprResult Sema::BuildUnaryOp(Scope *S, > SourceLocation OpLoc, > if (getLangOpts().CPlusPlus && Input->getType()->isOverloadableType() && > UnaryOperator::getOverloadedOperator(Opc) != OO_None && > !(Opc == UO_AddrOf && isQualifiedMemberAccess(Input))) { > - // Find all of the overloaded operators visible from this > - // point. We perform both an operator-name lookup from the local > - // scope and an argument-dependent lookup based on the types of > - // the arguments. > + // Find all of the overloaded operators visible from this point. > UnresolvedSet<16> Functions; > OverloadedOperatorKind OverOp = > UnaryOperator::getOverloadedOperator(Opc); > if (S && OverOp != OO_None) > - LookupOverloadedOperatorName(OverOp, S, Input->getType(), > QualType(), > - Functions); > + LookupOverloadedOperatorName(OverOp, S, Functions); > > return CreateOverloadedUnaryOp(OpLoc, Opc, Functions, Input); > } > > diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp > index 5757eaf3fac0..8de1060889e2 100644 > --- a/clang/lib/Sema/SemaLookup.cpp > +++ b/clang/lib/Sema/SemaLookup.cpp > @@ -2981,7 +2981,6 @@ ObjCProtocolDecl > *Sema::LookupProtocol(IdentifierInfo *II, > } > > void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope > *S, > - QualType T1, QualType T2, > UnresolvedSetImpl &Functions) { > // C++ [over.match.oper]p3: > // -- The set of non-member candidates is the result of the > > diff --git a/clang/lib/Sema/SemaOverload.cpp > b/clang/lib/Sema/SemaOverload.cpp > index 00563cff62cf..5a20a7990c3b 100644 > --- a/clang/lib/Sema/SemaOverload.cpp > +++ b/clang/lib/Sema/SemaOverload.cpp > @@ -12994,7 +12994,18 @@ ExprResult Sema::BuildOverloadedCallExpr(Scope > *S, Expr *Fn, > > static bool IsOverloaded(const UnresolvedSetImpl &Functions) { > return Functions.size() > 1 || > - (Functions.size() == 1 && > isa<FunctionTemplateDecl>(*Functions.begin())); > + (Functions.size() == 1 && > + > isa<FunctionTemplateDecl>((*Functions.begin())->getUnderlyingDecl())); > +} > + > +ExprResult Sema::CreateUnresolvedLookupExpr(CXXRecordDecl *NamingClass, > + NestedNameSpecifierLoc NNSLoc, > + DeclarationNameInfo DNI, > + const UnresolvedSetImpl &Fns, > + bool PerformADL) { > + return UnresolvedLookupExpr::Create(Context, NamingClass, NNSLoc, DNI, > + PerformADL, IsOverloaded(Fns), > + Fns.begin(), Fns.end()); > } > > /// Create a unary operation that may resolve to an overloaded > @@ -13047,10 +13058,11 @@ Sema::CreateOverloadedUnaryOp(SourceLocation > OpLoc, UnaryOperatorKind Opc, > CurFPFeatureOverrides()); > > CXXRecordDecl *NamingClass = nullptr; // lookup ignores member > operators > - UnresolvedLookupExpr *Fn = UnresolvedLookupExpr::Create( > - Context, NamingClass, NestedNameSpecifierLoc(), OpNameInfo, > - /*ADL*/ true, IsOverloaded(Fns), Fns.begin(), Fns.end()); > - return CXXOperatorCallExpr::Create(Context, Op, Fn, ArgsArray, > + ExprResult Fn = CreateUnresolvedLookupExpr( > + NamingClass, NestedNameSpecifierLoc(), OpNameInfo, Fns); > + if (Fn.isInvalid()) > + return ExprError(); > + return CXXOperatorCallExpr::Create(Context, Op, Fn.get(), ArgsArray, > Context.DependentTy, VK_RValue, > OpLoc, > CurFPFeatureOverrides()); > } > @@ -13309,10 +13321,11 @@ ExprResult > Sema::CreateOverloadedBinOp(SourceLocation OpLoc, > // TODO: provide better source location info in DNLoc component. > DeclarationName OpName = > Context.DeclarationNames.getCXXOperatorName(Op); > DeclarationNameInfo OpNameInfo(OpName, OpLoc); > - UnresolvedLookupExpr *Fn = UnresolvedLookupExpr::Create( > - Context, NamingClass, NestedNameSpecifierLoc(), OpNameInfo, > - /*ADL*/ PerformADL, IsOverloaded(Fns), Fns.begin(), Fns.end()); > - return CXXOperatorCallExpr::Create(Context, Op, Fn, Args, > + ExprResult Fn = CreateUnresolvedLookupExpr( > + NamingClass, NestedNameSpecifierLoc(), OpNameInfo, Fns, > PerformADL); > + if (Fn.isInvalid()) > + return ExprError(); > + return CXXOperatorCallExpr::Create(Context, Op, Fn.get(), Args, > Context.DependentTy, VK_RValue, > OpLoc, > CurFPFeatureOverrides()); > } > @@ -13776,15 +13789,13 @@ > Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, > // CHECKME: no 'operator' keyword? > DeclarationNameInfo OpNameInfo(OpName, LLoc); > OpNameInfo.setCXXOperatorNameRange(SourceRange(LLoc, RLoc)); > - UnresolvedLookupExpr *Fn > - = UnresolvedLookupExpr::Create(Context, NamingClass, > - NestedNameSpecifierLoc(), OpNameInfo, > - /*ADL*/ true, /*Overloaded*/ false, > - UnresolvedSetIterator(), > - UnresolvedSetIterator()); > + ExprResult Fn = CreateUnresolvedLookupExpr( > + NamingClass, NestedNameSpecifierLoc(), OpNameInfo, > UnresolvedSet<0>()); > + if (Fn.isInvalid()) > + return ExprError(); > // Can't add any actual overloads yet > > - return CXXOperatorCallExpr::Create(Context, OO_Subscript, Fn, Args, > + return CXXOperatorCallExpr::Create(Context, OO_Subscript, Fn.get(), > Args, > Context.DependentTy, VK_RValue, > RLoc, > CurFPFeatureOverrides()); > } > @@ -14727,12 +14738,12 @@ Sema::BuildForRangeBeginEndCall(SourceLocation > Loc, > return FRS_DiagnosticIssued; > } > } else { > - UnresolvedSet<0> FoundNames; > - UnresolvedLookupExpr *Fn = > - UnresolvedLookupExpr::Create(Context, /*NamingClass=*/nullptr, > - NestedNameSpecifierLoc(), NameInfo, > - /*NeedsADL=*/true, > /*Overloaded=*/false, > - FoundNames.begin(), FoundNames.end()); > + ExprResult FnR = CreateUnresolvedLookupExpr(/*NamingClass=*/nullptr, > + NestedNameSpecifierLoc(), > + NameInfo, > UnresolvedSet<0>()); > + if (FnR.isInvalid()) > + return FRS_DiagnosticIssued; > + UnresolvedLookupExpr *Fn = cast<UnresolvedLookupExpr>(FnR.get()); > > bool CandidateSetError = buildOverloadedCallSet(S, Fn, Fn, Range, Loc, > CandidateSet, > CallExpr); > > diff --git a/clang/lib/Sema/SemaTemplate.cpp > b/clang/lib/Sema/SemaTemplate.cpp > index 3991f2b47977..5d037e58de51 100644 > --- a/clang/lib/Sema/SemaTemplate.cpp > +++ b/clang/lib/Sema/SemaTemplate.cpp > @@ -1176,7 +1176,11 @@ static ExprResult formImmediatelyDeclaredConstraint( > // template<C1... T> struct s1; > // > // The constraint: (C1<T> && ...) > - return S.BuildCXXFoldExpr(/*LParenLoc=*/SourceLocation(), > + // > + // Note that the type of C1<T> is known to be 'bool', so we don't need > to do > + // any unqualified lookups for 'operator&&' here. > + return S.BuildCXXFoldExpr(/*UnqualifiedLookup=*/nullptr, > + /*LParenLoc=*/SourceLocation(), > ImmediatelyDeclaredConstraint.get(), BO_LAnd, > EllipsisLoc, /*RHS=*/nullptr, > /*RParenLoc=*/SourceLocation(), > > diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp > b/clang/lib/Sema/SemaTemplateVariadic.cpp > index 259cc5165776..c95d67b7c732 100644 > --- a/clang/lib/Sema/SemaTemplateVariadic.cpp > +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp > @@ -1160,7 +1160,7 @@ static void CheckFoldOperand(Sema &S, Expr *E) { > } > } > > -ExprResult Sema::ActOnCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS, > +ExprResult Sema::ActOnCXXFoldExpr(Scope *S, SourceLocation LParenLoc, > Expr *LHS, > tok::TokenKind Operator, > SourceLocation EllipsisLoc, Expr *RHS, > SourceLocation RParenLoc) { > @@ -1202,18 +1202,37 @@ ExprResult Sema::ActOnCXXFoldExpr(SourceLocation > LParenLoc, Expr *LHS, > } > > BinaryOperatorKind Opc = ConvertTokenKindToBinaryOpcode(Operator); > - return BuildCXXFoldExpr(LParenLoc, LHS, Opc, EllipsisLoc, RHS, > RParenLoc, > + > + // Perform first-phase name lookup now. > + UnresolvedLookupExpr *ULE = nullptr; > + { > + UnresolvedSet<16> Functions; > + LookupBinOp(S, EllipsisLoc, Opc, Functions); > + if (!Functions.empty()) { > + DeclarationName OpName = > Context.DeclarationNames.getCXXOperatorName( > + BinaryOperator::getOverloadedOperator(Opc)); > + ExprResult Callee = CreateUnresolvedLookupExpr( > + /*NamingClass*/ nullptr, NestedNameSpecifierLoc(), > + DeclarationNameInfo(OpName, EllipsisLoc), Functions); > + if (Callee.isInvalid()) > + return ExprError(); > + ULE = cast<UnresolvedLookupExpr>(Callee.get()); > + } > + } > + > + return BuildCXXFoldExpr(ULE, LParenLoc, LHS, Opc, EllipsisLoc, RHS, > RParenLoc, > None); > } > > -ExprResult Sema::BuildCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS, > +ExprResult Sema::BuildCXXFoldExpr(UnresolvedLookupExpr *Callee, > + SourceLocation LParenLoc, Expr *LHS, > BinaryOperatorKind Operator, > SourceLocation EllipsisLoc, Expr *RHS, > SourceLocation RParenLoc, > Optional<unsigned> NumExpansions) { > - return new (Context) CXXFoldExpr(Context.DependentTy, LParenLoc, LHS, > - Operator, EllipsisLoc, RHS, RParenLoc, > - NumExpansions); > + return new (Context) > + CXXFoldExpr(Context.DependentTy, Callee, LParenLoc, LHS, Operator, > + EllipsisLoc, RHS, RParenLoc, NumExpansions); > } > > ExprResult Sema::BuildEmptyCXXFoldExpr(SourceLocation EllipsisLoc, > > diff --git a/clang/lib/Sema/TreeTransform.h > b/clang/lib/Sema/TreeTransform.h > index 53064d28dd99..29d263de6e88 100644 > --- a/clang/lib/Sema/TreeTransform.h > +++ b/clang/lib/Sema/TreeTransform.h > @@ -3583,13 +3583,15 @@ class TreeTransform { > /// > /// By default, performs semantic analysis in order to build a new fold > /// expression. > - ExprResult RebuildCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS, > + ExprResult RebuildCXXFoldExpr(UnresolvedLookupExpr *ULE, > + SourceLocation LParenLoc, Expr *LHS, > BinaryOperatorKind Operator, > SourceLocation EllipsisLoc, Expr *RHS, > SourceLocation RParenLoc, > Optional<unsigned> NumExpansions) { > - return getSema().BuildCXXFoldExpr(LParenLoc, LHS, Operator, > EllipsisLoc, > - RHS, RParenLoc, NumExpansions); > + return getSema().BuildCXXFoldExpr(ULE, LParenLoc, LHS, Operator, > + EllipsisLoc, RHS, RParenLoc, > + NumExpansions); > } > > /// Build an empty C++1z fold-expression with the given operator. > @@ -13128,6 +13130,14 @@ > TreeTransform<Derived>::TransformMaterializeTemporaryExpr( > template<typename Derived> > ExprResult > TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) { > + UnresolvedLookupExpr *Callee = nullptr; > + if (Expr *OldCallee = E->getCallee()) { > + ExprResult CalleeResult = getDerived().TransformExpr(OldCallee); > + if (CalleeResult.isInvalid()) > + return ExprError(); > + Callee = cast<UnresolvedLookupExpr>(CalleeResult.get()); > + } > + > Expr *Pattern = E->getPattern(); > > SmallVector<UnexpandedParameterPack, 2> Unexpanded; > @@ -13167,8 +13177,8 @@ > TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) { > return E; > > return getDerived().RebuildCXXFoldExpr( > - E->getBeginLoc(), LHS.get(), E->getOperator(), > E->getEllipsisLoc(), > - RHS.get(), E->getEndLoc(), NumExpansions); > + Callee, E->getBeginLoc(), LHS.get(), E->getOperator(), > + E->getEllipsisLoc(), RHS.get(), E->getEndLoc(), NumExpansions); > } > > // The transform has determined that we should perform an elementwise > @@ -13188,8 +13198,8 @@ > TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) { > return true; > > Result = getDerived().RebuildCXXFoldExpr( > - E->getBeginLoc(), Out.get(), E->getOperator(), > E->getEllipsisLoc(), > - Result.get(), E->getEndLoc(), OrigNumExpansions); > + Callee, E->getBeginLoc(), Out.get(), E->getOperator(), > + E->getEllipsisLoc(), Result.get(), E->getEndLoc(), > OrigNumExpansions); > if (Result.isInvalid()) > return true; > } > @@ -13204,16 +13214,21 @@ > TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) { > if (Out.get()->containsUnexpandedParameterPack()) { > // We still have a pack; retain a pack expansion for this slice. > Result = getDerived().RebuildCXXFoldExpr( > - E->getBeginLoc(), LeftFold ? Result.get() : Out.get(), > + Callee, E->getBeginLoc(), LeftFold ? Result.get() : Out.get(), > E->getOperator(), E->getEllipsisLoc(), > 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( > - E->getEllipsisLoc(), E->getOperator(), > - LeftFold ? Result.get() : Out.get(), > - LeftFold ? Out.get() : Result.get()); > + Expr *LHS = LeftFold ? Result.get() : Out.get(); > + Expr *RHS = LeftFold ? Out.get() : Result.get(); > + if (Callee) > + Result = getDerived().RebuildCXXOperatorCallExpr( > + BinaryOperator::getOverloadedOperator(E->getOperator()), > + E->getEllipsisLoc(), Callee, LHS, RHS); > + else > + Result = getDerived().RebuildBinaryOperator(E->getEllipsisLoc(), > + E->getOperator(), > LHS, RHS); > } else > Result = Out; > > @@ -13231,8 +13246,8 @@ > TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) { > return true; > > Result = getDerived().RebuildCXXFoldExpr( > - E->getBeginLoc(), Result.get(), E->getOperator(), > E->getEllipsisLoc(), > - Out.get(), E->getEndLoc(), OrigNumExpansions); > + Callee, E->getBeginLoc(), Result.get(), E->getOperator(), > + E->getEllipsisLoc(), Out.get(), E->getEndLoc(), > OrigNumExpansions); > if (Result.isInvalid()) > return true; > } > > diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp > b/clang/lib/Serialization/ASTReaderStmt.cpp > index 2715c7f3f191..1b8699b78b7d 100644 > --- a/clang/lib/Serialization/ASTReaderStmt.cpp > +++ b/clang/lib/Serialization/ASTReaderStmt.cpp > @@ -2154,6 +2154,7 @@ void ASTStmtReader::VisitCXXFoldExpr(CXXFoldExpr *E) > { > E->NumExpansions = Record.readInt(); > E->SubExprs[0] = Record.readSubExpr(); > E->SubExprs[1] = Record.readSubExpr(); > + E->SubExprs[2] = Record.readSubExpr(); > E->Opcode = (BinaryOperatorKind)Record.readInt(); > } > > > diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp > b/clang/lib/Serialization/ASTWriterStmt.cpp > index d977c4e53535..da61d88c684c 100644 > --- a/clang/lib/Serialization/ASTWriterStmt.cpp > +++ b/clang/lib/Serialization/ASTWriterStmt.cpp > @@ -2053,6 +2053,7 @@ void ASTStmtWriter::VisitCXXFoldExpr(CXXFoldExpr *E) > { > Record.push_back(E->NumExpansions); > Record.AddStmt(E->SubExprs[0]); > Record.AddStmt(E->SubExprs[1]); > + Record.AddStmt(E->SubExprs[2]); > Record.push_back(E->Opcode); > Code = serialization::EXPR_CXX_FOLD; > } > > diff --git a/clang/test/AST/ast-dump-expr-json.cpp > b/clang/test/AST/ast-dump-expr-json.cpp > index 245c56cafdae..02bd8c470d5a 100644 > --- a/clang/test/AST/ast-dump-expr-json.cpp > +++ b/clang/test/AST/ast-dump-expr-json.cpp > @@ -7587,6 +7587,7 @@ void TestNonADLCall3() { > // CHECK-NEXT: }, > // CHECK-NEXT: "valueCategory": "rvalue", > // CHECK-NEXT: "inner": [ > +// CHECK-NEXT: {}, > // CHECK-NEXT: { > // CHECK-NEXT: "id": "0x{{.*}}", > // CHECK-NEXT: "kind": "DeclRefExpr", > @@ -7640,6 +7641,7 @@ void TestNonADLCall3() { > // CHECK-NEXT: "valueCategory": "rvalue", > // CHECK-NEXT: "inner": [ > // CHECK-NEXT: {}, > +// CHECK-NEXT: {}, > // CHECK-NEXT: { > // CHECK-NEXT: "id": "0x{{.*}}", > // CHECK-NEXT: "kind": "DeclRefExpr", > @@ -7691,6 +7693,7 @@ void TestNonADLCall3() { > // CHECK-NEXT: }, > // CHECK-NEXT: "valueCategory": "rvalue", > // CHECK-NEXT: "inner": [ > +// CHECK-NEXT: {}, > // CHECK-NEXT: { > // CHECK-NEXT: "id": "0x{{.*}}", > // CHECK-NEXT: "kind": "DeclRefExpr", > > diff --git a/clang/test/AST/ast-dump-expr.cpp > b/clang/test/AST/ast-dump-expr.cpp > index 33b00f6d6e6d..747a6a5cd539 100644 > --- a/clang/test/AST/ast-dump-expr.cpp > +++ b/clang/test/AST/ast-dump-expr.cpp > @@ -523,16 +523,19 @@ void PrimaryExpressions(Ts... a) { > > (a + ...); > // CHECK: CXXFoldExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:11> > '<dependent type>' > + // CHECK-NEXT: <<<NULL>>> > // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:4> 'Ts' lvalue ParmVar > 0x{{[^ ]*}} 'a' 'Ts...' > // CHECK-NEXT: <<<NULL>>> > > (... + a); > // CHECK: CXXFoldExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:11> > '<dependent type>' > // CHECK-NEXT: <<<NULL>>> > + // CHECK-NEXT: <<<NULL>>> > // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:10> 'Ts' lvalue ParmVar > 0x{{[^ ]*}} 'a' 'Ts...' > > (a + ... + b); > // CHECK: CXXFoldExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:15> > '<dependent type>' > + // CHECK-NEXT: <<<NULL>>> > // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:4> 'Ts' lvalue ParmVar > 0x{{[^ ]*}} 'a' 'Ts...' > // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:14> 'int' lvalue Var 0x{{[^ > ]*}} 'b' 'int' > } > > diff --git a/clang/test/SemaTemplate/cxx1z-fold-expressions.cpp > b/clang/test/SemaTemplate/cxx1z-fold-expressions.cpp > index 44f388843b39..518eaf0e0523 100644 > --- a/clang/test/SemaTemplate/cxx1z-fold-expressions.cpp > +++ b/clang/test/SemaTemplate/cxx1z-fold-expressions.cpp > @@ -102,3 +102,25 @@ namespace PR41845 { > > Sum<1>::type<1, 2> x; // expected-note {{instantiation of}} > } > + > +namespace PR30738 { > + namespace N { > + struct S {}; > + } > + > + namespace T { > + void operator+(N::S, N::S) {} > + template<typename ...Ts> void f() { (Ts{} + ...); } > + } > + > + void g() { T::f<N::S, N::S>(); } > + > + template<typename T, typename ...U> auto h(U ...v) { > + T operator+(T, T); // expected-note {{candidate}} > + return (v + ...); // expected-error {{invalid operands}} > + } > + int test_h1 = h<N::S>(1, 2, 3); > + N::S test_h2 = h<N::S>(N::S(), N::S(), N::S()); > + int test_h3 = h<struct X>(1, 2, 3); > + N::S test_h4 = h<struct X>(N::S(), N::S(), N::S()); // expected-note > {{instantiation of}} > +} > > > > _______________________________________________ > cfe-commits mailing list > cfe-commits@lists.llvm.org > https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits