diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2010-12-22 19:46:35 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2010-12-22 19:46:35 +0000 |
commit | 0f0b302ffe8e64e93ad3b428523a244a1bcc044f (patch) | |
tree | 7b38965f35168a93ec0afb1d0930b00e1bb59d3b | |
parent | d161a8570021d6c3e0ea68fd18ea0526eea73107 (diff) | |
download | bcm5719-llvm-0f0b302ffe8e64e93ad3b428523a244a1bcc044f.tar.gz bcm5719-llvm-0f0b302ffe8e64e93ad3b428523a244a1bcc044f.zip |
Complain on missing property getter method only
if property-dot expression is decidedly
an rvalue. // rdar://8155806.
llvm-svn: 122430
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | clang/lib/AST/StmtDumper.cpp | 10 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 11 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprObjC.cpp | 15 | ||||
-rw-r--r-- | clang/test/SemaObjC/error-missing-getter.m | 19 | ||||
-rw-r--r-- | clang/test/SemaObjC/property-user-setter.m | 10 |
6 files changed, 53 insertions, 14 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index adc005bcd62..97425010888 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -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< diff --git a/clang/lib/AST/StmtDumper.cpp b/clang/lib/AST/StmtDumper.cpp index 56bfa35425d..8b62dcc940b 100644 --- a/clang/lib/AST/StmtDumper.cpp +++ b/clang/lib/AST/StmtDumper.cpp @@ -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 diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 56ad9b42410..e2a6d346164 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -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, diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index bbb047990bb..f4c593b0dae 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -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(); } diff --git a/clang/test/SemaObjC/error-missing-getter.m b/clang/test/SemaObjC/error-missing-getter.m new file mode 100644 index 00000000000..3c91ab2ffcd --- /dev/null +++ b/clang/test/SemaObjC/error-missing-getter.m @@ -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 *'}} +} + diff --git a/clang/test/SemaObjC/property-user-setter.m b/clang/test/SemaObjC/property-user-setter.m index 9479bc6a73b..2f1e19727a8 100644 --- a/clang/test/SemaObjC/property-user-setter.m +++ b/clang/test/SemaObjC/property-user-setter.m @@ -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; |