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