1bdd1243dSDimitry Andric //===-- LVType.cpp --------------------------------------------------------===//
2bdd1243dSDimitry Andric //
3bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6bdd1243dSDimitry Andric //
7bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
8bdd1243dSDimitry Andric //
9bdd1243dSDimitry Andric // This implements the LVType class.
10bdd1243dSDimitry Andric //
11bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
12bdd1243dSDimitry Andric 
13bdd1243dSDimitry Andric #include "llvm/DebugInfo/LogicalView/Core/LVType.h"
14bdd1243dSDimitry Andric #include "llvm/DebugInfo/LogicalView/Core/LVCompare.h"
15bdd1243dSDimitry Andric #include "llvm/DebugInfo/LogicalView/Core/LVReader.h"
16bdd1243dSDimitry Andric #include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
17bdd1243dSDimitry Andric 
18bdd1243dSDimitry Andric using namespace llvm;
19bdd1243dSDimitry Andric using namespace llvm::logicalview;
20bdd1243dSDimitry Andric 
21bdd1243dSDimitry Andric #define DEBUG_TYPE "Type"
22bdd1243dSDimitry Andric 
23bdd1243dSDimitry Andric namespace {
24bdd1243dSDimitry Andric const char *const KindBaseType = "BaseType";
25bdd1243dSDimitry Andric const char *const KindConst = "Const";
26bdd1243dSDimitry Andric const char *const KindEnumerator = "Enumerator";
27bdd1243dSDimitry Andric const char *const KindImport = "Import";
28bdd1243dSDimitry Andric const char *const KindPointer = "Pointer";
29bdd1243dSDimitry Andric const char *const KindPointerMember = "PointerMember";
30bdd1243dSDimitry Andric const char *const KindReference = "Reference";
31bdd1243dSDimitry Andric const char *const KindRestrict = "Restrict";
32bdd1243dSDimitry Andric const char *const KindRvalueReference = "RvalueReference";
33bdd1243dSDimitry Andric const char *const KindSubrange = "Subrange";
34bdd1243dSDimitry Andric const char *const KindTemplateTemplate = "TemplateTemplate";
35bdd1243dSDimitry Andric const char *const KindTemplateType = "TemplateType";
36bdd1243dSDimitry Andric const char *const KindTemplateValue = "TemplateValue";
37bdd1243dSDimitry Andric const char *const KindTypeAlias = "TypeAlias";
38bdd1243dSDimitry Andric const char *const KindUndefined = "Undefined";
39bdd1243dSDimitry Andric const char *const KindUnaligned = "Unaligned";
40bdd1243dSDimitry Andric const char *const KindUnspecified = "Unspecified";
41bdd1243dSDimitry Andric const char *const KindVolatile = "Volatile";
42bdd1243dSDimitry Andric } // end anonymous namespace
43bdd1243dSDimitry Andric 
44bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
45bdd1243dSDimitry Andric // DWARF Type.
46bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
47bdd1243dSDimitry Andric // Return a string representation for the type kind.
kind() const48bdd1243dSDimitry Andric const char *LVType::kind() const {
49bdd1243dSDimitry Andric   const char *Kind = KindUndefined;
50bdd1243dSDimitry Andric   if (getIsBase())
51bdd1243dSDimitry Andric     Kind = KindBaseType;
52bdd1243dSDimitry Andric   else if (getIsConst())
53bdd1243dSDimitry Andric     Kind = KindConst;
54bdd1243dSDimitry Andric   else if (getIsEnumerator())
55bdd1243dSDimitry Andric     Kind = KindEnumerator;
56bdd1243dSDimitry Andric   else if (getIsImport())
57bdd1243dSDimitry Andric     Kind = KindImport;
58bdd1243dSDimitry Andric   else if (getIsPointerMember())
59bdd1243dSDimitry Andric     Kind = KindPointerMember;
60bdd1243dSDimitry Andric   else if (getIsPointer())
61bdd1243dSDimitry Andric     Kind = KindPointer;
62bdd1243dSDimitry Andric   else if (getIsReference())
63bdd1243dSDimitry Andric     Kind = KindReference;
64bdd1243dSDimitry Andric   else if (getIsRestrict())
65bdd1243dSDimitry Andric     Kind = KindRestrict;
66bdd1243dSDimitry Andric   else if (getIsRvalueReference())
67bdd1243dSDimitry Andric     Kind = KindRvalueReference;
68bdd1243dSDimitry Andric   else if (getIsSubrange())
69bdd1243dSDimitry Andric     Kind = KindSubrange;
70bdd1243dSDimitry Andric   else if (getIsTemplateTypeParam())
71bdd1243dSDimitry Andric     Kind = KindTemplateType;
72bdd1243dSDimitry Andric   else if (getIsTemplateValueParam())
73bdd1243dSDimitry Andric     Kind = KindTemplateValue;
74bdd1243dSDimitry Andric   else if (getIsTemplateTemplateParam())
75bdd1243dSDimitry Andric     Kind = KindTemplateTemplate;
76bdd1243dSDimitry Andric   else if (getIsTypedef())
77bdd1243dSDimitry Andric     Kind = KindTypeAlias;
78bdd1243dSDimitry Andric   else if (getIsUnaligned())
79bdd1243dSDimitry Andric     Kind = KindUnaligned;
80bdd1243dSDimitry Andric   else if (getIsUnspecified())
81bdd1243dSDimitry Andric     Kind = KindUnspecified;
82bdd1243dSDimitry Andric   else if (getIsVolatile())
83bdd1243dSDimitry Andric     Kind = KindVolatile;
84bdd1243dSDimitry Andric   return Kind;
85bdd1243dSDimitry Andric }
86bdd1243dSDimitry Andric 
87bdd1243dSDimitry Andric LVTypeDispatch LVType::Dispatch = {
88bdd1243dSDimitry Andric     {LVTypeKind::IsBase, &LVType::getIsBase},
89bdd1243dSDimitry Andric     {LVTypeKind::IsConst, &LVType::getIsConst},
90bdd1243dSDimitry Andric     {LVTypeKind::IsEnumerator, &LVType::getIsEnumerator},
91bdd1243dSDimitry Andric     {LVTypeKind::IsImport, &LVType::getIsImport},
92bdd1243dSDimitry Andric     {LVTypeKind::IsImportDeclaration, &LVType::getIsImportDeclaration},
93bdd1243dSDimitry Andric     {LVTypeKind::IsImportModule, &LVType::getIsImportModule},
94bdd1243dSDimitry Andric     {LVTypeKind::IsPointer, &LVType::getIsPointer},
95bdd1243dSDimitry Andric     {LVTypeKind::IsPointerMember, &LVType::getIsPointerMember},
96bdd1243dSDimitry Andric     {LVTypeKind::IsReference, &LVType::getIsReference},
97bdd1243dSDimitry Andric     {LVTypeKind::IsRestrict, &LVType::getIsRestrict},
98bdd1243dSDimitry Andric     {LVTypeKind::IsRvalueReference, &LVType::getIsRvalueReference},
99bdd1243dSDimitry Andric     {LVTypeKind::IsSubrange, &LVType::getIsSubrange},
100bdd1243dSDimitry Andric     {LVTypeKind::IsTemplateParam, &LVType::getIsTemplateParam},
101bdd1243dSDimitry Andric     {LVTypeKind::IsTemplateTemplateParam, &LVType::getIsTemplateTemplateParam},
102bdd1243dSDimitry Andric     {LVTypeKind::IsTemplateTypeParam, &LVType::getIsTemplateTypeParam},
103bdd1243dSDimitry Andric     {LVTypeKind::IsTemplateValueParam, &LVType::getIsTemplateValueParam},
104bdd1243dSDimitry Andric     {LVTypeKind::IsTypedef, &LVType::getIsTypedef},
105bdd1243dSDimitry Andric     {LVTypeKind::IsUnaligned, &LVType::getIsUnaligned},
106bdd1243dSDimitry Andric     {LVTypeKind::IsUnspecified, &LVType::getIsUnspecified},
107bdd1243dSDimitry Andric     {LVTypeKind::IsVolatile, &LVType::getIsVolatile}};
108bdd1243dSDimitry Andric 
resolveReferences()109bdd1243dSDimitry Andric void LVType::resolveReferences() {
110bdd1243dSDimitry Andric   // Some DWARF tags are the representation of types. However, we associate
111bdd1243dSDimitry Andric   // some of them to scopes. The ones associated with types, do not have
112bdd1243dSDimitry Andric   // any reference tags, such as DW_AT_specification, DW_AT_abstract_origin,
113bdd1243dSDimitry Andric   // DW_AT_extension.
114bdd1243dSDimitry Andric 
115bdd1243dSDimitry Andric   // Set the file/line information using the Debug Information entry.
116bdd1243dSDimitry Andric   setFile(/*Reference=*/nullptr);
117bdd1243dSDimitry Andric 
118bdd1243dSDimitry Andric   if (LVElement *Element = getType())
119bdd1243dSDimitry Andric     Element->resolve();
120bdd1243dSDimitry Andric }
121bdd1243dSDimitry Andric 
resolveName()122bdd1243dSDimitry Andric void LVType::resolveName() {
123bdd1243dSDimitry Andric   if (getIsResolvedName())
124bdd1243dSDimitry Andric     return;
125bdd1243dSDimitry Andric   setIsResolvedName();
126bdd1243dSDimitry Andric 
127bdd1243dSDimitry Andric   // The templates are recorded as normal DWARF objects relationships;
128bdd1243dSDimitry Andric   // the template parameters are preserved to show the types used during
129bdd1243dSDimitry Andric   // the instantiation; however if a compare have been requested, those
130bdd1243dSDimitry Andric   // parameters needs to be resolved, so no conflicts are generated.
131bdd1243dSDimitry Andric   // The following DWARF illustrates this issue:
132bdd1243dSDimitry Andric   //
133bdd1243dSDimitry Andric   // a) Template Parameters are preserved:
134bdd1243dSDimitry Andric   //      {Class} 'ConstArray<AtomTable>'
135bdd1243dSDimitry Andric   //        {Inherits} -> 'ArrayBase'
136bdd1243dSDimitry Andric   //        {TemplateType} 'taTYPE' -> 'AtomTable'
137bdd1243dSDimitry Andric   //        {Member} 'mData' -> '* taTYPE'
138bdd1243dSDimitry Andric   //
139bdd1243dSDimitry Andric   // b) Template Parameters are resolved:
140bdd1243dSDimitry Andric   //      {Class} 'ConstArray<AtomTable>'
141bdd1243dSDimitry Andric   //        {Inherits} -> 'ArrayBase'
142bdd1243dSDimitry Andric   //        {TemplateType} 'taTYPE' -> 'AtomTable'
143bdd1243dSDimitry Andric   //        {Member} 'mData' -> '* AtomTable'
144bdd1243dSDimitry Andric   //
145bdd1243dSDimitry Andric   // In (b), the {Member} type have been resolved to use the real type.
146bdd1243dSDimitry Andric 
147bdd1243dSDimitry Andric   LVElement *BaseType = getType();
148bdd1243dSDimitry Andric   if (BaseType && options().getAttributeArgument())
149bdd1243dSDimitry Andric     if (BaseType->isTemplateParam())
150bdd1243dSDimitry Andric       BaseType = BaseType->getType();
151bdd1243dSDimitry Andric 
152bdd1243dSDimitry Andric   if (BaseType && !BaseType->getIsResolvedName())
153bdd1243dSDimitry Andric     BaseType->resolveName();
154bdd1243dSDimitry Andric   resolveFullname(BaseType, getName());
155bdd1243dSDimitry Andric 
156bdd1243dSDimitry Andric   // In the case of unnamed types, try to generate a name for it, using
157bdd1243dSDimitry Andric   // the parents name and the line information. Ignore the template parameters.
158bdd1243dSDimitry Andric   if (!isNamed() && !getIsTemplateParam())
159bdd1243dSDimitry Andric     generateName();
160bdd1243dSDimitry Andric 
161bdd1243dSDimitry Andric   LVElement::resolveName();
162bdd1243dSDimitry Andric 
163bdd1243dSDimitry Andric   // Resolve any given pattern.
164bdd1243dSDimitry Andric   patterns().resolvePatternMatch(this);
165bdd1243dSDimitry Andric }
166bdd1243dSDimitry Andric 
resolveReferencesChain()167bdd1243dSDimitry Andric StringRef LVType::resolveReferencesChain() {
168bdd1243dSDimitry Andric   // The types do not have a DW_AT_specification or DW_AT_abstract_origin
169bdd1243dSDimitry Andric   // reference. Just return the type name.
170bdd1243dSDimitry Andric   return getName();
171bdd1243dSDimitry Andric }
172bdd1243dSDimitry Andric 
markMissingParents(const LVTypes * References,const LVTypes * Targets)173bdd1243dSDimitry Andric void LVType::markMissingParents(const LVTypes *References,
174bdd1243dSDimitry Andric                                 const LVTypes *Targets) {
175bdd1243dSDimitry Andric   if (!(References && Targets))
176bdd1243dSDimitry Andric     return;
177bdd1243dSDimitry Andric 
178bdd1243dSDimitry Andric   LLVM_DEBUG({
179bdd1243dSDimitry Andric     dbgs() << "\n[LVType::markMissingParents]\n";
180bdd1243dSDimitry Andric     for (const LVType *Reference : *References)
181bdd1243dSDimitry Andric       dbgs() << "References: "
182bdd1243dSDimitry Andric              << "Kind = " << formattedKind(Reference->kind()) << ", "
183bdd1243dSDimitry Andric              << "Name = " << formattedName(Reference->getName()) << "\n";
184bdd1243dSDimitry Andric     for (const LVType *Target : *Targets)
185bdd1243dSDimitry Andric       dbgs() << "Targets   : "
186bdd1243dSDimitry Andric              << "Kind = " << formattedKind(Target->kind()) << ", "
187bdd1243dSDimitry Andric              << "Name = " << formattedName(Target->getName()) << "\n";
188bdd1243dSDimitry Andric   });
189bdd1243dSDimitry Andric 
190bdd1243dSDimitry Andric   for (LVType *Reference : *References) {
191bdd1243dSDimitry Andric     LLVM_DEBUG({
192bdd1243dSDimitry Andric       dbgs() << "Search Reference: Name = "
193bdd1243dSDimitry Andric              << formattedName(Reference->getName()) << "\n";
194bdd1243dSDimitry Andric     });
195bdd1243dSDimitry Andric     if (!Reference->findIn(Targets))
196bdd1243dSDimitry Andric       Reference->markBranchAsMissing();
197bdd1243dSDimitry Andric   }
198bdd1243dSDimitry Andric }
199bdd1243dSDimitry Andric 
findIn(const LVTypes * Targets) const200bdd1243dSDimitry Andric LVType *LVType::findIn(const LVTypes *Targets) const {
201bdd1243dSDimitry Andric   if (!Targets)
202bdd1243dSDimitry Andric     return nullptr;
203bdd1243dSDimitry Andric 
204bdd1243dSDimitry Andric   LLVM_DEBUG({
205bdd1243dSDimitry Andric     dbgs() << "\n[LVType::findIn]\n"
206bdd1243dSDimitry Andric            << "Reference: "
207bdd1243dSDimitry Andric            << "Level = " << getLevel() << ", "
208bdd1243dSDimitry Andric            << "Kind = " << formattedKind(kind()) << ", "
209bdd1243dSDimitry Andric            << "Name = " << formattedName(getName()) << "\n";
210bdd1243dSDimitry Andric     for (const LVType *Target : *Targets)
211bdd1243dSDimitry Andric       dbgs() << "Target   : "
212bdd1243dSDimitry Andric              << "Level = " << Target->getLevel() << ", "
213bdd1243dSDimitry Andric              << "Kind = " << formattedKind(Target->kind()) << ", "
214bdd1243dSDimitry Andric              << "Name = " << formattedName(Target->getName()) << "\n";
215bdd1243dSDimitry Andric   });
216bdd1243dSDimitry Andric 
217bdd1243dSDimitry Andric   for (LVType *Target : *Targets)
218bdd1243dSDimitry Andric     if (equals(Target))
219bdd1243dSDimitry Andric       return Target;
220bdd1243dSDimitry Andric 
221bdd1243dSDimitry Andric   return nullptr;
222bdd1243dSDimitry Andric }
223bdd1243dSDimitry Andric 
224bdd1243dSDimitry Andric // Check for a match on the arguments of a function.
parametersMatch(const LVTypes * References,const LVTypes * Targets)225bdd1243dSDimitry Andric bool LVType::parametersMatch(const LVTypes *References,
226bdd1243dSDimitry Andric                              const LVTypes *Targets) {
227bdd1243dSDimitry Andric   if (!References && !Targets)
228bdd1243dSDimitry Andric     return true;
229bdd1243dSDimitry Andric   if (References && Targets) {
230bdd1243dSDimitry Andric     LVTypes ReferenceTypes;
231bdd1243dSDimitry Andric     LVScopes ReferenceScopes;
232bdd1243dSDimitry Andric     getParameters(References, &ReferenceTypes, &ReferenceScopes);
233bdd1243dSDimitry Andric     LVTypes TargetTypes;
234bdd1243dSDimitry Andric     LVScopes TargetScopes;
235bdd1243dSDimitry Andric     getParameters(Targets, &TargetTypes, &TargetScopes);
236bdd1243dSDimitry Andric     if (!LVType::equals(&ReferenceTypes, &TargetTypes) ||
237bdd1243dSDimitry Andric         !LVScope::equals(&ReferenceScopes, &TargetScopes))
238bdd1243dSDimitry Andric       return false;
239bdd1243dSDimitry Andric     return true;
240bdd1243dSDimitry Andric   }
241bdd1243dSDimitry Andric   return false;
242bdd1243dSDimitry Andric }
243bdd1243dSDimitry Andric 
244bdd1243dSDimitry Andric // Return the types which are parameters.
getParameters(const LVTypes * Types,LVTypes * TypesParam,LVScopes * ScopesParam)245bdd1243dSDimitry Andric void LVType::getParameters(const LVTypes *Types, LVTypes *TypesParam,
246bdd1243dSDimitry Andric                            LVScopes *ScopesParam) {
247bdd1243dSDimitry Andric   if (!Types)
248bdd1243dSDimitry Andric     return;
249bdd1243dSDimitry Andric 
250bdd1243dSDimitry Andric   // During a compare task, the template parameters are expanded to
251bdd1243dSDimitry Andric   // point to their real types, to avoid compare conflicts.
252bdd1243dSDimitry Andric   for (LVType *Type : *Types) {
253bdd1243dSDimitry Andric     if (!Type->getIsTemplateParam())
254bdd1243dSDimitry Andric       continue;
255bdd1243dSDimitry Andric     if (options().getAttributeArgument()) {
256bdd1243dSDimitry Andric       if (Type->getIsKindType())
257*06c3fb27SDimitry Andric         TypesParam->push_back(Type->getTypeAsType());
258*06c3fb27SDimitry Andric       else if (Type->getIsKindScope())
259*06c3fb27SDimitry Andric         ScopesParam->push_back(Type->getTypeAsScope());
260bdd1243dSDimitry Andric     } else
261bdd1243dSDimitry Andric       TypesParam->push_back(Type);
262bdd1243dSDimitry Andric   }
263bdd1243dSDimitry Andric }
264bdd1243dSDimitry Andric 
equals(const LVType * Type) const265bdd1243dSDimitry Andric bool LVType::equals(const LVType *Type) const {
266bdd1243dSDimitry Andric   return LVElement::equals(Type);
267bdd1243dSDimitry Andric }
268bdd1243dSDimitry Andric 
equals(const LVTypes * References,const LVTypes * Targets)269bdd1243dSDimitry Andric bool LVType::equals(const LVTypes *References, const LVTypes *Targets) {
270bdd1243dSDimitry Andric   if (!References && !Targets)
271bdd1243dSDimitry Andric     return true;
272bdd1243dSDimitry Andric   if (References && Targets && References->size() == Targets->size()) {
273bdd1243dSDimitry Andric     for (const LVType *Reference : *References)
274bdd1243dSDimitry Andric       if (!Reference->findIn(Targets))
275bdd1243dSDimitry Andric         return false;
276bdd1243dSDimitry Andric     return true;
277bdd1243dSDimitry Andric   }
278bdd1243dSDimitry Andric   return false;
279bdd1243dSDimitry Andric }
280bdd1243dSDimitry Andric 
report(LVComparePass Pass)281bdd1243dSDimitry Andric void LVType::report(LVComparePass Pass) {
282bdd1243dSDimitry Andric   getComparator().printItem(this, Pass);
283bdd1243dSDimitry Andric }
284bdd1243dSDimitry Andric 
print(raw_ostream & OS,bool Full) const285bdd1243dSDimitry Andric void LVType::print(raw_ostream &OS, bool Full) const {
286bdd1243dSDimitry Andric   if (getIncludeInPrint() &&
287bdd1243dSDimitry Andric       (getIsReference() || getReader().doPrintType(this))) {
288bdd1243dSDimitry Andric     getReaderCompileUnit()->incrementPrintedTypes();
289bdd1243dSDimitry Andric     LVElement::print(OS, Full);
290bdd1243dSDimitry Andric     printExtra(OS, Full);
291bdd1243dSDimitry Andric   }
292bdd1243dSDimitry Andric }
293bdd1243dSDimitry Andric 
printExtra(raw_ostream & OS,bool Full) const294bdd1243dSDimitry Andric void LVType::printExtra(raw_ostream &OS, bool Full) const {
295bdd1243dSDimitry Andric   OS << formattedKind(kind()) << " " << formattedName(getName()) << "\n";
296bdd1243dSDimitry Andric }
297bdd1243dSDimitry Andric 
298bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
299bdd1243dSDimitry Andric // DWARF typedef.
300bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
301bdd1243dSDimitry Andric // Return the underlying type for a typedef, which can be a type or scope.
getUnderlyingType()302bdd1243dSDimitry Andric LVElement *LVTypeDefinition::getUnderlyingType() {
303bdd1243dSDimitry Andric   LVElement *BaseType = getTypeAsScope();
304bdd1243dSDimitry Andric   if (BaseType)
305bdd1243dSDimitry Andric     // Underlying type is a scope.
306bdd1243dSDimitry Andric     return BaseType;
307bdd1243dSDimitry Andric 
308bdd1243dSDimitry Andric   LVType *Type = getTypeAsType();
309bdd1243dSDimitry Andric   assert(Type && "Type definition does not have a type.");
310bdd1243dSDimitry Andric 
311bdd1243dSDimitry Andric   BaseType = Type;
312bdd1243dSDimitry Andric   while (Type->getIsTypedef()) {
313bdd1243dSDimitry Andric     BaseType = Type->getTypeAsScope();
314bdd1243dSDimitry Andric     if (BaseType)
315bdd1243dSDimitry Andric       // Underlying type is a scope.
316bdd1243dSDimitry Andric       return BaseType;
317bdd1243dSDimitry Andric 
318bdd1243dSDimitry Andric     Type = Type->getTypeAsType();
319bdd1243dSDimitry Andric     if (Type)
320bdd1243dSDimitry Andric       BaseType = Type;
321bdd1243dSDimitry Andric   }
322bdd1243dSDimitry Andric 
323bdd1243dSDimitry Andric   return BaseType;
324bdd1243dSDimitry Andric }
325bdd1243dSDimitry Andric 
resolveExtra()326bdd1243dSDimitry Andric void LVTypeDefinition::resolveExtra() {
327*06c3fb27SDimitry Andric   // In the case of CodeView, the MSVC toolset generates a series of typedefs
328*06c3fb27SDimitry Andric   // that refer to internal runtime structures, that we do not process. Those
329*06c3fb27SDimitry Andric   // typedefs are marked as 'system'. They have an associated logical type,
330*06c3fb27SDimitry Andric   // but the underlying type always is null.
331*06c3fb27SDimitry Andric   if (getIsSystem())
332*06c3fb27SDimitry Andric     return;
333*06c3fb27SDimitry Andric 
334bdd1243dSDimitry Andric   // Set the reference to the typedef type.
335bdd1243dSDimitry Andric   if (options().getAttributeUnderlying()) {
336bdd1243dSDimitry Andric     setUnderlyingType(getUnderlyingType());
337bdd1243dSDimitry Andric     setIsTypedefReduced();
338bdd1243dSDimitry Andric     if (LVElement *Type = getType()) {
339bdd1243dSDimitry Andric       Type->resolveName();
340bdd1243dSDimitry Andric       resolveFullname(Type);
341bdd1243dSDimitry Andric     }
342bdd1243dSDimitry Andric   }
343bdd1243dSDimitry Andric 
344bdd1243dSDimitry Andric   // For the case of typedef'd anonymous structures:
345bdd1243dSDimitry Andric   //   typedef struct { ... } Name;
346bdd1243dSDimitry Andric   // Propagate the typedef name to the anonymous structure.
347bdd1243dSDimitry Andric   LVScope *Aggregate = getTypeAsScope();
348bdd1243dSDimitry Andric   if (Aggregate && Aggregate->getIsAnonymous())
349bdd1243dSDimitry Andric     Aggregate->setName(getName());
350bdd1243dSDimitry Andric }
351bdd1243dSDimitry Andric 
equals(const LVType * Type) const352bdd1243dSDimitry Andric bool LVTypeDefinition::equals(const LVType *Type) const {
353bdd1243dSDimitry Andric   return LVType::equals(Type);
354bdd1243dSDimitry Andric }
355bdd1243dSDimitry Andric 
printExtra(raw_ostream & OS,bool Full) const356bdd1243dSDimitry Andric void LVTypeDefinition::printExtra(raw_ostream &OS, bool Full) const {
357bdd1243dSDimitry Andric   OS << formattedKind(kind()) << " " << formattedName(getName()) << " -> "
358bdd1243dSDimitry Andric      << typeOffsetAsString()
359bdd1243dSDimitry Andric      << formattedName((getType() ? getType()->getName() : "")) << "\n";
360bdd1243dSDimitry Andric }
361bdd1243dSDimitry Andric 
362bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
363bdd1243dSDimitry Andric // DWARF enumerator (DW_TAG_enumerator).
364bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
equals(const LVType * Type) const365bdd1243dSDimitry Andric bool LVTypeEnumerator::equals(const LVType *Type) const {
366bdd1243dSDimitry Andric   return LVType::equals(Type);
367bdd1243dSDimitry Andric }
368bdd1243dSDimitry Andric 
printExtra(raw_ostream & OS,bool Full) const369bdd1243dSDimitry Andric void LVTypeEnumerator::printExtra(raw_ostream &OS, bool Full) const {
370bdd1243dSDimitry Andric   OS << formattedKind(kind()) << " '" << getName()
371bdd1243dSDimitry Andric      << "' = " << formattedName(getValue()) << "\n";
372bdd1243dSDimitry Andric }
373bdd1243dSDimitry Andric 
374bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
375bdd1243dSDimitry Andric // DWARF import (DW_TAG_imported_module / DW_TAG_imported_declaration).
376bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
equals(const LVType * Type) const377bdd1243dSDimitry Andric bool LVTypeImport::equals(const LVType *Type) const {
378bdd1243dSDimitry Andric   return LVType::equals(Type);
379bdd1243dSDimitry Andric }
380bdd1243dSDimitry Andric 
printExtra(raw_ostream & OS,bool Full) const381bdd1243dSDimitry Andric void LVTypeImport::printExtra(raw_ostream &OS, bool Full) const {
382bdd1243dSDimitry Andric   std::string Attributes =
383bdd1243dSDimitry Andric       formatAttributes(virtualityString(), accessibilityString());
384bdd1243dSDimitry Andric 
385bdd1243dSDimitry Andric   OS << formattedKind(kind()) << " " << typeOffsetAsString() << Attributes
386bdd1243dSDimitry Andric      << formattedName((getType() ? getType()->getName() : "")) << "\n";
387bdd1243dSDimitry Andric }
388bdd1243dSDimitry Andric 
389bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
390bdd1243dSDimitry Andric // DWARF Template parameter holder (type or param).
391bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
LVTypeParam()392bdd1243dSDimitry Andric LVTypeParam::LVTypeParam() : LVType() {
393bdd1243dSDimitry Andric   options().getAttributeTypename() ? setIncludeInPrint()
394bdd1243dSDimitry Andric                                    : resetIncludeInPrint();
395bdd1243dSDimitry Andric }
396bdd1243dSDimitry Andric 
397bdd1243dSDimitry Andric // Encode the specific template argument.
encodeTemplateArgument(std::string & Name) const398bdd1243dSDimitry Andric void LVTypeParam::encodeTemplateArgument(std::string &Name) const {
399bdd1243dSDimitry Andric   // The incoming type is a template parameter; we have 3 kinds of parameters:
400bdd1243dSDimitry Andric   // - type parameter: resolve the instance (type);
401bdd1243dSDimitry Andric   // - value parameter: resolve the constant value
402bdd1243dSDimitry Andric   // - template parameter: resolve the name of the template.
403bdd1243dSDimitry Andric   // If the parameter type is a template instance (STL sample), we need to
404bdd1243dSDimitry Andric   // expand the type (template template case). For the following variable
405bdd1243dSDimitry Andric   // declarations:
406bdd1243dSDimitry Andric   //   std::type<float> a_float;
407bdd1243dSDimitry Andric   //   std::type<int> a_int;
408bdd1243dSDimitry Andric   // We must generate names like:
409bdd1243dSDimitry Andric   //   "std::type<float,std::less<float>,std::allocator<float>,false>"
410bdd1243dSDimitry Andric   //   "std::type<int,std::less<int>,std::allocator<int>,false>"
411bdd1243dSDimitry Andric   // Instead of the incomplete names:
412bdd1243dSDimitry Andric   //   "type<float,less,allocator,false>"
413bdd1243dSDimitry Andric   //   "type<int,less,allocator,false>"
414bdd1243dSDimitry Andric 
415bdd1243dSDimitry Andric   if (getIsTemplateTypeParam()) {
416bdd1243dSDimitry Andric     // Get the type instance recorded in the template type; it can be a
417bdd1243dSDimitry Andric     // reference to a type or to a scope.
418bdd1243dSDimitry Andric 
419bdd1243dSDimitry Andric     if (getIsKindType()) {
420bdd1243dSDimitry Andric       // The argument types always are qualified.
421bdd1243dSDimitry Andric       Name.append(std::string(getTypeQualifiedName()));
422bdd1243dSDimitry Andric 
423bdd1243dSDimitry Andric       LVType *ArgType = getTypeAsType();
424bdd1243dSDimitry Andric       // For template arguments that are typedefs, use the underlying type,
425bdd1243dSDimitry Andric       // which can be a type or scope.
426bdd1243dSDimitry Andric       if (ArgType->getIsTypedef()) {
427bdd1243dSDimitry Andric         LVObject *BaseType = ArgType->getUnderlyingType();
428bdd1243dSDimitry Andric         Name.append(std::string(BaseType->getName()));
429bdd1243dSDimitry Andric       } else {
430bdd1243dSDimitry Andric         Name.append(std::string(ArgType->getName()));
431bdd1243dSDimitry Andric       }
432bdd1243dSDimitry Andric     } else {
433bdd1243dSDimitry Andric       if (getIsKindScope()) {
434bdd1243dSDimitry Andric         LVScope *ArgScope = getTypeAsScope();
435bdd1243dSDimitry Andric         // If the scope is a template, we have to resolve that template,
436bdd1243dSDimitry Andric         // by recursively traversing its arguments.
437bdd1243dSDimitry Andric         if (ArgScope->getIsTemplate())
438bdd1243dSDimitry Andric           ArgScope->encodeTemplateArguments(Name);
439bdd1243dSDimitry Andric         else {
440bdd1243dSDimitry Andric           // The argument types always are qualified.
441bdd1243dSDimitry Andric           Name.append(std::string(getTypeQualifiedName()));
442bdd1243dSDimitry Andric           Name.append(std::string(ArgScope->getName()));
443bdd1243dSDimitry Andric         }
444bdd1243dSDimitry Andric       }
445bdd1243dSDimitry Andric     }
446bdd1243dSDimitry Andric   } else
447bdd1243dSDimitry Andric     // Template value parameter or template template parameter.
448bdd1243dSDimitry Andric     Name.append(getValue());
449bdd1243dSDimitry Andric }
450bdd1243dSDimitry Andric 
equals(const LVType * Type) const451bdd1243dSDimitry Andric bool LVTypeParam::equals(const LVType *Type) const {
452bdd1243dSDimitry Andric   if (!LVType::equals(Type))
453bdd1243dSDimitry Andric     return false;
454bdd1243dSDimitry Andric 
455bdd1243dSDimitry Andric   // Checks the kind of template argument.
456bdd1243dSDimitry Andric   if (getIsTemplateTypeParam() && Type->getIsTemplateTypeParam())
457bdd1243dSDimitry Andric     return getType()->equals(Type->getType());
458bdd1243dSDimitry Andric 
459bdd1243dSDimitry Andric   if ((getIsTemplateValueParam() && Type->getIsTemplateValueParam()) ||
460bdd1243dSDimitry Andric       (getIsTemplateTemplateParam() && Type->getIsTemplateTemplateParam()))
461bdd1243dSDimitry Andric     return getValueIndex() == Type->getValueIndex();
462bdd1243dSDimitry Andric 
463bdd1243dSDimitry Andric   return false;
464bdd1243dSDimitry Andric }
465bdd1243dSDimitry Andric 
printExtra(raw_ostream & OS,bool Full) const466bdd1243dSDimitry Andric void LVTypeParam::printExtra(raw_ostream &OS, bool Full) const {
467bdd1243dSDimitry Andric   OS << formattedKind(kind()) << " " << formattedName(getName()) << " -> "
468bdd1243dSDimitry Andric      << typeOffsetAsString();
469bdd1243dSDimitry Andric 
470bdd1243dSDimitry Andric   // Depending on the type of parameter, the print includes different
471bdd1243dSDimitry Andric   // information: type, value or reference to a template.
472bdd1243dSDimitry Andric   if (getIsTemplateTypeParam()) {
473bdd1243dSDimitry Andric     OS << formattedNames(getTypeQualifiedName(), getTypeName()) << "\n";
474bdd1243dSDimitry Andric     return;
475bdd1243dSDimitry Andric   }
476bdd1243dSDimitry Andric   if (getIsTemplateValueParam()) {
477bdd1243dSDimitry Andric     OS << formattedName(getValue()) << " " << formattedName(getName()) << "\n";
478bdd1243dSDimitry Andric     return;
479bdd1243dSDimitry Andric   }
480bdd1243dSDimitry Andric   if (getIsTemplateTemplateParam())
481bdd1243dSDimitry Andric     OS << formattedName(getValue()) << "\n";
482bdd1243dSDimitry Andric }
483bdd1243dSDimitry Andric 
484bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
485bdd1243dSDimitry Andric // DW_TAG_subrange_type
486bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
resolveExtra()487bdd1243dSDimitry Andric void LVTypeSubrange::resolveExtra() {
488bdd1243dSDimitry Andric   // There are 2 cases to represent the bounds information for an array:
489bdd1243dSDimitry Andric   // 1) DW_TAG_subrange_type
490bdd1243dSDimitry Andric   //      DW_AT_type --> ref_type (type of count)
491bdd1243dSDimitry Andric   //      DW_AT_count --> value (number of elements in subrange)
492bdd1243dSDimitry Andric 
493bdd1243dSDimitry Andric   // 2) DW_TAG_subrange_type
494bdd1243dSDimitry Andric   //      DW_AT_lower_bound --> value
495bdd1243dSDimitry Andric   //      DW_AT_upper_bound --> value
496bdd1243dSDimitry Andric 
497bdd1243dSDimitry Andric   // The idea is to represent the bounds as a string, depending on the format:
498bdd1243dSDimitry Andric   // 1) [count]
499bdd1243dSDimitry Andric   // 2) [lower..upper]
500bdd1243dSDimitry Andric 
501bdd1243dSDimitry Andric   // Subrange information.
502bdd1243dSDimitry Andric   std::string String;
503bdd1243dSDimitry Andric 
504bdd1243dSDimitry Andric   // Check if we have DW_AT_count subrange style.
505bdd1243dSDimitry Andric   if (getIsSubrangeCount())
506bdd1243dSDimitry Andric     // Get count subrange value. Assume 0 if missing.
507bdd1243dSDimitry Andric     raw_string_ostream(String) << "[" << getCount() << "]";
508bdd1243dSDimitry Andric   else
509bdd1243dSDimitry Andric     raw_string_ostream(String)
510bdd1243dSDimitry Andric         << "[" << getLowerBound() << ".." << getUpperBound() << "]";
511bdd1243dSDimitry Andric 
512bdd1243dSDimitry Andric   setName(String);
513bdd1243dSDimitry Andric }
514bdd1243dSDimitry Andric 
equals(const LVType * Type) const515bdd1243dSDimitry Andric bool LVTypeSubrange::equals(const LVType *Type) const {
516bdd1243dSDimitry Andric   if (!LVType::equals(Type))
517bdd1243dSDimitry Andric     return false;
518bdd1243dSDimitry Andric 
519bdd1243dSDimitry Andric   return getTypeName() == Type->getTypeName() && getName() == Type->getName();
520bdd1243dSDimitry Andric }
521bdd1243dSDimitry Andric 
printExtra(raw_ostream & OS,bool Full) const522bdd1243dSDimitry Andric void LVTypeSubrange::printExtra(raw_ostream &OS, bool Full) const {
523bdd1243dSDimitry Andric   OS << formattedKind(kind()) << " -> " << typeOffsetAsString()
524bdd1243dSDimitry Andric      << formattedName(getTypeName()) << " " << formattedName(getName()) << "\n";
525bdd1243dSDimitry Andric }
526