Skip to content

Commit ac7c8eb

Browse files
authored
[NFC][analyzer] Simplify ownership of checker objects (#128887)
Previously checker objects were created by raw `new` calls, which necessitated managing and calling their destructors explicitly. This commit refactors this convoluted logic by introducing `unique_ptr`s that to manage the ownership of these objects automatically. This change can be thought of as stand-alone code quality improvement; but I also have a secondary motivation that I'm planning further changes in the checker registration/initialization process (to formalize our tradition of multi-part checker) and this commit "prepares the ground" for those changes.
1 parent f8cc509 commit ac7c8eb

File tree

2 files changed

+34
-41
lines changed

2 files changed

+34
-41
lines changed

clang/include/clang/StaticAnalyzer/Core/CheckerManager.h

Lines changed: 30 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -185,13 +185,11 @@ class CheckerManager {
185185
StringRef OptionName,
186186
StringRef ExpectedValueDesc) const;
187187

188-
using CheckerRef = CheckerBase *;
189188
using CheckerTag = const void *;
190-
using CheckerDtor = CheckerFn<void ()>;
191189

192-
//===----------------------------------------------------------------------===//
193-
// Checker registration.
194-
//===----------------------------------------------------------------------===//
190+
//===--------------------------------------------------------------------===//
191+
// Checker registration.
192+
//===--------------------------------------------------------------------===//
195193

196194
/// Used to register checkers.
197195
/// All arguments are automatically passed through to the checker
@@ -200,25 +198,25 @@ class CheckerManager {
200198
/// \returns a pointer to the checker object.
201199
template <typename CHECKER, typename... AT>
202200
CHECKER *registerChecker(AT &&... Args) {
203-
CheckerTag tag = getTag<CHECKER>();
204-
CheckerRef &ref = CheckerTags[tag];
205-
assert(!ref && "Checker already registered, use getChecker!");
206-
207-
CHECKER *checker = new CHECKER(std::forward<AT>(Args)...);
208-
checker->Name = CurrentCheckerName;
209-
CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>));
210-
CHECKER::_register(checker, *this);
211-
ref = checker;
212-
return checker;
201+
CheckerTag Tag = getTag<CHECKER>();
202+
std::unique_ptr<CheckerBase> &Ref = CheckerTags[Tag];
203+
assert(!Ref && "Checker already registered, use getChecker!");
204+
205+
std::unique_ptr<CHECKER> Checker =
206+
std::make_unique<CHECKER>(std::forward<AT>(Args)...);
207+
Checker->Name = CurrentCheckerName;
208+
CHECKER::_register(Checker.get(), *this);
209+
Ref = std::move(Checker);
210+
return static_cast<CHECKER *>(Ref.get());
213211
}
214212

215213
template <typename CHECKER>
216214
CHECKER *getChecker() {
217-
CheckerTag tag = getTag<CHECKER>();
218-
assert(CheckerTags.count(tag) != 0 &&
219-
"Requested checker is not registered! Maybe you should add it as a "
220-
"dependency in Checkers.td?");
221-
return static_cast<CHECKER *>(CheckerTags[tag]);
215+
CheckerTag Tag = getTag<CHECKER>();
216+
std::unique_ptr<CheckerBase> &Ref = CheckerTags[Tag];
217+
assert(Ref && "Requested checker is not registered! Maybe you should add it"
218+
" as a dependency in Checkers.td?");
219+
return static_cast<CHECKER *>(Ref.get());
222220
}
223221

224222
template <typename CHECKER> bool isRegisteredChecker() {
@@ -462,9 +460,9 @@ class CheckerManager {
462460
unsigned int Space = 0,
463461
bool IsDot = false) const;
464462

465-
//===----------------------------------------------------------------------===//
463+
//===--------------------------------------------------------------------===//
466464
// Internal registration functions for AST traversing.
467-
//===----------------------------------------------------------------------===//
465+
//===--------------------------------------------------------------------===//
468466

469467
// Functions used by the registration mechanism, checkers should not touch
470468
// these directly.
@@ -478,9 +476,9 @@ class CheckerManager {
478476

479477
void _registerForBody(CheckDeclFunc checkfn);
480478

481-
//===----------------------------------------------------------------------===//
482-
// Internal registration functions for path-sensitive checking.
483-
//===----------------------------------------------------------------------===//
479+
//===--------------------------------------------------------------------===//
480+
// Internal registration functions for path-sensitive checking.
481+
//===--------------------------------------------------------------------===//
484482

485483
using CheckStmtFunc = CheckerFn<void (const Stmt *, CheckerContext &)>;
486484

@@ -582,9 +580,9 @@ class CheckerManager {
582580

583581
void _registerForEndOfTranslationUnit(CheckEndOfTranslationUnit checkfn);
584582

585-
//===----------------------------------------------------------------------===//
586-
// Internal registration functions for events.
587-
//===----------------------------------------------------------------------===//
583+
//===--------------------------------------------------------------------===//
584+
// Internal registration functions for events.
585+
//===--------------------------------------------------------------------===//
588586

589587
using EventTag = void *;
590588
using CheckEventFunc = CheckerFn<void (const void *event)>;
@@ -611,20 +609,15 @@ class CheckerManager {
611609
Checker(&event);
612610
}
613611

614-
//===----------------------------------------------------------------------===//
615-
// Implementation details.
616-
//===----------------------------------------------------------------------===//
612+
//===--------------------------------------------------------------------===//
613+
// Implementation details.
614+
//===--------------------------------------------------------------------===//
617615

618616
private:
619-
template <typename CHECKER>
620-
static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); }
621-
622617
template <typename T>
623618
static void *getTag() { static int tag; return &tag; }
624619

625-
llvm::DenseMap<CheckerTag, CheckerRef> CheckerTags;
626-
627-
std::vector<CheckerDtor> CheckerDtors;
620+
llvm::DenseMap<CheckerTag, std::unique_ptr<CheckerBase>> CheckerTags;
628621

629622
struct DeclCheckerInfo {
630623
CheckDeclFunc CheckFn;

clang/lib/StaticAnalyzer/Frontend/CreateCheckerManager.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
//
1313
//===----------------------------------------------------------------------===//
1414

15+
#include "clang/StaticAnalyzer/Core/Checker.h"
1516
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
1617
#include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h"
1718
#include <memory>
@@ -42,10 +43,9 @@ CheckerManager::CheckerManager(AnalyzerOptions &AOptions,
4243
Registry.initializeRegistry(*this);
4344
}
4445

45-
CheckerManager::~CheckerManager() {
46-
for (const auto &CheckerDtor : CheckerDtors)
47-
CheckerDtor();
48-
}
46+
// This is declared here to ensure that the destructors of `CheckerBase` and
47+
// `CheckerRegistryData` are available.
48+
CheckerManager::~CheckerManager() = default;
4949

5050
} // namespace ento
5151
} // namespace clang

0 commit comments

Comments
 (0)