mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-29 14:16:07 +00:00

Previously, if accidentally multiple checkers `eval::Call`-ed the same `CallEvent`, in debug builds the analyzer detected this and crashed with the message stating this. Unfortunately, the message did not state the offending checkers violating this invariant. This revision addresses this by printing a more descriptive message before aborting. Reviewed By: martong Differential Revision: https://reviews.llvm.org/D112889
59 lines
2.1 KiB
C++
59 lines
2.1 KiB
C++
//===----------------------------------------------------------------------===//
|
|
//
|
|
// 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 "CheckerRegistration.h"
|
|
#include "clang/StaticAnalyzer/Core/Checker.h"
|
|
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
|
|
#include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
using namespace clang;
|
|
using namespace ento;
|
|
|
|
namespace {
|
|
class EvalCallBase : public Checker<eval::Call> {
|
|
const CallDescription Foo = {"foo", 0};
|
|
|
|
public:
|
|
bool evalCall(const CallEvent &Call, CheckerContext &C) const {
|
|
return Call.isCalled(Foo);
|
|
}
|
|
};
|
|
|
|
class EvalCallFoo1 : public EvalCallBase {};
|
|
class EvalCallFoo2 : public EvalCallBase {};
|
|
void addEvalFooCheckers(AnalysisASTConsumer &AnalysisConsumer,
|
|
AnalyzerOptions &AnOpts) {
|
|
AnOpts.CheckersAndPackages = {{"test.EvalFoo1", true},
|
|
{"test.EvalFoo2", true}};
|
|
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
|
|
Registry.addChecker<EvalCallFoo1>("test.EvalFoo1", "EmptyDescription",
|
|
"EmptyDocsUri");
|
|
Registry.addChecker<EvalCallFoo2>("test.EvalFoo2", "EmptyDescription",
|
|
"EmptyDocsUri");
|
|
});
|
|
}
|
|
} // namespace
|
|
|
|
TEST(EvalCall, DetectConflictingEvalCalls) {
|
|
#ifdef NDEBUG
|
|
GTEST_SKIP() << "This test is only available for debug builds.";
|
|
#endif
|
|
const std::string Code = R"code(
|
|
void foo();
|
|
void top() {
|
|
foo(); // crash
|
|
}
|
|
)code";
|
|
constexpr auto Regex =
|
|
"The 'foo\\(\\)' call has been already evaluated by the test\\.EvalFoo1 "
|
|
"checker, while the test\\.EvalFoo2 checker also tried to evaluate the "
|
|
"same call\\. At most one checker supposed to evaluate a call\\.";
|
|
ASSERT_DEATH(runCheckerOnCode<addEvalFooCheckers>(Code), Regex);
|
|
}
|