llvm/clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp

// unittests/ASTMatchers/ASTMatchersInternalTest.cpp - AST matcher unit 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 "ASTMatchersTest.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/TargetParser/Host.h"
#include "llvm/TargetParser/Triple.h"
#include "llvm/Testing/Support/SupportHelpers.h"
#include "gtest/gtest.h"

namespace clang {
namespace ast_matchers {
DynTypedMatcher;

#if GTEST_HAS_DEATH_TEST
TEST(HasNameDeathTest, DiesOnEmptyName) {}

TEST(HasNameDeathTest, DiesOnEmptyPattern) {}

// FIXME Re-enable these tests without breaking standalone builds.
#if 0
// FIXME: Figure out why back traces aren't being generated on clang builds on
// windows.
#if ENABLE_BACKTRACES && (!defined(_MSC_VER) || !defined(__clang__))

AST_MATCHER(Decl, causeCrash) {
  abort();
  return true;
}

TEST(MatcherCrashDeathTest, CrashOnMatcherDump) {
  llvm::EnablePrettyStackTrace();
  auto Matcher = testing::HasSubstr(
      "ASTMatcher: Matching '<unknown>' against:\n\tFunctionDecl foo : "
      "<input.cc:1:1, col:10>");
  ASSERT_DEATH(matches("void foo();", functionDecl(causeCrash())), Matcher);
}

template <typename MatcherT>
static void crashTestNodeDump(MatcherT Matcher,
                              ArrayRef<StringRef> MatchedNodes,
                              StringRef Against, StringRef Code) {
  llvm::EnablePrettyStackTrace();
  MatchFinder Finder;

  struct CrashCallback : public MatchFinder::MatchCallback {
    void run(const MatchFinder::MatchResult &Result) override { abort(); }
    std::optional<TraversalKind> getCheckTraversalKind() const override {
      return TK_IgnoreUnlessSpelledInSource;
    }
    StringRef getID() const override { return "CrashTester"; }
  } Callback;
  Finder.addMatcher(std::move(Matcher), &Callback);
  if (MatchedNodes.empty()) {
    ASSERT_DEATH(tooling::runToolOnCode(
                     newFrontendActionFactory(&Finder)->create(), Code),
                 testing::HasSubstr(
                     ("ASTMatcher: Processing 'CrashTester' against:\n\t" +
                      Against + "\nNo bound nodes")
                         .str()));
  } else {
    std::vector<testing::PolymorphicMatcher<
        testing::internal::HasSubstrMatcher<std::string>>>
        Matchers;
    Matchers.reserve(MatchedNodes.size());
    for (auto Node : MatchedNodes) {
      Matchers.push_back(testing::HasSubstr(Node.str()));
    }
    auto CrashMatcher = testing::AllOf(
        testing::HasSubstr(
            ("ASTMatcher: Processing 'CrashTester' against:\n\t" + Against +
             "\n--- Bound Nodes Begin ---")
                .str()),
        testing::HasSubstr("--- Bound Nodes End ---"),
        testing::AllOfArray(Matchers));

    ASSERT_DEATH(tooling::runToolOnCode(
                     newFrontendActionFactory(&Finder)->create(), Code),
                 CrashMatcher);
  }
}
TEST(MatcherCrashDeathTest, CrashOnCallbackDump) {
  crashTestNodeDump(forStmt(), {}, "ForStmt : <input.cc:1:14, col:21>",
                    "void foo() { for(;;); }");
  crashTestNodeDump(
      forStmt(hasLoopInit(declStmt(hasSingleDecl(
                                       varDecl(hasType(qualType().bind("QT")),
                                               hasType(type().bind("T")),
                                               hasInitializer(
                                                   integerLiteral().bind("IL")))
                                           .bind("VD")))
                              .bind("DS")))
          .bind("FS"),
      {"FS - { ForStmt : <input.cc:3:5, line:4:5> }",
       "DS - { DeclStmt : <input.cc:3:10, col:19> }",
       "IL - { IntegerLiteral : <input.cc:3:18> }", "QT - { QualType : int }",
       "T - { BuiltinType : int }",
       "VD - { VarDecl I : <input.cc:3:10, col:18> }"},
      "ForStmt : <input.cc:3:5, line:4:5>",
      R"cpp(
  void foo() {
    for (int I = 0; I < 5; ++I) {
    }
  }
  )cpp");
  crashTestNodeDump(
      cxxRecordDecl(hasMethod(cxxMethodDecl(hasName("operator+")).bind("Op+")))
          .bind("Unnamed"),
      {"Unnamed - { CXXRecordDecl (anonymous) : <input.cc:1:1, col:36> }",
       "Op+ - { CXXMethodDecl (anonymous struct)::operator+ : <input.cc:1:10, "
       "col:29> }"},
      "CXXRecordDecl (anonymous) : <input.cc:1:1, col:36>",
      "struct { int operator+(int) const; } Unnamed;");
  crashTestNodeDump(
      cxxRecordDecl(hasMethod(cxxConstructorDecl(isDefaulted()).bind("Ctor")),
                    hasMethod(cxxDestructorDecl(isDefaulted()).bind("Dtor"))),
      {"Ctor - { CXXConstructorDecl Foo::Foo : <input.cc:1:14, col:28> }",
       "Dtor - { CXXDestructorDecl Foo::~Foo : <input.cc:1:31, col:46> }"},
      "CXXRecordDecl Foo : <input.cc:1:1, col:49>",
      "struct Foo { Foo() = default; ~Foo() = default; };");
}
#endif // ENABLE_BACKTRACES
#endif
#endif

TEST(ConstructVariadic, MismatchedTypes_Regression) {}

// For testing AST_MATCHER_P().
AST_MATCHER_P(Decl, just, internal::Matcher<Decl>, AMatcher) {}

TEST(AstMatcherPMacro, Works) {}

AST_POLYMORPHIC_MATCHER_P(polymorphicHas,
                          AST_POLYMORPHIC_SUPPORTED_TYPES(Decl, Stmt),
                          internal::Matcher<Decl>, AMatcher) {}

TEST(AstPolymorphicMatcherPMacro, Works) {}

TEST(MatchFinder, CheckProfiling) {}

class VerifyStartOfTranslationUnit : public MatchFinder::MatchCallback {};

TEST(MatchFinder, InterceptsStartOfTranslationUnit) {}

class VerifyEndOfTranslationUnit : public MatchFinder::MatchCallback {};

TEST(MatchFinder, InterceptsEndOfTranslationUnit) {}

TEST(Matcher, matchOverEntireASTContext) {}

TEST(DynTypedMatcherTest, TraversalKindForwardsToImpl) {}

TEST(DynTypedMatcherTest, ConstructWithTraversalKindSetsTK) {}

TEST(DynTypedMatcherTest, ConstructWithTraversalKindOverridesNestedTK) {}

TEST(IsInlineMatcher, IsInline) {}

// FIXME: Figure out how to specify paths so the following tests pass on
// Windows.
#ifndef _WIN32

TEST(Matcher, IsExpansionInMainFileMatcher) {}

TEST(Matcher, IsExpansionInSystemHeader) {}

TEST(Matcher, IsExpansionInFileMatching) {}

#endif // _WIN32

} // end namespace ast_matchers
} // end namespace clang