llvm-project
165 строк · 5.6 Кб
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "Reusables.h"10#include "clang/Frontend/CompilerInstance.h"11#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"12#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"13#include "clang/StaticAnalyzer/Core/Checker.h"14#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"15#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"16#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"17#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"18#include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h"19#include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h"20#include "clang/Tooling/Tooling.h"21#include "gtest/gtest.h"22
23using namespace clang;24using namespace ento;25using namespace llvm;26
27namespace {28
29class InterestingnessTestChecker : public Checker<check::PreCall> {30BugType BT_TestBug;31
32using HandlerFn = std::function<void(const InterestingnessTestChecker *,33const CallEvent &, CheckerContext &)>;34
35CallDescriptionMap<HandlerFn> Handlers = {36{{CDM::SimpleFunc, {"setInteresting"}, 1},37&InterestingnessTestChecker::handleInteresting},38{{CDM::SimpleFunc, {"setNotInteresting"}, 1},39&InterestingnessTestChecker::handleNotInteresting},40{{CDM::SimpleFunc, {"check"}, 1},41&InterestingnessTestChecker::handleCheck},42{{CDM::SimpleFunc, {"bug"}, 1}, &InterestingnessTestChecker::handleBug},43};44
45void handleInteresting(const CallEvent &Call, CheckerContext &C) const;46void handleNotInteresting(const CallEvent &Call, CheckerContext &C) const;47void handleCheck(const CallEvent &Call, CheckerContext &C) const;48void handleBug(const CallEvent &Call, CheckerContext &C) const;49
50public:51InterestingnessTestChecker()52: BT_TestBug(this, "InterestingnessTestBug", "Test") {}53
54void checkPreCall(const CallEvent &Call, CheckerContext &C) const {55const HandlerFn *Handler = Handlers.lookup(Call);56if (!Handler)57return;58
59(*Handler)(this, Call, C);60}61};62
63} // namespace64
65void InterestingnessTestChecker::handleInteresting(const CallEvent &Call,66CheckerContext &C) const {67SymbolRef Sym = Call.getArgSVal(0).getAsSymbol();68assert(Sym);69C.addTransition(nullptr, C.getNoteTag([Sym](PathSensitiveBugReport &BR) {70BR.markInteresting(Sym);71return "";72}));73}
74
75void InterestingnessTestChecker::handleNotInteresting(const CallEvent &Call,76CheckerContext &C) const {77SymbolRef Sym = Call.getArgSVal(0).getAsSymbol();78assert(Sym);79C.addTransition(nullptr, C.getNoteTag([Sym](PathSensitiveBugReport &BR) {80BR.markNotInteresting(Sym);81return "";82}));83}
84
85void InterestingnessTestChecker::handleCheck(const CallEvent &Call,86CheckerContext &C) const {87SymbolRef Sym = Call.getArgSVal(0).getAsSymbol();88assert(Sym);89C.addTransition(nullptr, C.getNoteTag([Sym](PathSensitiveBugReport &BR) {90if (BR.isInteresting(Sym))91return "Interesting";92else93return "NotInteresting";94}));95}
96
97void InterestingnessTestChecker::handleBug(const CallEvent &Call,98CheckerContext &C) const {99ExplodedNode *N = C.generateErrorNode();100C.emitReport(101std::make_unique<PathSensitiveBugReport>(BT_TestBug, "test bug", N));102}
103
104namespace {105
106class TestAction : public ASTFrontendAction {107ExpectedDiagsTy ExpectedDiags;108
109public:110TestAction(ExpectedDiagsTy &&ExpectedDiags)111: ExpectedDiags(std::move(ExpectedDiags)) {}112
113std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler,114StringRef File) override {115std::unique_ptr<AnalysisASTConsumer> AnalysisConsumer =116CreateAnalysisConsumer(Compiler);117AnalysisConsumer->AddDiagnosticConsumer(new VerifyPathDiagnosticConsumer(118std::move(ExpectedDiags), Compiler.getSourceManager()));119AnalysisConsumer->AddCheckerRegistrationFn([](CheckerRegistry &Registry) {120Registry.addChecker<InterestingnessTestChecker>("test.Interestingness",121"Description", "");122});123Compiler.getAnalyzerOpts().CheckersAndPackages = {124{"test.Interestingness", true}};125return std::move(AnalysisConsumer);126}127};128
129} // namespace130
131TEST(BugReportInterestingness, Symbols) {132EXPECT_TRUE(tooling::runToolOnCode(133std::make_unique<TestAction>(ExpectedDiagsTy{134{{15, 7},135"test bug",136"test bug",137"test.Interestingness",138"InterestingnessTestBug",139"Test",140{141{{8, 7}, "Interesting", {{{8, 7}, {8, 14}}}},142{{10, 7}, "NotInteresting", {{{10, 7}, {10, 14}}}},143{{12, 7}, "Interesting", {{{12, 7}, {12, 14}}}},144{{14, 7}, "NotInteresting", {{{14, 7}, {14, 14}}}},145{{15, 7}, "test bug", {{{15, 7}, {15, 12}}}},146}}}),147R"(148void setInteresting(int);
149void setNotInteresting(int);
150void check(int);
151void bug(int);
152
153void f(int A) {
154check(A);
155setInteresting(A);
156check(A);
157setNotInteresting(A);
158check(A);
159setInteresting(A);
160check(A);
161bug(A);
162}
163)",164"input.cpp"));165}
166