1f4a2713aSLionel Sambuc //===--- ASTConsumers.cpp - ASTConsumer implementations -------------------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // AST Consumer Implementations.
11f4a2713aSLionel Sambuc //
12f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
13f4a2713aSLionel Sambuc
14f4a2713aSLionel Sambuc #include "clang/Frontend/ASTConsumers.h"
15f4a2713aSLionel Sambuc #include "clang/AST/AST.h"
16f4a2713aSLionel Sambuc #include "clang/AST/ASTConsumer.h"
17f4a2713aSLionel Sambuc #include "clang/AST/ASTContext.h"
18f4a2713aSLionel Sambuc #include "clang/AST/PrettyPrinter.h"
19f4a2713aSLionel Sambuc #include "clang/AST/RecordLayout.h"
20f4a2713aSLionel Sambuc #include "clang/AST/RecursiveASTVisitor.h"
21f4a2713aSLionel Sambuc #include "clang/Basic/Diagnostic.h"
22f4a2713aSLionel Sambuc #include "clang/Basic/FileManager.h"
23f4a2713aSLionel Sambuc #include "clang/Basic/SourceManager.h"
24f4a2713aSLionel Sambuc #include "llvm/IR/Module.h"
25f4a2713aSLionel Sambuc #include "llvm/Support/Path.h"
26f4a2713aSLionel Sambuc #include "llvm/Support/Timer.h"
27f4a2713aSLionel Sambuc #include "llvm/Support/raw_ostream.h"
28f4a2713aSLionel Sambuc using namespace clang;
29f4a2713aSLionel Sambuc
30f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
31f4a2713aSLionel Sambuc /// ASTPrinter - Pretty-printer and dumper of ASTs
32f4a2713aSLionel Sambuc
33f4a2713aSLionel Sambuc namespace {
34f4a2713aSLionel Sambuc class ASTPrinter : public ASTConsumer,
35f4a2713aSLionel Sambuc public RecursiveASTVisitor<ASTPrinter> {
36f4a2713aSLionel Sambuc typedef RecursiveASTVisitor<ASTPrinter> base;
37f4a2713aSLionel Sambuc
38f4a2713aSLionel Sambuc public:
ASTPrinter(raw_ostream * Out=nullptr,bool Dump=false,StringRef FilterString="",bool DumpLookups=false)39*0a6a1f1dSLionel Sambuc ASTPrinter(raw_ostream *Out = nullptr, bool Dump = false,
40f4a2713aSLionel Sambuc StringRef FilterString = "", bool DumpLookups = false)
41f4a2713aSLionel Sambuc : Out(Out ? *Out : llvm::outs()), Dump(Dump),
42f4a2713aSLionel Sambuc FilterString(FilterString), DumpLookups(DumpLookups) {}
43f4a2713aSLionel Sambuc
HandleTranslationUnit(ASTContext & Context)44*0a6a1f1dSLionel Sambuc void HandleTranslationUnit(ASTContext &Context) override {
45f4a2713aSLionel Sambuc TranslationUnitDecl *D = Context.getTranslationUnitDecl();
46f4a2713aSLionel Sambuc
47f4a2713aSLionel Sambuc if (FilterString.empty())
48f4a2713aSLionel Sambuc return print(D);
49f4a2713aSLionel Sambuc
50f4a2713aSLionel Sambuc TraverseDecl(D);
51f4a2713aSLionel Sambuc }
52f4a2713aSLionel Sambuc
shouldWalkTypesOfTypeLocs() const53f4a2713aSLionel Sambuc bool shouldWalkTypesOfTypeLocs() const { return false; }
54f4a2713aSLionel Sambuc
TraverseDecl(Decl * D)55f4a2713aSLionel Sambuc bool TraverseDecl(Decl *D) {
56*0a6a1f1dSLionel Sambuc if (D && filterMatches(D)) {
57f4a2713aSLionel Sambuc bool ShowColors = Out.has_colors();
58f4a2713aSLionel Sambuc if (ShowColors)
59f4a2713aSLionel Sambuc Out.changeColor(raw_ostream::BLUE);
60*0a6a1f1dSLionel Sambuc Out << ((Dump || DumpLookups) ? "Dumping " : "Printing ") << getName(D)
61*0a6a1f1dSLionel Sambuc << ":\n";
62f4a2713aSLionel Sambuc if (ShowColors)
63f4a2713aSLionel Sambuc Out.resetColor();
64f4a2713aSLionel Sambuc print(D);
65f4a2713aSLionel Sambuc Out << "\n";
66f4a2713aSLionel Sambuc // Don't traverse child nodes to avoid output duplication.
67f4a2713aSLionel Sambuc return true;
68f4a2713aSLionel Sambuc }
69f4a2713aSLionel Sambuc return base::TraverseDecl(D);
70f4a2713aSLionel Sambuc }
71f4a2713aSLionel Sambuc
72f4a2713aSLionel Sambuc private:
getName(Decl * D)73f4a2713aSLionel Sambuc std::string getName(Decl *D) {
74f4a2713aSLionel Sambuc if (isa<NamedDecl>(D))
75f4a2713aSLionel Sambuc return cast<NamedDecl>(D)->getQualifiedNameAsString();
76f4a2713aSLionel Sambuc return "";
77f4a2713aSLionel Sambuc }
filterMatches(Decl * D)78f4a2713aSLionel Sambuc bool filterMatches(Decl *D) {
79f4a2713aSLionel Sambuc return getName(D).find(FilterString) != std::string::npos;
80f4a2713aSLionel Sambuc }
print(Decl * D)81f4a2713aSLionel Sambuc void print(Decl *D) {
82f4a2713aSLionel Sambuc if (DumpLookups) {
83*0a6a1f1dSLionel Sambuc if (DeclContext *DC = dyn_cast<DeclContext>(D)) {
84*0a6a1f1dSLionel Sambuc if (DC == DC->getPrimaryContext())
85*0a6a1f1dSLionel Sambuc DC->dumpLookups(Out, Dump);
86f4a2713aSLionel Sambuc else
87*0a6a1f1dSLionel Sambuc Out << "Lookup map is in primary DeclContext "
88*0a6a1f1dSLionel Sambuc << DC->getPrimaryContext() << "\n";
89*0a6a1f1dSLionel Sambuc } else
90f4a2713aSLionel Sambuc Out << "Not a DeclContext\n";
91f4a2713aSLionel Sambuc } else if (Dump)
92f4a2713aSLionel Sambuc D->dump(Out);
93f4a2713aSLionel Sambuc else
94f4a2713aSLionel Sambuc D->print(Out, /*Indentation=*/0, /*PrintInstantiation=*/true);
95f4a2713aSLionel Sambuc }
96f4a2713aSLionel Sambuc
97f4a2713aSLionel Sambuc raw_ostream &Out;
98f4a2713aSLionel Sambuc bool Dump;
99f4a2713aSLionel Sambuc std::string FilterString;
100f4a2713aSLionel Sambuc bool DumpLookups;
101f4a2713aSLionel Sambuc };
102f4a2713aSLionel Sambuc
103f4a2713aSLionel Sambuc class ASTDeclNodeLister : public ASTConsumer,
104f4a2713aSLionel Sambuc public RecursiveASTVisitor<ASTDeclNodeLister> {
105f4a2713aSLionel Sambuc public:
ASTDeclNodeLister(raw_ostream * Out=nullptr)106*0a6a1f1dSLionel Sambuc ASTDeclNodeLister(raw_ostream *Out = nullptr)
107f4a2713aSLionel Sambuc : Out(Out ? *Out : llvm::outs()) {}
108f4a2713aSLionel Sambuc
HandleTranslationUnit(ASTContext & Context)109*0a6a1f1dSLionel Sambuc void HandleTranslationUnit(ASTContext &Context) override {
110f4a2713aSLionel Sambuc TraverseDecl(Context.getTranslationUnitDecl());
111f4a2713aSLionel Sambuc }
112f4a2713aSLionel Sambuc
shouldWalkTypesOfTypeLocs() const113f4a2713aSLionel Sambuc bool shouldWalkTypesOfTypeLocs() const { return false; }
114f4a2713aSLionel Sambuc
VisitNamedDecl(NamedDecl * D)115*0a6a1f1dSLionel Sambuc bool VisitNamedDecl(NamedDecl *D) {
116f4a2713aSLionel Sambuc D->printQualifiedName(Out);
117f4a2713aSLionel Sambuc Out << '\n';
118f4a2713aSLionel Sambuc return true;
119f4a2713aSLionel Sambuc }
120f4a2713aSLionel Sambuc
121f4a2713aSLionel Sambuc private:
122f4a2713aSLionel Sambuc raw_ostream &Out;
123f4a2713aSLionel Sambuc };
124f4a2713aSLionel Sambuc } // end anonymous namespace
125f4a2713aSLionel Sambuc
CreateASTPrinter(raw_ostream * Out,StringRef FilterString)126*0a6a1f1dSLionel Sambuc std::unique_ptr<ASTConsumer> clang::CreateASTPrinter(raw_ostream *Out,
127f4a2713aSLionel Sambuc StringRef FilterString) {
128*0a6a1f1dSLionel Sambuc return llvm::make_unique<ASTPrinter>(Out, /*Dump=*/false, FilterString);
129f4a2713aSLionel Sambuc }
130f4a2713aSLionel Sambuc
CreateASTDumper(StringRef FilterString,bool DumpDecls,bool DumpLookups)131*0a6a1f1dSLionel Sambuc std::unique_ptr<ASTConsumer> clang::CreateASTDumper(StringRef FilterString,
132*0a6a1f1dSLionel Sambuc bool DumpDecls,
133*0a6a1f1dSLionel Sambuc bool DumpLookups) {
134*0a6a1f1dSLionel Sambuc assert((DumpDecls || DumpLookups) && "nothing to dump");
135*0a6a1f1dSLionel Sambuc return llvm::make_unique<ASTPrinter>(nullptr, DumpDecls, FilterString,
136*0a6a1f1dSLionel Sambuc DumpLookups);
137f4a2713aSLionel Sambuc }
138f4a2713aSLionel Sambuc
CreateASTDeclNodeLister()139*0a6a1f1dSLionel Sambuc std::unique_ptr<ASTConsumer> clang::CreateASTDeclNodeLister() {
140*0a6a1f1dSLionel Sambuc return llvm::make_unique<ASTDeclNodeLister>(nullptr);
141f4a2713aSLionel Sambuc }
142f4a2713aSLionel Sambuc
143f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
144f4a2713aSLionel Sambuc /// ASTViewer - AST Visualization
145f4a2713aSLionel Sambuc
146f4a2713aSLionel Sambuc namespace {
147f4a2713aSLionel Sambuc class ASTViewer : public ASTConsumer {
148f4a2713aSLionel Sambuc ASTContext *Context;
149f4a2713aSLionel Sambuc public:
Initialize(ASTContext & Context)150*0a6a1f1dSLionel Sambuc void Initialize(ASTContext &Context) override {
151f4a2713aSLionel Sambuc this->Context = &Context;
152f4a2713aSLionel Sambuc }
153f4a2713aSLionel Sambuc
HandleTopLevelDecl(DeclGroupRef D)154*0a6a1f1dSLionel Sambuc bool HandleTopLevelDecl(DeclGroupRef D) override {
155f4a2713aSLionel Sambuc for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
156f4a2713aSLionel Sambuc HandleTopLevelSingleDecl(*I);
157f4a2713aSLionel Sambuc return true;
158f4a2713aSLionel Sambuc }
159f4a2713aSLionel Sambuc
160f4a2713aSLionel Sambuc void HandleTopLevelSingleDecl(Decl *D);
161f4a2713aSLionel Sambuc };
162f4a2713aSLionel Sambuc }
163f4a2713aSLionel Sambuc
HandleTopLevelSingleDecl(Decl * D)164f4a2713aSLionel Sambuc void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
165f4a2713aSLionel Sambuc if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
166f4a2713aSLionel Sambuc D->print(llvm::errs());
167f4a2713aSLionel Sambuc
168f4a2713aSLionel Sambuc if (Stmt *Body = D->getBody()) {
169f4a2713aSLionel Sambuc llvm::errs() << '\n';
170f4a2713aSLionel Sambuc Body->viewAST();
171f4a2713aSLionel Sambuc llvm::errs() << '\n';
172f4a2713aSLionel Sambuc }
173f4a2713aSLionel Sambuc }
174f4a2713aSLionel Sambuc }
175f4a2713aSLionel Sambuc
CreateASTViewer()176*0a6a1f1dSLionel Sambuc std::unique_ptr<ASTConsumer> clang::CreateASTViewer() {
177*0a6a1f1dSLionel Sambuc return llvm::make_unique<ASTViewer>();
178*0a6a1f1dSLionel Sambuc }
179f4a2713aSLionel Sambuc
180f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
181f4a2713aSLionel Sambuc /// DeclContextPrinter - Decl and DeclContext Visualization
182f4a2713aSLionel Sambuc
183f4a2713aSLionel Sambuc namespace {
184f4a2713aSLionel Sambuc
185f4a2713aSLionel Sambuc class DeclContextPrinter : public ASTConsumer {
186f4a2713aSLionel Sambuc raw_ostream& Out;
187f4a2713aSLionel Sambuc public:
DeclContextPrinter()188f4a2713aSLionel Sambuc DeclContextPrinter() : Out(llvm::errs()) {}
189f4a2713aSLionel Sambuc
HandleTranslationUnit(ASTContext & C)190*0a6a1f1dSLionel Sambuc void HandleTranslationUnit(ASTContext &C) override {
191f4a2713aSLionel Sambuc PrintDeclContext(C.getTranslationUnitDecl(), 4);
192f4a2713aSLionel Sambuc }
193f4a2713aSLionel Sambuc
194f4a2713aSLionel Sambuc void PrintDeclContext(const DeclContext* DC, unsigned Indentation);
195f4a2713aSLionel Sambuc };
196f4a2713aSLionel Sambuc } // end anonymous namespace
197f4a2713aSLionel Sambuc
PrintDeclContext(const DeclContext * DC,unsigned Indentation)198f4a2713aSLionel Sambuc void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
199f4a2713aSLionel Sambuc unsigned Indentation) {
200f4a2713aSLionel Sambuc // Print DeclContext name.
201f4a2713aSLionel Sambuc switch (DC->getDeclKind()) {
202f4a2713aSLionel Sambuc case Decl::TranslationUnit:
203f4a2713aSLionel Sambuc Out << "[translation unit] " << DC;
204f4a2713aSLionel Sambuc break;
205f4a2713aSLionel Sambuc case Decl::Namespace: {
206f4a2713aSLionel Sambuc Out << "[namespace] ";
207f4a2713aSLionel Sambuc const NamespaceDecl* ND = cast<NamespaceDecl>(DC);
208f4a2713aSLionel Sambuc Out << *ND;
209f4a2713aSLionel Sambuc break;
210f4a2713aSLionel Sambuc }
211f4a2713aSLionel Sambuc case Decl::Enum: {
212f4a2713aSLionel Sambuc const EnumDecl* ED = cast<EnumDecl>(DC);
213f4a2713aSLionel Sambuc if (ED->isCompleteDefinition())
214f4a2713aSLionel Sambuc Out << "[enum] ";
215f4a2713aSLionel Sambuc else
216f4a2713aSLionel Sambuc Out << "<enum> ";
217f4a2713aSLionel Sambuc Out << *ED;
218f4a2713aSLionel Sambuc break;
219f4a2713aSLionel Sambuc }
220f4a2713aSLionel Sambuc case Decl::Record: {
221f4a2713aSLionel Sambuc const RecordDecl* RD = cast<RecordDecl>(DC);
222f4a2713aSLionel Sambuc if (RD->isCompleteDefinition())
223f4a2713aSLionel Sambuc Out << "[struct] ";
224f4a2713aSLionel Sambuc else
225f4a2713aSLionel Sambuc Out << "<struct> ";
226f4a2713aSLionel Sambuc Out << *RD;
227f4a2713aSLionel Sambuc break;
228f4a2713aSLionel Sambuc }
229f4a2713aSLionel Sambuc case Decl::CXXRecord: {
230f4a2713aSLionel Sambuc const CXXRecordDecl* RD = cast<CXXRecordDecl>(DC);
231f4a2713aSLionel Sambuc if (RD->isCompleteDefinition())
232f4a2713aSLionel Sambuc Out << "[class] ";
233f4a2713aSLionel Sambuc else
234f4a2713aSLionel Sambuc Out << "<class> ";
235f4a2713aSLionel Sambuc Out << *RD << ' ' << DC;
236f4a2713aSLionel Sambuc break;
237f4a2713aSLionel Sambuc }
238f4a2713aSLionel Sambuc case Decl::ObjCMethod:
239f4a2713aSLionel Sambuc Out << "[objc method]";
240f4a2713aSLionel Sambuc break;
241f4a2713aSLionel Sambuc case Decl::ObjCInterface:
242f4a2713aSLionel Sambuc Out << "[objc interface]";
243f4a2713aSLionel Sambuc break;
244f4a2713aSLionel Sambuc case Decl::ObjCCategory:
245f4a2713aSLionel Sambuc Out << "[objc category]";
246f4a2713aSLionel Sambuc break;
247f4a2713aSLionel Sambuc case Decl::ObjCProtocol:
248f4a2713aSLionel Sambuc Out << "[objc protocol]";
249f4a2713aSLionel Sambuc break;
250f4a2713aSLionel Sambuc case Decl::ObjCImplementation:
251f4a2713aSLionel Sambuc Out << "[objc implementation]";
252f4a2713aSLionel Sambuc break;
253f4a2713aSLionel Sambuc case Decl::ObjCCategoryImpl:
254f4a2713aSLionel Sambuc Out << "[objc categoryimpl]";
255f4a2713aSLionel Sambuc break;
256f4a2713aSLionel Sambuc case Decl::LinkageSpec:
257f4a2713aSLionel Sambuc Out << "[linkage spec]";
258f4a2713aSLionel Sambuc break;
259f4a2713aSLionel Sambuc case Decl::Block:
260f4a2713aSLionel Sambuc Out << "[block]";
261f4a2713aSLionel Sambuc break;
262f4a2713aSLionel Sambuc case Decl::Function: {
263f4a2713aSLionel Sambuc const FunctionDecl* FD = cast<FunctionDecl>(DC);
264f4a2713aSLionel Sambuc if (FD->doesThisDeclarationHaveABody())
265f4a2713aSLionel Sambuc Out << "[function] ";
266f4a2713aSLionel Sambuc else
267f4a2713aSLionel Sambuc Out << "<function> ";
268f4a2713aSLionel Sambuc Out << *FD;
269f4a2713aSLionel Sambuc // Print the parameters.
270f4a2713aSLionel Sambuc Out << "(";
271f4a2713aSLionel Sambuc bool PrintComma = false;
272*0a6a1f1dSLionel Sambuc for (auto I : FD->params()) {
273f4a2713aSLionel Sambuc if (PrintComma)
274f4a2713aSLionel Sambuc Out << ", ";
275f4a2713aSLionel Sambuc else
276f4a2713aSLionel Sambuc PrintComma = true;
277*0a6a1f1dSLionel Sambuc Out << *I;
278f4a2713aSLionel Sambuc }
279f4a2713aSLionel Sambuc Out << ")";
280f4a2713aSLionel Sambuc break;
281f4a2713aSLionel Sambuc }
282f4a2713aSLionel Sambuc case Decl::CXXMethod: {
283f4a2713aSLionel Sambuc const CXXMethodDecl* D = cast<CXXMethodDecl>(DC);
284f4a2713aSLionel Sambuc if (D->isOutOfLine())
285f4a2713aSLionel Sambuc Out << "[c++ method] ";
286f4a2713aSLionel Sambuc else if (D->isImplicit())
287f4a2713aSLionel Sambuc Out << "(c++ method) ";
288f4a2713aSLionel Sambuc else
289f4a2713aSLionel Sambuc Out << "<c++ method> ";
290f4a2713aSLionel Sambuc Out << *D;
291f4a2713aSLionel Sambuc // Print the parameters.
292f4a2713aSLionel Sambuc Out << "(";
293f4a2713aSLionel Sambuc bool PrintComma = false;
294f4a2713aSLionel Sambuc for (FunctionDecl::param_const_iterator I = D->param_begin(),
295f4a2713aSLionel Sambuc E = D->param_end(); I != E; ++I) {
296f4a2713aSLionel Sambuc if (PrintComma)
297f4a2713aSLionel Sambuc Out << ", ";
298f4a2713aSLionel Sambuc else
299f4a2713aSLionel Sambuc PrintComma = true;
300f4a2713aSLionel Sambuc Out << **I;
301f4a2713aSLionel Sambuc }
302f4a2713aSLionel Sambuc Out << ")";
303f4a2713aSLionel Sambuc
304f4a2713aSLionel Sambuc // Check the semantic DeclContext.
305f4a2713aSLionel Sambuc const DeclContext* SemaDC = D->getDeclContext();
306f4a2713aSLionel Sambuc const DeclContext* LexicalDC = D->getLexicalDeclContext();
307f4a2713aSLionel Sambuc if (SemaDC != LexicalDC)
308f4a2713aSLionel Sambuc Out << " [[" << SemaDC << "]]";
309f4a2713aSLionel Sambuc
310f4a2713aSLionel Sambuc break;
311f4a2713aSLionel Sambuc }
312f4a2713aSLionel Sambuc case Decl::CXXConstructor: {
313f4a2713aSLionel Sambuc const CXXConstructorDecl* D = cast<CXXConstructorDecl>(DC);
314f4a2713aSLionel Sambuc if (D->isOutOfLine())
315f4a2713aSLionel Sambuc Out << "[c++ ctor] ";
316f4a2713aSLionel Sambuc else if (D->isImplicit())
317f4a2713aSLionel Sambuc Out << "(c++ ctor) ";
318f4a2713aSLionel Sambuc else
319f4a2713aSLionel Sambuc Out << "<c++ ctor> ";
320f4a2713aSLionel Sambuc Out << *D;
321f4a2713aSLionel Sambuc // Print the parameters.
322f4a2713aSLionel Sambuc Out << "(";
323f4a2713aSLionel Sambuc bool PrintComma = false;
324f4a2713aSLionel Sambuc for (FunctionDecl::param_const_iterator I = D->param_begin(),
325f4a2713aSLionel Sambuc E = D->param_end(); I != E; ++I) {
326f4a2713aSLionel Sambuc if (PrintComma)
327f4a2713aSLionel Sambuc Out << ", ";
328f4a2713aSLionel Sambuc else
329f4a2713aSLionel Sambuc PrintComma = true;
330f4a2713aSLionel Sambuc Out << **I;
331f4a2713aSLionel Sambuc }
332f4a2713aSLionel Sambuc Out << ")";
333f4a2713aSLionel Sambuc
334f4a2713aSLionel Sambuc // Check the semantic DC.
335f4a2713aSLionel Sambuc const DeclContext* SemaDC = D->getDeclContext();
336f4a2713aSLionel Sambuc const DeclContext* LexicalDC = D->getLexicalDeclContext();
337f4a2713aSLionel Sambuc if (SemaDC != LexicalDC)
338f4a2713aSLionel Sambuc Out << " [[" << SemaDC << "]]";
339f4a2713aSLionel Sambuc break;
340f4a2713aSLionel Sambuc }
341f4a2713aSLionel Sambuc case Decl::CXXDestructor: {
342f4a2713aSLionel Sambuc const CXXDestructorDecl* D = cast<CXXDestructorDecl>(DC);
343f4a2713aSLionel Sambuc if (D->isOutOfLine())
344f4a2713aSLionel Sambuc Out << "[c++ dtor] ";
345f4a2713aSLionel Sambuc else if (D->isImplicit())
346f4a2713aSLionel Sambuc Out << "(c++ dtor) ";
347f4a2713aSLionel Sambuc else
348f4a2713aSLionel Sambuc Out << "<c++ dtor> ";
349f4a2713aSLionel Sambuc Out << *D;
350f4a2713aSLionel Sambuc // Check the semantic DC.
351f4a2713aSLionel Sambuc const DeclContext* SemaDC = D->getDeclContext();
352f4a2713aSLionel Sambuc const DeclContext* LexicalDC = D->getLexicalDeclContext();
353f4a2713aSLionel Sambuc if (SemaDC != LexicalDC)
354f4a2713aSLionel Sambuc Out << " [[" << SemaDC << "]]";
355f4a2713aSLionel Sambuc break;
356f4a2713aSLionel Sambuc }
357f4a2713aSLionel Sambuc case Decl::CXXConversion: {
358f4a2713aSLionel Sambuc const CXXConversionDecl* D = cast<CXXConversionDecl>(DC);
359f4a2713aSLionel Sambuc if (D->isOutOfLine())
360f4a2713aSLionel Sambuc Out << "[c++ conversion] ";
361f4a2713aSLionel Sambuc else if (D->isImplicit())
362f4a2713aSLionel Sambuc Out << "(c++ conversion) ";
363f4a2713aSLionel Sambuc else
364f4a2713aSLionel Sambuc Out << "<c++ conversion> ";
365f4a2713aSLionel Sambuc Out << *D;
366f4a2713aSLionel Sambuc // Check the semantic DC.
367f4a2713aSLionel Sambuc const DeclContext* SemaDC = D->getDeclContext();
368f4a2713aSLionel Sambuc const DeclContext* LexicalDC = D->getLexicalDeclContext();
369f4a2713aSLionel Sambuc if (SemaDC != LexicalDC)
370f4a2713aSLionel Sambuc Out << " [[" << SemaDC << "]]";
371f4a2713aSLionel Sambuc break;
372f4a2713aSLionel Sambuc }
373f4a2713aSLionel Sambuc
374f4a2713aSLionel Sambuc default:
375f4a2713aSLionel Sambuc llvm_unreachable("a decl that inherits DeclContext isn't handled");
376f4a2713aSLionel Sambuc }
377f4a2713aSLionel Sambuc
378f4a2713aSLionel Sambuc Out << "\n";
379f4a2713aSLionel Sambuc
380f4a2713aSLionel Sambuc // Print decls in the DeclContext.
381*0a6a1f1dSLionel Sambuc for (auto *I : DC->decls()) {
382f4a2713aSLionel Sambuc for (unsigned i = 0; i < Indentation; ++i)
383f4a2713aSLionel Sambuc Out << " ";
384f4a2713aSLionel Sambuc
385f4a2713aSLionel Sambuc Decl::Kind DK = I->getKind();
386f4a2713aSLionel Sambuc switch (DK) {
387f4a2713aSLionel Sambuc case Decl::Namespace:
388f4a2713aSLionel Sambuc case Decl::Enum:
389f4a2713aSLionel Sambuc case Decl::Record:
390f4a2713aSLionel Sambuc case Decl::CXXRecord:
391f4a2713aSLionel Sambuc case Decl::ObjCMethod:
392f4a2713aSLionel Sambuc case Decl::ObjCInterface:
393f4a2713aSLionel Sambuc case Decl::ObjCCategory:
394f4a2713aSLionel Sambuc case Decl::ObjCProtocol:
395f4a2713aSLionel Sambuc case Decl::ObjCImplementation:
396f4a2713aSLionel Sambuc case Decl::ObjCCategoryImpl:
397f4a2713aSLionel Sambuc case Decl::LinkageSpec:
398f4a2713aSLionel Sambuc case Decl::Block:
399f4a2713aSLionel Sambuc case Decl::Function:
400f4a2713aSLionel Sambuc case Decl::CXXMethod:
401f4a2713aSLionel Sambuc case Decl::CXXConstructor:
402f4a2713aSLionel Sambuc case Decl::CXXDestructor:
403f4a2713aSLionel Sambuc case Decl::CXXConversion:
404f4a2713aSLionel Sambuc {
405*0a6a1f1dSLionel Sambuc DeclContext* DC = cast<DeclContext>(I);
406f4a2713aSLionel Sambuc PrintDeclContext(DC, Indentation+2);
407f4a2713aSLionel Sambuc break;
408f4a2713aSLionel Sambuc }
409f4a2713aSLionel Sambuc case Decl::IndirectField: {
410*0a6a1f1dSLionel Sambuc IndirectFieldDecl* IFD = cast<IndirectFieldDecl>(I);
411f4a2713aSLionel Sambuc Out << "<IndirectField> " << *IFD << '\n';
412f4a2713aSLionel Sambuc break;
413f4a2713aSLionel Sambuc }
414f4a2713aSLionel Sambuc case Decl::Label: {
415*0a6a1f1dSLionel Sambuc LabelDecl *LD = cast<LabelDecl>(I);
416f4a2713aSLionel Sambuc Out << "<Label> " << *LD << '\n';
417f4a2713aSLionel Sambuc break;
418f4a2713aSLionel Sambuc }
419f4a2713aSLionel Sambuc case Decl::Field: {
420*0a6a1f1dSLionel Sambuc FieldDecl *FD = cast<FieldDecl>(I);
421f4a2713aSLionel Sambuc Out << "<field> " << *FD << '\n';
422f4a2713aSLionel Sambuc break;
423f4a2713aSLionel Sambuc }
424f4a2713aSLionel Sambuc case Decl::Typedef:
425f4a2713aSLionel Sambuc case Decl::TypeAlias: {
426*0a6a1f1dSLionel Sambuc TypedefNameDecl* TD = cast<TypedefNameDecl>(I);
427f4a2713aSLionel Sambuc Out << "<typedef> " << *TD << '\n';
428f4a2713aSLionel Sambuc break;
429f4a2713aSLionel Sambuc }
430f4a2713aSLionel Sambuc case Decl::EnumConstant: {
431*0a6a1f1dSLionel Sambuc EnumConstantDecl* ECD = cast<EnumConstantDecl>(I);
432f4a2713aSLionel Sambuc Out << "<enum constant> " << *ECD << '\n';
433f4a2713aSLionel Sambuc break;
434f4a2713aSLionel Sambuc }
435f4a2713aSLionel Sambuc case Decl::Var: {
436*0a6a1f1dSLionel Sambuc VarDecl* VD = cast<VarDecl>(I);
437f4a2713aSLionel Sambuc Out << "<var> " << *VD << '\n';
438f4a2713aSLionel Sambuc break;
439f4a2713aSLionel Sambuc }
440f4a2713aSLionel Sambuc case Decl::ImplicitParam: {
441*0a6a1f1dSLionel Sambuc ImplicitParamDecl* IPD = cast<ImplicitParamDecl>(I);
442f4a2713aSLionel Sambuc Out << "<implicit parameter> " << *IPD << '\n';
443f4a2713aSLionel Sambuc break;
444f4a2713aSLionel Sambuc }
445f4a2713aSLionel Sambuc case Decl::ParmVar: {
446*0a6a1f1dSLionel Sambuc ParmVarDecl* PVD = cast<ParmVarDecl>(I);
447f4a2713aSLionel Sambuc Out << "<parameter> " << *PVD << '\n';
448f4a2713aSLionel Sambuc break;
449f4a2713aSLionel Sambuc }
450f4a2713aSLionel Sambuc case Decl::ObjCProperty: {
451*0a6a1f1dSLionel Sambuc ObjCPropertyDecl* OPD = cast<ObjCPropertyDecl>(I);
452f4a2713aSLionel Sambuc Out << "<objc property> " << *OPD << '\n';
453f4a2713aSLionel Sambuc break;
454f4a2713aSLionel Sambuc }
455f4a2713aSLionel Sambuc case Decl::FunctionTemplate: {
456*0a6a1f1dSLionel Sambuc FunctionTemplateDecl* FTD = cast<FunctionTemplateDecl>(I);
457f4a2713aSLionel Sambuc Out << "<function template> " << *FTD << '\n';
458f4a2713aSLionel Sambuc break;
459f4a2713aSLionel Sambuc }
460f4a2713aSLionel Sambuc case Decl::FileScopeAsm: {
461f4a2713aSLionel Sambuc Out << "<file-scope asm>\n";
462f4a2713aSLionel Sambuc break;
463f4a2713aSLionel Sambuc }
464f4a2713aSLionel Sambuc case Decl::UsingDirective: {
465f4a2713aSLionel Sambuc Out << "<using directive>\n";
466f4a2713aSLionel Sambuc break;
467f4a2713aSLionel Sambuc }
468f4a2713aSLionel Sambuc case Decl::NamespaceAlias: {
469*0a6a1f1dSLionel Sambuc NamespaceAliasDecl* NAD = cast<NamespaceAliasDecl>(I);
470f4a2713aSLionel Sambuc Out << "<namespace alias> " << *NAD << '\n';
471f4a2713aSLionel Sambuc break;
472f4a2713aSLionel Sambuc }
473f4a2713aSLionel Sambuc case Decl::ClassTemplate: {
474*0a6a1f1dSLionel Sambuc ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(I);
475f4a2713aSLionel Sambuc Out << "<class template> " << *CTD << '\n';
476f4a2713aSLionel Sambuc break;
477f4a2713aSLionel Sambuc }
478f4a2713aSLionel Sambuc case Decl::OMPThreadPrivate: {
479*0a6a1f1dSLionel Sambuc Out << "<omp threadprivate> " << '"' << I << "\"\n";
480f4a2713aSLionel Sambuc break;
481f4a2713aSLionel Sambuc }
482f4a2713aSLionel Sambuc default:
483*0a6a1f1dSLionel Sambuc Out << "DeclKind: " << DK << '"' << I << "\"\n";
484f4a2713aSLionel Sambuc llvm_unreachable("decl unhandled");
485f4a2713aSLionel Sambuc }
486f4a2713aSLionel Sambuc }
487f4a2713aSLionel Sambuc }
CreateDeclContextPrinter()488*0a6a1f1dSLionel Sambuc std::unique_ptr<ASTConsumer> clang::CreateDeclContextPrinter() {
489*0a6a1f1dSLionel Sambuc return llvm::make_unique<DeclContextPrinter>();
490f4a2713aSLionel Sambuc }
491