Skip to content

Commit 51e8aa7

Browse files
NagyDonatkrishna2803
authored andcommitted
[analyzer] Conversion to CheckerFamily: NSOrCFErrorDerefChecker (llvm#151171)
This commit converts the class `NSOrCFErrorDerefChecker` to the checker family framework and simplifies some parts of the implementation (e.g. removes two very trivial subclasses of `BugType`). This commit is almost NFC, the only technically "functional" change is that it removes the hidden modeling checker `NSOrCFErrorDerefChecker` which was only relevant as an implementation detail of the old checker registration procedure.
1 parent 5556f52 commit 51e8aa7

File tree

2 files changed

+35
-78
lines changed

2 files changed

+35
-78
lines changed

clang/include/clang/StaticAnalyzer/Checkers/Checkers.td

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,11 +1047,6 @@ def RetainCountBase : Checker<"RetainCountBase">,
10471047

10481048
let ParentPackage = OSX in {
10491049

1050-
def NSOrCFErrorDerefChecker : Checker<"NSOrCFErrorDerefChecker">,
1051-
HelpText<"Implementation checker for NSErrorChecker and CFErrorChecker">,
1052-
Documentation<NotDocumented>,
1053-
Hidden;
1054-
10551050
def NumberObjectConversionChecker : Checker<"NumberObjectConversion">,
10561051
HelpText<"Check for erroneous conversions of objects representing numbers "
10571052
"into numbers">,
@@ -1149,9 +1144,8 @@ def ObjCSuperCallChecker : Checker<"MissingSuperCall">,
11491144
Documentation<NotDocumented>;
11501145

11511146
def NSErrorChecker : Checker<"NSError">,
1152-
HelpText<"Check usage of NSError** parameters">,
1153-
Dependencies<[NSOrCFErrorDerefChecker]>,
1154-
Documentation<HasDocumentation>;
1147+
HelpText<"Check usage of NSError** parameters">,
1148+
Documentation<HasDocumentation>;
11551149

11561150
def RetainCountChecker : Checker<"RetainCount">,
11571151
HelpText<"Check for leaks and improper reference count management">,
@@ -1253,9 +1247,8 @@ def CFRetainReleaseChecker : Checker<"CFRetainRelease">,
12531247
Documentation<HasDocumentation>;
12541248

12551249
def CFErrorChecker : Checker<"CFError">,
1256-
HelpText<"Check usage of CFErrorRef* parameters">,
1257-
Dependencies<[NSOrCFErrorDerefChecker]>,
1258-
Documentation<HasDocumentation>;
1250+
HelpText<"Check usage of CFErrorRef* parameters">,
1251+
Documentation<HasDocumentation>;
12591252

12601253
} // end "osx.coreFoundation"
12611254

clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp

Lines changed: 31 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -142,34 +142,19 @@ void CFErrorFunctionChecker::checkASTDecl(const FunctionDecl *D,
142142
//===----------------------------------------------------------------------===//
143143

144144
namespace {
145+
class NSOrCFErrorDerefChecker
146+
: public CheckerFamily<check::Location,
147+
check::Event<ImplicitNullDerefEvent>> {
148+
mutable IdentifierInfo *NSErrorII = nullptr;
149+
mutable IdentifierInfo *CFErrorII = nullptr;
145150

146-
class NSErrorDerefBug : public BugType {
147-
public:
148-
NSErrorDerefBug(const CheckerNameRef Checker)
149-
: BugType(Checker, "NSError** null dereference",
150-
"Coding conventions (Apple)") {}
151-
};
152-
153-
class CFErrorDerefBug : public BugType {
154151
public:
155-
CFErrorDerefBug(const CheckerNameRef Checker)
156-
: BugType(Checker, "CFErrorRef* null dereference",
157-
"Coding conventions (Apple)") {}
158-
};
159-
160-
}
152+
CheckerFrontendWithBugType NSError{"NSError** null dereference",
153+
"Coding conventions (Apple)"};
154+
CheckerFrontendWithBugType CFError{"CFErrorRef* null dereference",
155+
"Coding conventions (Apple)"};
161156

162-
namespace {
163-
class NSOrCFErrorDerefChecker
164-
: public Checker< check::Location,
165-
check::Event<ImplicitNullDerefEvent> > {
166-
mutable IdentifierInfo *NSErrorII, *CFErrorII;
167-
mutable std::unique_ptr<NSErrorDerefBug> NSBT;
168-
mutable std::unique_ptr<CFErrorDerefBug> CFBT;
169-
public:
170-
bool ShouldCheckNSError = false, ShouldCheckCFError = false;
171-
CheckerNameRef NSErrorName, CFErrorName;
172-
NSOrCFErrorDerefChecker() : NSErrorII(nullptr), CFErrorII(nullptr) {}
157+
StringRef getDebugTag() const override { return "NSOrCFErrorDerefChecker"; }
173158

174159
void checkLocation(SVal loc, bool isLoad, const Stmt *S,
175160
CheckerContext &C) const;
@@ -236,12 +221,12 @@ void NSOrCFErrorDerefChecker::checkLocation(SVal loc, bool isLoad,
236221
if (!CFErrorII)
237222
CFErrorII = &Ctx.Idents.get("CFErrorRef");
238223

239-
if (ShouldCheckNSError && IsNSError(parmT, NSErrorII)) {
224+
if (NSError.isEnabled() && IsNSError(parmT, NSErrorII)) {
240225
setFlag<NSErrorOut>(state, state->getSVal(loc.castAs<Loc>()), C);
241226
return;
242227
}
243228

244-
if (ShouldCheckCFError && IsCFError(parmT, CFErrorII)) {
229+
if (CFError.isEnabled() && IsCFError(parmT, CFErrorII)) {
245230
setFlag<CFErrorOut>(state, state->getSVal(loc.castAs<Loc>()), C);
246231
return;
247232
}
@@ -274,19 +259,9 @@ void NSOrCFErrorDerefChecker::checkEvent(ImplicitNullDerefEvent event) const {
274259

275260
os << " may be null";
276261

277-
BugType *bug = nullptr;
278-
if (isNSError) {
279-
if (!NSBT)
280-
NSBT.reset(new NSErrorDerefBug(NSErrorName));
281-
bug = NSBT.get();
282-
}
283-
else {
284-
if (!CFBT)
285-
CFBT.reset(new CFErrorDerefBug(CFErrorName));
286-
bug = CFBT.get();
287-
}
262+
const BugType &BT = isNSError ? NSError : CFError;
288263
BR.emitReport(
289-
std::make_unique<PathSensitiveBugReport>(*bug, os.str(), event.SinkNode));
264+
std::make_unique<PathSensitiveBugReport>(BT, os.str(), event.SinkNode));
290265
}
291266

292267
static bool IsNSError(QualType T, IdentifierInfo *II) {
@@ -320,32 +295,21 @@ static bool IsCFError(QualType T, IdentifierInfo *II) {
320295
return TT->getDecl()->getIdentifier() == II;
321296
}
322297

323-
void ento::registerNSOrCFErrorDerefChecker(CheckerManager &mgr) {
324-
mgr.registerChecker<NSOrCFErrorDerefChecker>();
325-
}
326-
327-
bool ento::shouldRegisterNSOrCFErrorDerefChecker(const CheckerManager &mgr) {
328-
return true;
329-
}
330-
331-
void ento::registerNSErrorChecker(CheckerManager &mgr) {
332-
mgr.registerChecker<NSErrorMethodChecker>();
333-
NSOrCFErrorDerefChecker *checker = mgr.getChecker<NSOrCFErrorDerefChecker>();
334-
checker->ShouldCheckNSError = true;
335-
checker->NSErrorName = mgr.getCurrentCheckerName();
336-
}
337-
338-
bool ento::shouldRegisterNSErrorChecker(const CheckerManager &mgr) {
339-
return true;
340-
}
341-
342-
void ento::registerCFErrorChecker(CheckerManager &mgr) {
343-
mgr.registerChecker<CFErrorFunctionChecker>();
344-
NSOrCFErrorDerefChecker *checker = mgr.getChecker<NSOrCFErrorDerefChecker>();
345-
checker->ShouldCheckCFError = true;
346-
checker->CFErrorName = mgr.getCurrentCheckerName();
347-
}
298+
// This source file implements two user-facing checkers ("osx.cocoa.NSError"
299+
// and "osx.coreFoundation.CFError") which are both implemented as the
300+
// combination of two `CheckerFrontend`s that are registered under the same
301+
// name (but otherwise act independently). Among these 2+2 `CheckerFrontend`s
302+
// two are coming from the checker family `NSOrCFErrorDerefChecker` while the
303+
// other two (the `ADDITIONAL_PART`s) are small standalone checkers.
304+
#define REGISTER_CHECKER(NAME, ADDITIONAL_PART) \
305+
void ento::register##NAME##Checker(CheckerManager &Mgr) { \
306+
Mgr.getChecker<NSOrCFErrorDerefChecker>()->NAME.enable(Mgr); \
307+
Mgr.registerChecker<ADDITIONAL_PART>(); \
308+
} \
309+
\
310+
bool ento::shouldRegister##NAME##Checker(const CheckerManager &) { \
311+
return true; \
312+
}
348313

349-
bool ento::shouldRegisterCFErrorChecker(const CheckerManager &mgr) {
350-
return true;
351-
}
314+
REGISTER_CHECKER(NSError, NSErrorMethodChecker)
315+
REGISTER_CHECKER(CFError, CFErrorFunctionChecker)

0 commit comments

Comments
 (0)