diff options
| author | Fariborz Jahanian <fjahanian@apple.com> | 2012-05-19 18:17:17 +0000 |
|---|---|---|
| committer | Fariborz Jahanian <fjahanian@apple.com> | 2012-05-19 18:17:17 +0000 |
| commit | 199a9b57a6bb04c6c2fba8a04ab0c19de127c7c1 (patch) | |
| tree | 042ba17474e6498f87e416a685263999c8124b76 | |
| parent | cb1f153d4cc058f983ddb41eeb7999823fa4c6a1 (diff) | |
| download | bcm5719-llvm-199a9b57a6bb04c6c2fba8a04ab0c19de127c7c1.tar.gz bcm5719-llvm-199a9b57a6bb04c6c2fba8a04ab0c19de127c7c1.zip | |
objective-c: Warn if default synthesizing readonly IBOutlet properties
and provide a 'fixit' to change 'readonly' to 'readwrite'. 'fixit'
part needs little more work. // rdar://11448209
llvm-svn: 157121
| -rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 6 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaObjCProperty.cpp | 67 | ||||
| -rw-r--r-- | clang/test/SemaObjC/iboutlet.m | 15 |
3 files changed, 88 insertions, 0 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 8b76ccb1343..b3ae3aa4cfd 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -711,6 +711,12 @@ def warn_undeclared_selector : Warning< "undeclared selector %0">, InGroup<UndeclaredSelector>, DefaultIgnore; def warn_implicit_atomic_property : Warning< "property is assumed atomic by default">, InGroup<ImplicitAtomic>, DefaultIgnore; +def note_auto_readonly_iboutlet_fixup_suggest : Note< + "readonly IBOutlet property should be changed to be readwrite">; +def warn_auto_readonly_iboutlet_property : Warning< + "readonly IBOutlet property when auto-synthesized may " + "not work correctly with 'nib' loader">, + InGroup<DiagGroup<"readonly-iboutlet-property">>; def warn_auto_implicit_atomic_property : Warning< "property is assumed atomic when auto-synthesizing the property">, InGroup<ImplicitAtomic>, DefaultIgnore; diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp index f42259c6869..44e50852a55 100644 --- a/clang/lib/Sema/SemaObjCProperty.cpp +++ b/clang/lib/Sema/SemaObjCProperty.cpp @@ -200,6 +200,53 @@ makePropertyAttributesAsWritten(unsigned Attributes) { return (ObjCPropertyDecl::PropertyAttributeKind)attributesAsWritten; } +static std::string getPropertyAttributeString(const ObjCPropertyDecl *property, + unsigned Attributes) { + std::string attr; + if (!Attributes) + return attr; + attr = "("; + bool first = true; + if (Attributes & ObjCPropertyDecl::OBJC_PR_readonly) + {attr += !first ? ", readonly" : "readonly"; first = false; } + if (Attributes & ObjCPropertyDecl::OBJC_PR_readwrite) + {attr += !first ? ", readwrite" : "readwrite"; first = false; } + if (Attributes & ObjCPropertyDecl::OBJC_PR_getter) + { + if (!first) + attr += ", "; + attr += "getter="; + attr += property->getGetterName().getAsString(); + first = false; + } + if (Attributes & ObjCPropertyDecl::OBJC_PR_setter) + { + if (!first) + attr += ", "; + attr += "setter="; + attr += property->getSetterName().getAsString(); + first = false; + } + if (Attributes & ObjCPropertyDecl::OBJC_PR_assign) + {attr += !first ? ", assign" : "assign"; first = false; } + if (Attributes & ObjCPropertyDecl::OBJC_PR_retain) + {attr += !first ? ", retain" : "retain"; first = false; } + if (Attributes & ObjCPropertyDecl::OBJC_PR_strong) + {attr += !first ? ", strong" : "strong"; first = false; } + if (Attributes & ObjCPropertyDecl::OBJC_PR_weak) + {attr += !first ? ", weak" : "weak"; first = false; } + if (Attributes & ObjCPropertyDecl::OBJC_PR_copy) + {attr += !first ? ", copy" : "copy"; first = false; } + if (Attributes & ObjCPropertyDecl::OBJC_PR_unsafe_unretained) + {attr += !first ? ", unsafe_unretained" : "unsafe_unretained"; first = false; } + if (Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) + {attr += !first ? ", nonatomic" : "nonatomic"; first = false; } + if (Attributes & ObjCPropertyDecl::OBJC_PR_atomic) + {attr += !first ? ", atomic" : "atomic"; first = false; } + attr += ")"; + return attr; +} + Decl * Sema::HandlePropertyInClassExtension(Scope *S, SourceLocation AtLoc, @@ -628,6 +675,26 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, return 0; } } + + if (Synthesize&& + (PIkind & ObjCPropertyDecl::OBJC_PR_readonly) && + property->hasAttr<IBOutletAttr>() && + !AtLoc.isValid()) { + unsigned rwPIKind = (PIkind | ObjCPropertyDecl::OBJC_PR_readwrite); + rwPIKind &= (~ObjCPropertyDecl::OBJC_PR_readonly); + Diag(IC->getLocation(), diag::warn_auto_readonly_iboutlet_property); + Diag(property->getLocation(), diag::note_property_declare); + // FIXME. End location must be that of closing ')' which is currently + // unavailable. Need to add it. + SourceLocation endLoc = + property->getTypeSourceInfo()->getTypeLoc().getBeginLoc(); + SourceRange PropSourceRange(property->getLParenLoc(), endLoc); + Diag(property->getLocation(), + diag::note_auto_readonly_iboutlet_fixup_suggest) << + FixItHint::CreateReplacement(PropSourceRange, getPropertyAttributeString(property, + rwPIKind)); + } + } else if ((CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl))) { if (Synthesize) { Diag(AtLoc, diag::error_synthesize_category_decl); diff --git a/clang/test/SemaObjC/iboutlet.m b/clang/test/SemaObjC/iboutlet.m new file mode 100644 index 00000000000..13e5d53bb02 --- /dev/null +++ b/clang/test/SemaObjC/iboutlet.m @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -fobjc-default-synthesize-properties -verify %s +// RUN: %clang_cc1 -x objective-c++ -fsyntax-only -fobjc-default-synthesize-properties -verify %s +// rdar://11448209 + +@class NSView; + +#define IBOutlet __attribute__((iboutlet)) + +@interface I +@property (getter = MyGetter, readonly, assign) IBOutlet NSView *myView; // expected-note {{property declared here}} \ + // expected-note {{readonly IBOutlet property should be changed to be readwrite}} +@end + +@implementation I // expected-warning {{readonly IBOutlet property when auto-synthesized may not work correctly with 'nib' loader}} +@end |

