brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.7 KiB · 5de3dd8 Raw
209 lines · cpp
1#include "TestingSupport.h"2#include "clang/AST/ASTContext.h"3#include "clang/ASTMatchers/ASTMatchFinder.h"4#include "clang/ASTMatchers/ASTMatchers.h"5#include "clang/Analysis/FlowSensitive/NoopAnalysis.h"6#include "clang/Tooling/Tooling.h"7#include "llvm/Testing/ADT/StringMapEntry.h"8#include "llvm/Testing/Support/Error.h"9#include "gmock/gmock.h"10#include "gtest/gtest.h"11 12using namespace clang;13using namespace dataflow;14 15namespace {16 17using ::clang::ast_matchers::functionDecl;18using ::clang::ast_matchers::hasAnyName;19using ::clang::ast_matchers::hasName;20using ::clang::ast_matchers::isDefinition;21using ::clang::dataflow::test::AnalysisInputs;22using ::clang::dataflow::test::AnalysisOutputs;23using ::clang::dataflow::test::checkDataflow;24using ::llvm::IsStringMapEntry;25using ::testing::_;26using ::testing::IsEmpty;27using ::testing::UnorderedElementsAre;28 29template <typename T>30const FunctionDecl *findTargetFunc(ASTContext &Context, T FunctionMatcher) {31  auto TargetMatcher =32      functionDecl(FunctionMatcher, isDefinition()).bind("target");33  for (const auto &Node : ast_matchers::match(TargetMatcher, Context)) {34    const auto *Func = Node.template getNodeAs<FunctionDecl>("target");35    if (Func == nullptr)36      continue;37    if (Func->isTemplated())38      continue;39    return Func;40  }41  return nullptr;42}43 44void runTest(45    llvm::StringRef Code, llvm::StringRef TargetName,46    std::function<void(const llvm::DenseMap<const Stmt *, std::string> &)>47        RunChecks) {48  llvm::Annotations AnnotatedCode(Code);49  auto Unit = tooling::buildASTFromCodeWithArgs(50      AnnotatedCode.code(), {"-fsyntax-only", "-std=c++17"});51  auto &Context = Unit->getASTContext();52  const FunctionDecl *Func = findTargetFunc(Context, hasName(TargetName));53  ASSERT_NE(Func, nullptr);54 55  llvm::Expected<llvm::DenseMap<const Stmt *, std::string>> Mapping =56      test::buildStatementToAnnotationMapping(Func, AnnotatedCode);57  ASSERT_TRUE(static_cast<bool>(Mapping));58 59  RunChecks(Mapping.get());60}61 62TEST(BuildStatementToAnnotationMappingTest, ReturnStmt) {63  runTest(R"(64    int target() {65      return 42;66      /*[[ok]]*/67    }68  )",69          "target",70          [](const llvm::DenseMap<const Stmt *, std::string> &Annotations) {71            ASSERT_EQ(Annotations.size(), static_cast<unsigned int>(1));72            EXPECT_TRUE(isa<ReturnStmt>(Annotations.begin()->first));73            EXPECT_EQ(Annotations.begin()->second, "ok");74          });75}76 77void checkDataflow(78    llvm::StringRef Code,79    ast_matchers::internal::Matcher<FunctionDecl> TargetFuncMatcher,80    std::function<81        void(const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,82             const AnalysisOutputs &)>83        Expectations) {84  ASSERT_THAT_ERROR(checkDataflow<NoopAnalysis>(85                        AnalysisInputs<NoopAnalysis>(86                            Code, std::move(TargetFuncMatcher),87                            [](ASTContext &Context, Environment &) {88                              return NoopAnalysis(89                                  Context,90                                  // Don't apply builtin transfer function.91                                  DataflowAnalysisOptions{std::nullopt});92                            })93                            .withASTBuildArgs({"-fsyntax-only", "-std=c++17"}),94                        /*VerifyResults=*/std::move(Expectations)),95                    llvm::Succeeded());96}97 98TEST(ProgramPointAnnotations, NoAnnotations) {99  ::testing::MockFunction<void(100      const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,101      const AnalysisOutputs &)>102      Expectations;103 104  EXPECT_CALL(Expectations, Call(IsEmpty(), _)).Times(1);105 106  checkDataflow("void target() {}", hasName("target"),107                Expectations.AsStdFunction());108}109 110TEST(ProgramPointAnnotations, NoAnnotationsDifferentTarget) {111  ::testing::MockFunction<void(112      const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,113      const AnalysisOutputs &)>114      Expectations;115 116  EXPECT_CALL(Expectations, Call(IsEmpty(), _)).Times(1);117 118  checkDataflow("void target() {}", hasName("target"),119                Expectations.AsStdFunction());120}121 122TEST(ProgramPointAnnotations, WithProgramPoint) {123  ::testing::MockFunction<void(124      const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,125      const AnalysisOutputs &)>126      Expectations;127 128  EXPECT_CALL(129      Expectations,130      Call(UnorderedElementsAre(IsStringMapEntry("program-point", _)), _))131      .Times(1);132 133  checkDataflow(R"cc(void target() {134                       int n;135                       // [[program-point]]136                     })cc",137                hasName("target"), Expectations.AsStdFunction());138}139 140TEST(ProgramPointAnnotations, MultipleProgramPoints) {141  ::testing::MockFunction<void(142      const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,143      const AnalysisOutputs &)>144      Expectations;145 146  EXPECT_CALL(Expectations,147              Call(UnorderedElementsAre(IsStringMapEntry("program-point-1", _),148                                        IsStringMapEntry("program-point-2", _)),149                   _))150      .Times(1);151 152  checkDataflow(R"cc(void target(bool b) {153                       if (b) {154                         int n;155                         // [[program-point-1]]156                       } else {157                         int m;158                         // [[program-point-2]]159                       }160                     })cc",161                hasName("target"), Expectations.AsStdFunction());162}163 164TEST(ProgramPointAnnotations, MultipleFunctionsMultipleProgramPoints) {165  ::testing::MockFunction<void(166      const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,167      const AnalysisOutputs &)>168      Expectations;169 170  EXPECT_CALL(Expectations, Call(UnorderedElementsAre(171                                     IsStringMapEntry("program-point-1a", _),172                                     IsStringMapEntry("program-point-1b", _)),173                                 _))174      .Times(1);175 176  EXPECT_CALL(Expectations, Call(UnorderedElementsAre(177                                     IsStringMapEntry("program-point-2a", _),178                                     IsStringMapEntry("program-point-2b", _)),179                                 _))180      .Times(1);181 182  checkDataflow(183      R"cc(184        void target1(bool b) {185          if (b) {186            int n;187            // [[program-point-1a]]188          } else {189            int m;190            // [[program-point-1b]]191          }192        }193 194        void target2(bool b) {195          if (b) {196            int n;197            // [[program-point-2a]]198          } else {199            int m;200            // [[program-point-2b]]201          }202        }203      )cc",204      functionDecl(hasAnyName("target1", "target2")),205      Expectations.AsStdFunction());206}207 208} // namespace209