blob: 662cfd6a21d78c094c4156630c1ce3be8ba774ef [file] [log] [blame]
Chris Lattnerd1cdee72007-10-07 06:04:32 +00001//===--- ASTConsumers.cpp - ASTConsumer implementations -------------------===//
Bill Wendlingaec64c32007-06-23 00:39:57 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Bill Wendlingaec64c32007-06-23 00:39:57 +00006//
7//===----------------------------------------------------------------------===//
8//
Chris Lattnerd1cdee72007-10-07 06:04:32 +00009// AST Consumer Implementations.
Bill Wendlingaec64c32007-06-23 00:39:57 +000010//
11//===----------------------------------------------------------------------===//
12
Eli Friedman9f30fc32009-05-18 22:50:54 +000013#include "clang/Frontend/ASTConsumers.h"
Bill Wendlingaec64c32007-06-23 00:39:57 +000014#include "clang/AST/AST.h"
Chris Lattner09c39db2007-09-15 23:02:28 +000015#include "clang/AST/ASTConsumer.h"
Chris Lattnera5adead2009-03-28 04:27:18 +000016#include "clang/AST/ASTContext.h"
Douglas Gregor7de59662009-05-29 20:38:28 +000017#include "clang/AST/PrettyPrinter.h"
Alexander Kornienko3db68ee2012-07-26 16:01:23 +000018#include "clang/AST/RecordLayout.h"
19#include "clang/AST/RecursiveASTVisitor.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000020#include "clang/Basic/Diagnostic.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000021#include "clang/Basic/SourceManager.h"
Michael J. Spencer8aaf4992010-11-29 18:12:39 +000022#include "llvm/Support/Path.h"
Alexander Kornienko3db68ee2012-07-26 16:01:23 +000023#include "llvm/Support/Timer.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000024#include "llvm/Support/raw_ostream.h"
Chris Lattnercbe4f772007-08-08 22:51:59 +000025using namespace clang;
Bill Wendlingaec64c32007-06-23 00:39:57 +000026
Ted Kremenek7c81bdd2007-11-27 21:46:50 +000027//===----------------------------------------------------------------------===//
Douglas Gregor278f52e2009-05-30 00:08:05 +000028/// ASTPrinter - Pretty-printer and dumper of ASTs
Chris Lattnercbe4f772007-08-08 22:51:59 +000029
Ted Kremenek7c81bdd2007-11-27 21:46:50 +000030namespace {
Alexander Kornienko3db68ee2012-07-26 16:01:23 +000031 class ASTPrinter : public ASTConsumer,
32 public RecursiveASTVisitor<ASTPrinter> {
33 typedef RecursiveASTVisitor<ASTPrinter> base;
Mike Stump11289f42009-09-09 15:08:12 +000034
Ted Kremenek7c81bdd2007-11-27 21:46:50 +000035 public:
Richard Smith3a36ac12017-03-09 22:00:01 +000036 enum Kind { DumpFull, Dump, Print, None };
37 ASTPrinter(std::unique_ptr<raw_ostream> Out, Kind K, StringRef FilterString,
38 bool DumpLookups = false)
39 : Out(Out ? *Out : llvm::outs()), OwnedOut(std::move(Out)),
40 OutputKind(K), FilterString(FilterString), DumpLookups(DumpLookups) {}
Mike Stump11289f42009-09-09 15:08:12 +000041
Craig Topperafa7cb32014-03-13 06:07:04 +000042 void HandleTranslationUnit(ASTContext &Context) override {
Alexander Kornienko3db68ee2012-07-26 16:01:23 +000043 TranslationUnitDecl *D = Context.getTranslationUnitDecl();
44
Richard Smith6ea05822013-06-24 01:45:33 +000045 if (FilterString.empty())
46 return print(D);
Alexander Kornienko3db68ee2012-07-26 16:01:23 +000047
48 TraverseDecl(D);
Bill Wendlingaec64c32007-06-23 00:39:57 +000049 }
Alexander Kornienko3db68ee2012-07-26 16:01:23 +000050
51 bool shouldWalkTypesOfTypeLocs() const { return false; }
52
53 bool TraverseDecl(Decl *D) {
Craig Topper49a27902014-05-22 04:46:25 +000054 if (D && filterMatches(D)) {
Dmitri Gribenko32333912012-11-21 10:54:55 +000055 bool ShowColors = Out.has_colors();
56 if (ShowColors)
Dmitri Gribenkof8579502013-01-12 19:30:44 +000057 Out.changeColor(raw_ostream::BLUE);
Richard Smith3a36ac12017-03-09 22:00:01 +000058 Out << (OutputKind != Print ? "Dumping " : "Printing ") << getName(D)
Richard Smith35f986d2014-08-11 22:11:07 +000059 << ":\n";
Dmitri Gribenko32333912012-11-21 10:54:55 +000060 if (ShowColors)
61 Out.resetColor();
Richard Smith6ea05822013-06-24 01:45:33 +000062 print(D);
Alexander Kornienko20186182012-08-17 17:38:39 +000063 Out << "\n";
Alexander Kornienko3db68ee2012-07-26 16:01:23 +000064 // Don't traverse child nodes to avoid output duplication.
65 return true;
66 }
67 return base::TraverseDecl(D);
68 }
69
70 private:
71 std::string getName(Decl *D) {
72 if (isa<NamedDecl>(D))
73 return cast<NamedDecl>(D)->getQualifiedNameAsString();
74 return "";
75 }
76 bool filterMatches(Decl *D) {
77 return getName(D).find(FilterString) != std::string::npos;
78 }
Richard Smith6ea05822013-06-24 01:45:33 +000079 void print(Decl *D) {
80 if (DumpLookups) {
Richard Smith35f986d2014-08-11 22:11:07 +000081 if (DeclContext *DC = dyn_cast<DeclContext>(D)) {
82 if (DC == DC->getPrimaryContext())
Richard Smith3a36ac12017-03-09 22:00:01 +000083 DC->dumpLookups(Out, OutputKind != None, OutputKind == DumpFull);
Richard Smith35f986d2014-08-11 22:11:07 +000084 else
85 Out << "Lookup map is in primary DeclContext "
86 << DC->getPrimaryContext() << "\n";
87 } else
Richard Smith6ea05822013-06-24 01:45:33 +000088 Out << "Not a DeclContext\n";
Joel E. Denny7bcc2102018-05-14 18:41:44 +000089 } else if (OutputKind == Print) {
90 PrintingPolicy Policy(D->getASTContext().getLangOpts());
91 D->print(Out, Policy, /*Indentation=*/0, /*PrintInstantiation=*/true);
92 } else if (OutputKind != None)
Richard Smith3a36ac12017-03-09 22:00:01 +000093 D->dump(Out, OutputKind == DumpFull);
Richard Smith6ea05822013-06-24 01:45:33 +000094 }
Alexander Kornienko3db68ee2012-07-26 16:01:23 +000095
96 raw_ostream &Out;
Peter Collingbourne03f89072016-07-15 00:55:40 +000097 std::unique_ptr<raw_ostream> OwnedOut;
Richard Smith3a36ac12017-03-09 22:00:01 +000098
99 /// How to output individual declarations.
100 Kind OutputKind;
101
102 /// Which declarations or DeclContexts to display.
Alexander Kornienko3db68ee2012-07-26 16:01:23 +0000103 std::string FilterString;
Richard Smith3a36ac12017-03-09 22:00:01 +0000104
105 /// Whether the primary output is lookup results or declarations. Individual
106 /// results will be output with a format determined by OutputKind. This is
107 /// incompatible with OutputKind == Print.
Richard Smith6ea05822013-06-24 01:45:33 +0000108 bool DumpLookups;
Chris Lattner09c39db2007-09-15 23:02:28 +0000109 };
Alexander Kornienko4de03592012-07-31 09:37:40 +0000110
111 class ASTDeclNodeLister : public ASTConsumer,
112 public RecursiveASTVisitor<ASTDeclNodeLister> {
Alexander Kornienko4de03592012-07-31 09:37:40 +0000113 public:
Craig Topper49a27902014-05-22 04:46:25 +0000114 ASTDeclNodeLister(raw_ostream *Out = nullptr)
Alexander Kornienko4de03592012-07-31 09:37:40 +0000115 : Out(Out ? *Out : llvm::outs()) {}
116
Craig Topperafa7cb32014-03-13 06:07:04 +0000117 void HandleTranslationUnit(ASTContext &Context) override {
Alexander Kornienko4de03592012-07-31 09:37:40 +0000118 TraverseDecl(Context.getTranslationUnitDecl());
119 }
120
121 bool shouldWalkTypesOfTypeLocs() const { return false; }
122
Craig Topper45670532014-03-13 07:14:47 +0000123 bool VisitNamedDecl(NamedDecl *D) {
Benjamin Kramer24ebf7c2013-02-23 13:53:57 +0000124 D->printQualifiedName(Out);
125 Out << '\n';
Alexander Kornienko4de03592012-07-31 09:37:40 +0000126 return true;
127 }
128
129 private:
130 raw_ostream &Out;
131 };
Chris Lattnerc0c3dff2009-03-28 05:44:17 +0000132} // end anonymous namespace
Chris Lattnercbe4f772007-08-08 22:51:59 +0000133
Peter Collingbourne03f89072016-07-15 00:55:40 +0000134std::unique_ptr<ASTConsumer>
135clang::CreateASTPrinter(std::unique_ptr<raw_ostream> Out,
136 StringRef FilterString) {
Richard Smith3a36ac12017-03-09 22:00:01 +0000137 return llvm::make_unique<ASTPrinter>(std::move(Out), ASTPrinter::Print,
Peter Collingbourne03f89072016-07-15 00:55:40 +0000138 FilterString);
Ted Kremenek59337682007-11-28 21:32:21 +0000139}
Ted Kremenek7c81bdd2007-11-27 21:46:50 +0000140
Alexander Kornienkod10d7902018-04-06 13:01:12 +0000141std::unique_ptr<ASTConsumer>
142clang::CreateASTDumper(std::unique_ptr<raw_ostream> Out,
143 StringRef FilterString,
144 bool DumpDecls,
145 bool Deserialize,
146 bool DumpLookups) {
Aaron Ballman08d3b392017-06-15 00:00:08 +0000147 assert((DumpDecls || Deserialize || DumpLookups) && "nothing to dump");
Alexander Kornienkod10d7902018-04-06 13:01:12 +0000148 return llvm::make_unique<ASTPrinter>(std::move(Out),
Richard Smith3a36ac12017-03-09 22:00:01 +0000149 Deserialize ? ASTPrinter::DumpFull :
150 DumpDecls ? ASTPrinter::Dump :
151 ASTPrinter::None,
152 FilterString, DumpLookups);
Douglas Gregor32887f02009-04-26 02:02:08 +0000153}
Chris Lattner09c39db2007-09-15 23:02:28 +0000154
David Blaikie6beb6aa2014-08-10 19:56:51 +0000155std::unique_ptr<ASTConsumer> clang::CreateASTDeclNodeLister() {
156 return llvm::make_unique<ASTDeclNodeLister>(nullptr);
Alexander Kornienko4de03592012-07-31 09:37:40 +0000157}
158
Ted Kremenek7c81bdd2007-11-27 21:46:50 +0000159//===----------------------------------------------------------------------===//
160/// ASTViewer - AST Visualization
161
Ted Kremenek66d130a2007-09-19 21:29:43 +0000162namespace {
163 class ASTViewer : public ASTConsumer {
Douglas Gregor278f52e2009-05-30 00:08:05 +0000164 ASTContext *Context;
Ted Kremenek66d130a2007-09-19 21:29:43 +0000165 public:
Craig Topperafa7cb32014-03-13 06:07:04 +0000166 void Initialize(ASTContext &Context) override {
Douglas Gregor278f52e2009-05-30 00:08:05 +0000167 this->Context = &Context;
Ted Kremenek66d130a2007-09-19 21:29:43 +0000168 }
Chris Lattner5bbb3c82009-03-29 16:50:03 +0000169
Craig Topperafa7cb32014-03-13 06:07:04 +0000170 bool HandleTopLevelDecl(DeclGroupRef D) override {
Chris Lattner5bbb3c82009-03-29 16:50:03 +0000171 for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
172 HandleTopLevelSingleDecl(*I);
Argyrios Kyrtzidis841dd882011-11-18 00:26:59 +0000173 return true;
Chris Lattner5bbb3c82009-03-29 16:50:03 +0000174 }
Mike Stump11289f42009-09-09 15:08:12 +0000175
Chris Lattner5bbb3c82009-03-29 16:50:03 +0000176 void HandleTopLevelSingleDecl(Decl *D);
Ted Kremenek66d130a2007-09-19 21:29:43 +0000177 };
Alexander Kornienkoab9db512015-06-22 23:07:51 +0000178}
Ted Kremenek66d130a2007-09-19 21:29:43 +0000179
Chris Lattner5bbb3c82009-03-29 16:50:03 +0000180void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
Argyrios Kyrtzidis46f556d2010-07-07 11:31:23 +0000181 if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
182 D->print(llvm::errs());
Fangrui Song6907ce22018-07-30 19:24:48 +0000183
Argyrios Kyrtzidis46f556d2010-07-07 11:31:23 +0000184 if (Stmt *Body = D->getBody()) {
Benjamin Kramer89b422c2009-08-23 12:08:50 +0000185 llvm::errs() << '\n';
Douglas Gregore2350a32009-09-12 00:08:48 +0000186 Body->viewAST();
Benjamin Kramer89b422c2009-08-23 12:08:50 +0000187 llvm::errs() << '\n';
Chris Lattnerc0c3dff2009-03-28 05:44:17 +0000188 }
Chris Lattnerc0c3dff2009-03-28 05:44:17 +0000189 }
190}
191
David Blaikie6beb6aa2014-08-10 19:56:51 +0000192std::unique_ptr<ASTConsumer> clang::CreateASTViewer() {
193 return llvm::make_unique<ASTViewer>();
194}