diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Frontend/ASTConsumers.cpp')
| -rw-r--r-- | contrib/llvm-project/clang/lib/Frontend/ASTConsumers.cpp | 214 | 
1 files changed, 214 insertions, 0 deletions
diff --git a/contrib/llvm-project/clang/lib/Frontend/ASTConsumers.cpp b/contrib/llvm-project/clang/lib/Frontend/ASTConsumers.cpp new file mode 100644 index 000000000000..a73cc8876d5d --- /dev/null +++ b/contrib/llvm-project/clang/lib/Frontend/ASTConsumers.cpp @@ -0,0 +1,214 @@ +//===--- ASTConsumers.cpp - ASTConsumer implementations -------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// AST Consumer Implementations. +// +//===----------------------------------------------------------------------===// + +#include "clang/Frontend/ASTConsumers.h" +#include "clang/AST/AST.h" +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/PrettyPrinter.h" +#include "clang/AST/RecordLayout.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/SourceManager.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Timer.h" +#include "llvm/Support/raw_ostream.h" +using namespace clang; + +//===----------------------------------------------------------------------===// +/// ASTPrinter - Pretty-printer and dumper of ASTs + +namespace { +  class ASTPrinter : public ASTConsumer, +                     public RecursiveASTVisitor<ASTPrinter> { +    typedef RecursiveASTVisitor<ASTPrinter> base; + +  public: +    enum Kind { DumpFull, Dump, Print, None }; +    ASTPrinter(std::unique_ptr<raw_ostream> Out, Kind K, +               ASTDumpOutputFormat Format, StringRef FilterString, +               bool DumpLookups = false, bool DumpDeclTypes = false) +        : Out(Out ? *Out : llvm::outs()), OwnedOut(std::move(Out)), +          OutputKind(K), OutputFormat(Format), FilterString(FilterString), +          DumpLookups(DumpLookups), DumpDeclTypes(DumpDeclTypes) {} + +    void HandleTranslationUnit(ASTContext &Context) override { +      TranslationUnitDecl *D = Context.getTranslationUnitDecl(); + +      if (FilterString.empty()) +        return print(D); + +      TraverseDecl(D); +    } + +    bool shouldWalkTypesOfTypeLocs() const { return false; } + +    bool TraverseDecl(Decl *D) { +      if (D && filterMatches(D)) { +        bool ShowColors = Out.has_colors(); +        if (ShowColors) +          Out.changeColor(raw_ostream::BLUE); +        Out << (OutputKind != Print ? "Dumping " : "Printing ") << getName(D) +            << ":\n"; +        if (ShowColors) +          Out.resetColor(); +        print(D); +        Out << "\n"; +        // Don't traverse child nodes to avoid output duplication. +        return true; +      } +      return base::TraverseDecl(D); +    } + +  private: +    std::string getName(Decl *D) { +      if (isa<NamedDecl>(D)) +        return cast<NamedDecl>(D)->getQualifiedNameAsString(); +      return ""; +    } +    bool filterMatches(Decl *D) { +      return getName(D).find(FilterString) != std::string::npos; +    } +    void print(Decl *D) { +      if (DumpLookups) { +        if (DeclContext *DC = dyn_cast<DeclContext>(D)) { +          if (DC == DC->getPrimaryContext()) +            DC->dumpLookups(Out, OutputKind != None, OutputKind == DumpFull); +          else +            Out << "Lookup map is in primary DeclContext " +                << DC->getPrimaryContext() << "\n"; +        } else +          Out << "Not a DeclContext\n"; +      } else if (OutputKind == Print) { +        PrintingPolicy Policy(D->getASTContext().getLangOpts()); +        D->print(Out, Policy, /*Indentation=*/0, /*PrintInstantiation=*/true); +      } else if (OutputKind != None) { +        D->dump(Out, OutputKind == DumpFull, OutputFormat); +      } + +      if (DumpDeclTypes) { +        Decl *InnerD = D; +        if (auto *TD = dyn_cast<TemplateDecl>(D)) +          InnerD = TD->getTemplatedDecl(); + +        // FIXME: Support OutputFormat in type dumping. +        // FIXME: Support combining -ast-dump-decl-types with -ast-dump-lookups. +        if (auto *VD = dyn_cast<ValueDecl>(InnerD)) +          VD->getType().dump(Out, VD->getASTContext()); +        if (auto *TD = dyn_cast<TypeDecl>(InnerD)) +          TD->getTypeForDecl()->dump(Out, TD->getASTContext()); +      } +    } + +    raw_ostream &Out; +    std::unique_ptr<raw_ostream> OwnedOut; + +    /// How to output individual declarations. +    Kind OutputKind; + +    /// What format should the output take? +    ASTDumpOutputFormat OutputFormat; + +    /// Which declarations or DeclContexts to display. +    std::string FilterString; + +    /// Whether the primary output is lookup results or declarations. Individual +    /// results will be output with a format determined by OutputKind. This is +    /// incompatible with OutputKind == Print. +    bool DumpLookups; + +    /// Whether to dump the type for each declaration dumped. +    bool DumpDeclTypes; +  }; + +  class ASTDeclNodeLister : public ASTConsumer, +                     public RecursiveASTVisitor<ASTDeclNodeLister> { +  public: +    ASTDeclNodeLister(raw_ostream *Out = nullptr) +        : Out(Out ? *Out : llvm::outs()) {} + +    void HandleTranslationUnit(ASTContext &Context) override { +      TraverseDecl(Context.getTranslationUnitDecl()); +    } + +    bool shouldWalkTypesOfTypeLocs() const { return false; } + +    bool VisitNamedDecl(NamedDecl *D) { +      D->printQualifiedName(Out); +      Out << '\n'; +      return true; +    } + +  private: +    raw_ostream &Out; +  }; +} // end anonymous namespace + +std::unique_ptr<ASTConsumer> +clang::CreateASTPrinter(std::unique_ptr<raw_ostream> Out, +                        StringRef FilterString) { +  return std::make_unique<ASTPrinter>(std::move(Out), ASTPrinter::Print, +                                       ADOF_Default, FilterString); +} + +std::unique_ptr<ASTConsumer> +clang::CreateASTDumper(std::unique_ptr<raw_ostream> Out, StringRef FilterString, +                       bool DumpDecls, bool Deserialize, bool DumpLookups, +                       bool DumpDeclTypes, ASTDumpOutputFormat Format) { +  assert((DumpDecls || Deserialize || DumpLookups) && "nothing to dump"); +  return std::make_unique<ASTPrinter>( +      std::move(Out), +      Deserialize ? ASTPrinter::DumpFull +                  : DumpDecls ? ASTPrinter::Dump : ASTPrinter::None, +      Format, FilterString, DumpLookups, DumpDeclTypes); +} + +std::unique_ptr<ASTConsumer> clang::CreateASTDeclNodeLister() { +  return std::make_unique<ASTDeclNodeLister>(nullptr); +} + +//===----------------------------------------------------------------------===// +/// ASTViewer - AST Visualization + +namespace { +  class ASTViewer : public ASTConsumer { +    ASTContext *Context; +  public: +    void Initialize(ASTContext &Context) override { +      this->Context = &Context; +    } + +    bool HandleTopLevelDecl(DeclGroupRef D) override { +      for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) +        HandleTopLevelSingleDecl(*I); +      return true; +    } + +    void HandleTopLevelSingleDecl(Decl *D); +  }; +} + +void ASTViewer::HandleTopLevelSingleDecl(Decl *D) { +  if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) { +    D->print(llvm::errs()); + +    if (Stmt *Body = D->getBody()) { +      llvm::errs() << '\n'; +      Body->viewAST(); +      llvm::errs() << '\n'; +    } +  } +} + +std::unique_ptr<ASTConsumer> clang::CreateASTViewer() { +  return std::make_unique<ASTViewer>(); +}  | 
