Author: PeterChou1 Date: 2024-07-25T02:03:20-04:00 New Revision: 1b7631a699e6af7f497548a1ceb5be0570c60ed0
URL: https://github.com/llvm/llvm-project/commit/1b7631a699e6af7f497548a1ceb5be0570c60ed0 DIFF: https://github.com/llvm/llvm-project/commit/1b7631a699e6af7f497548a1ceb5be0570c60ed0.diff LOG: [clang-doc] Improve clang-doc performance through memoization (#96809) Added: Modified: clang-tools-extra/clang-doc/Mapper.cpp clang-tools-extra/clang-doc/Mapper.h clang-tools-extra/clang-doc/tool/ClangDocMain.cpp Removed: ################################################################################ diff --git a/clang-tools-extra/clang-doc/Mapper.cpp b/clang-tools-extra/clang-doc/Mapper.cpp index bb8b7952980ac..6c90db03424c6 100644 --- a/clang-tools-extra/clang-doc/Mapper.cpp +++ b/clang-tools-extra/clang-doc/Mapper.cpp @@ -12,16 +12,28 @@ #include "clang/AST/Comment.h" #include "clang/Index/USRGeneration.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/Support/Error.h" +#include "llvm/ADT/StringSet.h" +#include "llvm/Support/Mutex.h" namespace clang { namespace doc { +static llvm::StringSet<> USRVisited; +static llvm::sys::Mutex USRVisitedGuard; + +template <typename T> bool isTypedefAnonRecord(const T *D) { + if (const auto *C = dyn_cast<CXXRecordDecl>(D)) { + return C->getTypedefNameForAnonDecl(); + } + return false; +} + void MapASTVisitor::HandleTranslationUnit(ASTContext &Context) { TraverseDecl(Context.getTranslationUnitDecl()); } -template <typename T> bool MapASTVisitor::mapDecl(const T *D) { +template <typename T> +bool MapASTVisitor::mapDecl(const T *D, bool IsDefinition) { // If we're looking a decl not in user files, skip this decl. if (D->getASTContext().getSourceManager().isInSystemHeader(D->getLocation())) return true; @@ -34,6 +46,16 @@ template <typename T> bool MapASTVisitor::mapDecl(const T *D) { // If there is an error generating a USR for the decl, skip this decl. if (index::generateUSRForDecl(D, USR)) return true; + // Prevent Visiting USR twice + { + std::lock_guard<llvm::sys::Mutex> Guard(USRVisitedGuard); + StringRef Visited = USR.str(); + if (USRVisited.count(Visited) && !isTypedefAnonRecord<T>(D)) + return true; + // We considered a USR to be visited only when its defined + if (IsDefinition) + USRVisited.insert(Visited); + } bool IsFileInRootDir; llvm::SmallString<128> File = getFile(D, D->getASTContext(), CDCtx.SourceRoot, IsFileInRootDir); @@ -53,30 +75,34 @@ template <typename T> bool MapASTVisitor::mapDecl(const T *D) { } bool MapASTVisitor::VisitNamespaceDecl(const NamespaceDecl *D) { - return mapDecl(D); + return mapDecl(D, /*isDefinition=*/true); } -bool MapASTVisitor::VisitRecordDecl(const RecordDecl *D) { return mapDecl(D); } +bool MapASTVisitor::VisitRecordDecl(const RecordDecl *D) { + return mapDecl(D, D->isThisDeclarationADefinition()); +} -bool MapASTVisitor::VisitEnumDecl(const EnumDecl *D) { return mapDecl(D); } +bool MapASTVisitor::VisitEnumDecl(const EnumDecl *D) { + return mapDecl(D, D->isThisDeclarationADefinition()); +} bool MapASTVisitor::VisitCXXMethodDecl(const CXXMethodDecl *D) { - return mapDecl(D); + return mapDecl(D, D->isThisDeclarationADefinition()); } bool MapASTVisitor::VisitFunctionDecl(const FunctionDecl *D) { // Don't visit CXXMethodDecls twice if (isa<CXXMethodDecl>(D)) return true; - return mapDecl(D); + return mapDecl(D, D->isThisDeclarationADefinition()); } bool MapASTVisitor::VisitTypedefDecl(const TypedefDecl *D) { - return mapDecl(D); + return mapDecl(D, /*isDefinition=*/true); } bool MapASTVisitor::VisitTypeAliasDecl(const TypeAliasDecl *D) { - return mapDecl(D); + return mapDecl(D, /*isDefinition=*/true); } comments::FullComment * diff --git a/clang-tools-extra/clang-doc/Mapper.h b/clang-tools-extra/clang-doc/Mapper.h index cedde935ab743..75c8e947c8f90 100644 --- a/clang-tools-extra/clang-doc/Mapper.h +++ b/clang-tools-extra/clang-doc/Mapper.h @@ -43,7 +43,7 @@ class MapASTVisitor : public clang::RecursiveASTVisitor<MapASTVisitor>, bool VisitTypeAliasDecl(const TypeAliasDecl *D); private: - template <typename T> bool mapDecl(const T *D); + template <typename T> bool mapDecl(const T *D, bool IsDefinition); int getLine(const NamedDecl *D, const ASTContext &Context) const; llvm::SmallString<128> getFile(const NamedDecl *D, const ASTContext &Context, diff --git a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp index 6198a6e0cdcc3..3363cafeded5e 100644 --- a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp +++ b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp @@ -303,7 +303,6 @@ Example usage for a project using a compile commands database: for (auto &Group : USRToBitcode) { Pool.async([&]() { std::vector<std::unique_ptr<doc::Info>> Infos; - for (auto &Bitcode : Group.getValue()) { llvm::BitstreamCursor Stream(Bitcode); doc::ClangDocBitcodeReader Reader(Stream); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits