1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | #include "clang/Frontend/ASTConsumers.h" |
14 | #include "clang/AST/AST.h" |
15 | #include "clang/AST/ASTConsumer.h" |
16 | #include "clang/AST/ASTContext.h" |
17 | #include "clang/AST/PrettyPrinter.h" |
18 | #include "clang/AST/RecordLayout.h" |
19 | #include "clang/AST/RecursiveASTVisitor.h" |
20 | #include "clang/Basic/Diagnostic.h" |
21 | #include "clang/Basic/SourceManager.h" |
22 | #include "llvm/Support/Path.h" |
23 | #include "llvm/Support/Timer.h" |
24 | #include "llvm/Support/raw_ostream.h" |
25 | using namespace clang; |
26 | |
27 | |
28 | |
29 | |
30 | namespace { |
31 | class ASTPrinter : public ASTConsumer, |
32 | public RecursiveASTVisitor<ASTPrinter> { |
33 | typedef RecursiveASTVisitor<ASTPrinter> base; |
34 | |
35 | public: |
36 | enum Kind { DumpFull, Dump, Print, None }; |
37 | ASTPrinter(std::unique_ptr<raw_ostream> Out, Kind K, StringRef FilterString, |
38 | bool DumpLookups = false) |
39 | : Out(Out ? *Out : llvm::outs()), OwnedOut(std::move(Out)), |
40 | OutputKind(K), 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 << (OutputKind != Print ? "Dumping " : "Printing ") << getName(D) |
59 | << ":\n"; |
60 | if (ShowColors) |
61 | Out.resetColor(); |
62 | print(D); |
63 | Out << "\n"; |
64 | |
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, OutputKind != None, OutputKind == DumpFull); |
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 (OutputKind == Print) { |
90 | PrintingPolicy Policy(D->getASTContext().getLangOpts()); |
91 | D->print(Out, Policy, , ); |
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 | |
100 | Kind OutputKind; |
101 | |
102 | |
103 | std::string FilterString; |
104 | |
105 | |
106 | |
107 | |
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 | } |
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> |
142 | clang::CreateASTDumper(std::unique_ptr<raw_ostream> Out, |
143 | StringRef FilterString, |
144 | bool DumpDecls, |
145 | bool Deserialize, |
146 | bool DumpLookups) { |
147 | (0) . __assert_fail ("(DumpDecls || Deserialize || DumpLookups) && \"nothing to dump\"", "/home/seafit/code_projects/clang_source/clang/lib/Frontend/ASTConsumers.cpp", 147, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert((DumpDecls || Deserialize || DumpLookups) && "nothing to dump"); |
148 | return llvm::make_unique<ASTPrinter>(std::move(Out), |
149 | Deserialize ? ASTPrinter::DumpFull : |
150 | DumpDecls ? ASTPrinter::Dump : |
151 | ASTPrinter::None, |
152 | FilterString, DumpLookups); |
153 | } |
154 | |
155 | std::unique_ptr<ASTConsumer> clang::CreateASTDeclNodeLister() { |
156 | return llvm::make_unique<ASTDeclNodeLister>(nullptr); |
157 | } |
158 | |
159 | |
160 | |
161 | |
162 | namespace { |
163 | class ASTViewer : public ASTConsumer { |
164 | ASTContext *Context; |
165 | public: |
166 | void Initialize(ASTContext &Context) override { |
167 | this->Context = &Context; |
168 | } |
169 | |
170 | bool HandleTopLevelDecl(DeclGroupRef D) override { |
171 | for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) |
172 | HandleTopLevelSingleDecl(*I); |
173 | return true; |
174 | } |
175 | |
176 | void HandleTopLevelSingleDecl(Decl *D); |
177 | }; |
178 | } |
179 | |
180 | void ASTViewer::HandleTopLevelSingleDecl(Decl *D) { |
181 | if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) { |
182 | D->print(llvm::errs()); |
183 | |
184 | if (Stmt *Body = D->getBody()) { |
185 | llvm::errs() << '\n'; |
186 | Body->viewAST(); |
187 | llvm::errs() << '\n'; |
188 | } |
189 | } |
190 | } |
191 | |
192 | std::unique_ptr<ASTConsumer> clang::CreateASTViewer() { |
193 | return llvm::make_unique<ASTViewer>(); |
194 | } |
195 | |