[cfe-commits] r120896 - in /cfe/trunk: include/clang/AST/Expr.h lib/CodeGen/CGExpr.cpp lib/CodeGen/CGExprCXX.cpp lib/CodeGen/CGExprComplex.cpp lib/Sema/SemaOverload.cpp
John McCall
rjmccall at apple.com
Sat Dec 4 00:14:53 PST 2010
Author: rjmccall
Date: Sat Dec 4 02:14:53 2010
New Revision: 120896
URL: http://llvm.org/viewvc/llvm-project?rev=120896&view=rev
Log:
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.
Modified:
cfe/trunk/include/clang/AST/Expr.h
cfe/trunk/lib/CodeGen/CGExpr.cpp
cfe/trunk/lib/CodeGen/CGExprCXX.cpp
cfe/trunk/lib/CodeGen/CGExprComplex.cpp
cfe/trunk/lib/Sema/SemaOverload.cpp
Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=120896&r1=120895&r2=120896&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Sat Dec 4 02:14:53 2010
@@ -2395,13 +2395,24 @@
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 &&
Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=120896&r1=120895&r2=120896&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Sat Dec 4 02:14:53 2010
@@ -195,13 +195,6 @@
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 @@
const PointerType *PTy =
BaseExpr->getType()->getAs<PointerType>();
BaseQuals = PTy->getPointeeType().getQualifiers();
- } else if (ObjCPropertyRefExpr *PRE
- = dyn_cast<ObjCPropertyRefExpr>(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 @@
}
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 @@
cast<CXXRecordDecl>(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 =
Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=120896&r1=120895&r2=120896&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Sat Dec 4 02:14:53 2010
@@ -122,16 +122,8 @@
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<CXXDestructorDecl>(MD)) return RValue::get(0);
@@ -233,22 +225,14 @@
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<CXXRecordDecl>(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 @@
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);
Modified: cfe/trunk/lib/CodeGen/CGExprComplex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprComplex.cpp?rev=120896&r1=120895&r2=120896&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprComplex.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprComplex.cpp Sat Dec 4 02:14:53 2010
@@ -60,7 +60,10 @@
/// 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 @@
/// 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 @@
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 @@
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 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;
}
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=120896&r1=120895&r2=120896&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Sat Dec 4 02:14:53 2010
@@ -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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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:
More information about the cfe-commits
mailing list