================ @@ -49,6 +51,150 @@ LLVM_INSTANTIATE_REGISTRY(FrontendPluginRegistry) namespace { +/// DeserializedDeclsLineRangePrinter dumps ranges of deserialized declarations +/// to aid debugging and bug minimization. It implements ASTConsumer and +/// ASTDeserializationListener, so that an object of +/// DeserializedDeclsLineRangePrinter registers as its own listener. The +/// ASTDeserializationListener interface provides the DeclRead callback that we +/// use to collect the deserialized Decls. Note that printing or otherwise +/// processing them as this point is dangerous, since that could trigger +/// additional deserialization and crash compilation. Therefore, we process the +/// collected Decls in HandleTranslationUnit method of ASTConsumer. This is a +/// safe point, since we know that by this point all the Decls needed by the +/// compiler frontend have been deserialized. In case our processing causes +/// further deserialization, DeclRead from the listener might be called again. +/// However, at that point we don't accept any more Decls for processing. +class DeserializedDeclsLineRangePrinter : public ASTDeserializationListener, + public ASTConsumer { +public: + explicit DeserializedDeclsLineRangePrinter( + SourceManager &SM, std::unique_ptr<llvm::raw_fd_ostream> OS) + : ASTDeserializationListener(), SM(SM), OS(std::move(OS)) {} + + void DeclRead(GlobalDeclID ID, const Decl *D) override { + if (!IsCollectingDecls) { + return; + } + if (!D || isa<TranslationUnitDecl>(D) || isa<LinkageSpecDecl>(D) || + isa<NamespaceDecl>(D)) + return; + if (auto *DC = D->getDeclContext(); !DC || !DC->isFileContext()) + return; + PendingDecls.push_back(D); + ASTDeserializationListener::DeclRead(ID, D); + } + + using Position = std::pair<unsigned, unsigned>; + struct RequiredRanges { + StringRef Filename; + std::vector<std::pair<Position, Position>> FromTo; + }; + void HandleTranslationUnit(ASTContext &Context) override { + IsCollectingDecls = false; + std::vector<const Decl *> Decls = std::move(PendingDecls); + if (!PendingDecls.empty()) { + llvm::errs() << "Deserialized more decls while printing, total of " + << PendingDecls.size() << "\n"; + PendingDecls.clear(); + } + + // Merge ranges in each of the files. For simplicity, track lines and hope + // they do not break things. + struct FileData { + std::vector<std::pair<Position, Position>> FromTo; + std::vector<std::pair<unsigned, unsigned>> Columns; + OptionalFileEntryRef Ref; + }; + llvm::DenseMap<const FileEntry *, FileData> FileToLines; + for (const Decl *D : Decls) { + CharSourceRange R = SM.getExpansionRange(D->getSourceRange()); + if (!R.isValid()) + continue; + + auto *F = SM.getFileEntryForID(SM.getFileID(R.getBegin())); + if (F != SM.getFileEntryForID(SM.getFileID(R.getEnd()))) + continue; + + auto &Data = FileToLines[F]; + if (!Data.Ref) + Data.Ref = SM.getFileEntryRefForID(SM.getFileID(R.getBegin())); + Data.FromTo.push_back({{SM.getSpellingLineNumber(R.getBegin()), + SM.getSpellingColumnNumber(R.getBegin())}, + {SM.getSpellingLineNumber(R.getEnd()), + SM.getSpellingColumnNumber(R.getEnd())}}); + } + + std::vector<RequiredRanges> Result; ---------------- VitaNuo wrote:
Done. https://github.com/llvm/llvm-project/pull/133910 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits