aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Sema/SemaExpr.cpp36
1 files changed, 24 insertions, 12 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 880199bc7a..a733b81361 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -8007,6 +8007,12 @@ static ExprResult BuildOverloadedBinOp(Sema &S, Scope *Sc, SourceLocation OpLoc,
ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
BinaryOperatorKind Opc,
Expr *LHSExpr, Expr *RHSExpr) {
+ // We want to end up calling one of checkPseudoObjectAssignment
+ // (if the LHS is a pseudo-object), BuildOverloadedBinOp (if
+ // both expressions are overloadable or either is type-dependent),
+ // or CreateBuiltinBinOp (in any other case). We also want to get
+ // any placeholder types out of the way.
+
// Handle pseudo-objects in the LHS.
if (const BuiltinType *pty = LHSExpr->getType()->getAsPlaceholderType()) {
// Assignments with a pseudo-object l-value need special analysis.
@@ -8018,12 +8024,15 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
if (pty->getKind() == BuiltinType::Overload) {
// We can't actually test that if we still have a placeholder,
// though. Fortunately, none of the exceptions we see in that
- // code below are valid when the LHS is an overload set.
+ // code below are valid when the LHS is an overload set. Note
+ // that an overload set can be dependently-typed, but it never
+ // instantiates to having an overloadable type.
ExprResult resolvedRHS = CheckPlaceholderExpr(RHSExpr);
if (resolvedRHS.isInvalid()) return ExprError();
RHSExpr = resolvedRHS.take();
- if (RHSExpr->getType()->isOverloadableType())
+ if (RHSExpr->isTypeDependent() ||
+ RHSExpr->getType()->isOverloadableType())
return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
}
@@ -8036,8 +8045,12 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
if (const BuiltinType *pty = RHSExpr->getType()->getAsPlaceholderType()) {
// An overload in the RHS can potentially be resolved by the type
// being assigned to.
- if (Opc == BO_Assign && pty->getKind() == BuiltinType::Overload)
+ if (Opc == BO_Assign && pty->getKind() == BuiltinType::Overload) {
+ if (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent())
+ return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
+
return CreateBuiltinBinOp(OpLoc, Opc, LHSExpr, RHSExpr);
+ }
// Don't resolve overloads if the other type is overloadable.
if (pty->getKind() == BuiltinType::Overload &&
@@ -8050,16 +8063,15 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
}
if (getLangOptions().CPlusPlus) {
- bool UseBuiltinOperator;
-
- if (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent()) {
- UseBuiltinOperator = false;
- } else {
- UseBuiltinOperator = !LHSExpr->getType()->isOverloadableType() &&
- !RHSExpr->getType()->isOverloadableType();
- }
+ // If either expression is type-dependent, always build an
+ // overloaded op.
+ if (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent())
+ return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
- if (!UseBuiltinOperator)
+ // Otherwise, build an overloaded op if either expression has an
+ // overloadable type.
+ if (LHSExpr->getType()->isOverloadableType() ||
+ RHSExpr->getType()->isOverloadableType())
return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
}