diff options
author | Jordan Rose <jordan_rose@apple.com> | 2015-01-16 23:04:31 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2015-01-16 23:04:31 +0000 |
commit | a34d04d35e72c9104c32e2f772b8bccab7f0cd33 (patch) | |
tree | d11a22b32d20a9434fbcff50b82962ee4dda18e5 /clang/lib/Sema/SemaObjCProperty.cpp | |
parent | 16ba553f754a6ab6c934deaa6232be1cb74db904 (diff) | |
download | bcm5719-llvm-a34d04d35e72c9104c32e2f772b8bccab7f0cd33.tar.gz bcm5719-llvm-a34d04d35e72c9104c32e2f772b8bccab7f0cd33.zip |
Suggest objc_method_family(none) for a property named -newFoo or similar.
As mentioned in the previous commit, if a property (declared with @property)
has a name that matches a special Objective-C method family, the getter picks
up that family despite being declared by the property. The most correct way
to solve this problem is to add the 'objc_method_family' attribute to the
getter with an argument of 'none', which unfortunately requires an explicit
declaration of the getter.
This commit adds a note to the existing error (ARC) or warning (MRR) for
such a poorly-named property that suggests the solution; if there's already
a declaration of the getter, it even includes a fix-it.
llvm-svn: 226339
Diffstat (limited to 'clang/lib/Sema/SemaObjCProperty.cpp')
-rw-r--r-- | clang/lib/Sema/SemaObjCProperty.cpp | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp index 72b6020351f..f4f43360f5e 100644 --- a/clang/lib/Sema/SemaObjCProperty.cpp +++ b/clang/lib/Sema/SemaObjCProperty.cpp @@ -19,6 +19,7 @@ #include "clang/AST/ExprObjC.h" #include "clang/Basic/SourceManager.h" #include "clang/Lex/Lexer.h" +#include "clang/Lex/Preprocessor.h" #include "clang/Sema/Initialization.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallString.h" @@ -1854,6 +1855,39 @@ void Sema::DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D Diag(PD->getLocation(), diag::err_cocoa_naming_owned_rule); else Diag(PD->getLocation(), diag::warn_cocoa_naming_owned_rule); + + // Look for a getter explicitly declared alongside the property. + // If we find one, use its location for the note. + SourceLocation noteLoc = PD->getLocation(); + SourceLocation fixItLoc; + for (auto *getterRedecl : method->redecls()) { + if (getterRedecl->isImplicit()) + continue; + if (getterRedecl->getDeclContext() != PD->getDeclContext()) + continue; + noteLoc = getterRedecl->getLocation(); + fixItLoc = getterRedecl->getLocEnd(); + } + + Preprocessor &PP = getPreprocessor(); + TokenValue tokens[] = { + tok::kw___attribute, tok::l_paren, tok::l_paren, + PP.getIdentifierInfo("objc_method_family"), tok::l_paren, + PP.getIdentifierInfo("none"), tok::r_paren, + tok::r_paren, tok::r_paren + }; + StringRef spelling = "__attribute__((objc_method_family(none)))"; + StringRef macroName = PP.getLastMacroWithSpelling(noteLoc, tokens); + if (!macroName.empty()) + spelling = macroName; + + auto noteDiag = Diag(noteLoc, diag::note_cocoa_naming_declare_family) + << method->getDeclName() << spelling; + if (fixItLoc.isValid()) { + SmallString<64> fixItText(" "); + fixItText += spelling; + noteDiag << FixItHint::CreateInsertion(fixItLoc, fixItText); + } } } } |