forked from OSchip/llvm-project
Complain on missing property getter method only
if property-dot expression is decidedly an rvalue. // rdar://8155806. llvm-svn: 122430
This commit is contained in:
parent
d161a85700
commit
0f0b302ffe
|
@ -2450,6 +2450,8 @@ def err_ref_array_type : Error<
|
|||
"cannot refer to declaration with an array type inside block">;
|
||||
def err_property_not_found : Error<
|
||||
"property %0 not found on object of type %1">;
|
||||
def err_getter_not_found : Error<
|
||||
"expected getter method not found on object of type %0">;
|
||||
def err_property_not_found_forward_class : Error<
|
||||
"property %0 cannot be found in forward class object %1">;
|
||||
def note_forward_class : Note<
|
||||
|
|
|
@ -598,9 +598,13 @@ void StmtDumper::VisitObjCProtocolExpr(ObjCProtocolExpr *Node) {
|
|||
void StmtDumper::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) {
|
||||
DumpExpr(Node);
|
||||
if (Node->isImplicitProperty()) {
|
||||
OS << " Kind=MethodRef Getter=\""
|
||||
<< Node->getImplicitPropertyGetter()->getSelector().getAsString()
|
||||
<< "\" Setter=\"";
|
||||
OS << " Kind=MethodRef Getter=\"";
|
||||
if (Node->getImplicitPropertyGetter())
|
||||
OS << Node->getImplicitPropertyGetter()->getSelector().getAsString();
|
||||
else
|
||||
OS << "(null)";
|
||||
|
||||
OS << "\" Setter=\"";
|
||||
if (ObjCMethodDecl *Setter = Node->getImplicitPropertySetter())
|
||||
OS << Setter->getSelector().getAsString();
|
||||
else
|
||||
|
|
|
@ -7097,8 +7097,15 @@ void Sema::ConvertPropertyForRValue(Expr *&E) {
|
|||
|
||||
ExprValueKind VK = VK_RValue;
|
||||
if (PRE->isImplicitProperty()) {
|
||||
QualType Result = PRE->getImplicitPropertyGetter()->getResultType();
|
||||
VK = Expr::getValueKindForType(Result);
|
||||
if (const ObjCMethodDecl *GetterMethod =
|
||||
PRE->getImplicitPropertyGetter()) {
|
||||
QualType Result = GetterMethod->getResultType();
|
||||
VK = Expr::getValueKindForType(Result);
|
||||
}
|
||||
else {
|
||||
Diag(PRE->getLocation(), diag::err_getter_not_found)
|
||||
<< PRE->getBase()->getType();
|
||||
}
|
||||
}
|
||||
|
||||
E = ImplicitCastExpr::Create(Context, E->getType(), CK_GetObjCProperty,
|
||||
|
|
|
@ -439,8 +439,15 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
|
|||
if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc))
|
||||
return ExprError();
|
||||
|
||||
if (Getter) {
|
||||
QualType PType = Getter->getSendResultType();
|
||||
if (Getter || Setter) {
|
||||
QualType PType;
|
||||
if (Getter)
|
||||
PType = Getter->getSendResultType();
|
||||
else {
|
||||
ParmVarDecl *ArgDecl = *Setter->param_begin();
|
||||
PType = ArgDecl->getType();
|
||||
}
|
||||
|
||||
ExprValueKind VK = VK_LValue;
|
||||
ExprObjectKind OK = OK_ObjCProperty;
|
||||
if (!getLangOptions().CPlusPlus && !PType.hasQualifiers() &&
|
||||
|
@ -476,9 +483,9 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
|
|||
|
||||
Diag(MemberLoc, diag::err_property_not_found)
|
||||
<< MemberName << QualType(OPT, 0);
|
||||
if (Setter && !Getter)
|
||||
if (Setter)
|
||||
Diag(Setter->getLocation(), diag::note_getter_unavailable)
|
||||
<< MemberName << BaseExpr->getSourceRange();
|
||||
<< MemberName << BaseExpr->getSourceRange();
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
// rdar://8155806
|
||||
|
||||
@interface Subclass
|
||||
{
|
||||
int setterOnly;
|
||||
}
|
||||
- (void) setSetterOnly : (int) arg;
|
||||
@end
|
||||
|
||||
int func (int arg, Subclass *x) {
|
||||
if (x.setterOnly) { // expected-error {{expected getter method not found on object of type 'Subclass *'}}
|
||||
x.setterOnly = 1;
|
||||
}
|
||||
func(x.setterOnly + 1, x); // expected-error {{expected getter method not found on object of type 'Subclass *'}}
|
||||
int i = x.setterOnly + 1; // expected-error {{expected getter method not found on object of type 'Subclass *'}}
|
||||
return x.setterOnly + 1; // expected-error {{expected getter method not found on object of type 'Subclass *'}}
|
||||
}
|
||||
|
|
@ -70,7 +70,7 @@ static int g_val;
|
|||
{
|
||||
int setterOnly;
|
||||
}
|
||||
- (void) setSetterOnly:(int)value; // expected-note {{or because setter is declared here, but no getter method 'setterOnly' is found}}
|
||||
- (void) setSetterOnly:(int)value;
|
||||
@end
|
||||
|
||||
@implementation Subclass
|
||||
|
@ -82,14 +82,14 @@ static int g_val;
|
|||
|
||||
@interface C {}
|
||||
// - (int)Foo;
|
||||
- (void)setFoo:(int)value; // expected-note 2 {{or because setter is declared here, but no getter method 'Foo' is found}}
|
||||
- (void)setFoo:(int)value;
|
||||
@end
|
||||
|
||||
void g(int);
|
||||
|
||||
void f(C *c) {
|
||||
c.Foo = 17; // expected-error {{property 'Foo' not found on object of type 'C *'}}
|
||||
g(c.Foo); // expected-error {{property 'Foo' not found on object of type 'C *'}}
|
||||
c.Foo = 17; // OK
|
||||
g(c.Foo); // expected-error {{expected getter method not found on object of type 'C *'}}
|
||||
}
|
||||
|
||||
|
||||
|
@ -97,7 +97,7 @@ void abort(void);
|
|||
int main (void) {
|
||||
Subclass *x = [[Subclass alloc] init];
|
||||
|
||||
x.setterOnly = 4; // expected-error {{property 'setterOnly' not found on object of type 'Subclass *'}}
|
||||
x.setterOnly = 4; // OK
|
||||
if (g_val != 4)
|
||||
abort ();
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue