================ @@ -49,6 +54,185 @@ 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 ASTConsumer, + ASTDeserializationListener { +public: + explicit DeserializedDeclsLineRangePrinter( + SourceManager &SM, std::unique_ptr<llvm::raw_fd_ostream> OS) + : ASTDeserializationListener(), SM(SM), OS(std::move(OS)) {} + + ASTDeserializationListener *GetASTDeserializationListener() override { + return this; + } + + void DeclRead(GlobalDeclID ID, const Decl *D) override { + if (!IsCollectingDecls) + return; + if (!D || isa<TranslationUnitDecl>(D) || isa<LinkageSpecDecl>(D) || + isa<NamespaceDecl>(D)) { + // These decls cover a lot of nested declarations that might not be used, + // reducing the granularity and making the output less useful. + return; + } + if (auto *DC = D->getDeclContext(); !DC || !DC->isFileContext()) { + // We choose to work at namespace level to reduce complexity and the + // number of cases we care about. + return; + } + PendingDecls.push_back(D); + } + + struct Position { + unsigned Line; + unsigned Column; + + bool operator<(const Position &other) const { + if (Line < other.Line) + return true; + if (Line > other.Line) + return false; + return Column < other.Column; + } + + static Position GetBeginSpelling(const SourceManager &SM, + const CharSourceRange &R) { + SourceLocation Begin = R.getBegin(); + return {SM.getSpellingLineNumber(Begin), + SM.getSpellingColumnNumber(Begin)}; + } + + static Position GetEndSpelling(const SourceManager &SM, + const CharSourceRange &Range, + const LangOptions &LangOpts) { + // For token ranges, compute end location for end character of the range. + // The end location of returned range is exclusive. ---------------- emaxx-google wrote:
This sounds good. Just please document it somewhere, because the exact semantics isn't immediately obvious. 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