1 //===- unittests/Analysis/CFGBuildResult.h - CFG tests --------------------===// 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 "clang/ASTMatchers/ASTMatchFinder.h" 10 #include "clang/Analysis/CFG.h" 11 #include "clang/Tooling/Tooling.h" 12 #include <memory> 13 14 namespace clang { 15 namespace analysis { 16 17 class BuildResult { 18 public: 19 enum Status { 20 ToolFailed, 21 ToolRan, 22 SawFunctionBody, 23 BuiltCFG, 24 }; 25 26 BuildResult(Status S, const FunctionDecl *Func = nullptr, 27 std::unique_ptr<CFG> Cfg = nullptr, 28 std::unique_ptr<ASTUnit> AST = nullptr) 29 : S(S), Cfg(std::move(Cfg)), AST(std::move(AST)), Func(Func) {} 30 31 Status getStatus() const { return S; } 32 CFG *getCFG() const { return Cfg.get(); } 33 ASTUnit *getAST() const { return AST.get(); } 34 const FunctionDecl *getFunc() const { return Func; } 35 36 private: 37 Status S; 38 std::unique_ptr<CFG> Cfg; 39 std::unique_ptr<ASTUnit> AST; 40 const FunctionDecl *Func; 41 }; 42 43 class CFGCallback : public ast_matchers::MatchFinder::MatchCallback { 44 public: 45 CFGCallback(std::unique_ptr<ASTUnit> AST) : AST(std::move(AST)) {} 46 47 std::unique_ptr<ASTUnit> AST; 48 BuildResult TheBuildResult = BuildResult::ToolRan; 49 CFG::BuildOptions Options; 50 51 void run(const ast_matchers::MatchFinder::MatchResult &Result) override { 52 const auto *Func = Result.Nodes.getNodeAs<FunctionDecl>("func"); 53 Stmt *Body = Func->getBody(); 54 if (!Body) 55 return; 56 TheBuildResult = BuildResult::SawFunctionBody; 57 Options.AddImplicitDtors = true; 58 if (std::unique_ptr<CFG> Cfg = 59 CFG::buildCFG(Func, Body, Result.Context, Options)) 60 TheBuildResult = {BuildResult::BuiltCFG, Func, std::move(Cfg), 61 std::move(AST)}; 62 } 63 }; 64 65 template <typename FuncMatcherT = ast_matchers::internal::TrueMatcher> 66 BuildResult BuildCFG(const char *Code, CFG::BuildOptions Options = {}, 67 FuncMatcherT FuncMatcher = ast_matchers::anything()) { 68 const std::vector<std::string> Args = { 69 "-std=c++11", "-fno-delayed-template-parsing", "-Wno-everything"}; 70 std::unique_ptr<ASTUnit> AST = tooling::buildASTFromCodeWithArgs(Code, Args); 71 if (!AST) 72 return BuildResult::ToolFailed; 73 74 CFGCallback Callback(std::move(AST)); 75 Callback.Options = Options; 76 ast_matchers::MatchFinder Finder; 77 Finder.addMatcher(ast_matchers::functionDecl(FuncMatcher).bind("func"), 78 &Callback); 79 80 Finder.matchAST(Callback.AST->getASTContext()); 81 return std::move(Callback.TheBuildResult); 82 } 83 84 } // namespace analysis 85 } // namespace clang 86