[clang] ed5a18f - PR30738: Implement two-phase name lookup for fold-expressions.

Nico Weber via cfe-commits cfe-commits at lists.llvm.org
Thu Aug 6 18:04:53 PDT 2020


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 at 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 at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20200806/8524eec8/attachment-0001.html>


More information about the cfe-commits mailing list