Author: Stephen Kelly Date: 2021-04-25T12:12:04+01:00 New Revision: 8d018c79ee5f14e1433b8cbb02dd89d0941516ff
URL: https://github.com/llvm/llvm-project/commit/8d018c79ee5f14e1433b8cbb02dd89d0941516ff DIFF: https://github.com/llvm/llvm-project/commit/8d018c79ee5f14e1433b8cbb02dd89d0941516ff.diff LOG: Add srcloc output to clang-query Differential Revision: https://reviews.llvm.org/D93325 Added: Modified: clang-tools-extra/clang-query/CMakeLists.txt clang-tools-extra/clang-query/Query.cpp clang-tools-extra/clang-query/Query.h clang-tools-extra/clang-query/QueryParser.cpp clang-tools-extra/clang-query/QuerySession.h clang-tools-extra/unittests/clang-query/QueryParserTest.cpp Removed: ################################################################################ diff --git a/clang-tools-extra/clang-query/CMakeLists.txt b/clang-tools-extra/clang-query/CMakeLists.txt index 043d26147a7f..8355ef0aba5e 100644 --- a/clang-tools-extra/clang-query/CMakeLists.txt +++ b/clang-tools-extra/clang-query/CMakeLists.txt @@ -19,6 +19,7 @@ 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 5cf24dbb58a7..2c169b1f9a7f 100644 --- a/clang-tools-extra/clang-query/Query.cpp +++ b/clang-tools-extra/clang-query/Query.cpp @@ -12,6 +12,7 @@ #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" using namespace clang::ast_matchers; @@ -66,6 +67,8 @@ 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; @@ -86,6 +89,90 @@ 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<std::string> 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", None, None); + + 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), None); + + 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), None); + + 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())), + None); + + Iter = PrintLocations(OS, Iter, Locs.RangeAccessors.end()); + } + OS << "\n"; +} + } // namespace bool MatchQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const { @@ -106,8 +193,10 @@ bool MatchQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const { return false; } - AST->getASTContext().getParentMapContext().setTraversalKind(QS.TK); - Finder.matchAST(AST->getASTContext()); + auto &Ctx = AST->getASTContext(); + const auto &SM = Ctx.getSourceManager(); + Ctx.getParentMapContext().setTraversalKind(QS.TK); + Finder.matchAST(Ctx); if (QS.PrintMatcher) { SmallVector<StringRef, 4> Lines; @@ -159,6 +248,13 @@ bool MatchQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const { 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 4c95195d96c1..38be29101c96 100644 --- a/clang-tools-extra/clang-query/Query.h +++ b/clang-tools-extra/clang-query/Query.h @@ -18,7 +18,7 @@ namespace clang { namespace query { -enum OutputKind { OK_Diag, OK_Print, OK_DetailedAST }; +enum OutputKind { OK_Diag, OK_Print, OK_DetailedAST, OK_SrcLoc }; enum QueryKind { QK_Invalid, diff --git a/clang-tools-extra/clang-query/QueryParser.cpp b/clang-tools-extra/clang-query/QueryParser.cpp index b01d8001b669..b444162cfc0a 100644 --- a/clang-tools-extra/clang-query/QueryParser.cpp +++ b/clang-tools-extra/clang-query/QueryParser.cpp @@ -108,6 +108,7 @@ template <typename QueryType> QueryRef QueryParser::parseSetOutputKind() { .Case("diag", OK_Diag) .Case("print", OK_Print) .Case("detailed-ast", OK_DetailedAST) + .Case("srcloc", OK_SrcLoc) .Case("dump", OK_DetailedAST) .Default(~0u); if (OutKind == ~0u) { @@ -123,6 +124,8 @@ template <typename QueryType> QueryRef QueryParser::parseSetOutputKind() { return new QueryType(&QuerySession::DiagOutput); case OK_Print: return new QueryType(&QuerySession::PrintOutput); + case OK_SrcLoc: + return new QueryType(&QuerySession::SrcLocOutput); } llvm_unreachable("Invalid output kind"); diff --git a/clang-tools-extra/clang-query/QuerySession.h b/clang-tools-extra/clang-query/QuerySession.h index 31a4900e2619..9a08289a2534 100644 --- a/clang-tools-extra/clang-query/QuerySession.h +++ b/clang-tools-extra/clang-query/QuerySession.h @@ -25,14 +25,15 @@ class QuerySession { public: QuerySession(llvm::ArrayRef<std::unique_ptr<ASTUnit>> ASTs) : ASTs(ASTs), PrintOutput(false), DiagOutput(true), - DetailedASTOutput(false), BindRoot(true), PrintMatcher(false), - Terminate(false), TK(TK_AsIs) {} + DetailedASTOutput(false), SrcLocOutput(false), BindRoot(true), + PrintMatcher(false), Terminate(false), TK(TK_AsIs) {} llvm::ArrayRef<std::unique_ptr<ASTUnit>> ASTs; bool PrintOutput; bool DiagOutput; bool DetailedASTOutput; + bool SrcLocOutput; bool BindRoot; bool PrintMatcher; diff --git a/clang-tools-extra/unittests/clang-query/QueryParserTest.cpp b/clang-tools-extra/unittests/clang-query/QueryParserTest.cpp index 76ab85680b9f..713a6c23848a 100644 --- a/clang-tools-extra/unittests/clang-query/QueryParserTest.cpp +++ b/clang-tools-extra/unittests/clang-query/QueryParserTest.cpp @@ -218,7 +218,7 @@ TEST_F(QueryParserTest, Complete) { EXPECT_EQ("output", Comps[0].DisplayText); Comps = QueryParser::complete("enable output ", 14, QS); - ASSERT_EQ(4u, Comps.size()); + ASSERT_EQ(5u, Comps.size()); EXPECT_EQ("diag ", Comps[0].TypedText); EXPECT_EQ("diag", Comps[0].DisplayText); @@ -226,8 +226,10 @@ TEST_F(QueryParserTest, Complete) { EXPECT_EQ("print", Comps[1].DisplayText); EXPECT_EQ("detailed-ast ", Comps[2].TypedText); EXPECT_EQ("detailed-ast", Comps[2].DisplayText); - EXPECT_EQ("dump ", Comps[3].TypedText); - EXPECT_EQ("dump", Comps[3].DisplayText); + EXPECT_EQ("srcloc ", Comps[3].TypedText); + EXPECT_EQ("srcloc", Comps[3].DisplayText); + EXPECT_EQ("dump ", Comps[4].TypedText); + EXPECT_EQ("dump", Comps[4].DisplayText); Comps = QueryParser::complete("set traversal ", 14, QS); ASSERT_EQ(2u, Comps.size()); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits