Implements property of reference types. Adding

an executable test to llvm test suite.
// rdar://9070460.

llvm-svn: 128435
This commit is contained in:
Fariborz Jahanian 2011-03-28 23:47:18 +00:00
parent 96f962fdff
commit b24b568725
5 changed files with 48 additions and 19 deletions

View File

@ -294,11 +294,17 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP,
else {
LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(),
Ivar, 0);
CodeGenTypes &Types = CGM.getTypes();
RValue RV = EmitLoadOfLValue(LV, IVART);
RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(),
if (PD->getType()->isReferenceType()) {
RValue RV = RValue::get(LV.getAddress());
EmitReturnOfRValue(RV, PD->getType());
}
else {
CodeGenTypes &Types = CGM.getTypes();
RValue RV = EmitLoadOfLValue(LV, IVART);
RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(),
Types.ConvertType(PD->getType())));
EmitReturnOfRValue(RV, PD->getType());
EmitReturnOfRValue(RV, PD->getType());
}
}
}
@ -436,7 +442,10 @@ void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP,
ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl();
DeclRefExpr Base(Self, Self->getType(), VK_RValue, Loc);
ParmVarDecl *ArgDecl = *OMD->param_begin();
DeclRefExpr Arg(ArgDecl, ArgDecl->getType(), VK_LValue, Loc);
QualType T = ArgDecl->getType();
if (T->isReferenceType())
T = cast<ReferenceType>(T)->getPointeeType();
DeclRefExpr Arg(ArgDecl, T, VK_LValue, Loc);
ObjCIvarRefExpr IvarRef(Ivar, Ivar->getType(), Loc, &Base, true, true);
// The property type can differ from the ivar type in some situations with

View File

@ -7413,6 +7413,21 @@ static bool IsReadonlyProperty(Expr *E, Sema &S) {
return false;
}
static bool IsConstProperty(Expr *E, Sema &S) {
if (E->getStmtClass() == Expr::ObjCPropertyRefExprClass) {
const ObjCPropertyRefExpr* PropExpr = cast<ObjCPropertyRefExpr>(E);
if (PropExpr->isImplicitProperty()) return false;
ObjCPropertyDecl *PDecl = PropExpr->getExplicitProperty();
QualType T = PDecl->getType();
if (T->isReferenceType())
T = cast<ReferenceType>(T)->getPointeeType();
CanQualType CT = S.Context.getCanonicalType(T);
return CT.isConstQualified();
}
return false;
}
static bool IsReadonlyMessage(Expr *E, Sema &S) {
if (E->getStmtClass() != Expr::MemberExprClass)
return false;
@ -7435,6 +7450,8 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
&Loc);
if (IsLV == Expr::MLV_Valid && IsReadonlyProperty(E, S))
IsLV = Expr::MLV_ReadonlyProperty;
else if (Expr::MLV_ConstQualified && IsConstProperty(E, S))
IsLV = Expr::MLV_Valid;
else if (IsLV == Expr::MLV_ClassTemporary && IsReadonlyMessage(E, S))
IsLV = Expr::MLV_InvalidMessageExpression;
if (IsLV == Expr::MLV_Valid)

View File

@ -428,6 +428,7 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
if (DiagnoseUseOfDecl(PD, MemberLoc))
return ExprError();
QualType ResTy = PD->getType();
ResTy = ResTy.getNonLValueExprType(Context);
Selector Sel = PP.getSelectorTable().getNullarySelector(Member);
ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel);
if (DiagnosePropertyAccessorMismatch(PD, Getter, MemberLoc))

View File

@ -45,11 +45,7 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
!(Attributes & ObjCDeclSpec::DQ_PR_copy)));
TypeSourceInfo *TSI = GetTypeForDeclarator(FD.D, S);
QualType T = TSI->getType();
if (T->isReferenceType()) {
Diag(AtLoc, diag::error_reference_property);
return 0;
}
// Proceed with constructing the ObjCPropertDecls.
ObjCContainerDecl *ClassDecl =
cast<ObjCContainerDecl>(ClassCategory);
@ -404,13 +400,16 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
if (!PropertyIvar)
PropertyIvar = PropertyId;
QualType PropType = Context.getCanonicalType(property->getType());
QualType PropertyIvarType = PropType;
if (PropType->isReferenceType())
PropertyIvarType = cast<ReferenceType>(PropType)->getPointeeType();
// Check that this is a previously declared 'ivar' in 'IDecl' interface
ObjCInterfaceDecl *ClassDeclared;
Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared);
if (!Ivar) {
Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl,
PropertyLoc, PropertyLoc, PropertyIvar,
PropType, /*Dinfo=*/0,
PropertyIvarType, /*Dinfo=*/0,
ObjCIvarDecl::Private,
(Expr *)0, true);
ClassImpDecl->addDecl(Ivar);
@ -433,19 +432,19 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
QualType IvarType = Context.getCanonicalType(Ivar->getType());
// Check that type of property and its ivar are type compatible.
if (PropType != IvarType) {
if (PropertyIvarType != IvarType) {
bool compat = false;
if (isa<ObjCObjectPointerType>(PropType)
if (isa<ObjCObjectPointerType>(PropertyIvarType)
&& isa<ObjCObjectPointerType>(IvarType))
compat =
Context.canAssignObjCInterfaces(
PropType->getAs<ObjCObjectPointerType>(),
PropertyIvarType->getAs<ObjCObjectPointerType>(),
IvarType->getAs<ObjCObjectPointerType>());
else {
SourceLocation Loc = PropertyIvarLoc;
if (Loc.isInvalid())
Loc = PropertyLoc;
compat = (CheckAssignmentConstraints(Loc, PropType, IvarType)
compat = (CheckAssignmentConstraints(Loc, PropertyIvarType, IvarType)
== Compatible);
}
if (!compat) {
@ -460,7 +459,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
// FIXME! Rules for properties are somewhat different that those
// for assignments. Use a new routine to consolidate all cases;
// specifically for property redeclarations as well as for ivars.
QualType lhsType =Context.getCanonicalType(PropType).getUnqualifiedType();
QualType lhsType =Context.getCanonicalType(PropertyIvarType).getUnqualifiedType();
QualType rhsType =Context.getCanonicalType(IvarType).getUnqualifiedType();
if (lhsType != rhsType &&
lhsType->isArithmeticType()) {
@ -539,7 +538,10 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
SelfExpr, true, true);
ObjCMethodDecl::param_iterator P = setterMethod->param_begin();
ParmVarDecl *Param = (*P);
Expr *rhs = new (Context) DeclRefExpr(Param, Param->getType(),
QualType T = Param->getType();
if (T->isReferenceType())
T = cast<ReferenceType>(T)->getPointeeType();
Expr *rhs = new (Context) DeclRefExpr(Param, T,
VK_LValue, SourceLocation());
ExprResult Res = BuildBinOp(S, lhs->getLocEnd(),
BO_Assign, lhs, rhs);

View File

@ -9,7 +9,7 @@ typedef struct {
@interface A
@property (assign) T p0;
@property (assign) T& p1; // expected-error {{property of reference type is not supported}}
@property (assign) T& p1;
@end
int f0(const T& t) {
@ -21,7 +21,7 @@ int f1(A *a) {
}
int f2(A *a) {
return f0(a.p1); // expected-error {{property 'p1' not found on object of type 'A *'}}
return f0(a.p1);
}
// PR7740