aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/clang16/lib/Tooling/DumpTool/ASTSrcLocProcessor.cpp
diff options
context:
space:
mode:
authorthegeorg <thegeorg@yandex-team.com>2024-03-13 13:58:24 +0300
committerthegeorg <thegeorg@yandex-team.com>2024-03-13 14:11:53 +0300
commit11a895b7e15d1c5a1f52706396b82e3f9db953cb (patch)
treefabc6d883b0f946151f61ae7865cee9f529a1fdd /contrib/libs/clang16/lib/Tooling/DumpTool/ASTSrcLocProcessor.cpp
parent9685917341315774aad5733b1793b1e533a88bbb (diff)
downloadydb-11a895b7e15d1c5a1f52706396b82e3f9db953cb.tar.gz
Export clang-format16 via ydblib project
6e6be3a95868fde888d801b7590af4044049563f
Diffstat (limited to 'contrib/libs/clang16/lib/Tooling/DumpTool/ASTSrcLocProcessor.cpp')
-rw-r--r--contrib/libs/clang16/lib/Tooling/DumpTool/ASTSrcLocProcessor.cpp271
1 files changed, 271 insertions, 0 deletions
diff --git a/contrib/libs/clang16/lib/Tooling/DumpTool/ASTSrcLocProcessor.cpp b/contrib/libs/clang16/lib/Tooling/DumpTool/ASTSrcLocProcessor.cpp
new file mode 100644
index 0000000000..42691d556d
--- /dev/null
+++ b/contrib/libs/clang16/lib/Tooling/DumpTool/ASTSrcLocProcessor.cpp
@@ -0,0 +1,271 @@
+//===- 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<MatchFinder>(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<clang::ASTConsumer>
+ASTSrcLocProcessor::createASTConsumer(clang::CompilerInstance &Compiler,
+ StringRef File) {
+ return Finder->newASTConsumer();
+}
+
+llvm::json::Object toJSON(llvm::StringMap<std::vector<StringRef>> 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<std::string> 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<ClassData> 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<std::string>
+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<std::string> Methods;
+ for (const auto &BN : BoundNodesVec) {
+ if (const auto *Node = BN.getNodeAs<clang::NamedDecl>("classMethod")) {
+ const auto *StmtOrDeclBase =
+ BN.getNodeAs<clang::CXXRecordDecl>("stmtOrDeclBase");
+ const auto *TypeLocBase =
+ BN.getNodeAs<clang::CXXRecordDecl>("typeLocBase");
+ const auto *ExprBase = BN.getNodeAs<clang::CXXRecordDecl>("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<clang::CXXRecordDecl>("className");
+
+ StringRef CladeName;
+ if (ASTClass) {
+ if (const auto *NodeClade =
+ Result.Nodes.getNodeAs<clang::CXXRecordDecl>("nodeClade"))
+ CladeName = NodeClade->getName();
+ } else {
+ ASTClass = Result.Nodes.getNodeAs<clang::CXXRecordDecl>("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<clang::CXXRecordDecl>("derivedFrom")) {
+
+ if (const auto *Templ =
+ llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(
+ 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);
+}