diff options
Diffstat (limited to 'lib/Sema/TreeTransform.h')
-rw-r--r-- | lib/Sema/TreeTransform.h | 59 |
1 files changed, 40 insertions, 19 deletions
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 461cd909c2..89a7b8cc84 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -2355,13 +2355,13 @@ public: /// Build a new rewritten operator expression. /// - /// By default, builds the rewritten operator without performing any semantic - /// analysis. Subclasses may override this routine to provide different - /// behavior. - ExprResult RebuildCXXRewrittenBinaryOperator(Expr *SemanticForm, - bool IsReversed) { - return new (getSema().Context) - CXXRewrittenBinaryOperator(SemanticForm, IsReversed); + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildCXXRewrittenBinaryOperator( + SourceLocation OpLoc, BinaryOperatorKind Opcode, + const UnresolvedSetImpl &UnqualLookups, Expr *LHS, Expr *RHS) { + return getSema().CreateOverloadedBinOp(OpLoc, Opcode, UnqualLookups, LHS, + RHS, /*RequiresADL*/false); } /// Build a new conditional operator expression. @@ -9783,24 +9783,45 @@ TreeTransform<Derived>::TransformBinaryOperator(BinaryOperator *E) { template <typename Derived> ExprResult TreeTransform<Derived>::TransformCXXRewrittenBinaryOperator( CXXRewrittenBinaryOperator *E) { - // FIXME: C++ [temp.deduct]p7 "The substitution proceeds in lexical order and - // stops when a condition that causes deduction to fail is encountered." - // requires us to substitute into the LHS before the RHS, even in a rewrite - // that reversed the operand order. - // - // We can't decompose back to a binary operator here, because that would lose - // the unqualified lookup results from the phase 1 name lookup. + CXXRewrittenBinaryOperator::DecomposedForm Decomp = E->getDecomposedForm(); - ExprResult SemanticForm = getDerived().TransformExpr(E->getSemanticForm()); - if (SemanticForm.isInvalid()) + ExprResult LHS = getDerived().TransformExpr(const_cast<Expr*>(Decomp.LHS)); + if (LHS.isInvalid()) + return ExprError(); + + ExprResult RHS = getDerived().TransformExpr(const_cast<Expr*>(Decomp.RHS)); + if (RHS.isInvalid()) return ExprError(); if (!getDerived().AlwaysRebuild() && - SemanticForm.get() == E->getSemanticForm()) + LHS.get() == Decomp.LHS && + RHS.get() == Decomp.RHS) return E; - return getDerived().RebuildCXXRewrittenBinaryOperator(SemanticForm.get(), - E->isReversed()); + // Extract the already-resolved callee declarations so that we can restrict + // ourselves to using them as the unqualified lookup results when rebuilding. + UnresolvedSet<2> UnqualLookups; + Expr *PossibleBinOps[] = {E->getSemanticForm(), + const_cast<Expr *>(Decomp.InnerBinOp)}; + for (Expr *PossibleBinOp : PossibleBinOps) { + auto *Op = dyn_cast<CXXOperatorCallExpr>(PossibleBinOp->IgnoreImplicit()); + if (!Op) + continue; + auto *Callee = dyn_cast<DeclRefExpr>(Op->getCallee()->IgnoreImplicit()); + if (!Callee || isa<CXXMethodDecl>(Callee->getDecl())) + continue; + + // Transform the callee in case we built a call to a local extern + // declaration. + NamedDecl *Found = cast_or_null<NamedDecl>(getDerived().TransformDecl( + E->getOperatorLoc(), Callee->getFoundDecl())); + if (!Found) + return ExprError(); + UnqualLookups.addDecl(Found); + } + + return getDerived().RebuildCXXRewrittenBinaryOperator( + E->getOperatorLoc(), Decomp.Opcode, UnqualLookups, LHS.get(), RHS.get()); } template<typename Derived> |