xref: /llvm-project/clang/unittests/StaticAnalyzer/ExprEngineVisitTest.cpp (revision 87c51e2af006b96d928d55b077c8bb510c4b6e33)
1*87c51e2aST-Gruber //===- ExprEngineVisitTest.cpp --------------------------------------------===//
2*87c51e2aST-Gruber //
3*87c51e2aST-Gruber // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*87c51e2aST-Gruber // See https://llvm.org/LICENSE.txt for license information.
5*87c51e2aST-Gruber // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*87c51e2aST-Gruber //
7*87c51e2aST-Gruber //===----------------------------------------------------------------------===//
8*87c51e2aST-Gruber 
9*87c51e2aST-Gruber #include "CheckerRegistration.h"
10*87c51e2aST-Gruber #include "clang/AST/Stmt.h"
11*87c51e2aST-Gruber #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
12*87c51e2aST-Gruber #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
13*87c51e2aST-Gruber #include "clang/StaticAnalyzer/Core/Checker.h"
14*87c51e2aST-Gruber #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
15*87c51e2aST-Gruber #include "gtest/gtest.h"
16*87c51e2aST-Gruber 
17*87c51e2aST-Gruber using namespace clang;
18*87c51e2aST-Gruber using namespace ento;
19*87c51e2aST-Gruber 
20*87c51e2aST-Gruber namespace {
21*87c51e2aST-Gruber 
22*87c51e2aST-Gruber void emitErrorReport(CheckerContext &C, const BugType &Bug,
23*87c51e2aST-Gruber                      const std::string &Desc) {
24*87c51e2aST-Gruber   if (ExplodedNode *Node = C.generateNonFatalErrorNode(C.getState())) {
25*87c51e2aST-Gruber     auto Report = std::make_unique<PathSensitiveBugReport>(Bug, Desc, Node);
26*87c51e2aST-Gruber     C.emitReport(std::move(Report));
27*87c51e2aST-Gruber   }
28*87c51e2aST-Gruber }
29*87c51e2aST-Gruber 
30*87c51e2aST-Gruber #define CREATE_EXPR_ENGINE_CHECKER(CHECKER_NAME, CALLBACK, STMT_TYPE,          \
31*87c51e2aST-Gruber                                    BUG_NAME)                                   \
32*87c51e2aST-Gruber   class CHECKER_NAME : public Checker<check::CALLBACK<STMT_TYPE>> {            \
33*87c51e2aST-Gruber   public:                                                                      \
34*87c51e2aST-Gruber     void check##CALLBACK(const STMT_TYPE *ASM, CheckerContext &C) const {      \
35*87c51e2aST-Gruber       emitErrorReport(C, Bug, "check" #CALLBACK "<" #STMT_TYPE ">");           \
36*87c51e2aST-Gruber     }                                                                          \
37*87c51e2aST-Gruber                                                                                \
38*87c51e2aST-Gruber   private:                                                                     \
39*87c51e2aST-Gruber     const BugType Bug{this, BUG_NAME};                                         \
40*87c51e2aST-Gruber   };
41*87c51e2aST-Gruber 
42*87c51e2aST-Gruber CREATE_EXPR_ENGINE_CHECKER(ExprEngineVisitPreChecker, PreStmt, GCCAsmStmt,
43*87c51e2aST-Gruber                            "GCCAsmStmtBug")
44*87c51e2aST-Gruber CREATE_EXPR_ENGINE_CHECKER(ExprEngineVisitPostChecker, PostStmt, GCCAsmStmt,
45*87c51e2aST-Gruber                            "GCCAsmStmtBug")
46*87c51e2aST-Gruber 
47*87c51e2aST-Gruber void addExprEngineVisitPreChecker(AnalysisASTConsumer &AnalysisConsumer,
48*87c51e2aST-Gruber                                   AnalyzerOptions &AnOpts) {
49*87c51e2aST-Gruber   AnOpts.CheckersAndPackages = {{"ExprEngineVisitPreChecker", true}};
50*87c51e2aST-Gruber   AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
51*87c51e2aST-Gruber     Registry.addChecker<ExprEngineVisitPreChecker>("ExprEngineVisitPreChecker",
52*87c51e2aST-Gruber                                                    "Desc", "DocsURI");
53*87c51e2aST-Gruber   });
54*87c51e2aST-Gruber }
55*87c51e2aST-Gruber 
56*87c51e2aST-Gruber void addExprEngineVisitPostChecker(AnalysisASTConsumer &AnalysisConsumer,
57*87c51e2aST-Gruber                                    AnalyzerOptions &AnOpts) {
58*87c51e2aST-Gruber   AnOpts.CheckersAndPackages = {{"ExprEngineVisitPostChecker", true}};
59*87c51e2aST-Gruber   AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
60*87c51e2aST-Gruber     Registry.addChecker<ExprEngineVisitPostChecker>(
61*87c51e2aST-Gruber         "ExprEngineVisitPostChecker", "Desc", "DocsURI");
62*87c51e2aST-Gruber   });
63*87c51e2aST-Gruber }
64*87c51e2aST-Gruber 
65*87c51e2aST-Gruber TEST(ExprEngineVisitTest, checkPreStmtGCCAsmStmt) {
66*87c51e2aST-Gruber   std::string Diags;
67*87c51e2aST-Gruber   EXPECT_TRUE(runCheckerOnCode<addExprEngineVisitPreChecker>(R"(
68*87c51e2aST-Gruber     void top() {
69*87c51e2aST-Gruber       asm("");
70*87c51e2aST-Gruber     }
71*87c51e2aST-Gruber   )",
72*87c51e2aST-Gruber                                                              Diags));
73*87c51e2aST-Gruber   EXPECT_EQ(Diags, "ExprEngineVisitPreChecker: checkPreStmt<GCCAsmStmt>\n");
74*87c51e2aST-Gruber }
75*87c51e2aST-Gruber 
76*87c51e2aST-Gruber TEST(ExprEngineVisitTest, checkPostStmtGCCAsmStmt) {
77*87c51e2aST-Gruber   std::string Diags;
78*87c51e2aST-Gruber   EXPECT_TRUE(runCheckerOnCode<addExprEngineVisitPostChecker>(R"(
79*87c51e2aST-Gruber     void top() {
80*87c51e2aST-Gruber       asm("");
81*87c51e2aST-Gruber     }
82*87c51e2aST-Gruber   )",
83*87c51e2aST-Gruber                                                               Diags));
84*87c51e2aST-Gruber   EXPECT_EQ(Diags, "ExprEngineVisitPostChecker: checkPostStmt<GCCAsmStmt>\n");
85*87c51e2aST-Gruber }
86*87c51e2aST-Gruber 
87*87c51e2aST-Gruber } // namespace
88