From 4c65dfc895d03d1c3bfa1ccfe9567c9ea8557492 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Wed, 17 Mar 2021 22:56:39 +0000 Subject: [PATCH] [AST] Add introspection support for Decls The test code has lots of interesting locations which are not yet introspected, but those will come later: http://ce.steveire.com/z/3T90hR Differential Revision: https://reviews.llvm.org/D98775 --- clang/include/clang/Tooling/NodeIntrospection.h | 2 + clang/lib/Tooling/CMakeLists.txt | 3 + clang/lib/Tooling/DumpTool/ASTSrcLocProcessor.cpp | 3 +- .../lib/Tooling/DumpTool/generate_cxx_src_locs.py | 3 + .../unittests/Introspection/IntrospectionTest.cpp | 68 +++++++++++++++++++++- 5 files changed, 77 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/Tooling/NodeIntrospection.h b/clang/include/clang/Tooling/NodeIntrospection.h index abaa58b..3b40e68 100644 --- a/clang/include/clang/Tooling/NodeIntrospection.h +++ b/clang/include/clang/Tooling/NodeIntrospection.h @@ -22,6 +22,7 @@ namespace clang { class Stmt; +class Decl; namespace tooling { @@ -78,6 +79,7 @@ struct NodeLocationAccessors { namespace NodeIntrospection { NodeLocationAccessors GetLocations(clang::Stmt const *Object); +NodeLocationAccessors GetLocations(clang::Decl const *Object); NodeLocationAccessors GetLocations(clang::DynTypedNode const &Node); } // namespace NodeIntrospection } // namespace tooling diff --git a/clang/lib/Tooling/CMakeLists.txt b/clang/lib/Tooling/CMakeLists.txt index e820f63..0a6fb99 100644 --- a/clang/lib/Tooling/CMakeLists.txt +++ b/clang/lib/Tooling/CMakeLists.txt @@ -40,6 +40,9 @@ namespace tooling { NodeLocationAccessors NodeIntrospection::GetLocations(clang::Stmt const *) { return {}; } +NodeLocationAccessors NodeIntrospection::GetLocations(clang::Decl const *) { + return {}; +} NodeLocationAccessors NodeIntrospection::GetLocations(clang::DynTypedNode const &) { return {}; diff --git a/clang/lib/Tooling/DumpTool/ASTSrcLocProcessor.cpp b/clang/lib/Tooling/DumpTool/ASTSrcLocProcessor.cpp index e7400e9..d611261 100644 --- a/clang/lib/Tooling/DumpTool/ASTSrcLocProcessor.cpp +++ b/clang/lib/Tooling/DumpTool/ASTSrcLocProcessor.cpp @@ -26,7 +26,8 @@ ASTSrcLocProcessor::ASTSrcLocProcessor(StringRef JsonPath) isDefinition(), isSameOrDerivedFrom( // TODO: Extend this with other clades - namedDecl(hasName("clang::Stmt")).bind("nodeClade")), + namedDecl(hasAnyName("clang::Stmt", "clang::Decl")) + .bind("nodeClade")), optionally(isDerivedFrom(cxxRecordDecl().bind("derivedFrom")))) .bind("className"), this); diff --git a/clang/lib/Tooling/DumpTool/generate_cxx_src_locs.py b/clang/lib/Tooling/DumpTool/generate_cxx_src_locs.py index b4d31d3..15a373e 100755 --- a/clang/lib/Tooling/DumpTool/generate_cxx_src_locs.py +++ b/clang/lib/Tooling/DumpTool/generate_cxx_src_locs.py @@ -177,6 +177,9 @@ namespace tooling { NodeLocationAccessors NodeIntrospection::GetLocations(clang::Stmt const *) { return {}; } +NodeLocationAccessors NodeIntrospection::GetLocations(clang::Decl const *) { + return {}; +} NodeLocationAccessors NodeIntrospection::GetLocations(clang::DynTypedNode const &) { return {}; diff --git a/clang/unittests/Introspection/IntrospectionTest.cpp b/clang/unittests/Introspection/IntrospectionTest.cpp index a1280d9..5e32d7d 100644 --- a/clang/unittests/Introspection/IntrospectionTest.cpp +++ b/clang/unittests/Introspection/IntrospectionTest.cpp @@ -42,7 +42,7 @@ FormatExpected(const MapType &Accessors) { #define STRING_LOCATION_PAIR(INSTANCE, LOC) Pair(#LOC, INSTANCE->LOC) -TEST(Introspection, SourceLocations) { +TEST(Introspection, SourceLocations_Stmt) { auto AST = buildASTFromCode("void foo() {} void bar() { foo(); }", "foo.cpp", std::make_shared()); auto &Ctx = AST->getASTContext(); @@ -79,3 +79,69 @@ TEST(Introspection, SourceLocations) { EXPECT_THAT(ExpectedRanges, UnorderedElementsAre(STRING_LOCATION_PAIR( FooCall, getSourceRange()))); } + +TEST(Introspection, SourceLocations_Decl) { + 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")).bind("method"))), + TU, Ctx); + + EXPECT_EQ(BoundNodes.size(), 1u); + + const auto *MethodDecl = BoundNodes[0].getNodeAs("method"); + + auto Result = NodeIntrospection::GetLocations(MethodDecl); + + if (Result.LocationAccessors.empty() && Result.RangeAccessors.empty()) { + return; + } + + auto ExpectedLocations = + FormatExpected(Result.LocationAccessors); + + EXPECT_THAT(ExpectedLocations, + UnorderedElementsAre( + STRING_LOCATION_PAIR(MethodDecl, getBeginLoc()), + STRING_LOCATION_PAIR(MethodDecl, getBodyRBrace()), + STRING_LOCATION_PAIR(MethodDecl, getEllipsisLoc()), + STRING_LOCATION_PAIR(MethodDecl, getInnerLocStart()), + STRING_LOCATION_PAIR(MethodDecl, getLocation()), + STRING_LOCATION_PAIR(MethodDecl, getOuterLocStart()), + STRING_LOCATION_PAIR(MethodDecl, getPointOfInstantiation()), + STRING_LOCATION_PAIR(MethodDecl, getTypeSpecEndLoc()), + STRING_LOCATION_PAIR(MethodDecl, getTypeSpecStartLoc()), + STRING_LOCATION_PAIR(MethodDecl, getEndLoc()))); + + auto ExpectedRanges = FormatExpected(Result.RangeAccessors); + + EXPECT_THAT( + ExpectedRanges, + UnorderedElementsAre( + STRING_LOCATION_PAIR(MethodDecl, getExceptionSpecSourceRange()), + STRING_LOCATION_PAIR(MethodDecl, getParametersSourceRange()), + STRING_LOCATION_PAIR(MethodDecl, getReturnTypeSourceRange()), + STRING_LOCATION_PAIR(MethodDecl, getSourceRange()))); +} -- 2.7.4