diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 217e99ee560a..a2e00675d73d 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -2395,13 +2395,24 @@ public: static bool isLogicalOp(Opcode Opc) { return Opc == BO_LAnd || Opc==BO_LOr; } bool isLogicalOp() const { return isLogicalOp(getOpcode()); } - bool isAssignmentOp() const { return Opc >= BO_Assign && Opc <= BO_OrAssign; } - bool isCompoundAssignmentOp() const { + static bool isAssignmentOp(Opcode Opc) { + return Opc >= BO_Assign && Opc <= BO_OrAssign; + } + bool isAssignmentOp() const { return isAssignmentOp(getOpcode()); } + + static bool isCompoundAssignmentOp(Opcode Opc) { return Opc > BO_Assign && Opc <= BO_OrAssign; } - bool isShiftAssignOp() const { + bool isCompoundAssignmentOp() const { + return isCompoundAssignmentOp(getOpcode()); + } + + static bool isShiftAssignOp(Opcode Opc) { return Opc == BO_ShlAssign || Opc == BO_ShrAssign; } + bool isShiftAssignOp() const { + return isShiftAssignOp(getOpcode()); + } static bool classof(const Stmt *S) { return S->getStmtClass() >= firstBinaryOperatorConstant && diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 78605ba8b1e8..35ba2543efa4 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -195,13 +195,6 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E, if (E->isLValue()) { // Emit the expression as an lvalue. LValue LV = CGF.EmitLValue(E); - if (LV.isPropertyRef()) { - QualType QT = E->getType(); - RValue RV = CGF.EmitLoadOfPropertyRefLValue(LV); - assert(RV.isScalar() && "EmitExprForReferenceBinding"); - return RV.getScalarVal(); - } - if (LV.isSimple()) return LV.getAddress(); @@ -1537,11 +1530,6 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) { const PointerType *PTy = BaseExpr->getType()->getAs(); BaseQuals = PTy->getPointeeType().getQualifiers(); - } else if (ObjCPropertyRefExpr *PRE - = dyn_cast(BaseExpr->IgnoreParens())) { - RValue RV = EmitLoadOfPropertyRefLValue(EmitObjCPropertyRefLValue(PRE)); - BaseValue = RV.getAggregateAddr(); - BaseQuals = BaseExpr->getType().getQualifiers(); } else { LValue BaseLV = EmitLValue(BaseExpr); if (BaseLV.isNonGC()) @@ -1771,17 +1759,8 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { } case CK_NoOp: - if (!E->getSubExpr()->isRValue() || E->getType()->isRecordType()) { - LValue LV = EmitLValue(E->getSubExpr()); - if (LV.isPropertyRef()) { - QualType QT = E->getSubExpr()->getType(); - RValue RV = EmitLoadOfPropertyRefLValue(LV); - assert(RV.isAggregate()); - llvm::Value *V = RV.getAggregateAddr(); - return MakeAddrLValue(V, QT); - } - return LV; - } + if (!E->getSubExpr()->isRValue() || E->getType()->isRecordType()) + return EmitLValue(E->getSubExpr()); // Fall through to synthesize a temporary. case CK_LValueToRValue: @@ -1843,15 +1822,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { cast(DerivedClassTy->getDecl()); LValue LV = EmitLValue(E->getSubExpr()); - llvm::Value *This; - if (LV.isPropertyRef()) { - QualType QT = E->getSubExpr()->getType(); - RValue RV = EmitLoadOfPropertyRefLValue(LV); - assert (!RV.isScalar() && "EmitCastLValue"); - This = RV.getAggregateAddr(); - } - else - This = LV.getAddress(); + llvm::Value *This = LV.getAddress(); // Perform the derived-to-base conversion llvm::Value *Base = diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index e88315137ad6..945aa2a18262 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -122,16 +122,8 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE, llvm::Value *This; if (ME->isArrow()) This = EmitScalarExpr(ME->getBase()); - else { - LValue BaseLV = EmitLValue(ME->getBase()); - if (BaseLV.isPropertyRef()) { - QualType QT = ME->getBase()->getType(); - RValue RV = EmitLoadOfPropertyRefLValue(BaseLV); - This = RV.isScalar() ? RV.getScalarVal() : RV.getAggregateAddr(); - } - else - This = BaseLV.getAddress(); - } + else + This = EmitLValue(ME->getBase()).getAddress(); if (MD->isTrivial()) { if (isa(MD)) return RValue::get(0); @@ -233,22 +225,14 @@ CodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E, ReturnValueSlot ReturnValue) { assert(MD->isInstance() && "Trying to emit a member call expr on a static method!"); + LValue LV = EmitLValue(E->getArg(0)); + llvm::Value *This = LV.getAddress(); + if (MD->isCopyAssignmentOperator()) { const CXXRecordDecl *ClassDecl = cast(MD->getDeclContext()); if (ClassDecl->hasTrivialCopyAssignment()) { assert(!ClassDecl->hasUserDeclaredCopyAssignment() && "EmitCXXOperatorMemberCallExpr - user declared copy assignment"); - LValue LV = EmitLValue(E->getArg(0)); - llvm::Value *This; - if (LV.isPropertyRef()) { - AggValueSlot Slot = CreateAggTemp(E->getArg(1)->getType()); - EmitAggExpr(E->getArg(1), Slot); - EmitStoreThroughPropertyRefLValue(Slot.asRValue(), LV); - return RValue::getAggregate(0, false); - } - else - This = LV.getAddress(); - llvm::Value *Src = EmitLValue(E->getArg(1)).getAddress(); QualType Ty = E->getType(); EmitAggregateCopy(This, Src, Ty); @@ -260,17 +244,6 @@ CodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E, const llvm::Type *Ty = CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), FPT->isVariadic()); - LValue LV = EmitLValue(E->getArg(0)); - llvm::Value *This; - if (LV.isPropertyRef()) { - QualType QT = E->getArg(0)->getType(); - RValue RV = EmitLoadOfPropertyRefLValue(LV); - assert (!RV.isScalar() && "EmitCXXOperatorMemberCallExpr"); - This = RV.getAggregateAddr(); - } - else - This = LV.getAddress(); - llvm::Value *Callee; if (MD->isVirtual() && !canDevirtualizeMemberFunctionCalls(E->getArg(0), MD)) Callee = BuildVirtualCall(MD, This, Ty); diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp index fbb3d4860a8e..28f324b1b28d 100644 --- a/clang/lib/CodeGen/CGExprComplex.cpp +++ b/clang/lib/CodeGen/CGExprComplex.cpp @@ -60,7 +60,10 @@ public: /// value l-value, this method emits the address of the l-value, then loads /// and returns the result. ComplexPairTy EmitLoadOfLValue(const Expr *E) { - LValue LV = CGF.EmitLValue(E); + return EmitLoadOfLValue(CGF.EmitLValue(E)); + } + + ComplexPairTy EmitLoadOfLValue(LValue LV) { if (LV.isSimple()) return EmitLoadOfComplex(LV.getAddress(), LV.isVolatileQualified()); @@ -72,6 +75,16 @@ public: /// the real and imaginary pieces. ComplexPairTy EmitLoadOfComplex(llvm::Value *SrcPtr, bool isVolatile); + /// EmitStoreThroughLValue - Given an l-value of complex type, store + /// a complex number into it. + void EmitStoreThroughLValue(ComplexPairTy Val, LValue LV) { + if (LV.isSimple()) + return EmitStoreOfComplex(Val, LV.getAddress(), LV.isVolatileQualified()); + + assert(LV.isPropertyRef() && "Unknown LValue type!"); + CGF.EmitStoreThroughPropertyRefLValue(RValue::getComplex(Val), LV); + } + /// EmitStoreOfComplex - Store the specified real/imag parts into the /// specified value pointer. void EmitStoreOfComplex(ComplexPairTy Val, llvm::Value *ResPtr, bool isVol); @@ -540,13 +553,9 @@ EmitCompoundAssignLValue(const CompoundAssignOperator *E, OpInfo.RHS = Visit(E->getRHS()); LValue LHS = CGF.EmitLValue(E->getLHS()); - // We know the LHS is a complex lvalue. - ComplexPairTy LHSComplexPair; - if (LHS.isPropertyRef()) - LHSComplexPair = CGF.EmitLoadOfPropertyRefLValue(LHS).getComplexVal(); - else - LHSComplexPair = EmitLoadOfComplex(LHS.getAddress(), - LHS.isVolatileQualified()); + + // Load from the l-value. + ComplexPairTy LHSComplexPair = EmitLoadOfLValue(LHS); OpInfo.LHS = EmitComplexToComplexCast(LHSComplexPair, LHSTy, OpInfo.Ty); @@ -558,10 +567,7 @@ EmitCompoundAssignLValue(const CompoundAssignOperator *E, Val = Result; // Store the result value into the LHS lvalue. - if (LHS.isPropertyRef()) - CGF.EmitStoreThroughPropertyRefLValue(RValue::getComplex(Result), LHS); - else - EmitStoreOfComplex(Result, LHS.getAddress(), LHS.isVolatileQualified()); + EmitStoreThroughLValue(Result, LHS); return LHS; } @@ -603,10 +609,7 @@ LValue ComplexExprEmitter::EmitBinAssignLValue(const BinaryOperator *E, LValue LHS = CGF.EmitLValue(E->getLHS()); // Store the result value into the LHS lvalue. - if (LHS.isPropertyRef()) - CGF.EmitStoreThroughPropertyRefLValue(RValue::getComplex(Val), LHS); - else - EmitStoreOfComplex(Val, LHS.getAddress(), LHS.isVolatileQualified()); + EmitStoreThroughLValue(Val, LHS); return LHS; } diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index ce66c3c0fc29..8319996727a7 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/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(); @@ -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: