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