Author: Stephen Kelly Date: 2021-04-25T12:12:03+01:00 New Revision: a9676febb99d54289117a497c3fea4ba35cef2b4
URL: https://github.com/llvm/llvm-project/commit/a9676febb99d54289117a497c3fea4ba35cef2b4 DIFF: https://github.com/llvm/llvm-project/commit/a9676febb99d54289117a497c3fea4ba35cef2b4.diff LOG: [AST] Add DeclarationNameInfo to node introspection Differential Revision: https://reviews.llvm.org/D101049 Added: Modified: clang/include/clang/Tooling/NodeIntrospection.h clang/lib/Tooling/DumpTool/APIData.h clang/lib/Tooling/DumpTool/ASTSrcLocProcessor.cpp clang/lib/Tooling/DumpTool/generate_cxx_src_locs.py clang/lib/Tooling/EmptyNodeIntrospection.inc.in clang/unittests/Introspection/IntrospectionTest.cpp Removed: ################################################################################ diff --git a/clang/include/clang/Tooling/NodeIntrospection.h b/clang/include/clang/Tooling/NodeIntrospection.h index 7e0d5e8d14f5..91552cad2eca 100644 --- a/clang/include/clang/Tooling/NodeIntrospection.h +++ b/clang/include/clang/Tooling/NodeIntrospection.h @@ -26,6 +26,7 @@ class CXXCtorInitializer; class NestedNameSpecifierLoc; class TemplateArgumentLoc; class CXXBaseSpecifier; +struct DeclarationNameInfo; namespace tooling { @@ -92,6 +93,7 @@ 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 diff --git a/clang/lib/Tooling/DumpTool/APIData.h b/clang/lib/Tooling/DumpTool/APIData.h index ada19d6f1e46..03e247a8bd95 100644 --- a/clang/lib/Tooling/DumpTool/APIData.h +++ b/clang/lib/Tooling/DumpTool/APIData.h @@ -22,7 +22,7 @@ struct ClassData { std::vector<std::string> TypeSourceInfos; std::vector<std::string> TypeLocs; std::vector<std::string> NestedNameLocs; - // TODO: Extend this with locations available via typelocs etc. + std::vector<std::string> DeclNameInfos; }; } // namespace tooling diff --git a/clang/lib/Tooling/DumpTool/ASTSrcLocProcessor.cpp b/clang/lib/Tooling/DumpTool/ASTSrcLocProcessor.cpp index dcad05745eca..0aeb3a7703f7 100644 --- a/clang/lib/Tooling/DumpTool/ASTSrcLocProcessor.cpp +++ b/clang/lib/Tooling/DumpTool/ASTSrcLocProcessor.cpp @@ -23,19 +23,18 @@ ASTSrcLocProcessor::ASTSrcLocProcessor(StringRef JsonPath) Finder = std::make_unique<MatchFinder>(std::move(FinderOptions)); Finder->addMatcher( - cxxRecordDecl( - isDefinition(), - isSameOrDerivedFrom( - // TODO: Extend this with other clades - namedDecl(hasAnyName("clang::Stmt", "clang::Decl", - "clang::CXXCtorInitializer", - "clang::NestedNameSpecifierLoc", - "clang::TemplateArgumentLoc", - "clang::CXXBaseSpecifier", - "clang::TypeLoc")) - .bind("nodeClade")), - optionally(isDerivedFrom(cxxRecordDecl().bind("derivedFrom")))) - .bind("className"), + 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", @@ -85,6 +84,8 @@ llvm::json::Object toJSON(ClassData const &Obj) { JsonObj["typeLocs"] = Obj.TypeLocs; if (!Obj.NestedNameLocs.empty()) JsonObj["nestedNameLocs"] = Obj.NestedNameLocs; + if (!Obj.DeclNameInfos.empty()) + JsonObj["declNameInfos"] = Obj.DeclNameInfos; return JsonObj; } @@ -222,6 +223,8 @@ void ASTSrcLocProcessor::run(const MatchFinder::MatchResult &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); if (const auto *DerivedFrom = Result.Nodes.getNodeAs<clang::CXXRecordDecl>("derivedFrom")) { diff --git a/clang/lib/Tooling/DumpTool/generate_cxx_src_locs.py b/clang/lib/Tooling/DumpTool/generate_cxx_src_locs.py index 94795cfeb816..771da5d9c9f3 100755 --- a/clang/lib/Tooling/DumpTool/generate_cxx_src_locs.py +++ b/clang/lib/Tooling/DumpTool/generate_cxx_src_locs.py @@ -12,7 +12,10 @@ class Generator(object): implementationContent = '' - RefClades = {"NestedNameSpecifierLoc", "TemplateArgumentLoc", "TypeLoc"} + RefClades = {"DeclarationNameInfo", + "NestedNameSpecifierLoc", + "TemplateArgumentLoc", + "TypeLoc"} def __init__(self, templateClasses): self.templateClasses = templateClasses @@ -121,7 +124,8 @@ def GenerateSrcLocMethod(self, self.implementationContent += '\n' if 'typeLocs' in ClassData or 'typeSourceInfos' in ClassData \ - or 'nestedNameLocs' in ClassData: + or 'nestedNameLocs' in ClassData \ + or 'declNameInfos' in ClassData: if CreateLocalRecursionGuard: self.implementationContent += \ 'std::vector<clang::TypeLoc> TypeLocRecursionGuard;\n' @@ -165,6 +169,15 @@ def GenerateSrcLocMethod(self, Object.{0}(), Locs, Rngs, TypeLocRecursionGuard); """.format(NN) + if 'declNameInfos' in ClassData: + for declName in ClassData['declNameInfos']: + + self.implementationContent += \ + """ + GetLocationsImpl( + llvm::makeIntrusiveRefCnt<LocationCall>(Prefix, "{0}"), + Object.{0}(), Locs, Rngs, TypeLocRecursionGuard); + """.format(declName) self.implementationContent += '}\n' @@ -300,6 +313,8 @@ def GenerateDynNodeVisitor(self, CladeNames): + ' NodeIntrospection::' + Signature + '{' for CladeName in CladeNames: + if CladeName == "DeclarationNameInfo": + continue self.implementationContent += \ """ if (const auto *N = Node.get<{0}>()) @@ -376,10 +391,7 @@ def getCladeName(ClassName): cladeName = getCladeName(ClassName) g.GenerateSrcLocMethod( ClassName, ClassAccessors, - cladeName not in [ - 'NestedNameSpecifierLoc', - 'TemplateArgumentLoc', - 'TypeLoc']) + cladeName not in Generator.RefClades) for (CladeName, ClassNameData) in jsonData['classesInClade'].items(): g.GenerateBaseGetLocationsFunction( @@ -387,10 +399,7 @@ def getCladeName(ClassName): jsonData['classEntries'], CladeName, jsonData["classInheritance"], - CladeName not in [ - 'NestedNameSpecifierLoc', - 'TemplateArgumentLoc', - 'TypeLoc']) + CladeName not in Generator.RefClades) g.GenerateDynNodeVisitor(jsonData['classesInClade'].keys()) diff --git a/clang/lib/Tooling/EmptyNodeIntrospection.inc.in b/clang/lib/Tooling/EmptyNodeIntrospection.inc.in index 04a7647c6d19..2071c34cbd04 100644 --- a/clang/lib/Tooling/EmptyNodeIntrospection.inc.in +++ b/clang/lib/Tooling/EmptyNodeIntrospection.inc.in @@ -36,6 +36,10 @@ NodeLocationAccessors NodeIntrospection::GetLocations( clang::TypeLoc const&) { return {}; } +NodeLocationAccessors NodeIntrospection::GetLocations( + clang::DeclarationNameInfo const&) { + return {}; +} NodeLocationAccessors NodeIntrospection::GetLocations(clang::DynTypedNode const &) { return {}; diff --git a/clang/unittests/Introspection/IntrospectionTest.cpp b/clang/unittests/Introspection/IntrospectionTest.cpp index 62198f56ac7d..521520c9a7c7 100644 --- a/clang/unittests/Introspection/IntrospectionTest.cpp +++ b/clang/unittests/Introspection/IntrospectionTest.cpp @@ -216,6 +216,9 @@ 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()), @@ -305,6 +308,7 @@ STRING_LOCATION_STDPAIR(MethodDecl, getTypeSpecStartLoc()) llvm::makeArrayRef(ExpectedRanges), (ArrayRef<std::pair<std::string, SourceRange>>{ 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()), @@ -1395,3 +1399,142 @@ typeof (static_cast<void *>(0)) i; TL, getAs<clang::TypeOfExprTypeLoc>().getParensRange()))); } #endif + +TEST(Introspection, SourceLocations_DeclarationNameInfo_Dtor) { + if (!NodeIntrospection::hasIntrospectionSupport()) + return; + auto AST = + buildASTFromCode(R"cpp( +class Foo +{ + ~Foo() {} +}; +)cpp", + "foo.cpp", std::make_shared<PCHContainerOperations>()); + auto &Ctx = AST->getASTContext(); + auto &TU = *Ctx.getTranslationUnitDecl(); + + auto BoundNodes = ast_matchers::match( + decl(hasDescendant(cxxDestructorDecl(hasName("~Foo")).bind("dtor"))), TU, + Ctx); + + EXPECT_EQ(BoundNodes.size(), 1u); + + const auto *Dtor = BoundNodes[0].getNodeAs<CXXDestructorDecl>("dtor"); + auto NI = Dtor->getNameInfo(); + auto Result = NodeIntrospection::GetLocations(NI); + + auto ExpectedLocations = + FormatExpected<SourceLocation>(Result.LocationAccessors); + + llvm::sort(ExpectedLocations); + + // clang-format off + EXPECT_EQ( + llvm::makeArrayRef(ExpectedLocations), + (ArrayRef<std::pair<std::string, SourceLocation>>{ + STRING_LOCATION_STDPAIR((&NI), getBeginLoc()), + STRING_LOCATION_STDPAIR((&NI), getEndLoc()), + STRING_LOCATION_STDPAIR((&NI), getLoc()), + STRING_LOCATION_STDPAIR((&NI), +getNamedTypeInfo()->getTypeLoc().getAs<clang::TypeSpecTypeLoc>().getNameLoc()), + STRING_LOCATION_STDPAIR( + (&NI), getNamedTypeInfo()->getTypeLoc().getBeginLoc()), + STRING_LOCATION_STDPAIR( + (&NI), getNamedTypeInfo()->getTypeLoc().getEndLoc())})); + // clang-format on + + auto ExpectedRanges = FormatExpected<SourceRange>(Result.RangeAccessors); + + EXPECT_THAT( + ExpectedRanges, + UnorderedElementsAre( + STRING_LOCATION_PAIR( + (&NI), getNamedTypeInfo()->getTypeLoc().getLocalSourceRange()), + STRING_LOCATION_PAIR( + (&NI), getNamedTypeInfo()->getTypeLoc().getSourceRange()), + STRING_LOCATION_PAIR((&NI), getSourceRange()))); +} + +TEST(Introspection, SourceLocations_DeclarationNameInfo_ConvOp) { + if (!NodeIntrospection::hasIntrospectionSupport()) + return; + auto AST = + buildASTFromCode(R"cpp( +class Foo +{ + bool operator==(const Foo&) const { return false; } +}; +)cpp", + "foo.cpp", std::make_shared<PCHContainerOperations>()); + auto &Ctx = AST->getASTContext(); + auto &TU = *Ctx.getTranslationUnitDecl(); + + auto BoundNodes = ast_matchers::match( + decl(hasDescendant(cxxMethodDecl().bind("opeq"))), TU, Ctx); + + EXPECT_EQ(BoundNodes.size(), 1u); + + const auto *Opeq = BoundNodes[0].getNodeAs<CXXMethodDecl>("opeq"); + auto NI = Opeq->getNameInfo(); + auto Result = NodeIntrospection::GetLocations(NI); + + auto ExpectedLocations = + FormatExpected<SourceLocation>(Result.LocationAccessors); + + llvm::sort(ExpectedLocations); + + EXPECT_EQ(llvm::makeArrayRef(ExpectedLocations), + (ArrayRef<std::pair<std::string, SourceLocation>>{ + STRING_LOCATION_STDPAIR((&NI), getBeginLoc()), + STRING_LOCATION_STDPAIR((&NI), getEndLoc()), + STRING_LOCATION_STDPAIR((&NI), getLoc())})); + + auto ExpectedRanges = FormatExpected<SourceRange>(Result.RangeAccessors); + + EXPECT_THAT(ExpectedRanges, + UnorderedElementsAre( + STRING_LOCATION_PAIR((&NI), getSourceRange()), + STRING_LOCATION_PAIR((&NI), getCXXOperatorNameRange()))); +} + +TEST(Introspection, SourceLocations_DeclarationNameInfo_LitOp) { + if (!NodeIntrospection::hasIntrospectionSupport()) + return; + auto AST = + buildASTFromCode(R"cpp( +long double operator"" _identity ( long double val ) +{ + return val; +} +)cpp", + "foo.cpp", std::make_shared<PCHContainerOperations>()); + auto &Ctx = AST->getASTContext(); + auto &TU = *Ctx.getTranslationUnitDecl(); + + auto BoundNodes = ast_matchers::match( + decl(hasDescendant(functionDecl().bind("litop"))), TU, Ctx); + + EXPECT_EQ(BoundNodes.size(), 1u); + + const auto *LitOp = BoundNodes[0].getNodeAs<FunctionDecl>("litop"); + auto NI = LitOp->getNameInfo(); + auto Result = NodeIntrospection::GetLocations(NI); + + auto ExpectedLocations = + FormatExpected<SourceLocation>(Result.LocationAccessors); + + llvm::sort(ExpectedLocations); + + EXPECT_EQ(llvm::makeArrayRef(ExpectedLocations), + (ArrayRef<std::pair<std::string, SourceLocation>>{ + STRING_LOCATION_STDPAIR((&NI), getBeginLoc()), + STRING_LOCATION_STDPAIR((&NI), getCXXLiteralOperatorNameLoc()), + STRING_LOCATION_STDPAIR((&NI), getEndLoc()), + STRING_LOCATION_STDPAIR((&NI), getLoc())})); + + auto ExpectedRanges = FormatExpected<SourceRange>(Result.RangeAccessors); + + EXPECT_THAT(ExpectedRanges, UnorderedElementsAre(STRING_LOCATION_PAIR( + (&NI), getSourceRange()))); +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits