//===- unittests/Analysis/CFGBuildResult.h - CFG tests --------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/Analysis/CFG.h" #include "clang/Tooling/Tooling.h" #include namespace clang { namespace analysis { class BuildResult { public: enum Status { ToolFailed, ToolRan, SawFunctionBody, BuiltCFG, }; BuildResult(Status S, const FunctionDecl *Func = nullptr, std::unique_ptr Cfg = nullptr, std::unique_ptr AST = nullptr) : S(S), Cfg(std::move(Cfg)), AST(std::move(AST)), Func(Func) {} Status getStatus() const { return S; } CFG *getCFG() const { return Cfg.get(); } ASTUnit *getAST() const { return AST.get(); } const FunctionDecl *getFunc() const { return Func; } private: Status S; std::unique_ptr Cfg; std::unique_ptr AST; const FunctionDecl *Func; }; class CFGCallback : public ast_matchers::MatchFinder::MatchCallback { public: CFGCallback(std::unique_ptr AST) : AST(std::move(AST)) {} std::unique_ptr AST; BuildResult TheBuildResult = BuildResult::ToolRan; CFG::BuildOptions Options; void run(const ast_matchers::MatchFinder::MatchResult &Result) override { const auto *Func = Result.Nodes.getNodeAs("func"); Stmt *Body = Func->getBody(); if (!Body) return; TheBuildResult = BuildResult::SawFunctionBody; Options.AddImplicitDtors = true; if (std::unique_ptr Cfg = CFG::buildCFG(Func, Body, Result.Context, Options)) TheBuildResult = {BuildResult::BuiltCFG, Func, std::move(Cfg), std::move(AST)}; } }; template BuildResult BuildCFG(const char *Code, CFG::BuildOptions Options = {}, FuncMatcherT FuncMatcher = ast_matchers::anything()) { std::vector Args = {"-std=c++11", "-fno-delayed-template-parsing"}; std::unique_ptr AST = tooling::buildASTFromCodeWithArgs(Code, Args); if (!AST) return BuildResult::ToolFailed; CFGCallback Callback(std::move(AST)); Callback.Options = Options; ast_matchers::MatchFinder Finder; Finder.addMatcher(ast_matchers::functionDecl(FuncMatcher).bind("func"), &Callback); Finder.matchAST(Callback.AST->getASTContext()); return std::move(Callback.TheBuildResult); } } // namespace analysis } // namespace clang