1 //===- ExprEngineVisitTest.cpp --------------------------------------------===// 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 "CheckerRegistration.h" 10 #include "clang/AST/Stmt.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/CheckerContext.h" 15 #include "gtest/gtest.h" 16 17 using namespace clang; 18 using namespace ento; 19 20 namespace { 21 22 void emitErrorReport(CheckerContext &C, const BugType &Bug, 23 const std::string &Desc) { 24 if (ExplodedNode *Node = C.generateNonFatalErrorNode(C.getState())) { 25 auto Report = std::make_unique<PathSensitiveBugReport>(Bug, Desc, Node); 26 C.emitReport(std::move(Report)); 27 } 28 } 29 30 #define CREATE_EXPR_ENGINE_CHECKER(CHECKER_NAME, CALLBACK, STMT_TYPE, \ 31 BUG_NAME) \ 32 class CHECKER_NAME : public Checker<check::CALLBACK<STMT_TYPE>> { \ 33 public: \ 34 void check##CALLBACK(const STMT_TYPE *ASM, CheckerContext &C) const { \ 35 emitErrorReport(C, Bug, "check" #CALLBACK "<" #STMT_TYPE ">"); \ 36 } \ 37 \ 38 private: \ 39 const BugType Bug{this, BUG_NAME}; \ 40 }; 41 42 CREATE_EXPR_ENGINE_CHECKER(ExprEngineVisitPreChecker, PreStmt, GCCAsmStmt, 43 "GCCAsmStmtBug") 44 CREATE_EXPR_ENGINE_CHECKER(ExprEngineVisitPostChecker, PostStmt, GCCAsmStmt, 45 "GCCAsmStmtBug") 46 47 void addExprEngineVisitPreChecker(AnalysisASTConsumer &AnalysisConsumer, 48 AnalyzerOptions &AnOpts) { 49 AnOpts.CheckersAndPackages = {{"ExprEngineVisitPreChecker", true}}; 50 AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) { 51 Registry.addChecker<ExprEngineVisitPreChecker>("ExprEngineVisitPreChecker", 52 "Desc", "DocsURI"); 53 }); 54 } 55 56 void addExprEngineVisitPostChecker(AnalysisASTConsumer &AnalysisConsumer, 57 AnalyzerOptions &AnOpts) { 58 AnOpts.CheckersAndPackages = {{"ExprEngineVisitPostChecker", true}}; 59 AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) { 60 Registry.addChecker<ExprEngineVisitPostChecker>( 61 "ExprEngineVisitPostChecker", "Desc", "DocsURI"); 62 }); 63 } 64 65 TEST(ExprEngineVisitTest, checkPreStmtGCCAsmStmt) { 66 std::string Diags; 67 EXPECT_TRUE(runCheckerOnCode<addExprEngineVisitPreChecker>(R"( 68 void top() { 69 asm(""); 70 } 71 )", 72 Diags)); 73 EXPECT_EQ(Diags, "ExprEngineVisitPreChecker: checkPreStmt<GCCAsmStmt>\n"); 74 } 75 76 TEST(ExprEngineVisitTest, checkPostStmtGCCAsmStmt) { 77 std::string Diags; 78 EXPECT_TRUE(runCheckerOnCode<addExprEngineVisitPostChecker>(R"( 79 void top() { 80 asm(""); 81 } 82 )", 83 Diags)); 84 EXPECT_EQ(Diags, "ExprEngineVisitPostChecker: checkPostStmt<GCCAsmStmt>\n"); 85 } 86 87 } // namespace 88