llvm-project

Форк
0
/
BugReportInterestingnessTest.cpp 
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

23
using namespace clang;
24
using namespace ento;
25
using namespace llvm;
26

27
namespace {
28

29
class InterestingnessTestChecker : public Checker<check::PreCall> {
30
  BugType BT_TestBug;
31

32
  using HandlerFn = std::function<void(const InterestingnessTestChecker *,
33
                                       const CallEvent &, CheckerContext &)>;
34

35
  CallDescriptionMap<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

45
  void handleInteresting(const CallEvent &Call, CheckerContext &C) const;
46
  void handleNotInteresting(const CallEvent &Call, CheckerContext &C) const;
47
  void handleCheck(const CallEvent &Call, CheckerContext &C) const;
48
  void handleBug(const CallEvent &Call, CheckerContext &C) const;
49

50
public:
51
  InterestingnessTestChecker()
52
      : BT_TestBug(this, "InterestingnessTestBug", "Test") {}
53

54
  void checkPreCall(const CallEvent &Call, CheckerContext &C) const {
55
    const HandlerFn *Handler = Handlers.lookup(Call);
56
    if (!Handler)
57
      return;
58

59
    (*Handler)(this, Call, C);
60
  }
61
};
62

63
} // namespace
64

65
void InterestingnessTestChecker::handleInteresting(const CallEvent &Call,
66
                                                   CheckerContext &C) const {
67
  SymbolRef Sym = Call.getArgSVal(0).getAsSymbol();
68
  assert(Sym);
69
  C.addTransition(nullptr, C.getNoteTag([Sym](PathSensitiveBugReport &BR) {
70
    BR.markInteresting(Sym);
71
    return "";
72
  }));
73
}
74

75
void InterestingnessTestChecker::handleNotInteresting(const CallEvent &Call,
76
                                                      CheckerContext &C) const {
77
  SymbolRef Sym = Call.getArgSVal(0).getAsSymbol();
78
  assert(Sym);
79
  C.addTransition(nullptr, C.getNoteTag([Sym](PathSensitiveBugReport &BR) {
80
    BR.markNotInteresting(Sym);
81
    return "";
82
  }));
83
}
84

85
void InterestingnessTestChecker::handleCheck(const CallEvent &Call,
86
                                             CheckerContext &C) const {
87
  SymbolRef Sym = Call.getArgSVal(0).getAsSymbol();
88
  assert(Sym);
89
  C.addTransition(nullptr, C.getNoteTag([Sym](PathSensitiveBugReport &BR) {
90
    if (BR.isInteresting(Sym))
91
      return "Interesting";
92
    else
93
      return "NotInteresting";
94
  }));
95
}
96

97
void InterestingnessTestChecker::handleBug(const CallEvent &Call,
98
                                           CheckerContext &C) const {
99
  ExplodedNode *N = C.generateErrorNode();
100
  C.emitReport(
101
      std::make_unique<PathSensitiveBugReport>(BT_TestBug, "test bug", N));
102
}
103

104
namespace {
105

106
class TestAction : public ASTFrontendAction {
107
  ExpectedDiagsTy ExpectedDiags;
108

109
public:
110
  TestAction(ExpectedDiagsTy &&ExpectedDiags)
111
      : ExpectedDiags(std::move(ExpectedDiags)) {}
112

113
  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler,
114
                                                 StringRef File) override {
115
    std::unique_ptr<AnalysisASTConsumer> AnalysisConsumer =
116
        CreateAnalysisConsumer(Compiler);
117
    AnalysisConsumer->AddDiagnosticConsumer(new VerifyPathDiagnosticConsumer(
118
        std::move(ExpectedDiags), Compiler.getSourceManager()));
119
    AnalysisConsumer->AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
120
      Registry.addChecker<InterestingnessTestChecker>("test.Interestingness",
121
                                                      "Description", "");
122
    });
123
    Compiler.getAnalyzerOpts().CheckersAndPackages = {
124
        {"test.Interestingness", true}};
125
    return std::move(AnalysisConsumer);
126
  }
127
};
128

129
} // namespace
130

131
TEST(BugReportInterestingness, Symbols) {
132
  EXPECT_TRUE(tooling::runToolOnCode(
133
      std::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
           }}}),
147
      R"(
148
    void setInteresting(int);
149
    void setNotInteresting(int);
150
    void check(int);
151
    void bug(int);
152

153
    void f(int A) {
154
      check(A);
155
      setInteresting(A);
156
      check(A);
157
      setNotInteresting(A);
158
      check(A);
159
      setInteresting(A);
160
      check(A);
161
      bug(A);
162
    }
163
  )",
164
      "input.cpp"));
165
}
166

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.