8a0c04fc5e4951b5ebf316f305bb4d179cc9ddd7
[oota-llvm.git] / tools / llvm-pdbdump / ClassDefinitionDumper.cpp
1 //===- ClassDefinitionDumper.cpp --------------------------------*- C++ -*-===//
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 #include "ClassDefinitionDumper.h"
11 #include "FunctionDumper.h"
12 #include "LinePrinter.h"
13 #include "llvm-pdbdump.h"
14 #include "TypedefDumper.h"
15 #include "VariableDumper.h"
16
17 #include "llvm/DebugInfo/PDB/IPDBSession.h"
18 #include "llvm/DebugInfo/PDB/PDBExtras.h"
19 #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
20 #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
21 #include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
22 #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
23 #include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
24 #include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
25 #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
26 #include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h"
27 #include "llvm/Support/Format.h"
28
29 using namespace llvm;
30
31 ClassDefinitionDumper::ClassDefinitionDumper(LinePrinter &P)
32     : PDBSymDumper(true), Printer(P) {}
33
34 void ClassDefinitionDumper::start(const PDBSymbolTypeUDT &Class,
35                                   raw_ostream &OS, int Indent) {
36   std::string Name = Class.getName();
37   WithColor(Printer, PDB_ColorItem::Keyword).get() << "class ";
38   WithColor(Printer, PDB_ColorItem::Type).get() << Class.getName();
39   Printer << " {";
40   auto Children = Class.findAllChildren();
41   if (Children->getChildCount() == 0) {
42     OS << "}";
43     return;
44   }
45
46   // Try to dump symbols organized by member access level.  Public members
47   // first, then protected, then private.  This might be slow, so it's worth
48   // reconsidering the value of this if performance of large PDBs is a problem.
49   // NOTE: Access level of nested types is not recorded in the PDB, so we have
50   // a special case for them.
51   SymbolGroupByAccess Groups;
52   Groups.insert(std::make_pair(0, SymbolGroup()));
53   Groups.insert(std::make_pair((int)PDB_MemberAccess::Private, SymbolGroup()));
54   Groups.insert(
55       std::make_pair((int)PDB_MemberAccess::Protected, SymbolGroup()));
56   Groups.insert(std::make_pair((int)PDB_MemberAccess::Public, SymbolGroup()));
57
58   while (auto Child = Children->getNext()) {
59     PDB_MemberAccess Access = Child->getRawSymbol().getAccess();
60     if (isa<PDBSymbolTypeBaseClass>(*Child))
61       continue;
62
63     auto &AccessGroup = Groups.find((int)Access)->second;
64
65     if (auto Func = dyn_cast<PDBSymbolFunc>(Child.get())) {
66       if (Func->isCompilerGenerated())
67         continue;
68       if (Func->getLength() == 0 && !Func->isPureVirtual())
69         continue;
70       Child.release();
71       AccessGroup.Functions.push_back(std::unique_ptr<PDBSymbolFunc>(Func));
72     } else if (auto Data = dyn_cast<PDBSymbolData>(Child.get())) {
73       Child.release();
74       AccessGroup.Data.push_back(std::unique_ptr<PDBSymbolData>(Data));
75     } else {
76       AccessGroup.Unknown.push_back(std::move(Child));
77     }
78   }
79
80   int Count = 0;
81   Count += dumpAccessGroup((PDB_MemberAccess)0, Groups[0], OS, Indent);
82   Count += dumpAccessGroup(PDB_MemberAccess::Public,
83                            Groups[(int)PDB_MemberAccess::Public], OS, Indent);
84   Count +=
85       dumpAccessGroup(PDB_MemberAccess::Protected,
86                       Groups[(int)PDB_MemberAccess::Protected], OS, Indent);
87   Count += dumpAccessGroup(PDB_MemberAccess::Private,
88                            Groups[(int)PDB_MemberAccess::Private], OS, Indent);
89   if (Count > 0)
90     Printer.NewLine();
91   OS << "}";
92 }
93
94 int ClassDefinitionDumper::dumpAccessGroup(PDB_MemberAccess Access,
95                                            const SymbolGroup &Group,
96                                            raw_ostream &OS, int Indent) {
97   if (Group.Functions.empty() && Group.Data.empty() && Group.Unknown.empty())
98     return 0;
99
100   int Count = 0;
101   if (Access == PDB_MemberAccess::Private) {
102     Printer.NewLine();
103     WithColor(Printer, PDB_ColorItem::Keyword).get() << "private";
104     Printer << ":";
105   } else if (Access == PDB_MemberAccess::Protected) {
106     Printer.NewLine();
107     WithColor(Printer, PDB_ColorItem::Keyword).get() << "protected";
108     Printer << ":";
109   } else if (Access == PDB_MemberAccess::Public) {
110     Printer.NewLine();
111     WithColor(Printer, PDB_ColorItem::Keyword).get() << "public";
112     Printer << ":";
113   }
114   Printer.Indent();
115   for (auto iter = Group.Functions.begin(), end = Group.Functions.end();
116        iter != end; ++iter) {
117     ++Count;
118     (*iter)->dump(OS, Indent + 2, *this);
119   }
120   for (auto iter = Group.Data.begin(), end = Group.Data.end(); iter != end;
121        ++iter) {
122     ++Count;
123     (*iter)->dump(OS, Indent + 2, *this);
124   }
125   for (auto iter = Group.Unknown.begin(), end = Group.Unknown.end();
126        iter != end; ++iter) {
127     ++Count;
128     (*iter)->dump(OS, Indent + 2, *this);
129   }
130   Printer.Unindent();
131   return Count;
132 }
133
134 void ClassDefinitionDumper::dump(const PDBSymbolTypeBaseClass &Symbol,
135                                  raw_ostream &OS, int Indent) {}
136
137 void ClassDefinitionDumper::dump(const PDBSymbolData &Symbol, raw_ostream &OS,
138                                  int Indent) {
139   VariableDumper Dumper(Printer);
140   Dumper.start(Symbol, OS, Indent);
141 }
142
143 void ClassDefinitionDumper::dump(const PDBSymbolFunc &Symbol, raw_ostream &OS,
144                                  int Indent) {
145   Printer.NewLine();
146   FunctionDumper Dumper(Printer);
147   Dumper.start(Symbol, FunctionDumper::PointerType::None, OS, Indent);
148 }
149
150 void ClassDefinitionDumper::dump(const PDBSymbolTypeVTable &Symbol,
151                                  raw_ostream &OS, int Indent) {}
152
153 void ClassDefinitionDumper::dump(const PDBSymbolTypeEnum &Symbol,
154                                  raw_ostream &OS, int Indent) {
155   Printer.NewLine();
156   WithColor(Printer, PDB_ColorItem::Keyword).get() << "enum ";
157   WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
158 }
159
160 void ClassDefinitionDumper::dump(const PDBSymbolTypeTypedef &Symbol,
161                                  raw_ostream &OS, int Indent) {
162   Printer.NewLine();
163   TypedefDumper Dumper(Printer);
164   Dumper.start(Symbol, OS, Indent);
165 }
166
167 void ClassDefinitionDumper::dump(const PDBSymbolTypeUDT &Symbol,
168                                  raw_ostream &OS, int Indent) {}