[clang] 58884eb - [analyzer][NFC] Refactor the checker registration unit test file
Kirstóf Umann via cfe-commits
cfe-commits at lists.llvm.org
Mon Mar 9 08:48:10 PDT 2020
Author: Kirstóf Umann
Date: 2020-03-09T16:38:30+01:00
New Revision: 58884eb6489880646896d72fcd723813f8a13299
URL: https://github.com/llvm/llvm-project/commit/58884eb6489880646896d72fcd723813f8a13299
DIFF: https://github.com/llvm/llvm-project/commit/58884eb6489880646896d72fcd723813f8a13299.diff
LOG: [analyzer][NFC] Refactor the checker registration unit test file
Nothing exciting to see here! The new interface allows for more fine tuning
(register but disable a checker, add custom checker registry functions, etc),
that was basically the point.
Differential Revision: https://reviews.llvm.org/D67335
Added:
clang/unittests/StaticAnalyzer/CheckerRegistration.h
Modified:
clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h
clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h b/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h
index bc258160ada4..269c226f2e1d 100644
--- a/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h
+++ b/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h
@@ -204,16 +204,14 @@ class CheckerRegistry {
using PackageInfoList = llvm::SmallVector<PackageInfo, 0>;
-private:
- template <typename T> static void initializeManager(CheckerManager &mgr) {
+ template <typename T> static void addToCheckerMgr(CheckerManager &mgr) {
mgr.registerChecker<T>();
}
- template <typename T> static bool returnTrue(const LangOptions &LO) {
+ static bool returnTrue(const LangOptions &LO) {
return true;
}
-public:
/// Adds a checker to the registry. Use this non-templated overload when your
/// checker requires custom initialization.
void addChecker(InitializationFunction Fn, ShouldRegisterFunction sfn,
@@ -227,9 +225,8 @@ class CheckerRegistry {
bool IsHidden = false) {
// Avoid MSVC's Compiler Error C2276:
// http://msdn.microsoft.com/en-us/library/850cstw1(v=VS.80).aspx
- addChecker(&CheckerRegistry::initializeManager<T>,
- &CheckerRegistry::returnTrue<T>, FullName, Desc, DocsUri,
- IsHidden);
+ addChecker(&CheckerRegistry::addToCheckerMgr<T>,
+ &CheckerRegistry::returnTrue, FullName, Desc, DocsUri, IsHidden);
}
/// Makes the checker with the full name \p fullName depends on the checker
diff --git a/clang/unittests/StaticAnalyzer/CheckerRegistration.h b/clang/unittests/StaticAnalyzer/CheckerRegistration.h
new file mode 100644
index 000000000000..0bbed9b7784f
--- /dev/null
+++ b/clang/unittests/StaticAnalyzer/CheckerRegistration.h
@@ -0,0 +1,81 @@
+//===- unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp ------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
+#include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h"
+#include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h"
+#include "clang/Tooling/Tooling.h"
+
+namespace clang {
+namespace ento {
+
+class DiagConsumer : public PathDiagnosticConsumer {
+ llvm::raw_ostream &Output;
+
+public:
+ DiagConsumer(llvm::raw_ostream &Output) : Output(Output) {}
+ void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
+ FilesMade *filesMade) override {
+ for (const auto *PD : Diags)
+ Output << PD->getCheckerName() << ":" << PD->getShortDescription() << '\n';
+ }
+
+ StringRef getName() const override { return "Test"; }
+};
+
+using AddCheckerFn = void(AnalysisASTConsumer &AnalysisConsumer,
+ AnalyzerOptions &AnOpts);
+
+template <AddCheckerFn Fn1, AddCheckerFn Fn2, AddCheckerFn... Fns>
+void addChecker(AnalysisASTConsumer &AnalysisConsumer,
+ AnalyzerOptions &AnOpts) {
+ Fn1(AnalysisConsumer, AnOpts);
+ addChecker<Fn2, Fns...>(AnalysisConsumer, AnOpts);
+}
+
+template <AddCheckerFn Fn1>
+void addChecker(AnalysisASTConsumer &AnalysisConsumer,
+ AnalyzerOptions &AnOpts) {
+ Fn1(AnalysisConsumer, AnOpts);
+}
+
+template <AddCheckerFn... Fns>
+class TestAction : public ASTFrontendAction {
+ llvm::raw_ostream &DiagsOutput;
+
+public:
+ TestAction(llvm::raw_ostream &DiagsOutput) : DiagsOutput(DiagsOutput) {}
+
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler,
+ StringRef File) override {
+ std::unique_ptr<AnalysisASTConsumer> AnalysisConsumer =
+ CreateAnalysisConsumer(Compiler);
+ AnalysisConsumer->AddDiagnosticConsumer(new DiagConsumer(DiagsOutput));
+ addChecker<Fns...>(*AnalysisConsumer, *Compiler.getAnalyzerOpts());
+ return std::move(AnalysisConsumer);
+ }
+};
+
+template <AddCheckerFn... Fns>
+bool runCheckerOnCode(const std::string &Code, std::string &Diags) {
+ llvm::raw_string_ostream OS(Diags);
+ return tooling::runToolOnCode(std::make_unique<TestAction<Fns...>>(OS), Code);
+}
+
+template <AddCheckerFn... Fns>
+bool runCheckerOnCode(const std::string &Code) {
+ std::string Diags;
+ return runCheckerOnCode<Fns...>(Code, Diags);
+}
+
+} // namespace ento
+} // namespace clang
diff --git a/clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp b/clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp
index 4f504d2384cf..d0cf291eb2b8 100644
--- a/clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp
+++ b/clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp
@@ -6,11 +6,13 @@
//
//===----------------------------------------------------------------------===//
+#include "CheckerRegistration.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h"
#include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h"
#include "clang/Tooling/Tooling.h"
@@ -20,53 +22,10 @@ namespace clang {
namespace ento {
namespace {
-template <typename CheckerT>
-class TestAction : public ASTFrontendAction {
- class DiagConsumer : public PathDiagnosticConsumer {
- llvm::raw_ostream &Output;
-
- public:
- DiagConsumer(llvm::raw_ostream &Output) : Output(Output) {}
- void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
- FilesMade *filesMade) override {
- for (const auto *PD : Diags)
- Output << PD->getCheckerName() << ":" << PD->getShortDescription();
- }
-
- StringRef getName() const override { return "Test"; }
- };
-
- llvm::raw_ostream &DiagsOutput;
-
-public:
- TestAction(llvm::raw_ostream &DiagsOutput) : DiagsOutput(DiagsOutput) {}
-
- std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler,
- StringRef File) override {
- std::unique_ptr<AnalysisASTConsumer> AnalysisConsumer =
- CreateAnalysisConsumer(Compiler);
- AnalysisConsumer->AddDiagnosticConsumer(new DiagConsumer(DiagsOutput));
- Compiler.getAnalyzerOpts()->CheckersAndPackages = {
- {"custom.CustomChecker", true}};
- AnalysisConsumer->AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
- Registry.addChecker<CheckerT>("custom.CustomChecker", "Description", "");
- });
- return std::move(AnalysisConsumer);
- }
-};
-
-template <typename CheckerT>
-bool runCheckerOnCode(const std::string &Code, std::string &Diags) {
- llvm::raw_string_ostream OS(Diags);
- return tooling::runToolOnCode(std::make_unique<TestAction<CheckerT>>(OS),
- Code);
-}
-template <typename CheckerT>
-bool runCheckerOnCode(const std::string &Code) {
- std::string Diags;
- return runCheckerOnCode<CheckerT>(Code, Diags);
-}
-
+//===----------------------------------------------------------------------===//
+// Just a minimal test for how checker registration works with statically
+// linked, non TableGen generated checkers.
+//===----------------------------------------------------------------------===//
class CustomChecker : public Checker<check::ASTCodeBody> {
public:
@@ -78,12 +37,25 @@ class CustomChecker : public Checker<check::ASTCodeBody> {
}
};
+void addCustomChecker(AnalysisASTConsumer &AnalysisConsumer,
+ AnalyzerOptions &AnOpts) {
+ AnOpts.CheckersAndPackages = {{"custom.CustomChecker", true}};
+ AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
+ Registry.addChecker<CustomChecker>("custom.CustomChecker", "Description",
+ "");
+ });
+}
+
TEST(RegisterCustomCheckers, RegisterChecker) {
std::string Diags;
- EXPECT_TRUE(runCheckerOnCode<CustomChecker>("void f() {;}", Diags));
- EXPECT_EQ(Diags, "custom.CustomChecker:Custom diagnostic description");
+ EXPECT_TRUE(runCheckerOnCode<addCustomChecker>("void f() {;}", Diags));
+ EXPECT_EQ(Diags, "custom.CustomChecker:Custom diagnostic description\n");
}
+//===----------------------------------------------------------------------===//
+// Pretty much the same.
+//===----------------------------------------------------------------------===//
+
class LocIncDecChecker : public Checker<check::Location> {
public:
void checkLocation(SVal Loc, bool IsLoad, const Stmt *S,
@@ -95,11 +67,20 @@ class LocIncDecChecker : public Checker<check::Location> {
}
};
+void addLocIncDecChecker(AnalysisASTConsumer &AnalysisConsumer,
+ AnalyzerOptions &AnOpts) {
+ AnOpts.CheckersAndPackages = {{"test.LocIncDecChecker", true}};
+ AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
+ Registry.addChecker<CustomChecker>("test.LocIncDecChecker", "Description",
+ "");
+ });
+}
+
TEST(RegisterCustomCheckers, CheckLocationIncDec) {
EXPECT_TRUE(
- runCheckerOnCode<LocIncDecChecker>("void f() { int *p; (*p)++; }"));
+ runCheckerOnCode<addLocIncDecChecker>("void f() { int *p; (*p)++; }"));
}
-}
-}
-}
+} // namespace
+} // namespace ento
+} // namespace clang
More information about the cfe-commits
mailing list