/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/lib/AST/ASTDumper.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===--- ASTDumper.cpp - Dumping implementation for ASTs ------------------===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | // |
9 | | // This file implements the AST dump methods, which dump out the |
10 | | // AST in a form that exposes type details and other fields. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #include "clang/AST/ASTDumper.h" |
15 | | #include "clang/AST/ASTContext.h" |
16 | | #include "clang/AST/DeclLookups.h" |
17 | | #include "clang/AST/JSONNodeDumper.h" |
18 | | #include "clang/Basic/Builtins.h" |
19 | | #include "clang/Basic/Module.h" |
20 | | #include "clang/Basic/SourceManager.h" |
21 | | #include "llvm/Support/raw_ostream.h" |
22 | | using namespace clang; |
23 | | using namespace clang::comments; |
24 | | |
25 | 7 | void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) { |
26 | 7 | NodeDumper.AddChild([=] { |
27 | 7 | OS << "StoredDeclsMap "; |
28 | 7 | NodeDumper.dumpBareDeclRef(cast<Decl>(DC)); |
29 | 7 | |
30 | 7 | const DeclContext *Primary = DC->getPrimaryContext(); |
31 | 7 | if (Primary != DC) { |
32 | 0 | OS << " primary"; |
33 | 0 | NodeDumper.dumpPointer(cast<Decl>(Primary)); |
34 | 0 | } |
35 | 7 | |
36 | 7 | bool HasUndeserializedLookups = Primary->hasExternalVisibleStorage(); |
37 | 7 | |
38 | 7 | auto Range = getDeserialize() |
39 | 7 | ? Primary->lookups()0 |
40 | 7 | : Primary->noload_lookups(/*PreserveInternalState=*/true); |
41 | 140 | for (auto I = Range.begin(), E = Range.end(); I != E; ++I133 ) { |
42 | 133 | DeclarationName Name = I.getLookupName(); |
43 | 133 | DeclContextLookupResult R = *I; |
44 | 133 | |
45 | 133 | NodeDumper.AddChild([=] { |
46 | 133 | OS << "DeclarationName "; |
47 | 133 | { |
48 | 133 | ColorScope Color(OS, ShowColors, DeclNameColor); |
49 | 133 | OS << '\'' << Name << '\''; |
50 | 133 | } |
51 | 133 | |
52 | 133 | for (DeclContextLookupResult::iterator RI = R.begin(), RE = R.end(); |
53 | 303 | RI != RE; ++RI170 ) { |
54 | 170 | NodeDumper.AddChild([=] { |
55 | 170 | NodeDumper.dumpBareDeclRef(*RI); |
56 | 170 | |
57 | 170 | if ((*RI)->isHidden()) |
58 | 7 | OS << " hidden"; |
59 | 170 | |
60 | 170 | // If requested, dump the redecl chain for this lookup. |
61 | 170 | if (DumpDecls) { |
62 | 2 | // Dump earliest decl first. |
63 | 3 | std::function<void(Decl *)> DumpWithPrev = [&](Decl *D) { |
64 | 3 | if (Decl *Prev = D->getPreviousDecl()) |
65 | 1 | DumpWithPrev(Prev); |
66 | 3 | Visit(D); |
67 | 3 | }; |
68 | 2 | DumpWithPrev(*RI); |
69 | 2 | } |
70 | 170 | }); |
71 | 170 | } |
72 | 133 | }); |
73 | 133 | } |
74 | 7 | |
75 | 7 | if (HasUndeserializedLookups) { |
76 | 5 | NodeDumper.AddChild([=] { |
77 | 5 | ColorScope Color(OS, ShowColors, UndeserializedColor); |
78 | 5 | OS << "<undeserialized lookups>"; |
79 | 5 | }); |
80 | 5 | } |
81 | 7 | }); |
82 | 7 | } |
83 | | |
84 | | template <typename SpecializationDecl> |
85 | | void ASTDumper::dumpTemplateDeclSpecialization(const SpecializationDecl *D, |
86 | | bool DumpExplicitInst, |
87 | 116 | bool DumpRefOnly) { |
88 | 116 | bool DumpedAny = false; |
89 | 191 | for (const auto *RedeclWithBadType : D->redecls()) { |
90 | 191 | // FIXME: The redecls() range sometimes has elements of a less-specific |
91 | 191 | // type. (In particular, ClassTemplateSpecializationDecl::redecls() gives |
92 | 191 | // us TagDecls, and should give CXXRecordDecls). |
93 | 191 | auto *Redecl = dyn_cast<SpecializationDecl>(RedeclWithBadType); |
94 | 191 | if (!Redecl) { |
95 | 69 | // Found the injected-class-name for a class template. This will be dumped |
96 | 69 | // as part of its surrounding class so we don't need to dump it here. |
97 | 69 | assert(isa<CXXRecordDecl>(RedeclWithBadType) && |
98 | 69 | "expected an injected-class-name"); |
99 | 69 | continue; |
100 | 69 | } |
101 | 122 | |
102 | 122 | switch (Redecl->getTemplateSpecializationKind()) { |
103 | 122 | case TSK_ExplicitInstantiationDeclaration: |
104 | 15 | case TSK_ExplicitInstantiationDefinition: |
105 | 15 | if (!DumpExplicitInst) |
106 | 10 | break; |
107 | 5 | LLVM_FALLTHROUGH; |
108 | 101 | case TSK_Undeclared: |
109 | 101 | case TSK_ImplicitInstantiation: |
110 | 101 | if (DumpRefOnly) |
111 | 6 | NodeDumper.dumpDeclRef(Redecl); |
112 | 95 | else |
113 | 95 | Visit(Redecl); |
114 | 101 | DumpedAny = true; |
115 | 101 | break; |
116 | 101 | case TSK_ExplicitSpecialization: |
117 | 11 | break; |
118 | 122 | } |
119 | 122 | } |
120 | 116 | |
121 | 116 | // Ensure we dump at least one decl for each specialization. |
122 | 116 | if (!DumpedAny) |
123 | 19 | NodeDumper.dumpDeclRef(D); |
124 | 116 | } void clang::ASTDumper::dumpTemplateDeclSpecialization<clang::FunctionDecl>(clang::FunctionDecl const*, bool, bool) Line | Count | Source | 87 | 37 | bool DumpRefOnly) { | 88 | 37 | bool DumpedAny = false; | 89 | 39 | for (const auto *RedeclWithBadType : D->redecls()) { | 90 | 39 | // FIXME: The redecls() range sometimes has elements of a less-specific | 91 | 39 | // type. (In particular, ClassTemplateSpecializationDecl::redecls() gives | 92 | 39 | // us TagDecls, and should give CXXRecordDecls). | 93 | 39 | auto *Redecl = dyn_cast<SpecializationDecl>(RedeclWithBadType); | 94 | 39 | if (!Redecl) { | 95 | 0 | // Found the injected-class-name for a class template. This will be dumped | 96 | 0 | // as part of its surrounding class so we don't need to dump it here. | 97 | 0 | assert(isa<CXXRecordDecl>(RedeclWithBadType) && | 98 | 0 | "expected an injected-class-name"); | 99 | 0 | continue; | 100 | 0 | } | 101 | 39 | | 102 | 39 | switch (Redecl->getTemplateSpecializationKind()) { | 103 | 39 | case TSK_ExplicitInstantiationDeclaration: | 104 | 5 | case TSK_ExplicitInstantiationDefinition: | 105 | 5 | if (!DumpExplicitInst) | 106 | 0 | break; | 107 | 5 | LLVM_FALLTHROUGH; | 108 | 35 | case TSK_Undeclared: | 109 | 35 | case TSK_ImplicitInstantiation: | 110 | 35 | if (DumpRefOnly) | 111 | 1 | NodeDumper.dumpDeclRef(Redecl); | 112 | 34 | else | 113 | 34 | Visit(Redecl); | 114 | 35 | DumpedAny = true; | 115 | 35 | break; | 116 | 35 | case TSK_ExplicitSpecialization: | 117 | 4 | break; | 118 | 39 | } | 119 | 39 | } | 120 | 37 | | 121 | 37 | // Ensure we dump at least one decl for each specialization. | 122 | 37 | if (!DumpedAny) | 123 | 2 | NodeDumper.dumpDeclRef(D); | 124 | 37 | } |
void clang::ASTDumper::dumpTemplateDeclSpecialization<clang::ClassTemplateSpecializationDecl>(clang::ClassTemplateSpecializationDecl const*, bool, bool) Line | Count | Source | 87 | 77 | bool DumpRefOnly) { | 88 | 77 | bool DumpedAny = false; | 89 | 148 | for (const auto *RedeclWithBadType : D->redecls()) { | 90 | 148 | // FIXME: The redecls() range sometimes has elements of a less-specific | 91 | 148 | // type. (In particular, ClassTemplateSpecializationDecl::redecls() gives | 92 | 148 | // us TagDecls, and should give CXXRecordDecls). | 93 | 148 | auto *Redecl = dyn_cast<SpecializationDecl>(RedeclWithBadType); | 94 | 148 | if (!Redecl) { | 95 | 69 | // Found the injected-class-name for a class template. This will be dumped | 96 | 69 | // as part of its surrounding class so we don't need to dump it here. | 97 | 69 | assert(isa<CXXRecordDecl>(RedeclWithBadType) && | 98 | 69 | "expected an injected-class-name"); | 99 | 69 | continue; | 100 | 69 | } | 101 | 79 | | 102 | 79 | switch (Redecl->getTemplateSpecializationKind()) { | 103 | 79 | case TSK_ExplicitInstantiationDeclaration: | 104 | 10 | case TSK_ExplicitInstantiationDefinition: | 105 | 10 | if (!DumpExplicitInst) | 106 | 10 | break; | 107 | 0 | LLVM_FALLTHROUGH; | 108 | 62 | case TSK_Undeclared: | 109 | 62 | case TSK_ImplicitInstantiation: | 110 | 62 | if (DumpRefOnly) | 111 | 3 | NodeDumper.dumpDeclRef(Redecl); | 112 | 59 | else | 113 | 59 | Visit(Redecl); | 114 | 62 | DumpedAny = true; | 115 | 62 | break; | 116 | 62 | case TSK_ExplicitSpecialization: | 117 | 7 | break; | 118 | 79 | } | 119 | 79 | } | 120 | 77 | | 121 | 77 | // Ensure we dump at least one decl for each specialization. | 122 | 77 | if (!DumpedAny) | 123 | 17 | NodeDumper.dumpDeclRef(D); | 124 | 77 | } |
void clang::ASTDumper::dumpTemplateDeclSpecialization<clang::VarTemplateSpecializationDecl>(clang::VarTemplateSpecializationDecl const*, bool, bool) Line | Count | Source | 87 | 2 | bool DumpRefOnly) { | 88 | 2 | bool DumpedAny = false; | 89 | 4 | for (const auto *RedeclWithBadType : D->redecls()) { | 90 | 4 | // FIXME: The redecls() range sometimes has elements of a less-specific | 91 | 4 | // type. (In particular, ClassTemplateSpecializationDecl::redecls() gives | 92 | 4 | // us TagDecls, and should give CXXRecordDecls). | 93 | 4 | auto *Redecl = dyn_cast<SpecializationDecl>(RedeclWithBadType); | 94 | 4 | if (!Redecl) { | 95 | 0 | // Found the injected-class-name for a class template. This will be dumped | 96 | 0 | // as part of its surrounding class so we don't need to dump it here. | 97 | 0 | assert(isa<CXXRecordDecl>(RedeclWithBadType) && | 98 | 0 | "expected an injected-class-name"); | 99 | 0 | continue; | 100 | 0 | } | 101 | 4 | | 102 | 4 | switch (Redecl->getTemplateSpecializationKind()) { | 103 | 4 | case TSK_ExplicitInstantiationDeclaration: | 104 | 0 | case TSK_ExplicitInstantiationDefinition: | 105 | 0 | if (!DumpExplicitInst) | 106 | 0 | break; | 107 | 0 | LLVM_FALLTHROUGH; | 108 | 4 | case TSK_Undeclared: | 109 | 4 | case TSK_ImplicitInstantiation: | 110 | 4 | if (DumpRefOnly) | 111 | 2 | NodeDumper.dumpDeclRef(Redecl); | 112 | 2 | else | 113 | 2 | Visit(Redecl); | 114 | 4 | DumpedAny = true; | 115 | 4 | break; | 116 | 4 | case TSK_ExplicitSpecialization: | 117 | 0 | break; | 118 | 4 | } | 119 | 4 | } | 120 | 2 | | 121 | 2 | // Ensure we dump at least one decl for each specialization. | 122 | 2 | if (!DumpedAny) | 123 | 0 | NodeDumper.dumpDeclRef(D); | 124 | 2 | } |
|
125 | | |
126 | | template <typename TemplateDecl> |
127 | 223 | void ASTDumper::dumpTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst) { |
128 | 223 | dumpTemplateParameters(D->getTemplateParameters()); |
129 | 223 | |
130 | 223 | Visit(D->getTemplatedDecl()); |
131 | 223 | |
132 | 223 | for (const auto *Child : D->specializations()) |
133 | 116 | dumpTemplateDeclSpecialization(Child, DumpExplicitInst, |
134 | 116 | !D->isCanonicalDecl()); |
135 | 223 | } void clang::ASTDumper::dumpTemplateDecl<clang::FunctionTemplateDecl>(clang::FunctionTemplateDecl const*, bool) Line | Count | Source | 127 | 105 | void ASTDumper::dumpTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst) { | 128 | 105 | dumpTemplateParameters(D->getTemplateParameters()); | 129 | 105 | | 130 | 105 | Visit(D->getTemplatedDecl()); | 131 | 105 | | 132 | 105 | for (const auto *Child : D->specializations()) | 133 | 37 | dumpTemplateDeclSpecialization(Child, DumpExplicitInst, | 134 | 37 | !D->isCanonicalDecl()); | 135 | 105 | } |
void clang::ASTDumper::dumpTemplateDecl<clang::ClassTemplateDecl>(clang::ClassTemplateDecl const*, bool) Line | Count | Source | 127 | 114 | void ASTDumper::dumpTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst) { | 128 | 114 | dumpTemplateParameters(D->getTemplateParameters()); | 129 | 114 | | 130 | 114 | Visit(D->getTemplatedDecl()); | 131 | 114 | | 132 | 114 | for (const auto *Child : D->specializations()) | 133 | 77 | dumpTemplateDeclSpecialization(Child, DumpExplicitInst, | 134 | 77 | !D->isCanonicalDecl()); | 135 | 114 | } |
void clang::ASTDumper::dumpTemplateDecl<clang::VarTemplateDecl>(clang::VarTemplateDecl const*, bool) Line | Count | Source | 127 | 4 | void ASTDumper::dumpTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst) { | 128 | 4 | dumpTemplateParameters(D->getTemplateParameters()); | 129 | 4 | | 130 | 4 | Visit(D->getTemplatedDecl()); | 131 | 4 | | 132 | 4 | for (const auto *Child : D->specializations()) | 133 | 2 | dumpTemplateDeclSpecialization(Child, DumpExplicitInst, | 134 | 2 | !D->isCanonicalDecl()); | 135 | 4 | } |
|
136 | | |
137 | 105 | void ASTDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { |
138 | 105 | // FIXME: We don't add a declaration of a function template specialization |
139 | 105 | // to its context when it's explicitly instantiated, so dump explicit |
140 | 105 | // instantiations when we dump the template itself. |
141 | 105 | dumpTemplateDecl(D, true); |
142 | 105 | } |
143 | | |
144 | 114 | void ASTDumper::VisitClassTemplateDecl(const ClassTemplateDecl *D) { |
145 | 114 | dumpTemplateDecl(D, false); |
146 | 114 | } |
147 | | |
148 | 4 | void ASTDumper::VisitVarTemplateDecl(const VarTemplateDecl *D) { |
149 | 4 | dumpTemplateDecl(D, false); |
150 | 4 | } |
151 | | |
152 | | //===----------------------------------------------------------------------===// |
153 | | // Type method implementations |
154 | | //===----------------------------------------------------------------------===// |
155 | | |
156 | 0 | void QualType::dump(const char *msg) const { |
157 | 0 | if (msg) |
158 | 0 | llvm::errs() << msg << ": "; |
159 | 0 | dump(); |
160 | 0 | } |
161 | | |
162 | 0 | LLVM_DUMP_METHOD void QualType::dump() const { dump(llvm::errs()); } |
163 | | |
164 | 0 | LLVM_DUMP_METHOD void QualType::dump(llvm::raw_ostream &OS) const { |
165 | 0 | ASTDumper Dumper(OS, nullptr, nullptr); |
166 | 0 | Dumper.Visit(*this); |
167 | 0 | } |
168 | | |
169 | 0 | LLVM_DUMP_METHOD void Type::dump() const { dump(llvm::errs()); } |
170 | | |
171 | 0 | LLVM_DUMP_METHOD void Type::dump(llvm::raw_ostream &OS) const { |
172 | 0 | QualType(this, 0).dump(OS); |
173 | 0 | } |
174 | | |
175 | | //===----------------------------------------------------------------------===// |
176 | | // Decl method implementations |
177 | | //===----------------------------------------------------------------------===// |
178 | | |
179 | 18 | LLVM_DUMP_METHOD void Decl::dump() const { dump(llvm::errs()); } |
180 | | |
181 | | LLVM_DUMP_METHOD void Decl::dump(raw_ostream &OS, bool Deserialize, |
182 | 966 | ASTDumpOutputFormat Format) const { |
183 | 966 | ASTContext &Ctx = getASTContext(); |
184 | 966 | const SourceManager &SM = Ctx.getSourceManager(); |
185 | 966 | |
186 | 966 | if (ADOF_JSON == Format) { |
187 | 110 | JSONDumper P(OS, SM, Ctx, Ctx.getPrintingPolicy(), |
188 | 110 | &Ctx.getCommentCommandTraits()); |
189 | 110 | (void)Deserialize; // FIXME? |
190 | 110 | P.Visit(this); |
191 | 856 | } else { |
192 | 856 | ASTDumper P(OS, &Ctx.getCommentCommandTraits(), &SM, |
193 | 856 | SM.getDiagnostics().getShowColors(), Ctx.getPrintingPolicy()); |
194 | 856 | P.setDeserialize(Deserialize); |
195 | 856 | P.Visit(this); |
196 | 856 | } |
197 | 966 | } |
198 | | |
199 | 0 | LLVM_DUMP_METHOD void Decl::dumpColor() const { |
200 | 0 | const ASTContext &Ctx = getASTContext(); |
201 | 0 | ASTDumper P(llvm::errs(), &Ctx.getCommentCommandTraits(), |
202 | 0 | &Ctx.getSourceManager(), /*ShowColors*/ true, |
203 | 0 | Ctx.getPrintingPolicy()); |
204 | 0 | P.Visit(this); |
205 | 0 | } |
206 | | |
207 | 0 | LLVM_DUMP_METHOD void DeclContext::dumpLookups() const { |
208 | 0 | dumpLookups(llvm::errs()); |
209 | 0 | } |
210 | | |
211 | | LLVM_DUMP_METHOD void DeclContext::dumpLookups(raw_ostream &OS, |
212 | | bool DumpDecls, |
213 | 7 | bool Deserialize) const { |
214 | 7 | const DeclContext *DC = this; |
215 | 13 | while (!DC->isTranslationUnit()) |
216 | 6 | DC = DC->getParent(); |
217 | 7 | ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext(); |
218 | 7 | const SourceManager &SM = Ctx.getSourceManager(); |
219 | 7 | ASTDumper P(OS, &Ctx.getCommentCommandTraits(), &Ctx.getSourceManager(), |
220 | 7 | SM.getDiagnostics().getShowColors(), Ctx.getPrintingPolicy()); |
221 | 7 | P.setDeserialize(Deserialize); |
222 | 7 | P.dumpLookups(this, DumpDecls); |
223 | 7 | } |
224 | | |
225 | | //===----------------------------------------------------------------------===// |
226 | | // Stmt method implementations |
227 | | //===----------------------------------------------------------------------===// |
228 | | |
229 | 0 | LLVM_DUMP_METHOD void Stmt::dump(SourceManager &SM) const { |
230 | 0 | dump(llvm::errs(), SM); |
231 | 0 | } |
232 | | |
233 | 1 | LLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS, SourceManager &SM) const { |
234 | 1 | ASTDumper P(OS, nullptr, &SM); |
235 | 1 | P.Visit(this); |
236 | 1 | } |
237 | | |
238 | 0 | LLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS) const { |
239 | 0 | ASTDumper P(OS, nullptr, nullptr); |
240 | 0 | P.Visit(this); |
241 | 0 | } |
242 | | |
243 | 11 | LLVM_DUMP_METHOD void Stmt::dump() const { |
244 | 11 | ASTDumper P(llvm::errs(), nullptr, nullptr); |
245 | 11 | P.Visit(this); |
246 | 11 | } |
247 | | |
248 | 0 | LLVM_DUMP_METHOD void Stmt::dumpColor() const { |
249 | 0 | ASTDumper P(llvm::errs(), nullptr, nullptr, /*ShowColors*/true); |
250 | 0 | P.Visit(this); |
251 | 0 | } |
252 | | |
253 | | //===----------------------------------------------------------------------===// |
254 | | // Comment method implementations |
255 | | //===----------------------------------------------------------------------===// |
256 | | |
257 | 0 | LLVM_DUMP_METHOD void Comment::dump() const { |
258 | 0 | dump(llvm::errs(), nullptr, nullptr); |
259 | 0 | } |
260 | | |
261 | 0 | LLVM_DUMP_METHOD void Comment::dump(const ASTContext &Context) const { |
262 | 0 | dump(llvm::errs(), &Context.getCommentCommandTraits(), |
263 | 0 | &Context.getSourceManager()); |
264 | 0 | } |
265 | | |
266 | | void Comment::dump(raw_ostream &OS, const CommandTraits *Traits, |
267 | 79 | const SourceManager *SM) const { |
268 | 79 | const FullComment *FC = dyn_cast<FullComment>(this); |
269 | 79 | if (!FC) |
270 | 0 | return; |
271 | 79 | ASTDumper D(OS, Traits, SM); |
272 | 79 | D.Visit(FC, FC); |
273 | 79 | } |
274 | | |
275 | 0 | LLVM_DUMP_METHOD void Comment::dumpColor() const { |
276 | 0 | const FullComment *FC = dyn_cast<FullComment>(this); |
277 | 0 | if (!FC) |
278 | 0 | return; |
279 | 0 | ASTDumper D(llvm::errs(), nullptr, nullptr, /*ShowColors*/true); |
280 | 0 | D.Visit(FC, FC); |
281 | 0 | } |