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