diff options
author | thegeorg <thegeorg@yandex-team.com> | 2024-03-13 13:58:24 +0300 |
---|---|---|
committer | thegeorg <thegeorg@yandex-team.com> | 2024-03-13 14:11:53 +0300 |
commit | 11a895b7e15d1c5a1f52706396b82e3f9db953cb (patch) | |
tree | fabc6d883b0f946151f61ae7865cee9f529a1fdd /contrib/libs/clang16/lib/Tooling/DumpTool/ASTSrcLocProcessor.cpp | |
parent | 9685917341315774aad5733b1793b1e533a88bbb (diff) | |
download | ydb-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.cpp | 271 |
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); +} |