xref: /minix3/external/bsd/llvm/dist/clang/lib/Frontend/ASTConsumers.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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