24#include "llvm/ADT/SmallPtrSet.h"
25#include "llvm/ADT/SmallString.h"
26#include "llvm/Support/raw_ostream.h"
32struct SelectorDescriptor {
33 const char *SelectorName;
34 unsigned ArgumentCount;
43 explicit FindSuperCallVisitor(
Selector S) : DoesCallSuper(
false), Sel(S) {}
46 if (
E->getSelector() == Sel)
51 return !DoesCallSuper;
64class ObjCSuperCallChecker :
public Checker<
65 check::ASTDecl<ObjCImplementationDecl> > {
67 ObjCSuperCallChecker() =
default;
73 StringRef &SuperclassName)
const;
74 void initializeSelectors(
ASTContext &Ctx)
const;
76 StringRef ClassName)
const;
77 mutable llvm::StringMap<llvm::SmallPtrSet<Selector, 16>> SelectorsForClass;
78 mutable bool IsInitialized =
false;
89 StringRef &SuperclassName)
const {
91 for ( ;
ID ;
ID =
ID->getSuperClass())
93 SuperclassName =
ID->getIdentifier()->getName();
94 if (SelectorsForClass.count(SuperclassName))
100void ObjCSuperCallChecker::fillSelectors(
ASTContext &Ctx,
102 StringRef ClassName)
const {
104 SelectorsForClass[ClassName];
106 for (SelectorDescriptor Descriptor : Sel) {
107 assert(Descriptor.ArgumentCount <= 1);
113 ClassSelectors.insert(Sel);
117void ObjCSuperCallChecker::initializeSelectors(
ASTContext &Ctx)
const {
120 const SelectorDescriptor Selectors[] = {
121 {
"addChildViewController", 1 },
122 {
"viewDidAppear", 1 },
123 {
"viewDidDisappear", 1 },
124 {
"viewWillAppear", 1 },
125 {
"viewWillDisappear", 1 },
126 {
"removeFromParentViewController", 0 },
127 {
"didReceiveMemoryWarning", 0 },
128 {
"viewDidUnload", 0 },
129 {
"viewDidLoad", 0 },
130 {
"viewWillUnload", 0 },
131 {
"updateViewConstraints", 0 },
132 {
"encodeRestorableStateWithCoder", 1 },
133 {
"restoreStateWithCoder", 1 }};
135 fillSelectors(Ctx, Selectors,
"UIViewController");
139 const SelectorDescriptor Selectors[] = {
140 {
"resignFirstResponder", 0 }};
142 fillSelectors(Ctx, Selectors,
"UIResponder");
146 const SelectorDescriptor Selectors[] = {
147 {
"encodeRestorableStateWithCoder", 1 },
148 {
"restoreStateWithCoder", 1 }};
150 fillSelectors(Ctx, Selectors,
"NSResponder");
154 const SelectorDescriptor Selectors[] = {
155 {
"encodeRestorableStateWithCoder", 1 },
156 {
"restoreStateWithCoder", 1 }};
158 fillSelectors(Ctx, Selectors,
"NSDocument");
161 IsInitialized =
true;
171 initializeSelectors(Ctx);
174 StringRef SuperclassName;
175 if (!isCheckableClass(
D, SuperclassName))
180 for (
auto *MD :
D->instance_methods()) {
183 if (!SelectorsForClass[SuperclassName].count(S))
189 FindSuperCallVisitor Visitor(S);
190 Visitor.TraverseDecl(MD);
193 if (!Visitor.DoesCallSuper) {
199 const char *Name =
"Missing call to superclass";
201 llvm::raw_svector_ostream os(Buf);
203 os <<
"The '" << S.getAsString()
204 <<
"' instance method in " << SuperclassName.str() <<
" subclass '"
205 << *
D <<
"' is missing a [super " << S.getAsString() <<
"] call";
223bool ento::shouldRegisterObjCSuperCallChecker(
const CheckerManager &mgr) {
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SelectorTable & Selectors
One of these records is kept for each identifier that is lexed.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...
Represents an ObjC class declaration.
An expression that sends a message to the given Objective-C object or class.
@ SuperInstance
The receiver is the instance of the superclass object.
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
Selector getSelector(unsigned NumArgs, const IdentifierInfo **IIV)
Can create any sort of selector.
Smart pointer class that efficiently represents Objective-C method names.
AnalysisDeclContext * getAnalysisDeclContext(const Decl *D)
BugReporter is a utility class for generating PathDiagnostics for analysis.
const SourceManager & getSourceManager()
void EmitBasicReport(const Decl *DeclWithIssue, const CheckerBase *Checker, StringRef BugName, StringRef BugCategory, StringRef BugStr, PathDiagnosticLocation Loc, ArrayRef< SourceRange > Ranges=std::nullopt, ArrayRef< FixItHint > Fixits=std::nullopt)
ASTContext & getContext()
CHECKER * registerChecker(AT &&... Args)
Used to register checkers.
static PathDiagnosticLocation createEnd(const Stmt *S, const SourceManager &SM, const LocationOrAnalysisDeclContext LAC)
Create a location for the end of the statement.
const char *const CoreFoundationObjectiveC
The JSON file list parser is used to communicate input to InstallAPI.