aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/TreeTransform.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/TreeTransform.h')
-rw-r--r--lib/Sema/TreeTransform.h59
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>