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