return EmitObjCIvarRefLValue(cast<ObjCIvarRefExpr>(E));
case Expr::ObjCPropertyRefExprClass:
return EmitObjCPropertyRefLValue(cast<ObjCPropertyRefExpr>(E));
+ case Expr::ObjCKVCRefExprClass:
+ return EmitObjCKVCRefLValue(cast<ObjCKVCRefExpr>(E));
case Expr::ObjCSuperExprClass:
return EmitObjCSuperExpr(cast<ObjCSuperExpr>(E));
if (LV.isPropertyRef())
return EmitLoadOfPropertyRefLValue(LV, ExprType);
+ if (LV.isKVCRef())
+ return EmitLoadOfKVCRefLValue(LV, ExprType);
+
assert(0 && "Unknown LValue type!");
//an invalid RValue, but the assert will
//ensure that this point is never reached
return EmitObjCPropertyGet(LV.getPropertyRefExpr());
}
+RValue CodeGenFunction::EmitLoadOfKVCRefLValue(LValue LV,
+ QualType ExprType) {
+ return EmitObjCPropertyGet(LV.getKVCRefExpr());
+}
+
// If this is a reference to a subset of the elements of a vector, either
// shuffle the input or extract/insert them as appropriate.
RValue CodeGenFunction::EmitLoadOfExtVectorElementLValue(LValue LV,
if (Dst.isPropertyRef())
return EmitStoreThroughPropertyRefLValue(Src, Dst, Ty);
+ if (Dst.isKVCRef())
+ return EmitStoreThroughKVCRefLValue(Src, Dst, Ty);
+
assert(0 && "Unknown LValue type");
}
EmitObjCPropertySet(Dst.getPropertyRefExpr(), Src);
}
+void CodeGenFunction::EmitStoreThroughKVCRefLValue(RValue Src,
+ LValue Dst,
+ QualType Ty) {
+ EmitObjCPropertySet(Dst.getKVCRefExpr(), Src);
+}
+
void CodeGenFunction::EmitStoreThroughExtVectorComponentLValue(RValue Src,
LValue Dst,
QualType Ty) {
return LValue::MakePropertyRef(E, E->getType().getCVRQualifiers());
}
+LValue
+CodeGenFunction::EmitObjCKVCRefLValue(const ObjCKVCRefExpr *E) {
+ // This is a special l-value that just issues sends when we load or
+ // store through it.
+ return LValue::MakeKVCRef(E, E->getType().getCVRQualifiers());
+}
+
LValue
CodeGenFunction::EmitObjCSuperExpr(const ObjCSuperExpr *E) {
return EmitUnsupportedLValue(E, "use of super");
CGF.EmitAggExpr(E->getRHS(), AggLoc, false);
CGF.EmitObjCPropertySet(LHS.getPropertyRefExpr(),
RValue::getAggregate(AggLoc));
+ }
+ else if (LHS.isKVCRef()) {
+ // FIXME: Volatility?
+ llvm::Value *AggLoc = DestPtr;
+ if (!AggLoc)
+ AggLoc = CGF.CreateTempAlloca(CGF.ConvertType(E->getRHS()->getType()));
+ CGF.EmitAggExpr(E->getRHS(), AggLoc, false);
+ CGF.EmitObjCPropertySet(LHS.getKVCRefExpr(),
+ RValue::getAggregate(AggLoc));
} else {
// Codegen the RHS so that it stores directly into the LHS.
CGF.EmitAggExpr(E->getRHS(), LHS.getAddress(), false /*FIXME: VOLATILE LHS*/);
Value *VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
return EmitLoadOfLValue(E);
}
+ Value *VisitObjCKVCRefExpr(ObjCKVCRefExpr *E) {
+ return EmitLoadOfLValue(E);
+ }
Value *VisitObjCMessageExpr(ObjCMessageExpr *E) {
return CGF.EmitObjCMessageExpr(E).getScalarVal();
}
}
RValue CodeGenFunction::EmitObjCPropertyGet(const Expr *Exp) {
+ // FIXME: Split it into two separate routines.
if (const ObjCPropertyRefExpr *E = dyn_cast<ObjCPropertyRefExpr>(Exp)) {
Selector S = E->getProperty()->getGetterName();
-
return CGM.getObjCRuntime().
- GenerateMessageSend(*this, E->getType(), S,
- EmitScalarExpr(E->getBase()),
- false, CallArgList());
+ GenerateMessageSend(*this, Exp->getType(), S,
+ EmitScalarExpr(E->getBase()),
+ false, CallArgList());
+ }
+ else if (const ObjCKVCRefExpr *E = dyn_cast<ObjCKVCRefExpr>(Exp)) {
+ Selector S = E->getGetterMethod()->getSelector();
+ return CGM.getObjCRuntime().
+ GenerateMessageSend(*this, Exp->getType(), S,
+ EmitScalarExpr(E->getBase()),
+ false, CallArgList());
}
- assert (0);
+ else
+ assert (0 && "bad expression node in EmitObjCPropertyGet");
}
-void CodeGenFunction::EmitObjCPropertySet(const ObjCPropertyRefExpr *E,
+void CodeGenFunction::EmitObjCPropertySet(const Expr *Exp,
RValue Src) {
- Selector S = E->getProperty()->getSetterName();
- CallArgList Args;
- Args.push_back(std::make_pair(Src, E->getType()));
- CGM.getObjCRuntime().GenerateMessageSend(*this, getContext().VoidTy, S,
- EmitScalarExpr(E->getBase()),
- false, Args);
+ // FIXME: Split it into two separate routines.
+ if (const ObjCPropertyRefExpr *E = dyn_cast<ObjCPropertyRefExpr>(Exp)) {
+ Selector S = E->getProperty()->getSetterName();
+ CallArgList Args;
+ Args.push_back(std::make_pair(Src, E->getType()));
+ CGM.getObjCRuntime().GenerateMessageSend(*this, getContext().VoidTy, S,
+ EmitScalarExpr(E->getBase()),
+ false, Args);
+ }
+ else if (const ObjCKVCRefExpr *E = dyn_cast<ObjCKVCRefExpr>(Exp)) {
+ Selector S = E->getSetterMethod()->getSelector();
+ CallArgList Args;
+ Args.push_back(std::make_pair(Src, E->getType()));
+ CGM.getObjCRuntime().GenerateMessageSend(*this, getContext().VoidTy, S,
+ EmitScalarExpr(E->getBase()),
+ false, Args);
+ }
+ else
+ assert (0 && "bad expression node in EmitObjCPropertySet");
}
void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S)
namespace clang {
class ObjCPropertyRefExpr;
+ class ObjCKVCRefExpr;
namespace CodeGen {
VectorElt, // This is a vector element l-value (V[i]), use getVector*
BitField, // This is a bitfield l-value, use getBitfield*.
ExtVectorElt, // This is an extended vector subset, use getExtVectorComp
- PropertyRef // This is an Objective-C property reference, use
+ PropertyRef, // This is an Objective-C property reference, use
// getPropertyRefExpr
+ KVCRef // This is an objective-c 'implicit' property ref,
+ // use getKVCRefExpr
} LVType;
enum ObjCType {
// Obj-C property reference expression
const ObjCPropertyRefExpr *PropertyRefExpr;
+ // ObjC 'implicit' property reference expression
+ const ObjCKVCRefExpr *KVCRefExpr;
};
bool Volatile:1;
bool isBitfield() const { return LVType == BitField; }
bool isExtVectorElt() const { return LVType == ExtVectorElt; }
bool isPropertyRef() const { return LVType == PropertyRef; }
+ bool isKVCRef() const { return LVType == KVCRef; }
bool isVolatileQualified() const { return Volatile; }
bool isRestrictQualified() const { return Restrict; }
return PropertyRefExpr;
}
+ // 'implicit' property ref lvalue
+ const ObjCKVCRefExpr *getKVCRefExpr() const {
+ assert(isKVCRef());
+ return KVCRefExpr;
+ }
+
static LValue MakeAddr(llvm::Value *V, unsigned Qualifiers) {
LValue R;
R.LVType = Simple;
SetQualifiers(Qualifiers,R);
return R;
}
+ static LValue MakeKVCRef(const ObjCKVCRefExpr *E,
+ unsigned Qualifiers) {
+ LValue R;
+ R.LVType = KVCRef;
+ R.KVCRefExpr = E;
+ SetQualifiers(Qualifiers,R);
+ return R;
+ }
};
} // end namespace CodeGen
RValue EmitLoadOfExtVectorElementLValue(LValue V, QualType LVType);
RValue EmitLoadOfBitfieldLValue(LValue LV, QualType ExprType);
RValue EmitLoadOfPropertyRefLValue(LValue LV, QualType ExprType);
+ RValue EmitLoadOfKVCRefLValue(LValue LV, QualType ExprType);
/// EmitStoreThroughLValue - Store the specified rvalue into the specified
void EmitStoreThroughExtVectorComponentLValue(RValue Src, LValue Dst,
QualType Ty);
void EmitStoreThroughPropertyRefLValue(RValue Src, LValue Dst, QualType Ty);
+ void EmitStoreThroughKVCRefLValue(RValue Src, LValue Dst, QualType Ty);
/// EmitStoreThroughLValue - Store Src into Dst with same
/// constraints as EmitStoreThroughLValue.
LValue EmitObjCMessageExprLValue(const ObjCMessageExpr *E);
LValue EmitObjCIvarRefLValue(const ObjCIvarRefExpr *E);
LValue EmitObjCPropertyRefLValue(const ObjCPropertyRefExpr *E);
+ LValue EmitObjCKVCRefLValue(const ObjCKVCRefExpr *E);
LValue EmitObjCSuperExpr(const ObjCSuperExpr *E);
//===--------------------------------------------------------------------===//
llvm::Value *EmitObjCSelectorExpr(const ObjCSelectorExpr *E);
RValue EmitObjCMessageExpr(const ObjCMessageExpr *E);
RValue EmitObjCPropertyGet(const Expr *E);
- void EmitObjCPropertySet(const ObjCPropertyRefExpr *E, RValue Src);
+ void EmitObjCPropertySet(const Expr *E, RValue Src);
//===--------------------------------------------------------------------===//
--- /dev/null
+// RUN: clang -emit-llvm -triple=i686-apple-darwin8 -o %t %s
+// RUNX: clang -emit-llvm -o %t %s
+
+@interface A
+ -(void) setOk:(int)arg;
+ -(int) ok;
+
+ -(void) setX:(int)arg;
+ -(int) x;
+@end
+
+void f0(A *a) {
+ a.x = 1;
+ a.ok = a.x;
+}
+