86 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "clang/ASTMatchers/ASTMatchFinder.h"10#include "clang/Analysis/CFG.h"11#include "clang/Tooling/Tooling.h"12#include <memory>13 14namespace clang {15namespace analysis {16 17class BuildResult {18public: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 36private:37 Status S;38 std::unique_ptr<CFG> Cfg;39 std::unique_ptr<ASTUnit> AST;40 const FunctionDecl *Func;41};42 43class CFGCallback : public ast_matchers::MatchFinder::MatchCallback {44public: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 65template <typename FuncMatcherT = ast_matchers::internal::TrueMatcher>66BuildResult 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 analysis85} // namespace clang86