diff options
author | John McCall <rjmccall@apple.com> | 2010-12-04 08:14:53 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-12-04 08:14:53 +0000 |
commit | 0e800c9c20d1a658a91096c756c4a4a9e90264fc (patch) | |
tree | 7be31a9b8db7381808de7ee48736c6029c53840b /lib/Sema/SemaOverload.cpp | |
parent | abc56c726178fc7c8a3f45185768426a6e9d584e (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.cpp | 56 |
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: |