diff --git a/clang-tools-extra/clang-query/CMakeLists.txt b/clang-tools-extra/clang-query/CMakeLists.txt index 8a58d4224e049..34f018c4a03f3 100644 --- a/clang-tools-extra/clang-query/CMakeLists.txt +++ b/clang-tools-extra/clang-query/CMakeLists.txt @@ -20,7 +20,6 @@ clang_target_link_libraries(clangQuery clangBasic clangDynamicASTMatchers clangFrontend - clangTooling clangSerialization ) diff --git a/clang-tools-extra/clang-query/Query.cpp b/clang-tools-extra/clang-query/Query.cpp index 9d5807a52fa8e..93f4104d39db8 100644 --- a/clang-tools-extra/clang-query/Query.cpp +++ b/clang-tools-extra/clang-query/Query.cpp @@ -13,7 +13,6 @@ #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/Frontend/ASTUnit.h" #include "clang/Frontend/TextDiagnostic.h" -#include "clang/Tooling/NodeIntrospection.h" #include "llvm/Support/raw_ostream.h" #include @@ -69,8 +68,6 @@ bool HelpQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const { "Diagnostic location for bound nodes.\n" " detailed-ast " "Detailed AST output for bound nodes.\n" - " srcloc " - "Source locations and ranges for bound nodes.\n" " dump " "Detailed AST output for bound nodes (alias of detailed-ast).\n\n"; return true; @@ -91,90 +88,6 @@ struct CollectBoundNodes : MatchFinder::MatchCallback { } }; -void dumpLocations(llvm::raw_ostream &OS, DynTypedNode Node, ASTContext &Ctx, - const DiagnosticsEngine &Diags, SourceManager const &SM) { - auto Locs = clang::tooling::NodeIntrospection::GetLocations(Node); - - auto PrintLocations = [](llvm::raw_ostream &OS, auto Iter, auto End) { - auto CommonEntry = Iter->first; - auto Scout = Iter; - SmallVector LocationStrings; - while (Scout->first == CommonEntry) { - LocationStrings.push_back( - tooling::LocationCallFormatterCpp::format(*Iter->second)); - if (Scout == End) - break; - ++Scout; - if (Scout->first == CommonEntry) - ++Iter; - } - llvm::sort(LocationStrings); - for (auto &LS : LocationStrings) { - OS << " * \"" << LS << "\"\n"; - } - return Iter; - }; - - TextDiagnostic TD(OS, Ctx.getLangOpts(), &Diags.getDiagnosticOptions()); - - for (auto Iter = Locs.LocationAccessors.begin(); - Iter != Locs.LocationAccessors.end(); ++Iter) { - if (!Iter->first.isValid()) - continue; - - TD.emitDiagnostic(FullSourceLoc(Iter->first, SM), DiagnosticsEngine::Note, - "source locations here", std::nullopt, std::nullopt); - - Iter = PrintLocations(OS, Iter, Locs.LocationAccessors.end()); - OS << '\n'; - } - - for (auto Iter = Locs.RangeAccessors.begin(); - Iter != Locs.RangeAccessors.end(); ++Iter) { - - if (!Iter->first.getBegin().isValid()) - continue; - - if (SM.getPresumedLineNumber(Iter->first.getBegin()) != - SM.getPresumedLineNumber(Iter->first.getEnd())) - continue; - - TD.emitDiagnostic( - FullSourceLoc(Iter->first.getBegin(), SM), DiagnosticsEngine::Note, - "source ranges here " + Iter->first.printToString(SM), - CharSourceRange::getTokenRange(Iter->first), std::nullopt); - - Iter = PrintLocations(OS, Iter, Locs.RangeAccessors.end()); - } - for (auto Iter = Locs.RangeAccessors.begin(); - Iter != Locs.RangeAccessors.end(); ++Iter) { - - if (!Iter->first.getBegin().isValid()) - continue; - - if (SM.getPresumedLineNumber(Iter->first.getBegin()) == - SM.getPresumedLineNumber(Iter->first.getEnd())) - continue; - - TD.emitDiagnostic( - FullSourceLoc(Iter->first.getBegin(), SM), DiagnosticsEngine::Note, - "source range " + Iter->first.printToString(SM) + " starting here...", - CharSourceRange::getTokenRange(Iter->first), std::nullopt); - - auto ColNum = SM.getPresumedColumnNumber(Iter->first.getEnd()); - auto LastLineLoc = Iter->first.getEnd().getLocWithOffset(-(ColNum - 1)); - - TD.emitDiagnostic(FullSourceLoc(Iter->first.getEnd(), SM), - DiagnosticsEngine::Note, "... ending here", - CharSourceRange::getTokenRange( - SourceRange(LastLineLoc, Iter->first.getEnd())), - std::nullopt); - - Iter = PrintLocations(OS, Iter, Locs.RangeAccessors.end()); - } - OS << "\n"; -} - } // namespace bool MatchQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const { @@ -195,8 +108,7 @@ bool MatchQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const { return false; } - auto &Ctx = AST->getASTContext(); - const auto &SM = Ctx.getSourceManager(); + ASTContext &Ctx = AST->getASTContext(); Ctx.getParentMapContext().setTraversalKind(QS.TK); Finder.matchAST(Ctx); @@ -244,19 +156,11 @@ bool MatchQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const { } if (QS.DetailedASTOutput) { OS << "Binding for \"" << BI->first << "\":\n"; - const ASTContext &Ctx = AST->getASTContext(); ASTDumper Dumper(OS, Ctx, AST->getDiagnostics().getShowColors()); Dumper.SetTraversalKind(QS.TK); Dumper.Visit(BI->second); OS << "\n"; } - if (QS.SrcLocOutput) { - OS << "\n \"" << BI->first << "\" Source locations\n"; - OS << " " << std::string(19 + BI->first.size(), '-') << '\n'; - - dumpLocations(OS, BI->second, Ctx, AST->getDiagnostics(), SM); - OS << "\n"; - } } if (MI->getMap().empty()) diff --git a/clang-tools-extra/clang-query/Query.h b/clang-tools-extra/clang-query/Query.h index 7242479633c24..af250fbe13ce3 100644 --- a/clang-tools-extra/clang-query/Query.h +++ b/clang-tools-extra/clang-query/Query.h @@ -17,7 +17,7 @@ namespace clang { namespace query { -enum OutputKind { OK_Diag, OK_Print, OK_DetailedAST, OK_SrcLoc }; +enum OutputKind { OK_Diag, OK_Print, OK_DetailedAST }; enum QueryKind { QK_Invalid, @@ -149,7 +149,6 @@ struct SetExclusiveOutputQuery : Query { QS.DiagOutput = false; QS.DetailedASTOutput = false; QS.PrintOutput = false; - QS.SrcLocOutput = false; QS.*Var = true; return true; } diff --git a/clang-tools-extra/clang-query/QueryParser.cpp b/clang-tools-extra/clang-query/QueryParser.cpp index 85a442bdd7ded..1d0b7d9bc6fc8 100644 --- a/clang-tools-extra/clang-query/QueryParser.cpp +++ b/clang-tools-extra/clang-query/QueryParser.cpp @@ -11,7 +11,6 @@ #include "QuerySession.h" #include "clang/ASTMatchers/Dynamic/Parser.h" #include "clang/Basic/CharInfo.h" -#include "clang/Tooling/NodeIntrospection.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include @@ -104,19 +103,16 @@ QueryRef QueryParser::parseSetBool(bool QuerySession::*Var) { template QueryRef QueryParser::parseSetOutputKind() { StringRef ValStr; - bool HasIntrospection = tooling::NodeIntrospection::hasIntrospectionSupport(); - unsigned OutKind = - LexOrCompleteWord(this, ValStr) - .Case("diag", OK_Diag) - .Case("print", OK_Print) - .Case("detailed-ast", OK_DetailedAST) - .Case("srcloc", OK_SrcLoc, /*IsCompletion=*/HasIntrospection) - .Case("dump", OK_DetailedAST) - .Default(~0u); + unsigned OutKind = LexOrCompleteWord(this, ValStr) + .Case("diag", OK_Diag) + .Case("print", OK_Print) + .Case("detailed-ast", OK_DetailedAST) + .Case("dump", OK_DetailedAST) + .Default(~0u); if (OutKind == ~0u) { - return new InvalidQuery("expected 'diag', 'print', 'detailed-ast'" + - StringRef(HasIntrospection ? ", 'srcloc'" : "") + - " or 'dump', got '" + ValStr + "'"); + return new InvalidQuery("expected 'diag', 'print', 'detailed-ast' or " + "'dump', got '" + + ValStr + "'"); } switch (OutKind) { @@ -126,10 +122,6 @@ template QueryRef QueryParser::parseSetOutputKind() { return new QueryType(&QuerySession::DiagOutput); case OK_Print: return new QueryType(&QuerySession::PrintOutput); - case OK_SrcLoc: - if (HasIntrospection) - return new QueryType(&QuerySession::SrcLocOutput); - return new InvalidQuery("'srcloc' output support is not available."); } llvm_unreachable("Invalid output kind"); diff --git a/clang-tools-extra/clang-query/QuerySession.h b/clang-tools-extra/clang-query/QuerySession.h index 9a08289a25344..31a4900e26190 100644 --- a/clang-tools-extra/clang-query/QuerySession.h +++ b/clang-tools-extra/clang-query/QuerySession.h @@ -25,15 +25,14 @@ class QuerySession { public: QuerySession(llvm::ArrayRef> ASTs) : ASTs(ASTs), PrintOutput(false), DiagOutput(true), - DetailedASTOutput(false), SrcLocOutput(false), BindRoot(true), - PrintMatcher(false), Terminate(false), TK(TK_AsIs) {} + DetailedASTOutput(false), BindRoot(true), PrintMatcher(false), + Terminate(false), TK(TK_AsIs) {} llvm::ArrayRef> ASTs; bool PrintOutput; bool DiagOutput; bool DetailedASTOutput; - bool SrcLocOutput; bool BindRoot; bool PrintMatcher; diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 71734617bf7aa..6a9892bada915 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -94,6 +94,8 @@ Improvements to clang-query from an external file, allowing the cost of reading the compilation database and building the AST to be imposed just once for faster prototyping. +- Removed support for ``enable output srcloc``. Fixes #GH82591 + Improvements to clang-rename ---------------------------- diff --git a/clang-tools-extra/unittests/clang-query/QueryParserTest.cpp b/clang-tools-extra/unittests/clang-query/QueryParserTest.cpp index b561e2bb98332..e414587c568b7 100644 --- a/clang-tools-extra/unittests/clang-query/QueryParserTest.cpp +++ b/clang-tools-extra/unittests/clang-query/QueryParserTest.cpp @@ -9,7 +9,6 @@ #include "QueryParser.h" #include "Query.h" #include "QuerySession.h" -#include "clang/Tooling/NodeIntrospection.h" #include "llvm/LineEditor/LineEditor.h" #include "gtest/gtest.h" @@ -61,7 +60,6 @@ TEST_F(QueryParserTest, Quit) { TEST_F(QueryParserTest, Set) { - bool HasIntrospection = tooling::NodeIntrospection::hasIntrospectionSupport(); QueryRef Q = parse("set"); ASSERT_TRUE(isa(Q)); EXPECT_EQ("expected variable name", cast(Q)->ErrStr); @@ -72,13 +70,8 @@ TEST_F(QueryParserTest, Set) { Q = parse("set output"); ASSERT_TRUE(isa(Q)); - if (HasIntrospection) - EXPECT_EQ( - "expected 'diag', 'print', 'detailed-ast', 'srcloc' or 'dump', got ''", - cast(Q)->ErrStr); - else - EXPECT_EQ("expected 'diag', 'print', 'detailed-ast' or 'dump', got ''", - cast(Q)->ErrStr); + EXPECT_EQ("expected 'diag', 'print', 'detailed-ast' or 'dump', got ''", + cast(Q)->ErrStr); Q = parse("set bind-root true foo"); ASSERT_TRUE(isa(Q)); @@ -86,13 +79,8 @@ TEST_F(QueryParserTest, Set) { Q = parse("set output foo"); ASSERT_TRUE(isa(Q)); - if (HasIntrospection) - EXPECT_EQ("expected 'diag', 'print', 'detailed-ast', 'srcloc' or 'dump', " - "got 'foo'", - cast(Q)->ErrStr); - else - EXPECT_EQ("expected 'diag', 'print', 'detailed-ast' or 'dump', got 'foo'", - cast(Q)->ErrStr); + EXPECT_EQ("expected 'diag', 'print', 'detailed-ast' or 'dump', got 'foo'", + cast(Q)->ErrStr); Q = parse("set output dump"); ASSERT_TRUE(isa(Q)); @@ -232,10 +220,8 @@ TEST_F(QueryParserTest, Complete) { EXPECT_EQ("output ", Comps[0].TypedText); EXPECT_EQ("output", Comps[0].DisplayText); - bool HasIntrospection = tooling::NodeIntrospection::hasIntrospectionSupport(); - Comps = QueryParser::complete("enable output ", 14, QS); - ASSERT_EQ(HasIntrospection ? 5u : 4u, Comps.size()); + ASSERT_EQ(4u, Comps.size()); EXPECT_EQ("diag ", Comps[0].TypedText); EXPECT_EQ("diag", Comps[0].DisplayText); @@ -243,12 +229,8 @@ TEST_F(QueryParserTest, Complete) { EXPECT_EQ("print", Comps[1].DisplayText); EXPECT_EQ("detailed-ast ", Comps[2].TypedText); EXPECT_EQ("detailed-ast", Comps[2].DisplayText); - if (HasIntrospection) { - EXPECT_EQ("srcloc ", Comps[3].TypedText); - EXPECT_EQ("srcloc", Comps[3].DisplayText); - } - EXPECT_EQ("dump ", Comps[HasIntrospection ? 4 : 3].TypedText); - EXPECT_EQ("dump", Comps[HasIntrospection ? 4 : 3].DisplayText); + EXPECT_EQ("dump ", Comps[3].TypedText); + EXPECT_EQ("dump", Comps[3].DisplayText); Comps = QueryParser::complete("set traversal ", 14, QS); ASSERT_EQ(2u, Comps.size()); diff --git a/clang/docs/tools/clang-formatted-files.txt b/clang/docs/tools/clang-formatted-files.txt index eaeadf2656b0b..b747adfb6992e 100644 --- a/clang/docs/tools/clang-formatted-files.txt +++ b/clang/docs/tools/clang-formatted-files.txt @@ -252,7 +252,6 @@ clang/include/clang/Tooling/CompilationDatabasePluginRegistry.h clang/include/clang/Tooling/DiagnosticsYaml.h clang/include/clang/Tooling/Execution.h clang/include/clang/Tooling/JSONCompilationDatabase.h -clang/include/clang/Tooling/NodeIntrospection.h clang/include/clang/Tooling/Refactoring.h clang/include/clang/Tooling/StandaloneExecution.h clang/include/clang/Tooling/ToolExecutorPluginRegistry.h @@ -562,15 +561,11 @@ clang/lib/Tooling/Execution.cpp clang/lib/Tooling/ExpandResponseFilesCompilationDatabase.cpp clang/lib/Tooling/FixIt.cpp clang/lib/Tooling/GuessTargetAndModeCompilationDatabase.cpp -clang/lib/Tooling/NodeIntrospection.cpp clang/lib/Tooling/StandaloneExecution.cpp clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp clang/lib/Tooling/DependencyScanning/DependencyScanningService.cpp clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp -clang/lib/Tooling/DumpTool/APIData.h -clang/lib/Tooling/DumpTool/ASTSrcLocProcessor.h -clang/lib/Tooling/DumpTool/ClangSrcLocDump.cpp clang/lib/Tooling/Inclusions/HeaderIncludes.cpp clang/lib/Tooling/Inclusions/IncludeStyle.cpp clang/lib/Tooling/Inclusions/StandardLibrary.cpp diff --git a/clang/include/clang/Tooling/NodeIntrospection.h b/clang/include/clang/Tooling/NodeIntrospection.h deleted file mode 100644 index 91552cad2eca3..0000000000000 --- a/clang/include/clang/Tooling/NodeIntrospection.h +++ /dev/null @@ -1,101 +0,0 @@ -//===- NodeIntrospection.h ------------------------------------*- C++ -*---===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// This file contains the implementation of the NodeIntrospection. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_TOOLING_NODEINTROSPECTION_H -#define LLVM_CLANG_TOOLING_NODEINTROSPECTION_H - -#include "clang/AST/ASTTypeTraits.h" -#include "clang/AST/DeclarationName.h" -#include "llvm/ADT/IntrusiveRefCntPtr.h" -#include - -namespace clang { - -class Stmt; -class Decl; -class CXXCtorInitializer; -class NestedNameSpecifierLoc; -class TemplateArgumentLoc; -class CXXBaseSpecifier; -struct DeclarationNameInfo; - -namespace tooling { - -class LocationCall; -using SharedLocationCall = llvm::IntrusiveRefCntPtr; - -class LocationCall : public llvm::ThreadSafeRefCountedBase { -public: - enum LocationCallFlags { NoFlags, ReturnsPointer, IsCast }; - LocationCall(SharedLocationCall on, std::string name, - LocationCallFlags flags = NoFlags) - : m_flags(flags), m_on(std::move(on)), m_name(std::move(name)) {} - - LocationCall *on() const { return m_on.get(); } - StringRef name() const { return m_name; } - bool returnsPointer() const { return m_flags & ReturnsPointer; } - bool isCast() const { return m_flags & IsCast; } - -private: - LocationCallFlags m_flags; - SharedLocationCall m_on; - std::string m_name; -}; - -class LocationCallFormatterCpp { -public: - static void print(const LocationCall &Call, llvm::raw_ostream &OS); - static std::string format(const LocationCall &Call); -}; - -namespace internal { -struct RangeLessThan { - bool operator()(std::pair const &LHS, - std::pair const &RHS) const; - bool - operator()(std::pair const &LHS, - std::pair const &RHS) const; -}; - -} // namespace internal - -// Note that this container stores unique results in a deterministic, but -// the location calls are in an unspecified order. Clients which desire -// a particular order for the location calls, such as alphabetical, -// should sort results after retrieval, because the order is dependent -// on how the LocationCalls are formatted. -template -using UniqueMultiMap = std::set, internal::RangeLessThan>; - -using SourceLocationMap = UniqueMultiMap; -using SourceRangeMap = UniqueMultiMap; - -struct NodeLocationAccessors { - SourceLocationMap LocationAccessors; - SourceRangeMap RangeAccessors; -}; - -namespace NodeIntrospection { -bool hasIntrospectionSupport(); -NodeLocationAccessors GetLocations(clang::Stmt const *Object); -NodeLocationAccessors GetLocations(clang::Decl const *Object); -NodeLocationAccessors GetLocations(clang::CXXCtorInitializer const *Object); -NodeLocationAccessors GetLocations(clang::NestedNameSpecifierLoc const &); -NodeLocationAccessors GetLocations(clang::TemplateArgumentLoc const &); -NodeLocationAccessors GetLocations(clang::CXXBaseSpecifier const *); -NodeLocationAccessors GetLocations(clang::TypeLoc const &); -NodeLocationAccessors GetLocations(clang::DeclarationNameInfo const &); -NodeLocationAccessors GetLocations(clang::DynTypedNode const &Node); -} // namespace NodeIntrospection -} // namespace tooling -} // namespace clang -#endif diff --git a/clang/lib/Tooling/CMakeLists.txt b/clang/lib/Tooling/CMakeLists.txt index 91e6cbdcbc44f..93a9e707a134c 100644 --- a/clang/lib/Tooling/CMakeLists.txt +++ b/clang/lib/Tooling/CMakeLists.txt @@ -9,98 +9,10 @@ add_subdirectory(Core) add_subdirectory(Inclusions) add_subdirectory(Refactoring) add_subdirectory(ASTDiff) -add_subdirectory(DumpTool) add_subdirectory(Syntax) add_subdirectory(DependencyScanning) add_subdirectory(Transformer) -# Replace the last lib component of the current binary directory with include -string(FIND ${CMAKE_CURRENT_BINARY_DIR} "/lib/" PATH_LIB_START REVERSE) -if(PATH_LIB_START EQUAL -1) - message(FATAL_ERROR "Couldn't find lib component in binary directory") -endif() -math(EXPR PATH_LIB_END "${PATH_LIB_START}+5") -string(SUBSTRING ${CMAKE_CURRENT_BINARY_DIR} 0 ${PATH_LIB_START} PATH_HEAD) -string(SUBSTRING ${CMAKE_CURRENT_BINARY_DIR} ${PATH_LIB_END} -1 PATH_TAIL) -string(CONCAT BINARY_INCLUDE_DIR ${PATH_HEAD} "/include/clang/" ${PATH_TAIL}) - -if (NOT Python3_EXECUTABLE - OR APPLE - OR CMAKE_CROSSCOMPILING - OR GENERATOR_IS_MULTI_CONFIG - OR NOT LLVM_NATIVE_ARCH IN_LIST LLVM_TARGETS_TO_BUILD - ) - configure_file( - EmptyNodeIntrospection.inc.in - ${BINARY_INCLUDE_DIR}/NodeIntrospection.inc - COPYONLY - ) - set(CLANG_TOOLING_BUILD_AST_INTROSPECTION "OFF" CACHE BOOL "") -else() - # The generation of ASTNodeAPI.json takes a long time in a - # Debug build due to parsing AST.h. Disable the processing - # but setting CLANG_TOOLING_BUILD_AST_INTROSPECTION as an - # internal hidden setting to override. - # When the processing is disabled, a trivial/empty JSON - # file is generated by clang-ast-dump and generate_cxx_src_locs.py - # generates the same API, but with a trivial implementation. - option(CLANG_TOOLING_BUILD_AST_INTROSPECTION "Enable AST introspection" TRUE) - - set(skip_expensive_processing $,$>>) - - set(implicitDirs) - foreach(implicitDir ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}) - list(APPEND implicitDirs -I ${implicitDir}) - endforeach() - - include(GetClangResourceDir) - get_clang_resource_dir(resource_dir PREFIX ${LLVM_BINARY_DIR}) - add_custom_command( - COMMENT Generate ASTNodeAPI.json - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/ASTNodeAPI.json - DEPENDS clang-ast-dump clang-resource-headers - COMMAND - $ - # Skip this in debug mode because parsing AST.h is too slow - --skip-processing=${skip_expensive_processing} - -I ${resource_dir}/include - -I ${CLANG_SOURCE_DIR}/include - -I ${LLVM_BINARY_DIR}/tools/clang/include - -I ${LLVM_BINARY_DIR}/include - -I ${LLVM_SOURCE_DIR}/include - ${implicitDirs} - --json-output-path ${CMAKE_CURRENT_BINARY_DIR}/ASTNodeAPI.json - ) - - add_custom_target(run-ast-api-dump-tool - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/ASTNodeAPI.json - ) - - add_custom_command( - COMMENT Generate NodeIntrospection.inc - OUTPUT ${BINARY_INCLUDE_DIR}/NodeIntrospection.inc - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/ASTNodeAPI.json - ${CMAKE_CURRENT_SOURCE_DIR}/DumpTool/generate_cxx_src_locs.py - ${CMAKE_CURRENT_SOURCE_DIR}/EmptyNodeIntrospection.inc.in - COMMAND - ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/DumpTool/generate_cxx_src_locs.py - --json-input-path ${CMAKE_CURRENT_BINARY_DIR}/ASTNodeAPI.json - --output-file NodeIntrospection.inc - --use-empty-implementation ${skip_expensive_processing} - --empty-implementation - "${CMAKE_CURRENT_SOURCE_DIR}/EmptyNodeIntrospection.inc.in" - COMMAND - ${CMAKE_COMMAND} -E copy_if_different - ${CMAKE_CURRENT_BINARY_DIR}/NodeIntrospection.inc - ${BINARY_INCLUDE_DIR}/NodeIntrospection.inc - ) - - add_custom_target(run-ast-api-generate-tool - DEPENDS - ${BINARY_INCLUDE_DIR}/NodeIntrospection.inc - ) -endif() - add_clang_library(clangTooling AllTUsExecution.cpp ArgumentsAdjusters.cpp @@ -116,8 +28,6 @@ add_clang_library(clangTooling Refactoring.cpp RefactoringCallbacks.cpp StandaloneExecution.cpp - NodeIntrospection.cpp - ${BINARY_INCLUDE_DIR}/NodeIntrospection.inc Tooling.cpp DEPENDS diff --git a/clang/lib/Tooling/DumpTool/APIData.h b/clang/lib/Tooling/DumpTool/APIData.h deleted file mode 100644 index 03e247a8bd955..0000000000000 --- a/clang/lib/Tooling/DumpTool/APIData.h +++ /dev/null @@ -1,31 +0,0 @@ -//===- APIData.h ---------------------------------------------*- C++ -*----===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_TOOLING_DUMPTOOL_APIDATA_H -#define LLVM_CLANG_LIB_TOOLING_DUMPTOOL_APIDATA_H - -#include -#include - -namespace clang { -namespace tooling { - -struct ClassData { - std::vector ASTClassLocations; - std::vector ASTClassRanges; - std::vector TemplateParms; - std::vector TypeSourceInfos; - std::vector TypeLocs; - std::vector NestedNameLocs; - std::vector DeclNameInfos; -}; - -} // namespace tooling -} // namespace clang - -#endif diff --git a/clang/lib/Tooling/DumpTool/ASTSrcLocProcessor.cpp b/clang/lib/Tooling/DumpTool/ASTSrcLocProcessor.cpp deleted file mode 100644 index 42691d556d986..0000000000000 --- a/clang/lib/Tooling/DumpTool/ASTSrcLocProcessor.cpp +++ /dev/null @@ -1,271 +0,0 @@ -//===- ASTSrcLocProcessor.cpp --------------------------------*- C++ -*----===// -// -// 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 "ASTSrcLocProcessor.h" - -#include "clang/Frontend/CompilerInstance.h" -#include "llvm/Support/JSON.h" -#include "llvm/Support/MemoryBuffer.h" - -using namespace clang::tooling; -using namespace llvm; -using namespace clang::ast_matchers; - -ASTSrcLocProcessor::ASTSrcLocProcessor(StringRef JsonPath) - : JsonPath(JsonPath) { - - MatchFinder::MatchFinderOptions FinderOptions; - - Finder = std::make_unique(std::move(FinderOptions)); - Finder->addMatcher( - cxxRecordDecl( - isDefinition(), - isSameOrDerivedFrom( - namedDecl( - hasAnyName( - "clang::Stmt", "clang::Decl", "clang::CXXCtorInitializer", - "clang::NestedNameSpecifierLoc", - "clang::TemplateArgumentLoc", "clang::CXXBaseSpecifier", - "clang::DeclarationNameInfo", "clang::TypeLoc")) - .bind("nodeClade")), - optionally(isDerivedFrom(cxxRecordDecl().bind("derivedFrom")))) - .bind("className"), - this); - Finder->addMatcher( - cxxRecordDecl(isDefinition(), hasAnyName("clang::PointerLikeTypeLoc", - "clang::TypeofLikeTypeLoc")) - .bind("templateName"), - this); -} - -std::unique_ptr -ASTSrcLocProcessor::createASTConsumer(clang::CompilerInstance &Compiler, - StringRef File) { - return Finder->newASTConsumer(); -} - -llvm::json::Object toJSON(llvm::StringMap> const &Obj) { - using llvm::json::toJSON; - - llvm::json::Object JsonObj; - for (const auto &Item : Obj) { - JsonObj[Item.first()] = Item.second; - } - return JsonObj; -} - -llvm::json::Object toJSON(llvm::StringMap const &Obj) { - using llvm::json::toJSON; - - llvm::json::Object JsonObj; - for (const auto &Item : Obj) { - JsonObj[Item.first()] = Item.second; - } - return JsonObj; -} - -llvm::json::Object toJSON(ClassData const &Obj) { - llvm::json::Object JsonObj; - - if (!Obj.ASTClassLocations.empty()) - JsonObj["sourceLocations"] = Obj.ASTClassLocations; - if (!Obj.ASTClassRanges.empty()) - JsonObj["sourceRanges"] = Obj.ASTClassRanges; - if (!Obj.TemplateParms.empty()) - JsonObj["templateParms"] = Obj.TemplateParms; - if (!Obj.TypeSourceInfos.empty()) - JsonObj["typeSourceInfos"] = Obj.TypeSourceInfos; - if (!Obj.TypeLocs.empty()) - JsonObj["typeLocs"] = Obj.TypeLocs; - if (!Obj.NestedNameLocs.empty()) - JsonObj["nestedNameLocs"] = Obj.NestedNameLocs; - if (!Obj.DeclNameInfos.empty()) - JsonObj["declNameInfos"] = Obj.DeclNameInfos; - return JsonObj; -} - -llvm::json::Object toJSON(llvm::StringMap const &Obj) { - using llvm::json::toJSON; - - llvm::json::Object JsonObj; - for (const auto &Item : Obj) - JsonObj[Item.first()] = ::toJSON(Item.second); - return JsonObj; -} - -void WriteJSON(StringRef JsonPath, llvm::json::Object &&ClassInheritance, - llvm::json::Object &&ClassesInClade, - llvm::json::Object &&ClassEntries) { - llvm::json::Object JsonObj; - - using llvm::json::toJSON; - - JsonObj["classInheritance"] = std::move(ClassInheritance); - JsonObj["classesInClade"] = std::move(ClassesInClade); - JsonObj["classEntries"] = std::move(ClassEntries); - - llvm::json::Value JsonVal(std::move(JsonObj)); - - bool WriteChange = false; - std::string OutString; - if (auto ExistingOrErr = MemoryBuffer::getFile(JsonPath, /*IsText=*/true)) { - raw_string_ostream Out(OutString); - Out << formatv("{0:2}", JsonVal); - if (ExistingOrErr.get()->getBuffer() == Out.str()) - return; - WriteChange = true; - } - - std::error_code EC; - llvm::raw_fd_ostream JsonOut(JsonPath, EC, llvm::sys::fs::OF_Text); - if (EC) - return; - - if (WriteChange) - JsonOut << OutString; - else - JsonOut << formatv("{0:2}", JsonVal); -} - -void ASTSrcLocProcessor::generate() { - WriteJSON(JsonPath, ::toJSON(ClassInheritance), ::toJSON(ClassesInClade), - ::toJSON(ClassEntries)); -} - -void ASTSrcLocProcessor::generateEmpty() { WriteJSON(JsonPath, {}, {}, {}); } - -std::vector -CaptureMethods(std::string TypeString, const clang::CXXRecordDecl *ASTClass, - const MatchFinder::MatchResult &Result) { - - auto publicAccessor = [](auto... InnerMatcher) { - return cxxMethodDecl(isPublic(), parameterCountIs(0), isConst(), - InnerMatcher...); - }; - - auto BoundNodesVec = match( - findAll( - publicAccessor( - ofClass(cxxRecordDecl( - equalsNode(ASTClass), - optionally(isDerivedFrom( - cxxRecordDecl(hasAnyName("clang::Stmt", "clang::Decl")) - .bind("stmtOrDeclBase"))), - optionally(isDerivedFrom( - cxxRecordDecl(hasName("clang::Expr")).bind("exprBase"))), - optionally( - isDerivedFrom(cxxRecordDecl(hasName("clang::TypeLoc")) - .bind("typeLocBase"))))), - returns(hasCanonicalType(asString(TypeString)))) - .bind("classMethod")), - *ASTClass, *Result.Context); - - std::vector Methods; - for (const auto &BN : BoundNodesVec) { - if (const auto *Node = BN.getNodeAs("classMethod")) { - const auto *StmtOrDeclBase = - BN.getNodeAs("stmtOrDeclBase"); - const auto *TypeLocBase = - BN.getNodeAs("typeLocBase"); - const auto *ExprBase = BN.getNodeAs("exprBase"); - // The clang AST has several methods on base classes which are overriden - // pseudo-virtually by derived classes. - // We record only the pseudo-virtual methods on the base classes to - // avoid duplication. - if (StmtOrDeclBase && - (Node->getName() == "getBeginLoc" || Node->getName() == "getEndLoc" || - Node->getName() == "getSourceRange")) - continue; - if (ExprBase && Node->getName() == "getExprLoc") - continue; - if (TypeLocBase && Node->getName() == "getLocalSourceRange") - continue; - if ((ASTClass->getName() == "PointerLikeTypeLoc" || - ASTClass->getName() == "TypeofLikeTypeLoc") && - Node->getName() == "getLocalSourceRange") - continue; - Methods.push_back(Node->getName().str()); - } - } - return Methods; -} - -void ASTSrcLocProcessor::run(const MatchFinder::MatchResult &Result) { - - const auto *ASTClass = - Result.Nodes.getNodeAs("className"); - - StringRef CladeName; - if (ASTClass) { - if (const auto *NodeClade = - Result.Nodes.getNodeAs("nodeClade")) - CladeName = NodeClade->getName(); - } else { - ASTClass = Result.Nodes.getNodeAs("templateName"); - CladeName = "TypeLoc"; - } - - StringRef ClassName = ASTClass->getName(); - - ClassData CD; - - CD.ASTClassLocations = - CaptureMethods("class clang::SourceLocation", ASTClass, Result); - CD.ASTClassRanges = - CaptureMethods("class clang::SourceRange", ASTClass, Result); - CD.TypeSourceInfos = - CaptureMethods("class clang::TypeSourceInfo *", ASTClass, Result); - CD.TypeLocs = CaptureMethods("class clang::TypeLoc", ASTClass, Result); - CD.NestedNameLocs = - CaptureMethods("class clang::NestedNameSpecifierLoc", ASTClass, Result); - CD.DeclNameInfos = - CaptureMethods("struct clang::DeclarationNameInfo", ASTClass, Result); - auto DI = CaptureMethods("const struct clang::DeclarationNameInfo &", - ASTClass, Result); - CD.DeclNameInfos.insert(CD.DeclNameInfos.end(), DI.begin(), DI.end()); - - if (const auto *DerivedFrom = - Result.Nodes.getNodeAs("derivedFrom")) { - - if (const auto *Templ = - llvm::dyn_cast( - DerivedFrom)) { - - const auto &TArgs = Templ->getTemplateArgs(); - - SmallString<256> TArgsString; - llvm::raw_svector_ostream OS(TArgsString); - OS << DerivedFrom->getName() << '<'; - - clang::PrintingPolicy PPol(Result.Context->getLangOpts()); - PPol.TerseOutput = true; - - for (unsigned I = 0; I < TArgs.size(); ++I) { - if (I > 0) - OS << ", "; - TArgs.get(I).getAsType().print(OS, PPol); - } - OS << '>'; - - ClassInheritance[ClassName] = TArgsString.str().str(); - } else { - ClassInheritance[ClassName] = DerivedFrom->getName().str(); - } - } - - if (const auto *Templ = ASTClass->getDescribedClassTemplate()) { - if (auto *TParams = Templ->getTemplateParameters()) { - for (const auto &TParam : *TParams) { - CD.TemplateParms.push_back(TParam->getName().str()); - } - } - } - - ClassEntries[ClassName] = CD; - ClassesInClade[CladeName].push_back(ClassName); -} diff --git a/clang/lib/Tooling/DumpTool/ASTSrcLocProcessor.h b/clang/lib/Tooling/DumpTool/ASTSrcLocProcessor.h deleted file mode 100644 index 5f2b48173f281..0000000000000 --- a/clang/lib/Tooling/DumpTool/ASTSrcLocProcessor.h +++ /dev/null @@ -1,53 +0,0 @@ -//===- ASTSrcLocProcessor.h ---------------------------------*- C++ -*-----===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_TOOLING_DUMPTOOL_ASTSRCLOCPROCESSOR_H -#define LLVM_CLANG_TOOLING_DUMPTOOL_ASTSRCLOCPROCESSOR_H - -#include "APIData.h" -#include "clang/ASTMatchers/ASTMatchFinder.h" -#include "llvm/ADT/StringRef.h" -#include -#include -#include - -namespace clang { - -class CompilerInstance; - -namespace tooling { - -class ASTSrcLocProcessor : public ast_matchers::MatchFinder::MatchCallback { -public: - explicit ASTSrcLocProcessor(StringRef JsonPath); - - std::unique_ptr createASTConsumer(CompilerInstance &Compiler, - StringRef File); - - void generate(); - void generateEmpty(); - -private: - void run(const ast_matchers::MatchFinder::MatchResult &Result) override; - - std::optional getCheckTraversalKind() const override { - return TK_IgnoreUnlessSpelledInSource; - } - - llvm::StringMap ClassInheritance; - llvm::StringMap> ClassesInClade; - llvm::StringMap ClassEntries; - - std::string JsonPath; - std::unique_ptr Finder; -}; - -} // namespace tooling -} // namespace clang - -#endif diff --git a/clang/lib/Tooling/DumpTool/CMakeLists.txt b/clang/lib/Tooling/DumpTool/CMakeLists.txt deleted file mode 100644 index 712985bf7e2b4..0000000000000 --- a/clang/lib/Tooling/DumpTool/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ - -add_clang_executable(clang-ast-dump - ASTSrcLocProcessor.cpp - ClangSrcLocDump.cpp -) - -target_link_libraries(clang-ast-dump - PRIVATE - clangAST - clangASTMatchers - clangBasic - clangDriver - clangFrontend - clangSerialization - clangToolingCore -) diff --git a/clang/lib/Tooling/DumpTool/ClangSrcLocDump.cpp b/clang/lib/Tooling/DumpTool/ClangSrcLocDump.cpp deleted file mode 100644 index 1529bfa75d6d5..0000000000000 --- a/clang/lib/Tooling/DumpTool/ClangSrcLocDump.cpp +++ /dev/null @@ -1,155 +0,0 @@ -//===- ClangSrcLocDump.cpp ------------------------------------*- C++ -*---===// -// -// 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/Basic/Diagnostic.h" -#include "clang/Driver/Compilation.h" -#include "clang/Driver/Driver.h" -#include "clang/Driver/Job.h" -#include "clang/Driver/Options.h" -#include "clang/Driver/Tool.h" -#include "clang/Frontend/CompilerInstance.h" -#include "clang/Frontend/TextDiagnosticPrinter.h" -#include "clang/Lex/PreprocessorOptions.h" -#include "clang/Tooling/Tooling.h" -#include "llvm/Option/ArgList.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/JSON.h" -#include "llvm/TargetParser/Host.h" - -#include "ASTSrcLocProcessor.h" - -using namespace clang::tooling; -using namespace clang; -using namespace llvm; - -static cl::list IncludeDirectories( - "I", cl::desc("Include directories to use while compiling"), - cl::value_desc("directory"), cl::Required, cl::OneOrMore, cl::Prefix); - -static cl::opt - SkipProcessing("skip-processing", - cl::desc("Avoid processing the AST header file"), - cl::Required, cl::value_desc("bool")); - -static cl::opt JsonOutputPath("json-output-path", - cl::desc("json output path"), - cl::Required, - cl::value_desc("path")); - -class ASTSrcLocGenerationAction : public clang::ASTFrontendAction { -public: - ASTSrcLocGenerationAction() : Processor(JsonOutputPath) {} - - void ExecuteAction() override { - clang::ASTFrontendAction::ExecuteAction(); - if (getCompilerInstance().getDiagnostics().getNumErrors() > 0) - Processor.generateEmpty(); - else - Processor.generate(); - } - - std::unique_ptr - CreateASTConsumer(clang::CompilerInstance &Compiler, - llvm::StringRef File) override { - return Processor.createASTConsumer(Compiler, File); - } - -private: - ASTSrcLocProcessor Processor; -}; - -static const char Filename[] = "ASTTU.cpp"; - -int main(int argc, const char **argv) { - - cl::ParseCommandLineOptions(argc, argv); - - if (SkipProcessing) { - std::error_code EC; - llvm::raw_fd_ostream JsonOut(JsonOutputPath, EC, llvm::sys::fs::OF_Text); - if (EC) - return 1; - JsonOut << formatv("{0:2}", llvm::json::Value(llvm::json::Object())); - return 0; - } - - std::vector Args; - Args.push_back("-cc1"); - - llvm::transform(IncludeDirectories, std::back_inserter(Args), - [](const std::string &IncDir) { return "-I" + IncDir; }); - - Args.push_back("-fsyntax-only"); - Args.push_back(Filename); - - std::vector Argv(Args.size(), nullptr); - llvm::transform(Args, Argv.begin(), - [](const std::string &Arg) { return Arg.c_str(); }); - - IntrusiveRefCntPtr DiagOpts = - CreateAndPopulateDiagOpts(Argv); - - // Don't output diagnostics, because common scenarios such as - // cross-compiling fail with diagnostics. This is not fatal, but - // just causes attempts to use the introspection API to return no data. - TextDiagnosticPrinter DiagnosticPrinter(llvm::nulls(), &*DiagOpts); - DiagnosticsEngine Diagnostics( - IntrusiveRefCntPtr(new DiagnosticIDs()), &*DiagOpts, - &DiagnosticPrinter, false); - - auto *OFS = new llvm::vfs::OverlayFileSystem(vfs::getRealFileSystem()); - - auto *MemFS = new llvm::vfs::InMemoryFileSystem(); - OFS->pushOverlay(MemFS); - MemFS->addFile(Filename, 0, - MemoryBuffer::getMemBuffer("#include \"clang/AST/AST.h\"\n")); - - auto Files = llvm::makeIntrusiveRefCnt(FileSystemOptions(), OFS); - - auto Driver = std::make_unique( - "clang", llvm::sys::getDefaultTargetTriple(), Diagnostics, - "ast-api-dump-tool", OFS); - - std::unique_ptr Comp( - Driver->BuildCompilation(llvm::ArrayRef(Argv))); - if (!Comp) - return 1; - - const auto &Jobs = Comp->getJobs(); - if (Jobs.size() != 1 || !isa(*Jobs.begin())) { - SmallString<256> error_msg; - llvm::raw_svector_ostream error_stream(error_msg); - Jobs.Print(error_stream, "; ", true); - return 1; - } - - const auto &Cmd = cast(*Jobs.begin()); - const llvm::opt::ArgStringList &CC1Args = Cmd.getArguments(); - - auto Invocation = std::make_unique(); - CompilerInvocation::CreateFromArgs(*Invocation, CC1Args, Diagnostics); - - CompilerInstance Compiler(std::make_shared()); - Compiler.setInvocation(std::move(Invocation)); - - Compiler.createDiagnostics(&DiagnosticPrinter, false); - if (!Compiler.hasDiagnostics()) - return 1; - - // Suppress "2 errors generated" or similar messages - Compiler.getDiagnosticOpts().ShowCarets = false; - Compiler.createSourceManager(*Files); - Compiler.setFileManager(Files.get()); - - ASTSrcLocGenerationAction ScopedToolAction; - Compiler.ExecuteAction(ScopedToolAction); - - Files->clearStatCache(); - - return 0; -} diff --git a/clang/lib/Tooling/DumpTool/generate_cxx_src_locs.py b/clang/lib/Tooling/DumpTool/generate_cxx_src_locs.py deleted file mode 100755 index 7671f9691c096..0000000000000 --- a/clang/lib/Tooling/DumpTool/generate_cxx_src_locs.py +++ /dev/null @@ -1,452 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -import os -import sys -import json -import filecmp -import shutil -import argparse - - -class Generator(object): - - implementationContent = "" - - RefClades = { - "DeclarationNameInfo", - "NestedNameSpecifierLoc", - "TemplateArgumentLoc", - "TypeLoc", - } - - def __init__(self, templateClasses): - self.templateClasses = templateClasses - - def GeneratePrologue(self): - - self.implementationContent += r""" -/*===- Generated file -------------------------------------------*- C++ -*-===*\ -|* *| -|* Introspection of available AST node SourceLocations *| -|* *| -|* Automatically generated file, do not edit! *| -|* *| -\*===----------------------------------------------------------------------===*/ - -namespace clang { -namespace tooling { - -using LocationAndString = SourceLocationMap::value_type; -using RangeAndString = SourceRangeMap::value_type; - -bool NodeIntrospection::hasIntrospectionSupport() { return true; } - -struct RecursionPopper -{ - RecursionPopper(std::vector &TypeLocRecursionGuard) - : TLRG(TypeLocRecursionGuard) - { - - } - - ~RecursionPopper() - { - TLRG.pop_back(); - } - -private: -std::vector &TLRG; -}; -""" - - def GenerateBaseGetLocationsDeclaration(self, CladeName): - InstanceDecoration = "*" - if CladeName in self.RefClades: - InstanceDecoration = "&" - - self.implementationContent += """ -void GetLocationsImpl(SharedLocationCall const& Prefix, - clang::{0} const {1}Object, SourceLocationMap &Locs, - SourceRangeMap &Rngs, - std::vector &TypeLocRecursionGuard); -""".format( - CladeName, InstanceDecoration - ) - - def GenerateSrcLocMethod(self, ClassName, ClassData, CreateLocalRecursionGuard): - - NormalClassName = ClassName - RecursionGuardParam = ( - "" - if CreateLocalRecursionGuard - else ", std::vector& TypeLocRecursionGuard" - ) - - if "templateParms" in ClassData: - TemplatePreamble = "template (Prefix, "{0}"))); -""".format( - locName - ) - - self.implementationContent += "\n" - - if "sourceRanges" in ClassData: - for rngName in ClassData["sourceRanges"]: - self.implementationContent += """ - Rngs.insert(RangeAndString(Object.{0}(), - llvm::makeIntrusiveRefCnt(Prefix, "{0}"))); -""".format( - rngName - ) - - self.implementationContent += "\n" - - if ( - "typeLocs" in ClassData - or "typeSourceInfos" in ClassData - or "nestedNameLocs" in ClassData - or "declNameInfos" in ClassData - ): - if CreateLocalRecursionGuard: - self.implementationContent += ( - "std::vector TypeLocRecursionGuard;\n" - ) - - self.implementationContent += "\n" - - if "typeLocs" in ClassData: - for typeLoc in ClassData["typeLocs"]: - - self.implementationContent += """ - if (Object.{0}()) {{ - GetLocationsImpl( - llvm::makeIntrusiveRefCnt(Prefix, "{0}"), - Object.{0}(), Locs, Rngs, TypeLocRecursionGuard); - }} - """.format( - typeLoc - ) - - self.implementationContent += "\n" - if "typeSourceInfos" in ClassData: - for tsi in ClassData["typeSourceInfos"]: - self.implementationContent += """ - if (Object.{0}()) {{ - GetLocationsImpl(llvm::makeIntrusiveRefCnt( - llvm::makeIntrusiveRefCnt(Prefix, "{0}", - LocationCall::ReturnsPointer), "getTypeLoc"), - Object.{0}()->getTypeLoc(), Locs, Rngs, TypeLocRecursionGuard); - }} - """.format( - tsi - ) - - self.implementationContent += "\n" - - if "nestedNameLocs" in ClassData: - for NN in ClassData["nestedNameLocs"]: - self.implementationContent += """ - if (Object.{0}()) - GetLocationsImpl( - llvm::makeIntrusiveRefCnt(Prefix, "{0}"), - Object.{0}(), Locs, Rngs, TypeLocRecursionGuard); - """.format( - NN - ) - - if "declNameInfos" in ClassData: - for declName in ClassData["declNameInfos"]: - - self.implementationContent += """ - GetLocationsImpl( - llvm::makeIntrusiveRefCnt(Prefix, "{0}"), - Object.{0}(), Locs, Rngs, TypeLocRecursionGuard); - """.format( - declName - ) - - self.implementationContent += "}\n" - - def GenerateFiles(self, OutputFile): - with open(os.path.join(os.getcwd(), OutputFile), "w") as f: - f.write(self.implementationContent) - - def GenerateBaseGetLocationsFunction( - self, - ASTClassNames, - ClassEntries, - CladeName, - InheritanceMap, - CreateLocalRecursionGuard, - ): - - MethodReturnType = "NodeLocationAccessors" - InstanceDecoration = "*" - if CladeName in self.RefClades: - InstanceDecoration = "&" - - Signature = "GetLocations(clang::{0} const {1}Object)".format( - CladeName, InstanceDecoration - ) - ImplSignature = """ - GetLocationsImpl(SharedLocationCall const& Prefix, - clang::{0} const {1}Object, SourceLocationMap &Locs, - SourceRangeMap &Rngs, - std::vector &TypeLocRecursionGuard) - """.format( - CladeName, InstanceDecoration - ) - - self.implementationContent += "void {0} {{ ".format(ImplSignature) - - if CladeName == "TypeLoc": - self.implementationContent += "if (Object.isNull()) return;" - - self.implementationContent += """ - if (llvm::find(TypeLocRecursionGuard, Object) != TypeLocRecursionGuard.end()) - return; - TypeLocRecursionGuard.push_back(Object); - RecursionPopper RAII(TypeLocRecursionGuard); - """ - - RecursionGuardParam = "" - if not CreateLocalRecursionGuard: - RecursionGuardParam = ", TypeLocRecursionGuard" - - ArgPrefix = "*" - if CladeName in self.RefClades: - ArgPrefix = "" - self.implementationContent += ( - "GetLocations{0}(Prefix, {1}Object, Locs, Rngs {2});".format( - CladeName, ArgPrefix, RecursionGuardParam - ) - ) - - if CladeName == "TypeLoc": - self.implementationContent += """ - if (auto QTL = Object.getAs()) { - auto Dequalified = QTL.getNextTypeLoc(); - return GetLocationsImpl(llvm::makeIntrusiveRefCnt(Prefix, "getNextTypeLoc"), - Dequalified, - Locs, - Rngs, - TypeLocRecursionGuard); - }""" - - for ASTClassName in ASTClassNames: - if ASTClassName in self.templateClasses: - continue - if ASTClassName == CladeName: - continue - if CladeName != "TypeLoc": - self.implementationContent += """ -if (auto Derived = llvm::dyn_cast(Object)) {{ - GetLocations{0}(Prefix, *Derived, Locs, Rngs {1}); -}} -""".format( - ASTClassName, RecursionGuardParam - ) - continue - - self.GenerateBaseTypeLocVisit( - ASTClassName, ClassEntries, RecursionGuardParam, InheritanceMap - ) - - self.implementationContent += "}" - - self.implementationContent += """ -{0} NodeIntrospection::{1} {{ - NodeLocationAccessors Result; - SharedLocationCall Prefix; - std::vector TypeLocRecursionGuard; - - GetLocationsImpl(Prefix, Object, Result.LocationAccessors, - Result.RangeAccessors, TypeLocRecursionGuard); -""".format( - MethodReturnType, Signature - ) - - self.implementationContent += "return Result; }" - - def GenerateBaseTypeLocVisit( - self, ASTClassName, ClassEntries, RecursionGuardParam, InheritanceMap - ): - CallPrefix = "Prefix" - if ASTClassName != "TypeLoc": - CallPrefix = """llvm::makeIntrusiveRefCnt(Prefix, - "getAs", LocationCall::IsCast) - """.format( - ASTClassName - ) - - if ASTClassName in ClassEntries: - - self.implementationContent += """ - if (auto ConcreteTL = Object.getAs()) - GetLocations{1}({2}, ConcreteTL, Locs, Rngs {3}); - """.format( - ASTClassName, ASTClassName, CallPrefix, RecursionGuardParam - ) - - if ASTClassName in InheritanceMap: - for baseTemplate in self.templateClasses: - if baseTemplate in InheritanceMap[ASTClassName]: - self.implementationContent += """ - if (auto ConcreteTL = Object.getAs()) - GetLocations{1}({2}, ConcreteTL, Locs, Rngs {3}); - """.format( - InheritanceMap[ASTClassName], - baseTemplate, - CallPrefix, - RecursionGuardParam, - ) - - def GenerateDynNodeVisitor(self, CladeNames): - MethodReturnType = "NodeLocationAccessors" - - Signature = "GetLocations(clang::DynTypedNode const &Node)" - - self.implementationContent += ( - MethodReturnType + " NodeIntrospection::" + Signature + "{" - ) - - for CladeName in CladeNames: - if CladeName == "DeclarationNameInfo": - continue - self.implementationContent += """ - if (const auto *N = Node.get<{0}>()) - """.format( - CladeName - ) - ArgPrefix = "" - if CladeName in self.RefClades: - ArgPrefix = "*" - self.implementationContent += """ - return GetLocations({0}const_cast<{1} *>(N));""".format( - ArgPrefix, CladeName - ) - - self.implementationContent += "\nreturn {}; }" - - def GenerateEpilogue(self): - - self.implementationContent += """ - } -} -""" - - -def main(): - - parser = argparse.ArgumentParser() - parser.add_argument( - "--json-input-path", help="Read API description from FILE", metavar="FILE" - ) - parser.add_argument( - "--output-file", help="Generate output in FILEPATH", metavar="FILEPATH" - ) - parser.add_argument( - "--use-empty-implementation", - help="Generate empty implementation", - action="store", - type=int, - ) - parser.add_argument( - "--empty-implementation", - help="Copy empty implementation from FILEPATH", - action="store", - metavar="FILEPATH", - ) - - options = parser.parse_args() - - use_empty_implementation = options.use_empty_implementation - - if not use_empty_implementation and not os.path.exists(options.json_input_path): - use_empty_implementation = True - - if not use_empty_implementation: - with open(options.json_input_path) as f: - jsonData = json.load(f) - - if not "classesInClade" in jsonData or not jsonData["classesInClade"]: - use_empty_implementation = True - - if use_empty_implementation: - if not os.path.exists(options.output_file) or not filecmp.cmp( - options.empty_implementation, options.output_file - ): - shutil.copyfile(options.empty_implementation, options.output_file) - sys.exit(0) - - templateClasses = [] - for (ClassName, ClassAccessors) in jsonData["classEntries"].items(): - if "templateParms" in ClassAccessors: - templateClasses.append(ClassName) - - g = Generator(templateClasses) - - g.GeneratePrologue() - - for (CladeName, ClassNameData) in jsonData["classesInClade"].items(): - g.GenerateBaseGetLocationsDeclaration(CladeName) - - def getCladeName(ClassName): - for (CladeName, ClassNameData) in jsonData["classesInClade"].items(): - if ClassName in ClassNameData: - return CladeName - - for (ClassName, ClassAccessors) in jsonData["classEntries"].items(): - cladeName = getCladeName(ClassName) - g.GenerateSrcLocMethod( - ClassName, ClassAccessors, cladeName not in Generator.RefClades - ) - - for (CladeName, ClassNameData) in jsonData["classesInClade"].items(): - g.GenerateBaseGetLocationsFunction( - ClassNameData, - jsonData["classEntries"], - CladeName, - jsonData["classInheritance"], - CladeName not in Generator.RefClades, - ) - - g.GenerateDynNodeVisitor(jsonData["classesInClade"].keys()) - - g.GenerateEpilogue() - - g.GenerateFiles(options.output_file) - - -if __name__ == "__main__": - main() diff --git a/clang/lib/Tooling/EmptyNodeIntrospection.inc.in b/clang/lib/Tooling/EmptyNodeIntrospection.inc.in deleted file mode 100644 index 2071c34cbd04d..0000000000000 --- a/clang/lib/Tooling/EmptyNodeIntrospection.inc.in +++ /dev/null @@ -1,48 +0,0 @@ -//===- EmptyNodeIntrospection.inc.in --------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -namespace clang { -namespace tooling { -bool NodeIntrospection::hasIntrospectionSupport() { return false; } - -NodeLocationAccessors NodeIntrospection::GetLocations(clang::Stmt const *) { - return {}; -} -NodeLocationAccessors NodeIntrospection::GetLocations(clang::Decl const *) { - return {}; -} -NodeLocationAccessors NodeIntrospection::GetLocations( - clang::CXXCtorInitializer const *) { - return {}; -} -NodeLocationAccessors NodeIntrospection::GetLocations( - clang::NestedNameSpecifierLoc const&) { - return {}; -} -NodeLocationAccessors NodeIntrospection::GetLocations( - clang::TemplateArgumentLoc const&) { - return {}; -} -NodeLocationAccessors NodeIntrospection::GetLocations( - clang::CXXBaseSpecifier const*) { - return {}; -} -NodeLocationAccessors NodeIntrospection::GetLocations( - clang::TypeLoc const&) { - return {}; -} -NodeLocationAccessors NodeIntrospection::GetLocations( - clang::DeclarationNameInfo const&) { - return {}; -} -NodeLocationAccessors -NodeIntrospection::GetLocations(clang::DynTypedNode const &) { - return {}; -} -} // namespace tooling -} // namespace clang diff --git a/clang/lib/Tooling/NodeIntrospection.cpp b/clang/lib/Tooling/NodeIntrospection.cpp deleted file mode 100644 index f01bb1cb9c3ca..0000000000000 --- a/clang/lib/Tooling/NodeIntrospection.cpp +++ /dev/null @@ -1,88 +0,0 @@ -//===- NodeIntrospection.h -----------------------------------*- C++ -*----===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// This file contains the implementation of the NodeIntrospection. -// -//===----------------------------------------------------------------------===// - -#include "clang/Tooling/NodeIntrospection.h" - -#include "clang/AST/AST.h" -#include "llvm/Support/raw_ostream.h" - -namespace clang { - -namespace tooling { - -void LocationCallFormatterCpp::print(const LocationCall &Call, - llvm::raw_ostream &OS) { - if (const LocationCall *On = Call.on()) { - print(*On, OS); - if (On->returnsPointer()) - OS << "->"; - else - OS << '.'; - } - - OS << Call.name() << "()"; -} - -std::string LocationCallFormatterCpp::format(const LocationCall &Call) { - std::string Result; - llvm::raw_string_ostream OS(Result); - print(Call, OS); - OS.flush(); - return Result; -} - -namespace internal { - -static bool locationCallLessThan(const LocationCall *LHS, - const LocationCall *RHS) { - if (!LHS && !RHS) - return false; - if (LHS && !RHS) - return true; - if (!LHS && RHS) - return false; - auto compareResult = LHS->name().compare(RHS->name()); - if (compareResult < 0) - return true; - if (compareResult > 0) - return false; - return locationCallLessThan(LHS->on(), RHS->on()); -} - -bool RangeLessThan::operator()( - std::pair const &LHS, - std::pair const &RHS) const { - if (LHS.first.getBegin() < RHS.first.getBegin()) - return true; - else if (LHS.first.getBegin() != RHS.first.getBegin()) - return false; - - if (LHS.first.getEnd() < RHS.first.getEnd()) - return true; - else if (LHS.first.getEnd() != RHS.first.getEnd()) - return false; - - return locationCallLessThan(LHS.second.get(), RHS.second.get()); -} -bool RangeLessThan::operator()( - std::pair const &LHS, - std::pair const &RHS) const { - if (LHS.first == RHS.first) - return locationCallLessThan(LHS.second.get(), RHS.second.get()); - return LHS.first < RHS.first; -} -} // namespace internal - -} // namespace tooling -} // namespace clang - -#include "clang/Tooling/NodeIntrospection.inc" diff --git a/clang/unittests/CMakeLists.txt b/clang/unittests/CMakeLists.txt index 37ca3107b5477..a8363ffa481ee 100644 --- a/clang/unittests/CMakeLists.txt +++ b/clang/unittests/CMakeLists.txt @@ -34,7 +34,6 @@ add_subdirectory(ASTMatchers) add_subdirectory(AST) add_subdirectory(CrossTU) add_subdirectory(Tooling) -add_subdirectory(Introspection) add_subdirectory(Format) add_subdirectory(Frontend) add_subdirectory(Rewrite) diff --git a/clang/unittests/Introspection/CMakeLists.txt b/clang/unittests/Introspection/CMakeLists.txt deleted file mode 100644 index edc359ef4fcfd..0000000000000 --- a/clang/unittests/Introspection/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -set(LLVM_LINK_COMPONENTS - FrontendOpenMP - Support - ) - -add_clang_unittest(IntrospectionTests - IntrospectionTest.cpp - ) - -clang_target_link_libraries(IntrospectionTests - PRIVATE - clangAST - clangASTMatchers - clangBasic - clangFrontend - clangSerialization - clangTooling - ) -target_link_libraries(IntrospectionTests - PRIVATE - LLVMTestingSupport -) diff --git a/clang/unittests/Introspection/IntrospectionTest.cpp b/clang/unittests/Introspection/IntrospectionTest.cpp deleted file mode 100644 index 22321f241f3fc..0000000000000 --- a/clang/unittests/Introspection/IntrospectionTest.cpp +++ /dev/null @@ -1,1679 +0,0 @@ -//===- unittest/Introspection/IntrospectionTest.cpp ----------*- C++ -*---===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// Tests for AST location API introspection. -// -//===----------------------------------------------------------------------===// - -#include "clang/AST/ASTContext.h" -#include "clang/ASTMatchers/ASTMatchFinder.h" -#include "clang/ASTMatchers/ASTMatchers.h" -#include "clang/Tooling/NodeIntrospection.h" -#include "clang/Tooling/Tooling.h" -#include "gmock/gmock-matchers.h" -#include "gmock/gmock.h" -#include "gtest/gtest.h" - -using namespace clang; -using namespace clang::ast_matchers; -using namespace clang::tooling; - -using ::testing::Pair; -using ::testing::UnorderedElementsAre; - -template -std::vector> -FormatExpected(const MapType &Accessors) { - std::vector> Result; - llvm::transform(llvm::make_filter_range(Accessors, - [](const auto &Accessor) { - return Accessor.first.isValid(); - }), - std::back_inserter(Result), [](const auto &Accessor) { - return std::make_pair( - LocationCallFormatterCpp::format(*Accessor.second), - Accessor.first); - }); - return Result; -} - -#define STRING_LOCATION_PAIR(INSTANCE, LOC) Pair(#LOC, INSTANCE->LOC) - -#define STRING_LOCATION_STDPAIR(INSTANCE, LOC) \ - std::make_pair(std::string(#LOC), INSTANCE->LOC) - -/** - A test formatter for a hypothetical language which needs - neither casts nor '->'. -*/ -class LocationCallFormatterSimple { -public: - static void print(const LocationCall &Call, llvm::raw_ostream &OS) { - if (Call.isCast()) { - if (const LocationCall *On = Call.on()) - print(*On, OS); - return; - } - if (const LocationCall *On = Call.on()) { - print(*On, OS); - OS << '.'; - } - OS << Call.name() << "()"; - } - - static std::string format(const LocationCall &Call) { - std::string Result; - llvm::raw_string_ostream OS(Result); - print(Call, OS); - OS.flush(); - return Result; - } -}; - -TEST(Introspection, SourceLocations_CallContainer) { - SourceLocationMap slm; - SharedLocationCall Prefix; - slm.insert(std::make_pair( - SourceLocation(), - llvm::makeIntrusiveRefCnt(Prefix, "getSourceRange"))); - EXPECT_EQ(slm.size(), 1u); - - auto callTypeLoc = - llvm::makeIntrusiveRefCnt(Prefix, "getTypeLoc"); - slm.insert(std::make_pair( - SourceLocation(), - llvm::makeIntrusiveRefCnt(callTypeLoc, "getSourceRange"))); - EXPECT_EQ(slm.size(), 2u); -} - -TEST(Introspection, SourceLocations_CallContainer2) { - SourceRangeMap slm; - SharedLocationCall Prefix; - slm.insert( - std::make_pair(SourceRange(), llvm::makeIntrusiveRefCnt( - Prefix, "getCXXOperatorNameRange"))); - EXPECT_EQ(slm.size(), 1u); - - slm.insert(std::make_pair( - SourceRange(), - llvm::makeIntrusiveRefCnt(Prefix, "getSourceRange"))); - EXPECT_EQ(slm.size(), 2u); -} - -TEST(Introspection, SourceLocations_CallChainFormatting) { - SharedLocationCall Prefix; - auto chainedCall = llvm::makeIntrusiveRefCnt( - llvm::makeIntrusiveRefCnt(Prefix, "getTypeLoc"), - "getSourceRange"); - EXPECT_EQ(LocationCallFormatterCpp::format(*chainedCall), - "getTypeLoc().getSourceRange()"); -} - -TEST(Introspection, SourceLocations_Formatter) { - SharedLocationCall Prefix; - auto chainedCall = llvm::makeIntrusiveRefCnt( - llvm::makeIntrusiveRefCnt( - llvm::makeIntrusiveRefCnt( - llvm::makeIntrusiveRefCnt( - Prefix, "getTypeSourceInfo", LocationCall::ReturnsPointer), - "getTypeLoc"), - "getAs", LocationCall::IsCast), - "getNameLoc"); - - EXPECT_EQ("getTypeSourceInfo()->getTypeLoc().getAs()." - "getNameLoc()", - LocationCallFormatterCpp::format(*chainedCall)); - EXPECT_EQ("getTypeSourceInfo().getTypeLoc().getNameLoc()", - LocationCallFormatterSimple::format(*chainedCall)); -} - -TEST(Introspection, SourceLocations_Stmt) { - if (!NodeIntrospection::hasIntrospectionSupport()) - GTEST_SKIP(); - auto AST = buildASTFromCode("void foo() {} void bar() { foo(); }", "foo.cpp", - std::make_shared()); - auto &Ctx = AST->getASTContext(); - auto &TU = *Ctx.getTranslationUnitDecl(); - - auto BoundNodes = ast_matchers::match( - decl(hasDescendant( - callExpr(callee(functionDecl(hasName("foo")))).bind("fooCall"))), - TU, Ctx); - - EXPECT_EQ(BoundNodes.size(), 1u); - - auto *FooCall = BoundNodes[0].getNodeAs("fooCall"); - - auto Result = NodeIntrospection::GetLocations(FooCall); - - auto ExpectedLocations = - FormatExpected(Result.LocationAccessors); - - EXPECT_THAT( - ExpectedLocations, - UnorderedElementsAre(STRING_LOCATION_PAIR(FooCall, getBeginLoc()), - STRING_LOCATION_PAIR(FooCall, getEndLoc()), - STRING_LOCATION_PAIR(FooCall, getExprLoc()), - STRING_LOCATION_PAIR(FooCall, getRParenLoc()))); - - auto ExpectedRanges = FormatExpected(Result.RangeAccessors); - - EXPECT_THAT(ExpectedRanges, UnorderedElementsAre(STRING_LOCATION_PAIR( - FooCall, getSourceRange()))); -} - -TEST(Introspection, SourceLocations_Decl) { - if (!NodeIntrospection::hasIntrospectionSupport()) - GTEST_SKIP(); - auto AST = - buildASTFromCode(R"cpp( -namespace ns1 { -namespace ns2 { -template struct Foo {}; -template struct Bar { - struct Nested { - template - Foo method(int i, bool b) const noexcept(true); - }; -}; -} // namespace ns2 -} // namespace ns1 - -template -template -ns1::ns2::Foo ns1::ns2::Bar::Nested::method(int i, bool b) const - noexcept(true) {} -)cpp", - "foo.cpp", std::make_shared()); - auto &Ctx = AST->getASTContext(); - auto &TU = *Ctx.getTranslationUnitDecl(); - - auto BoundNodes = ast_matchers::match( - decl(hasDescendant( - cxxMethodDecl(hasName("method"), isDefinition()).bind("method"))), - TU, Ctx); - - EXPECT_EQ(BoundNodes.size(), 1u); - - const auto *MethodDecl = BoundNodes[0].getNodeAs("method"); - - auto Result = NodeIntrospection::GetLocations(MethodDecl); - - auto ExpectedLocations = - FormatExpected(Result.LocationAccessors); - - llvm::sort(ExpectedLocations); - - // clang-format off - std::vector> ActualLocations{ -STRING_LOCATION_STDPAIR(MethodDecl, getBeginLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getBodyRBrace()), -STRING_LOCATION_STDPAIR(MethodDecl, getEndLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getInnerLocStart()), -STRING_LOCATION_STDPAIR(MethodDecl, getLocation()), -STRING_LOCATION_STDPAIR(MethodDecl, getNameInfo().getBeginLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getNameInfo().getEndLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getNameInfo().getLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getOuterLocStart()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getBeginLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getEndLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getLocalBeginLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getLocalEndLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getBeginLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getEndLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getLocalBeginLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getLocalEndLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getPrefix().getBeginLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getPrefix().getEndLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getPrefix().getLocalBeginLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getPrefix().getLocalEndLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getPrefix().getPrefix().getBeginLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getPrefix().getPrefix().getEndLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getPrefix().getPrefix().getLocalBeginLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getPrefix().getPrefix().getLocalEndLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getTypeLoc().getAs().getLAngleLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getTypeLoc().getAs().getRAngleLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getTypeLoc().getAs().getTemplateNameLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getTypeLoc().getBeginLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getTypeLoc().getEndLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getTypeLoc().getAs().getNameLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getTypeLoc().getBeginLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getTypeLoc().getEndLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getLParenLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getLocalRangeBegin()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getLocalRangeEnd()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getRParenLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getReturnLoc().getAs().getNamedTypeLoc().getAs().getLAngleLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getReturnLoc().getAs().getNamedTypeLoc().getAs().getRAngleLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getReturnLoc().getAs().getNamedTypeLoc().getAs().getTemplateNameLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getReturnLoc().getAs().getNamedTypeLoc().getBeginLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getReturnLoc().getAs().getNamedTypeLoc().getEndLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getReturnLoc().getAs().getQualifierLoc().getBeginLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getReturnLoc().getAs().getQualifierLoc().getEndLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getReturnLoc().getAs().getQualifierLoc().getLocalBeginLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getReturnLoc().getAs().getQualifierLoc().getLocalEndLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getReturnLoc().getAs().getQualifierLoc().getPrefix().getBeginLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getReturnLoc().getAs().getQualifierLoc().getPrefix().getEndLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getReturnLoc().getAs().getQualifierLoc().getPrefix().getLocalBeginLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getReturnLoc().getAs().getQualifierLoc().getPrefix().getLocalEndLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getReturnLoc().getBeginLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getReturnLoc().getEndLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getReturnLoc().getNextTypeLoc().getAs().getLAngleLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getReturnLoc().getNextTypeLoc().getAs().getRAngleLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getReturnLoc().getNextTypeLoc().getAs().getTemplateNameLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getReturnLoc().getNextTypeLoc().getBeginLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getReturnLoc().getNextTypeLoc().getEndLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getBeginLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getEndLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs().getNamedTypeLoc().getAs().getLAngleLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs().getNamedTypeLoc().getAs().getRAngleLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs().getNamedTypeLoc().getAs().getTemplateNameLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs().getNamedTypeLoc().getBeginLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs().getNamedTypeLoc().getEndLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs().getQualifierLoc().getBeginLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs().getQualifierLoc().getEndLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs().getQualifierLoc().getLocalBeginLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs().getQualifierLoc().getLocalEndLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs().getQualifierLoc().getPrefix().getBeginLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs().getQualifierLoc().getPrefix().getEndLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs().getQualifierLoc().getPrefix().getLocalBeginLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs().getQualifierLoc().getPrefix().getLocalEndLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getBeginLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getEndLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getNextTypeLoc().getAs().getLAngleLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getNextTypeLoc().getAs().getRAngleLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getNextTypeLoc().getAs().getTemplateNameLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getNextTypeLoc().getBeginLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getNextTypeLoc().getEndLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSpecEndLoc()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSpecStartLoc()) - }; - // clang-format on - - EXPECT_EQ(ExpectedLocations, ActualLocations); - - auto ExpectedRanges = FormatExpected(Result.RangeAccessors); - - llvm::sort(ExpectedRanges, [](const auto &LHS, const auto &RHS) { - return LHS.first < RHS.first; - }); - - // clang-format off - EXPECT_EQ( - llvm::ArrayRef(ExpectedRanges), - (ArrayRef>{ -STRING_LOCATION_STDPAIR(MethodDecl, getExceptionSpecSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getNameInfo().getSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getParametersSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getLocalSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getLocalSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getPrefix().getLocalSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getPrefix().getPrefix().getLocalSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getPrefix().getPrefix().getSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getPrefix().getSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getTypeLoc().getLocalSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getTypeLoc().getSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getTypeLoc().getLocalSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getTypeLoc().getSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getReturnTypeSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getExceptionSpecRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getParensRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getReturnLoc().getAs().getNamedTypeLoc().getLocalSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getReturnLoc().getAs().getNamedTypeLoc().getSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getReturnLoc().getAs().getQualifierLoc().getLocalSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getReturnLoc().getAs().getQualifierLoc().getPrefix().getLocalSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getReturnLoc().getAs().getQualifierLoc().getPrefix().getSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getReturnLoc().getAs().getQualifierLoc().getSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getReturnLoc().getLocalSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getReturnLoc().getNextTypeLoc().getLocalSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getReturnLoc().getNextTypeLoc().getSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs().getReturnLoc().getSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getLocalSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs().getNamedTypeLoc().getLocalSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs().getNamedTypeLoc().getSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs().getQualifierLoc().getLocalSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs().getQualifierLoc().getPrefix().getLocalSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs().getQualifierLoc().getPrefix().getSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs().getQualifierLoc().getSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getLocalSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getNextTypeLoc().getLocalSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getNextTypeLoc().getSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getSourceRange()), -STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getSourceRange()) - })); - // clang-format on -} - -TEST(Introspection, SourceLocations_NNS) { - if (!NodeIntrospection::hasIntrospectionSupport()) - GTEST_SKIP(); - auto AST = - buildASTFromCode(R"cpp( -namespace ns -{ - struct A { - void foo(); -}; -} -void ns::A::foo() {} -)cpp", - "foo.cpp", std::make_shared()); - auto &Ctx = AST->getASTContext(); - auto &TU = *Ctx.getTranslationUnitDecl(); - - auto BoundNodes = ast_matchers::match( - decl(hasDescendant(nestedNameSpecifierLoc().bind("nns"))), TU, Ctx); - - EXPECT_EQ(BoundNodes.size(), 1u); - - const auto *NNS = BoundNodes[0].getNodeAs("nns"); - - auto Result = NodeIntrospection::GetLocations(*NNS); - - auto ExpectedLocations = - FormatExpected(Result.LocationAccessors); - - llvm::sort(ExpectedLocations); - - EXPECT_EQ( - llvm::ArrayRef(ExpectedLocations), - (ArrayRef>{ - STRING_LOCATION_STDPAIR(NNS, getBeginLoc()), - STRING_LOCATION_STDPAIR(NNS, getEndLoc()), - STRING_LOCATION_STDPAIR(NNS, getLocalBeginLoc()), - STRING_LOCATION_STDPAIR(NNS, getLocalEndLoc()), - STRING_LOCATION_STDPAIR(NNS, getPrefix().getBeginLoc()), - STRING_LOCATION_STDPAIR(NNS, getPrefix().getEndLoc()), - STRING_LOCATION_STDPAIR(NNS, getPrefix().getLocalBeginLoc()), - STRING_LOCATION_STDPAIR(NNS, getPrefix().getLocalEndLoc()), - STRING_LOCATION_STDPAIR( - NNS, getTypeLoc().getAs().getNameLoc()), - STRING_LOCATION_STDPAIR(NNS, getTypeLoc().getBeginLoc()), - STRING_LOCATION_STDPAIR(NNS, getTypeLoc().getEndLoc())})); - - auto ExpectedRanges = FormatExpected(Result.RangeAccessors); - - EXPECT_THAT( - ExpectedRanges, - UnorderedElementsAre( - STRING_LOCATION_PAIR(NNS, getPrefix().getLocalSourceRange()), - STRING_LOCATION_PAIR(NNS, getPrefix().getSourceRange()), - STRING_LOCATION_PAIR(NNS, getLocalSourceRange()), - STRING_LOCATION_PAIR(NNS, getSourceRange()), - STRING_LOCATION_PAIR(NNS, getTypeLoc().getSourceRange()), - STRING_LOCATION_PAIR(NNS, getTypeLoc().getLocalSourceRange()))); -} - -TEST(Introspection, SourceLocations_TA_Type) { - if (!NodeIntrospection::hasIntrospectionSupport()) - GTEST_SKIP(); - auto AST = - buildASTFromCode(R"cpp( -template - struct A { - void foo(); -}; - -void foo() -{ - A a; -} -)cpp", - "foo.cpp", std::make_shared()); - auto &Ctx = AST->getASTContext(); - auto &TU = *Ctx.getTranslationUnitDecl(); - - auto BoundNodes = ast_matchers::match( - decl(hasDescendant(templateArgumentLoc().bind("ta"))), TU, Ctx); - - EXPECT_EQ(BoundNodes.size(), 1u); - - const auto *TA = BoundNodes[0].getNodeAs("ta"); - - auto Result = NodeIntrospection::GetLocations(*TA); - - auto ExpectedLocations = - FormatExpected(Result.LocationAccessors); - - // clang-format off - EXPECT_THAT(ExpectedLocations, - UnorderedElementsAre( -STRING_LOCATION_PAIR(TA, getLocation()), -STRING_LOCATION_PAIR(TA, - getTypeSourceInfo()->getTypeLoc().getAs().getBuiltinLoc()), -STRING_LOCATION_PAIR(TA, - getTypeSourceInfo()->getTypeLoc().getAs().getNameLoc()), -STRING_LOCATION_PAIR( - TA, getTypeSourceInfo()->getTypeLoc().getBeginLoc()), -STRING_LOCATION_PAIR( - TA, getTypeSourceInfo()->getTypeLoc().getEndLoc()) - )); - // clang-format on - - auto ExpectedRanges = FormatExpected(Result.RangeAccessors); - - EXPECT_THAT( - ExpectedRanges, - UnorderedElementsAre( - STRING_LOCATION_PAIR(TA, getSourceRange()), - STRING_LOCATION_PAIR( - TA, getTypeSourceInfo()->getTypeLoc().getSourceRange()), - STRING_LOCATION_PAIR( - TA, getTypeSourceInfo()->getTypeLoc().getLocalSourceRange()))); -} - -TEST(Introspection, SourceLocations_TA_Decl) { - if (!NodeIntrospection::hasIntrospectionSupport()) - GTEST_SKIP(); - auto AST = - buildASTFromCode(R"cpp( -template -void test2() {} -void doNothing() {} -void test() { - test2(); -} -)cpp", - "foo.cpp", std::make_shared()); - auto &Ctx = AST->getASTContext(); - auto &TU = *Ctx.getTranslationUnitDecl(); - - auto BoundNodes = ast_matchers::match( - decl(hasDescendant(templateArgumentLoc().bind("ta"))), TU, Ctx); - - EXPECT_EQ(BoundNodes.size(), 1u); - - const auto *TA = BoundNodes[0].getNodeAs("ta"); - - auto Result = NodeIntrospection::GetLocations(*TA); - - auto ExpectedLocations = - FormatExpected(Result.LocationAccessors); - - EXPECT_THAT(ExpectedLocations, - UnorderedElementsAre(STRING_LOCATION_PAIR(TA, getLocation()))); - - auto ExpectedRanges = FormatExpected(Result.RangeAccessors); - - EXPECT_THAT(ExpectedRanges, - UnorderedElementsAre(STRING_LOCATION_PAIR(TA, getSourceRange()))); -} - -TEST(Introspection, SourceLocations_TA_Nullptr) { - if (!NodeIntrospection::hasIntrospectionSupport()) - GTEST_SKIP(); - auto AST = - buildASTFromCode(R"cpp( -template -void test2() {} -void doNothing() {} -void test() { - test2(); -} -)cpp", - "foo.cpp", std::make_shared()); - auto &Ctx = AST->getASTContext(); - auto &TU = *Ctx.getTranslationUnitDecl(); - - auto BoundNodes = ast_matchers::match( - decl(hasDescendant(templateArgumentLoc().bind("ta"))), TU, Ctx); - - EXPECT_EQ(BoundNodes.size(), 1u); - - const auto *TA = BoundNodes[0].getNodeAs("ta"); - - auto Result = NodeIntrospection::GetLocations(*TA); - - auto ExpectedLocations = - FormatExpected(Result.LocationAccessors); - - EXPECT_THAT(ExpectedLocations, - UnorderedElementsAre(STRING_LOCATION_PAIR(TA, getLocation()))); - - auto ExpectedRanges = FormatExpected(Result.RangeAccessors); - - EXPECT_THAT(ExpectedRanges, - UnorderedElementsAre(STRING_LOCATION_PAIR(TA, getSourceRange()))); -} - -TEST(Introspection, SourceLocations_TA_Integral) { - if (!NodeIntrospection::hasIntrospectionSupport()) - GTEST_SKIP(); - auto AST = - buildASTFromCode(R"cpp( -template -void test2() {} -void test() { - test2<42>(); -} -)cpp", - "foo.cpp", std::make_shared()); - auto &Ctx = AST->getASTContext(); - auto &TU = *Ctx.getTranslationUnitDecl(); - - auto BoundNodes = ast_matchers::match( - decl(hasDescendant(templateArgumentLoc().bind("ta"))), TU, Ctx); - - EXPECT_EQ(BoundNodes.size(), 1u); - - const auto *TA = BoundNodes[0].getNodeAs("ta"); - - auto Result = NodeIntrospection::GetLocations(*TA); - - auto ExpectedLocations = - FormatExpected(Result.LocationAccessors); - - EXPECT_THAT(ExpectedLocations, - UnorderedElementsAre(STRING_LOCATION_PAIR(TA, getLocation()))); - - auto ExpectedRanges = FormatExpected(Result.RangeAccessors); - - EXPECT_THAT(ExpectedRanges, - UnorderedElementsAre(STRING_LOCATION_PAIR(TA, getSourceRange()))); -} - -TEST(Introspection, SourceLocations_TA_Template) { - if (!NodeIntrospection::hasIntrospectionSupport()) - GTEST_SKIP(); - auto AST = - buildASTFromCode(R"cpp( -template class A; -template