aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaOverload.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-12-04 08:14:53 +0000
committerJohn McCall <rjmccall@apple.com>2010-12-04 08:14:53 +0000
commit0e800c9c20d1a658a91096c756c4a4a9e90264fc (patch)
tree7be31a9b8db7381808de7ee48736c6029c53840b /lib/Sema/SemaOverload.cpp
parentabc56c726178fc7c8a3f45185768426a6e9d584e (diff)
Remove some defensive calls to EmitLoadOfPropertyRefLValue that shouldn't
be required, and then fix up some missing loads on overloaded-operator paths which that exposed. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@120896 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaOverload.cpp')
-rw-r--r--lib/Sema/SemaOverload.cpp56
1 files changed, 52 insertions, 4 deletions
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index ce66c3c0fc..8319996727 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -23,6 +23,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
#include "clang/AST/TypeOrdering.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "llvm/ADT/DenseSet.h"
@@ -7081,6 +7082,9 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
// TODO: provide better source location info.
DeclarationNameInfo OpNameInfo(OpName, OpLoc);
+ if (Input->getObjectKind() == OK_ObjCProperty)
+ ConvertPropertyForRValue(Input);
+
Expr *Args[2] = { Input, 0 };
unsigned NumArgs = 1;
@@ -7292,10 +7296,38 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
OpLoc));
}
- // If this is the .* operator, which is not overloadable, just
- // create a built-in binary operator.
- if (Opc == BO_PtrMemD)
- return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
+ // Always do property rvalue conversions on the RHS.
+ if (Args[1]->getObjectKind() == OK_ObjCProperty)
+ ConvertPropertyForRValue(Args[1]);
+
+ // The LHS is more complicated.
+ if (Args[0]->getObjectKind() == OK_ObjCProperty) {
+
+ // There's a tension for assignment operators between primitive
+ // property assignment and the overloaded operators.
+ if (BinaryOperator::isAssignmentOp(Opc)) {
+ const ObjCPropertyRefExpr *PRE = LHS->getObjCProperty();
+
+ // Is the property "logically" settable?
+ bool Settable = (PRE->isExplicitProperty() ||
+ PRE->getImplicitPropertySetter());
+
+ // To avoid gratuitously inventing semantics, use the primitive
+ // unless it isn't. Thoughts in case we ever really care:
+ // - If the property isn't logically settable, we have to
+ // load and hope.
+ // - If the property is settable and this is simple assignment,
+ // we really should use the primitive.
+ // - If the property is settable, then we could try overloading
+ // on a generic lvalue of the appropriate type; if it works
+ // out to a builtin candidate, we would do that same operation
+ // on the property, and otherwise just error.
+ if (Settable)
+ return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
+ }
+
+ ConvertPropertyForRValue(Args[0]);
+ }
// If this is the assignment operator, we only perform overload resolution
// if the left-hand side is a class or enumeration type. This is actually
@@ -7306,6 +7338,11 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
if (Opc == BO_Assign && !Args[0]->getType()->isOverloadableType())
return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
+ // If this is the .* operator, which is not overloadable, just
+ // create a built-in binary operator.
+ if (Opc == BO_PtrMemD)
+ return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
+
// Build an empty overload set.
OverloadCandidateSet CandidateSet(OpLoc);
@@ -7496,6 +7533,11 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
RLoc));
}
+ if (Args[0]->getObjectKind() == OK_ObjCProperty)
+ ConvertPropertyForRValue(Args[0]);
+ if (Args[1]->getObjectKind() == OK_ObjCProperty)
+ ConvertPropertyForRValue(Args[1]);
+
// Build an empty overload set.
OverloadCandidateSet CandidateSet(LLoc);
@@ -7766,6 +7808,9 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
SourceLocation LParenLoc,
Expr **Args, unsigned NumArgs,
SourceLocation RParenLoc) {
+ if (Object->getObjectKind() == OK_ObjCProperty)
+ ConvertPropertyForRValue(Object);
+
assert(Object->getType()->isRecordType() && "Requires object type argument");
const RecordType *Record = Object->getType()->getAs<RecordType>();
@@ -8017,6 +8062,9 @@ ExprResult
Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) {
assert(Base->getType()->isRecordType() && "left-hand side must have class type");
+ if (Base->getObjectKind() == OK_ObjCProperty)
+ ConvertPropertyForRValue(Base);
+
SourceLocation Loc = Base->getExprLoc();
// C++ [over.ref]p1: