forked from OSchip/llvm-project
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. llvm-svn: 120896
This commit is contained in:
parent
29cb2fdbc1
commit
e26a872b02
|
@ -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 &&
|
||||
|
|
|
@ -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<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 @@ 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<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 =
|
||||
|
|
|
@ -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<CXXDestructorDecl>(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<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 @@ 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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue