forked from OSchip/llvm-project
Implements property of reference types. Adding
an executable test to llvm test suite. // rdar://9070460. llvm-svn: 128435
This commit is contained in:
parent
96f962fdff
commit
b24b568725
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue