 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
50.8% |
92 / 181 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
75.7% |
137 / 181 |
| |
|
Line Coverage: |
67.4% |
215 / 319 |
| |
 |
|
 |
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/Frontend/DocumentXML.h"
16 : #include "clang/Frontend/PathDiagnosticClients.h"
17 : #include "clang/Basic/Diagnostic.h"
18 : #include "clang/Basic/SourceManager.h"
19 : #include "clang/Basic/FileManager.h"
20 : #include "clang/AST/AST.h"
21 : #include "clang/AST/ASTConsumer.h"
22 : #include "clang/AST/ASTContext.h"
23 : #include "clang/AST/RecordLayout.h"
24 : #include "clang/AST/PrettyPrinter.h"
25 : #include "clang/CodeGen/ModuleBuilder.h"
26 : #include "llvm/Module.h"
27 : #include "llvm/Support/Format.h"
28 : #include "llvm/Support/Timer.h"
29 : #include "llvm/Support/raw_ostream.h"
30 : #include "llvm/System/Path.h"
31 : using namespace clang;
32 :
33 : //===----------------------------------------------------------------------===//
34 : /// ASTPrinter - Pretty-printer and dumper of ASTs
35 :
36 : namespace {
22: branch 1 taken
0: branch 2 not taken
0: branch 5 not taken
0: branch 6 not taken
37 22: class ASTPrinter : public ASTConsumer {
38 : llvm::raw_ostream &Out;
39 : bool Dump;
40 :
41 : public:
42 22: ASTPrinter(llvm::raw_ostream* o = NULL, bool Dump = false)
5: branch 1 taken
17: branch 2 taken
43 22: : Out(o? *o : llvm::errs()), Dump(Dump) { }
44 :
45 22: virtual void HandleTranslationUnit(ASTContext &Context) {
46 22: PrintingPolicy Policy = Context.PrintingPolicy;
47 22: Policy.Dump = Dump;
48 22: Context.getTranslationUnitDecl()->print(Out, Policy);
49 22: }
50 : };
51 : } // end anonymous namespace
52 :
53 17: ASTConsumer *clang::CreateASTPrinter(llvm::raw_ostream* out) {
54 17: return new ASTPrinter(out);
55 : }
56 :
57 : //===----------------------------------------------------------------------===//
58 : /// ASTPrinterXML - XML-printer of ASTs
59 :
60 : namespace {
1: branch 2 taken
0: branch 3 not taken
0: branch 7 not taken
0: branch 8 not taken
61 1: class ASTPrinterXML : public ASTConsumer {
62 : DocumentXML Doc;
63 :
64 : public:
65 1: ASTPrinterXML(llvm::raw_ostream& o) : Doc("CLANG_XML", o) {}
66 :
67 1: void Initialize(ASTContext &Context) {
68 1: Doc.initialize(Context);
69 1: }
70 :
71 1: virtual void HandleTranslationUnit(ASTContext &Ctx) {
72 1: Doc.addSubNode("TranslationUnit");
31: branch 2 taken
1: branch 3 taken
73 32: for (DeclContext::decl_iterator
74 1: D = Ctx.getTranslationUnitDecl()->decls_begin(),
75 1: DEnd = Ctx.getTranslationUnitDecl()->decls_end();
76 : D != DEnd;
77 : ++D)
78 31: Doc.PrintDecl(*D);
79 1: Doc.toParent();
80 1: Doc.finalize();
81 1: }
82 : };
83 : } // end anonymous namespace
84 :
85 :
86 1: ASTConsumer *clang::CreateASTPrinterXML(llvm::raw_ostream* out) {
0: branch 0 not taken
1: branch 1 taken
87 1: return new ASTPrinterXML(out ? *out : llvm::outs());
88 : }
89 :
90 5: ASTConsumer *clang::CreateASTDumper() {
91 5: return new ASTPrinter(0, true);
92 : }
93 :
94 : //===----------------------------------------------------------------------===//
95 : /// ASTViewer - AST Visualization
96 :
97 : namespace {
0: branch 2 not taken
0: branch 3 not taken
0: branch 6 not taken
0: branch 7 not taken
98 0: class ASTViewer : public ASTConsumer {
99 : ASTContext *Context;
100 : public:
101 0: void Initialize(ASTContext &Context) {
102 0: this->Context = &Context;
103 0: }
104 :
105 0: virtual void HandleTopLevelDecl(DeclGroupRef D) {
0: branch 2 not taken
0: branch 3 not taken
106 0: for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
107 0: HandleTopLevelSingleDecl(*I);
108 0: }
109 :
110 : void HandleTopLevelSingleDecl(Decl *D);
111 : };
112 : }
113 :
114 0: void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
0: branch 1 not taken
0: branch 2 not taken
115 0: if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
116 0: FD->print(llvm::errs());
117 :
0: branch 1 not taken
0: branch 2 not taken
118 0: if (Stmt *Body = FD->getBody()) {
119 0: llvm::errs() << '\n';
120 0: Body->viewAST();
121 0: llvm::errs() << '\n';
122 : }
123 0: return;
124 : }
125 :
0: branch 1 not taken
0: branch 2 not taken
126 0: if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
127 0: MD->print(llvm::errs());
128 :
0: branch 1 not taken
0: branch 2 not taken
129 0: if (MD->getBody()) {
130 0: llvm::errs() << '\n';
131 0: MD->getBody()->viewAST();
132 0: llvm::errs() << '\n';
133 : }
134 : }
135 : }
136 :
137 :
138 0: ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); }
139 :
140 : //===----------------------------------------------------------------------===//
141 : /// DeclContextPrinter - Decl and DeclContext Visualization
142 :
143 : namespace {
144 :
2: branch 1 taken
0: branch 2 not taken
0: branch 5 not taken
0: branch 6 not taken
145 2: class DeclContextPrinter : public ASTConsumer {
146 : llvm::raw_ostream& Out;
147 : public:
148 2: DeclContextPrinter() : Out(llvm::errs()) {}
149 :
150 2: void HandleTranslationUnit(ASTContext &C) {
2: branch 1 taken
0: branch 2 not taken
151 2: PrintDeclContext(C.getTranslationUnitDecl(), 4);
152 2: }
153 :
154 : void PrintDeclContext(const DeclContext* DC, unsigned Indentation);
155 : };
156 : } // end anonymous namespace
157 :
158 : void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
159 47: unsigned Indentation) {
160 : // Print DeclContext name.
2: branch 1 taken
2: branch 2 taken
1: branch 3 taken
7: branch 4 taken
6: branch 5 taken
0: branch 6 not taken
0: branch 7 not taken
0: branch 8 not taken
0: branch 9 not taken
0: branch 10 not taken
0: branch 11 not taken
0: branch 12 not taken
0: branch 13 not taken
17: branch 14 taken
3: branch 15 taken
6: branch 16 taken
3: branch 17 taken
0: branch 18 not taken
0: branch 19 not taken
161 47: switch (DC->getDeclKind()) {
162 : case Decl::TranslationUnit:
163 2: Out << "[translation unit] " << DC;
164 2: break;
165 : case Decl::Namespace: {
166 2: Out << "[namespace] ";
167 2: const NamespaceDecl* ND = cast<NamespaceDecl>(DC);
168 2: Out << ND->getNameAsString();
169 2: break;
170 : }
171 : case Decl::Enum: {
172 1: const EnumDecl* ED = cast<EnumDecl>(DC);
1: branch 1 taken
0: branch 2 not taken
173 1: if (ED->isDefinition())
174 1: Out << "[enum] ";
175 : else
176 0: Out << "<enum> ";
177 1: Out << ED->getNameAsString();
178 1: break;
179 : }
180 : case Decl::Record: {
181 7: const RecordDecl* RD = cast<RecordDecl>(DC);
6: branch 1 taken
1: branch 2 taken
182 7: if (RD->isDefinition())
183 6: Out << "[struct] ";
184 : else
185 1: Out << "<struct> ";
186 7: Out << RD->getNameAsString();
187 7: break;
188 : }
189 : case Decl::CXXRecord: {
190 6: const CXXRecordDecl* RD = cast<CXXRecordDecl>(DC);
3: branch 1 taken
3: branch 2 taken
191 6: if (RD->isDefinition())
192 3: Out << "[class] ";
193 : else
194 3: Out << "<class> ";
195 6: Out << RD->getNameAsString() << " " << DC;
196 6: break;
197 : }
198 : case Decl::ObjCMethod:
199 0: Out << "[objc method]";
200 0: break;
201 : case Decl::ObjCInterface:
202 0: Out << "[objc interface]";
203 0: break;
204 : case Decl::ObjCCategory:
205 0: Out << "[objc category]";
206 0: break;
207 : case Decl::ObjCProtocol:
208 0: Out << "[objc protocol]";
209 0: break;
210 : case Decl::ObjCImplementation:
211 0: Out << "[objc implementation]";
212 0: break;
213 : case Decl::ObjCCategoryImpl:
214 0: Out << "[objc categoryimpl]";
215 0: break;
216 : case Decl::LinkageSpec:
217 0: Out << "[linkage spec]";
218 0: break;
219 : case Decl::Block:
220 0: Out << "[block]";
221 0: break;
222 : case Decl::Function: {
223 17: const FunctionDecl* FD = cast<FunctionDecl>(DC);
11: branch 1 taken
6: branch 2 taken
224 17: if (FD->isThisDeclarationADefinition())
225 11: Out << "[function] ";
226 : else
227 6: Out << "<function> ";
228 17: Out << FD->getNameAsString();
229 : // Print the parameters.
230 17: Out << "(";
231 17: bool PrintComma = false;
17: branch 1 taken
17: branch 2 taken
232 51: for (FunctionDecl::param_const_iterator I = FD->param_begin(),
233 17: E = FD->param_end(); I != E; ++I) {
5: branch 0 taken
12: branch 1 taken
234 17: if (PrintComma)
235 5: Out << ", ";
236 : else
237 12: PrintComma = true;
238 17: Out << (*I)->getNameAsString();
239 : }
240 17: Out << ")";
241 17: break;
242 : }
243 : case Decl::CXXMethod: {
244 3: const CXXMethodDecl* D = cast<CXXMethodDecl>(DC);
0: branch 1 not taken
3: branch 2 taken
245 3: if (D->isOutOfLine())
246 0: Out << "[c++ method] ";
3: branch 1 taken
0: branch 2 not taken
247 3: else if (D->isImplicit())
248 3: Out << "(c++ method) ";
249 : else
250 0: Out << "<c++ method> ";
251 3: Out << D->getNameAsString();
252 : // Print the parameters.
253 3: Out << "(";
254 3: bool PrintComma = false;
3: branch 1 taken
3: branch 2 taken
255 9: for (FunctionDecl::param_const_iterator I = D->param_begin(),
256 3: E = D->param_end(); I != E; ++I) {
0: branch 0 not taken
3: branch 1 taken
257 3: if (PrintComma)
258 0: Out << ", ";
259 : else
260 3: PrintComma = true;
261 3: Out << (*I)->getNameAsString();
262 : }
263 3: Out << ")";
264 :
265 : // Check the semantic DeclContext.
266 3: const DeclContext* SemaDC = D->getDeclContext();
267 3: const DeclContext* LexicalDC = D->getLexicalDeclContext();
0: branch 0 not taken
3: branch 1 taken
268 3: if (SemaDC != LexicalDC)
269 0: Out << " [[" << SemaDC << "]]";
270 :
271 3: break;
272 : }
273 : case Decl::CXXConstructor: {
274 6: const CXXConstructorDecl* D = cast<CXXConstructorDecl>(DC);
0: branch 1 not taken
6: branch 2 taken
275 6: if (D->isOutOfLine())
276 0: Out << "[c++ ctor] ";
6: branch 1 taken
0: branch 2 not taken
277 6: else if (D->isImplicit())
278 6: Out << "(c++ ctor) ";
279 : else
280 0: Out << "<c++ ctor> ";
281 6: Out << D->getNameAsString();
282 : // Print the parameters.
283 6: Out << "(";
284 6: bool PrintComma = false;
3: branch 1 taken
6: branch 2 taken
285 15: for (FunctionDecl::param_const_iterator I = D->param_begin(),
286 6: E = D->param_end(); I != E; ++I) {
0: branch 0 not taken
3: branch 1 taken
287 3: if (PrintComma)
288 0: Out << ", ";
289 : else
290 3: PrintComma = true;
291 3: Out << (*I)->getNameAsString();
292 : }
293 6: Out << ")";
294 :
295 : // Check the semantic DC.
296 6: const DeclContext* SemaDC = D->getDeclContext();
297 6: const DeclContext* LexicalDC = D->getLexicalDeclContext();
0: branch 0 not taken
6: branch 1 taken
298 6: if (SemaDC != LexicalDC)
299 0: Out << " [[" << SemaDC << "]]";
300 6: break;
301 : }
302 : case Decl::CXXDestructor: {
303 3: const CXXDestructorDecl* D = cast<CXXDestructorDecl>(DC);
0: branch 1 not taken
3: branch 2 taken
304 3: if (D->isOutOfLine())
305 0: Out << "[c++ dtor] ";
3: branch 1 taken
0: branch 2 not taken
306 3: else if (D->isImplicit())
307 3: Out << "(c++ dtor) ";
308 : else
309 0: Out << "<c++ dtor> ";
310 3: Out << D->getNameAsString();
311 : // Check the semantic DC.
312 3: const DeclContext* SemaDC = D->getDeclContext();
313 3: const DeclContext* LexicalDC = D->getLexicalDeclContext();
0: branch 0 not taken
3: branch 1 taken
314 3: if (SemaDC != LexicalDC)
315 0: Out << " [[" << SemaDC << "]]";
316 3: break;
317 : }
318 : case Decl::CXXConversion: {
319 0: const CXXConversionDecl* D = cast<CXXConversionDecl>(DC);
0: branch 1 not taken
0: branch 2 not taken
320 0: if (D->isOutOfLine())
321 0: Out << "[c++ conversion] ";
0: branch 1 not taken
0: branch 2 not taken
322 0: else if (D->isImplicit())
323 0: Out << "(c++ conversion) ";
324 : else
325 0: Out << "<c++ conversion> ";
326 0: Out << D->getNameAsString();
327 : // Check the semantic DC.
328 0: const DeclContext* SemaDC = D->getDeclContext();
329 0: const DeclContext* LexicalDC = D->getLexicalDeclContext();
0: branch 0 not taken
0: branch 1 not taken
330 0: if (SemaDC != LexicalDC)
331 0: Out << " [[" << SemaDC << "]]";
332 0: break;
333 : }
334 :
335 : default:
336 0: assert(0 && "a decl that inherits DeclContext isn't handled");
337 : }
338 :
339 47: Out << "\n";
340 :
341 : // Print decls in the DeclContext.
139: branch 4 taken
47: branch 5 taken
342 186: for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
343 : I != E; ++I) {
766: branch 0 taken
139: branch 1 taken
344 905: for (unsigned i = 0; i < Indentation; ++i)
345 766: Out << " ";
346 :
347 139: Decl::Kind DK = I->getKind();
45: branch 0 taken
8: branch 1 taken
8: branch 2 taken
1: branch 3 taken
63: branch 4 taken
0: branch 5 not taken
10: branch 6 taken
0: branch 7 not taken
0: branch 8 not taken
1: branch 9 taken
2: branch 10 taken
1: branch 11 taken
0: branch 12 not taken
0: branch 13 not taken
348 139: switch (DK) {
349 : case Decl::Namespace:
350 : case Decl::Enum:
351 : case Decl::Record:
352 : case Decl::CXXRecord:
353 : case Decl::ObjCMethod:
354 : case Decl::ObjCInterface:
355 : case Decl::ObjCCategory:
356 : case Decl::ObjCProtocol:
357 : case Decl::ObjCImplementation:
358 : case Decl::ObjCCategoryImpl:
359 : case Decl::LinkageSpec:
360 : case Decl::Block:
361 : case Decl::Function:
362 : case Decl::CXXMethod:
363 : case Decl::CXXConstructor:
364 : case Decl::CXXDestructor:
365 : case Decl::CXXConversion:
366 : {
367 45: DeclContext* DC = cast<DeclContext>(*I);
368 45: PrintDeclContext(DC, Indentation+2);
369 45: break;
370 : }
371 : case Decl::Field: {
372 8: FieldDecl* FD = cast<FieldDecl>(*I);
373 8: Out << "<field> " << FD->getNameAsString() << "\n";
374 8: break;
375 : }
376 : case Decl::Typedef: {
377 8: TypedefDecl* TD = cast<TypedefDecl>(*I);
378 8: Out << "<typedef> " << TD->getNameAsString() << "\n";
379 8: break;
380 : }
381 : case Decl::EnumConstant: {
382 1: EnumConstantDecl* ECD = cast<EnumConstantDecl>(*I);
383 1: Out << "<enum constant> " << ECD->getNameAsString() << "\n";
384 1: break;
385 : }
386 : case Decl::Var: {
387 63: VarDecl* VD = cast<VarDecl>(*I);
388 63: Out << "<var> " << VD->getNameAsString() << "\n";
389 63: break;
390 : }
391 : case Decl::ImplicitParam: {
392 0: ImplicitParamDecl* IPD = cast<ImplicitParamDecl>(*I);
393 0: Out << "<implicit parameter> " << IPD->getNameAsString() << "\n";
394 0: break;
395 : }
396 : case Decl::ParmVar: {
397 10: ParmVarDecl* PVD = cast<ParmVarDecl>(*I);
398 10: Out << "<parameter> " << PVD->getNameAsString() << "\n";
399 10: break;
400 : }
401 : case Decl::ObjCProperty: {
402 0: ObjCPropertyDecl* OPD = cast<ObjCPropertyDecl>(*I);
403 0: Out << "<objc property> " << OPD->getNameAsString() << "\n";
404 0: break;
405 : }
406 : case Decl::FunctionTemplate: {
407 0: FunctionTemplateDecl* FTD = cast<FunctionTemplateDecl>(*I);
408 0: Out << "<function template> " << FTD->getNameAsString() << "\n";
409 0: break;
410 : }
411 : case Decl::FileScopeAsm: {
412 1: Out << "<file-scope asm>\n";
413 1: break;
414 : }
415 : case Decl::UsingDirective: {
416 2: Out << "<using directive>\n";
417 2: break;
418 : }
419 : case Decl::NamespaceAlias: {
420 1: NamespaceAliasDecl* NAD = cast<NamespaceAliasDecl>(*I);
421 1: Out << "<namespace alias> " << NAD->getNameAsString() << "\n";
422 1: break;
423 : }
424 : case Decl::ClassTemplate: {
425 0: ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(*I);
426 0: Out << "<class template> " << CTD->getNameAsString() << '\n';
427 0: break;
428 : }
429 : default:
430 0: Out << "DeclKind: " << DK << '"' << I->getDeclKindName() << "\"\n";
431 0: assert(0 && "decl unhandled");
432 : }
433 : }
434 47: }
435 2: ASTConsumer *clang::CreateDeclContextPrinter() {
436 2: return new DeclContextPrinter();
437 : }
438 :
439 : //===----------------------------------------------------------------------===//
440 : /// RecordLayoutDumper - C++ Record Layout Dumping.
441 : namespace {
1: branch 1 taken
0: branch 2 not taken
0: branch 5 not taken
0: branch 6 not taken
442 1: class RecordLayoutDumper : public ASTConsumer {
443 : llvm::raw_ostream& Out;
444 :
445 6: void PrintOffset(uint64_t Offset, unsigned IndentLevel) {
446 6: Out << llvm::format("%4d | ", Offset);
6: branch 1 taken
6: branch 2 taken
447 6: for (unsigned I = 0; I < IndentLevel * 2; ++I) Out << ' ';
448 6: }
449 :
450 : void DumpRecordLayoutOffsets(const CXXRecordDecl *RD, ASTContext &C,
451 : uint64_t Offset,
452 : unsigned IndentLevel, const char* Description,
453 5: bool IncludeVirtualBases) {
454 5: const ASTRecordLayout &Info = C.getASTRecordLayout(RD);
455 :
456 5: PrintOffset(Offset, IndentLevel);
457 5: Out << C.getTypeDeclType((CXXRecordDecl *)RD).getAsString();
2: branch 0 taken
3: branch 1 taken
458 5: if (Description)
459 2: Out << ' ' << Description;
4: branch 1 taken
1: branch 2 taken
460 5: if (RD->isEmpty())
461 4: Out << " (empty)";
462 5: Out << '\n';
463 :
464 5: IndentLevel++;
465 :
466 5: const CXXRecordDecl *PrimaryBase = Info.getPrimaryBase();
467 :
468 : // Vtable pointer.
1: branch 1 taken
4: branch 2 taken
1: branch 3 taken
0: branch 4 not taken
1: branch 5 taken
4: branch 6 taken
469 5: if (RD->isDynamicClass() && !PrimaryBase) {
470 1: PrintOffset(Offset, IndentLevel);
471 1: Out << '(' << RD->getNameAsString() << " vtable pointer)\n";
472 : }
473 : // Dump (non-virtual) bases
2: branch 1 taken
5: branch 2 taken
474 12: for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
475 5: E = RD->bases_end(); I != E; ++I) {
476 : assert(!I->getType()->isDependentType() &&
2: branch 3 taken
0: branch 4 not taken
477 2: "Cannot layout class with dependent bases.");
1: branch 1 taken
1: branch 2 taken
478 2: if (I->isVirtual())
479 1: continue;
480 :
481 : const CXXRecordDecl *Base =
482 1: cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
483 :
484 1: uint64_t BaseOffset = Offset + Info.getBaseClassOffset(Base) / 8;
485 :
486 : DumpRecordLayoutOffsets(Base, C, BaseOffset, IndentLevel,
487 : Base == PrimaryBase ? "(primary base)" : "(base)",
0: branch 0 not taken
1: branch 1 taken
488 1: /*IncludeVirtualBases=*/false);
489 : }
490 :
491 : // Dump fields.
492 5: uint64_t FieldNo = 0;
0: branch 3 not taken
5: branch 4 taken
493 10: for (CXXRecordDecl::field_iterator I = RD->field_begin(),
494 5: E = RD->field_end(); I != E; ++I, ++FieldNo) {
495 0: const FieldDecl *Field = *I;
496 0: uint64_t FieldOffset = Offset + Info.getFieldOffset(FieldNo) / 8;
497 :
0: branch 3 not taken
0: branch 4 not taken
498 0: if (const RecordType *RT = Field->getType()->getAs<RecordType>()) {
0: branch 2 not taken
0: branch 3 not taken
499 0: if (const CXXRecordDecl *D = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
500 : DumpRecordLayoutOffsets(D, C, FieldOffset, IndentLevel,
501 : Field->getNameAsCString(),
502 0: /*IncludeVirtualBases=*/true);
503 0: continue;
504 : }
505 : }
506 :
507 0: PrintOffset(FieldOffset, IndentLevel);
508 0: Out << Field->getType().getAsString() << ' ';
509 0: Out << Field->getNameAsString() << '\n';
510 : }
511 :
2: branch 0 taken
3: branch 1 taken
512 5: if (!IncludeVirtualBases)
513 2: return;
514 :
515 : // Dump virtual bases.
1: branch 1 taken
3: branch 2 taken
516 7: for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
517 3: E = RD->vbases_end(); I != E; ++I) {
1: branch 1 taken
0: branch 2 not taken
518 1: assert(I->isVirtual() && "Found non-virtual class!");
519 : const CXXRecordDecl *VBase =
520 1: cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
521 :
522 1: uint64_t VBaseOffset = Offset + Info.getVBaseClassOffset(VBase) / 8;
523 : DumpRecordLayoutOffsets(VBase, C, VBaseOffset, IndentLevel,
524 : VBase == PrimaryBase ?
525 : "(primary virtual base)" : "(virtual base)",
0: branch 0 not taken
1: branch 1 taken
526 1: /*IncludeVirtualBases=*/false);
527 : }
528 : }
529 :
530 : // FIXME: Maybe this could be useful in ASTContext.cpp.
531 3: void DumpRecordLayout(const CXXRecordDecl *RD, ASTContext &C) {
532 3: const ASTRecordLayout &Info = C.getASTRecordLayout(RD);
533 :
534 : DumpRecordLayoutOffsets(RD, C, 0, 0, 0,
535 3: /*IncludeVirtualBases=*/true);
536 3: Out << " sizeof=" << Info.getSize() / 8;
537 3: Out << ", dsize=" << Info.getDataSize() / 8;
538 3: Out << ", align=" << Info.getAlignment() / 8 << '\n';
539 3: Out << " nvsize=" << Info.getNonVirtualSize() / 8;
540 3: Out << ", nvalign=" << Info.getNonVirtualAlign() / 8 << '\n';
541 3: Out << '\n';
542 3: }
543 :
544 : public:
545 1: RecordLayoutDumper() : Out(llvm::errs()) {}
546 :
547 1: void HandleTranslationUnit(ASTContext &C) {
49: branch 4 taken
1: branch 5 taken
548 50: for (ASTContext::type_iterator I = C.types_begin(), E = C.types_end();
549 : I != E; ++I) {
550 49: const RecordType *RT = dyn_cast<RecordType>(*I);
46: branch 0 taken
3: branch 1 taken
551 49: if (!RT)
552 46: continue;
553 :
554 3: const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
0: branch 0 not taken
3: branch 1 taken
555 3: if (!RD)
556 0: continue;
557 :
0: branch 1 not taken
3: branch 2 taken
558 3: if (RD->isImplicit())
559 0: continue;
560 :
0: branch 1 not taken
3: branch 2 taken
561 3: if (RD->isDependentType())
562 0: continue;
563 :
0: branch 1 not taken
3: branch 2 taken
564 3: if (RD->isInvalidDecl())
565 0: continue;
566 :
0: branch 1 not taken
3: branch 2 taken
567 3: if (!RD->getDefinition(C))
568 0: continue;
569 :
570 : // FIXME: Do we really need to hard code this?
0: branch 3 not taken
3: branch 4 taken
571 3: if (RD->getQualifiedNameAsString() == "__va_list_tag")
572 0: continue;
573 :
574 3: DumpRecordLayout(RD, C);
575 : }
576 1: }
577 : };
578 : } // end anonymous namespace
579 1: ASTConsumer *clang::CreateRecordLayoutDumper() {
580 1: return new RecordLayoutDumper();
581 : }
582 :
583 : //===----------------------------------------------------------------------===//
584 : /// InheritanceViewer - C++ Inheritance Visualization
585 :
586 : namespace {
0: branch 2 not taken
0: branch 3 not taken
0: branch 7 not taken
0: branch 8 not taken
587 0: class InheritanceViewer : public ASTConsumer {
588 : const std::string clsname;
589 : public:
590 0: InheritanceViewer(const std::string& cname) : clsname(cname) {}
591 :
592 0: void HandleTranslationUnit(ASTContext &C) {
0: branch 4 not taken
0: branch 5 not taken
593 0: for (ASTContext::type_iterator I=C.types_begin(),E=C.types_end(); I!=E; ++I)
0: branch 2 not taken
0: branch 3 not taken
594 0: if (RecordType *T = dyn_cast<RecordType>(*I)) {
0: branch 2 not taken
0: branch 3 not taken
595 0: if (CXXRecordDecl *D = dyn_cast<CXXRecordDecl>(T->getDecl())) {
596 : // FIXME: This lookup needs to be generalized to handle namespaces and
597 : // (when we support them) templates.
0: branch 3 not taken
0: branch 4 not taken
598 0: if (D->getNameAsString() == clsname) {
599 0: D->viewInheritance(C);
600 : }
601 : }
602 : }
603 0: }
604 : };
605 : }
606 :
607 0: ASTConsumer *clang::CreateInheritanceViewer(const std::string& clsname) {
608 0: return new InheritanceViewer(clsname);
609 : }
Generated: 2010-02-10 01:31 by zcov