25 #include "llvm/ADT/SmallSet.h"
26 #include "llvm/ADT/SmallString.h"
27 #include "llvm/Support/raw_ostream.h"
29 using namespace clang;
33 struct SelectorDescriptor {
34 const char *SelectorName;
35 unsigned ArgumentCount;
44 explicit FindSuperCallVisitor(
Selector S) : DoesCallSuper(
false), Sel(S) {}
52 return !DoesCallSuper;
65 class ObjCSuperCallChecker :
public Checker<
66 check::ASTDecl<ObjCImplementationDecl> > {
68 ObjCSuperCallChecker() : IsInitialized(
false) {}
74 StringRef &SuperclassName)
const;
75 void initializeSelectors(
ASTContext &Ctx)
const;
77 StringRef ClassName)
const;
78 mutable llvm::StringMap<llvm::SmallSet<Selector, 16> > SelectorsForClass;
79 mutable bool IsInitialized;
90 StringRef &SuperclassName)
const {
95 if (SelectorsForClass.count(SuperclassName))
101 void ObjCSuperCallChecker::fillSelectors(
ASTContext &Ctx,
103 StringRef ClassName)
const {
104 llvm::SmallSet<Selector, 16> &ClassSelectors = SelectorsForClass[ClassName];
108 SelectorDescriptor Descriptor = *
I;
109 assert(Descriptor.ArgumentCount <= 1);
115 ClassSelectors.insert(Sel);
119 void ObjCSuperCallChecker::initializeSelectors(
ASTContext &Ctx)
const {
122 const SelectorDescriptor Selectors[] = {
123 {
"addChildViewController", 1 },
124 {
"viewDidAppear", 1 },
125 {
"viewDidDisappear", 1 },
126 {
"viewWillAppear", 1 },
127 {
"viewWillDisappear", 1 },
128 {
"removeFromParentViewController", 0 },
129 {
"didReceiveMemoryWarning", 0 },
130 {
"viewDidUnload", 0 },
131 {
"viewDidLoad", 0 },
132 {
"viewWillUnload", 0 },
133 {
"updateViewConstraints", 0 },
134 {
"encodeRestorableStateWithCoder", 1 },
135 {
"restoreStateWithCoder", 1 }};
137 fillSelectors(Ctx, Selectors,
"UIViewController");
141 const SelectorDescriptor Selectors[] = {
142 {
"resignFirstResponder", 0 }};
144 fillSelectors(Ctx, Selectors,
"UIResponder");
148 const SelectorDescriptor Selectors[] = {
149 {
"encodeRestorableStateWithCoder", 1 },
150 {
"restoreStateWithCoder", 1 }};
152 fillSelectors(Ctx, Selectors,
"NSResponder");
156 const SelectorDescriptor Selectors[] = {
157 {
"encodeRestorableStateWithCoder", 1 },
158 {
"restoreStateWithCoder", 1 }};
160 fillSelectors(Ctx, Selectors,
"NSDocument");
163 IsInitialized =
true;
173 initializeSelectors(Ctx);
176 StringRef SuperclassName;
177 if (!isCheckableClass(D, SuperclassName))
185 if (!SelectorsForClass[SuperclassName].count(S))
191 FindSuperCallVisitor Visitor(S);
192 Visitor.TraverseDecl(MD);
195 if (!Visitor.DoesCallSuper) {
201 const char *
Name =
"Missing call to superclass";
203 llvm::raw_svector_ostream os(Buf);
206 <<
"' instance method in " << SuperclassName.str() <<
" subclass '"
207 << *D <<
"' is missing a [super " << S.
getAsString() <<
"] call";
The receiver is the instance of the superclass object.
const char *const CoreFoundationObjectiveC
Smart pointer class that efficiently represents Objective-C method names.
IdentifierInfo * getIdentifier() const
getIdentifier - Get the identifier that names this declaration, if there is one.
One of these records is kept for each identifier that is lexed.
class LLVM_ALIGNAS(8) DependentTemplateSpecializationType const IdentifierInfo * Name
Represents a template specialization type whose template cannot be resolved, e.g. ...
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
ASTContext & getContext()
Selector getSelector() const
A class that does preordor or postorder depth-first traversal on the entire Clang AST and visits each...
Represents an ObjC class declaration.
detail::InMemoryDirectory::const_iterator I
AnalysisDeclContext * getAnalysisDeclContext(const Decl *D)
StringRef getName() const
Return the actual identifier string.
An expression that sends a message to the given Objective-C object or class.
BugReporter is a utility class for generating PathDiagnostics for analysis.
SelectorTable & Selectors
CHECKER * registerChecker()
Used to register checkers.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
void EmitBasicReport(const Decl *DeclWithIssue, const CheckerBase *Checker, StringRef BugName, StringRef BugCategory, StringRef BugStr, PathDiagnosticLocation Loc, ArrayRef< SourceRange > Ranges=None)
static PathDiagnosticLocation createEnd(const Stmt *S, const SourceManager &SM, const LocationOrAnalysisDeclContext LAC)
Create a location for the end of the statement.
const ObjCInterfaceDecl * getClassInterface() const
std::string getAsString() const
Derive the full selector name (e.g.
instmeth_range instance_methods() const
detail::InMemoryDirectory::const_iterator E
ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...
Selector getSelector(unsigned NumArgs, IdentifierInfo **IIV)
Can create any sort of selector.
SourceManager & getSourceManager()
ObjCInterfaceDecl * getSuperClass() const
ReceiverKind getReceiverKind() const
Determine the kind of receiver that this message is being sent to.