diff options
Diffstat (limited to 'llvm/lib/DebugInfo/LogicalView/Core')
| -rw-r--r-- | llvm/lib/DebugInfo/LogicalView/Core/LVElement.cpp | 37 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/LogicalView/Core/LVLocation.cpp | 19 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/LogicalView/Core/LVReader.cpp | 3 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp | 69 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/LogicalView/Core/LVSupport.cpp | 109 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/LogicalView/Core/LVSymbol.cpp | 22 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/LogicalView/Core/LVType.cpp | 19 |
7 files changed, 221 insertions, 57 deletions
diff --git a/llvm/lib/DebugInfo/LogicalView/Core/LVElement.cpp b/llvm/lib/DebugInfo/LogicalView/Core/LVElement.cpp index a320752befc4..cfe304eead51 100644 --- a/llvm/lib/DebugInfo/LogicalView/Core/LVElement.cpp +++ b/llvm/lib/DebugInfo/LogicalView/Core/LVElement.cpp @@ -17,6 +17,7 @@ #include "llvm/DebugInfo/LogicalView/Core/LVType.h" using namespace llvm; +using namespace llvm::codeview; using namespace llvm::logicalview; #define DEBUG_TYPE "Element" @@ -103,6 +104,14 @@ void LVElement::setFilename(StringRef Filename) { FilenameIndex = getStringIndex(Filename); } +void LVElement::setInnerComponent(StringRef Name) { + if (Name.size()) { + StringRef InnerComponent; + std::tie(std::ignore, InnerComponent) = getInnerComponent(Name); + setName(InnerComponent); + } +} + // Return the string representation of a DIE offset. std::string LVElement::typeOffsetAsString() const { if (options().getAttributeOffset()) { @@ -126,6 +135,19 @@ StringRef LVElement::accessibilityString(uint32_t Access) const { } } +std::optional<uint32_t> LVElement::getAccessibilityCode(MemberAccess Access) { + switch (Access) { + case MemberAccess::Private: + return dwarf::DW_ACCESS_private; + case MemberAccess::Protected: + return dwarf::DW_ACCESS_protected; + case MemberAccess::Public: + return dwarf::DW_ACCESS_public; + default: + return std::nullopt; + } +} + StringRef LVElement::externalString() const { return getIsExternal() ? "extern" : StringRef(); } @@ -160,6 +182,21 @@ StringRef LVElement::virtualityString(uint32_t Virtuality) const { } } +std::optional<uint32_t> LVElement::getVirtualityCode(MethodKind Virtuality) { + switch (Virtuality) { + case MethodKind::Virtual: + return dwarf::DW_VIRTUALITY_virtual; + case MethodKind::PureVirtual: + return dwarf::DW_VIRTUALITY_pure_virtual; + case MethodKind::IntroducingVirtual: + case MethodKind::PureIntroducingVirtual: + // No direct equivalents in DWARF. Assume Virtual. + return dwarf::DW_VIRTUALITY_virtual; + default: + return std::nullopt; + } +} + void LVElement::resolve() { if (getIsResolved()) return; diff --git a/llvm/lib/DebugInfo/LogicalView/Core/LVLocation.cpp b/llvm/lib/DebugInfo/LogicalView/Core/LVLocation.cpp index 115b903c6c7f..17b32a5f67b4 100644 --- a/llvm/lib/DebugInfo/LogicalView/Core/LVLocation.cpp +++ b/llvm/lib/DebugInfo/LogicalView/Core/LVLocation.cpp @@ -352,7 +352,7 @@ std::string LVOperation::getOperandsCodeViewInfo() { uint16_t OperationCode = getCodeViewOperationCode(Opcode); switch (OperationCode) { - // Operands: [Offset, 0]. + // Operands: [Offset]. case codeview::SymbolKind::S_DEFRANGE_FRAMEPOINTER_REL: Stream << "frame_pointer_rel " << int(Operands[0]); break; @@ -360,7 +360,7 @@ std::string LVOperation::getOperandsCodeViewInfo() { Stream << "frame_pointer_rel_full_scope " << int(Operands[0]); break; - // Operands: [Register, 0]. + // Operands: [Register]. case codeview::SymbolKind::S_DEFRANGE_REGISTER: Stream << "register " << getReader().getRegisterName(Opcode, Operands); break; @@ -375,7 +375,7 @@ std::string LVOperation::getOperandsCodeViewInfo() { << " offset " << int(Operands[1]); break; - // Operands: [Program, 0]. + // Operands: [Program]. case codeview::SymbolKind::S_DEFRANGE: Stream << "frame " << int(Operands[0]); break; @@ -576,11 +576,11 @@ void LVLocationSymbol::addObject(LVAddress LowPC, LVAddress HighPC, } // Add a Location Record. -void LVLocationSymbol::addObject(LVSmall Opcode, LVUnsigned Operand1, - LVUnsigned Operand2) { +void LVLocationSymbol::addObject(LVSmall Opcode, + ArrayRef<LVUnsigned> Operands) { if (!Entries) - Entries = new LVAutoOperations(); - Entries->emplace_back(new LVOperation(Opcode, Operand1, Operand2)); + Entries = std::make_unique<LVOperations>(); + Entries->push_back(getReader().createOperation(Opcode, Operands)); } // Based on the DWARF attribute, define the location kind. @@ -606,8 +606,7 @@ void LVLocation::setKind() { void LVLocationSymbol::updateKind() { // Update the location type for simple ones. if (Entries && Entries->size() == 1) { - LVOperation *Operation = Entries->front(); - if (dwarf::DW_OP_fbreg == Operation->getOpcode()) + if (dwarf::DW_OP_fbreg == Entries->front()->getOpcode()) setIsStackOffset(); } } @@ -660,7 +659,7 @@ void LVLocationSymbol::printExtra(raw_ostream &OS, bool Full) const { if (Full && Entries) { bool CodeViewLocation = getParentSymbol()->getHasCodeViewLocation(); std::stringstream Stream; - std::string Leading = ""; + std::string Leading; for (LVOperation *Operation : *Entries) { Stream << Leading << (CodeViewLocation ? Operation->getOperandsCodeViewInfo() diff --git a/llvm/lib/DebugInfo/LogicalView/Core/LVReader.cpp b/llvm/lib/DebugInfo/LogicalView/Core/LVReader.cpp index 88f66cf2093b..613452c0b501 100644 --- a/llvm/lib/DebugInfo/LogicalView/Core/LVReader.cpp +++ b/llvm/lib/DebugInfo/LogicalView/Core/LVReader.cpp @@ -182,6 +182,9 @@ Error LVReader::createSplitFolder() { // Get the filename for given object. StringRef LVReader::getFilename(LVObject *Object, size_t Index) const { + // TODO: The current CodeView Reader implementation does not have support + // for multiple compile units. Until we have a proper offset calculation, + // check only in the current compile unit. if (CompileUnits.size()) { // Get Compile Unit for the given object. LVCompileUnits::const_iterator Iter = diff --git a/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp b/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp index fb503f3d3e7e..2f26025d01ec 100644 --- a/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp +++ b/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp @@ -45,15 +45,6 @@ const char *const KindUnion = "Union"; //===----------------------------------------------------------------------===// // DWARF lexical block, such as: namespace, function, compile unit, module, etc. //===----------------------------------------------------------------------===// -LVScope::~LVScope() { - delete Types; - delete Symbols; - delete Scopes; - delete Lines; - delete Ranges; - delete Children; -} - // Return a string representation for the scope kind. const char *LVScope::kind() const { const char *Kind = KindUndefined; @@ -114,7 +105,7 @@ LVScopeDispatch LVScope::Dispatch = { void LVScope::addToChildren(LVElement *Element) { if (!Children) - Children = new LVElements(); + Children = std::make_unique<LVElements>(); Children->push_back(Element); } @@ -137,7 +128,7 @@ void LVScope::addElement(LVLine *Line) { assert(Line && "Invalid line."); assert(!Line->getParent() && "Line already inserted"); if (!Lines) - Lines = new LVAutoLines(); + Lines = std::make_unique<LVLines>(); // Add it to parent. Lines->push_back(Line); @@ -161,7 +152,7 @@ void LVScope::addObject(LVLocation *Location) { assert(Location && "Invalid location."); assert(!Location->getParent() && "Location already inserted"); if (!Ranges) - Ranges = new LVAutoLocations(); + Ranges = std::make_unique<LVLocations>(); // Add it to parent. Location->setParent(this); @@ -176,7 +167,7 @@ void LVScope::addElement(LVScope *Scope) { assert(Scope && "Invalid scope."); assert(!Scope->getParent() && "Scope already inserted"); if (!Scopes) - Scopes = new LVAutoScopes(); + Scopes = std::make_unique<LVScopes>(); // Add it to parent. Scopes->push_back(Scope); @@ -203,7 +194,7 @@ void LVScope::addElement(LVSymbol *Symbol) { assert(Symbol && "Invalid symbol."); assert(!Symbol->getParent() && "Symbol already inserted"); if (!Symbols) - Symbols = new LVAutoSymbols(); + Symbols = std::make_unique<LVSymbols>(); // Add it to parent. Symbols->push_back(Symbol); @@ -230,7 +221,7 @@ void LVScope::addElement(LVType *Type) { assert(Type && "Invalid type."); assert(!Type->getParent() && "Type already inserted"); if (!Types) - Types = new LVAutoTypes(); + Types = std::make_unique<LVTypes>(); // Add it to parent. Types->push_back(Type); @@ -255,7 +246,7 @@ void LVScope::addElement(LVType *Type) { // Add a pair of ranges. void LVScope::addObject(LVAddress LowerAddress, LVAddress UpperAddress) { // Pack the ranges into a Location object. - LVLocation *Location = new LVLocation(); + LVLocation *Location = getReader().createLocation(); Location->setLowerAddress(LowerAddress); Location->setUpperAddress(UpperAddress); Location->setIsAddressRange(); @@ -341,7 +332,7 @@ void LVScope::addMissingElements(LVScope *Reference) { // information that is incorrect for the element to be inserted. // As the symbol being added does not exist in the debug section, // use its parent scope offset, to indicate its DIE location. - LVSymbol *Symbol = new LVSymbol(); + LVSymbol *Symbol = getReader().createSymbol(); addElement(Symbol); Symbol->setOffset(getOffset()); Symbol->setIsOptimized(); @@ -598,6 +589,10 @@ Error LVScope::doPrint(bool Split, bool Match, bool Print, raw_ostream &OS, // split context, then switch to the reader output stream. raw_ostream *StreamSplit = &OS; + // Ignore the CU generated by the VS toolchain, when compiling to PDB. + if (getIsSystem() && !options().getAttributeSystem()) + return Error::success(); + // If 'Split', we use the scope name (CU name) as the ouput file; the // delimiters in the pathname, must be replaced by a normal character. if (getIsCompileUnit()) { @@ -690,7 +685,7 @@ void LVScope::sort() { if (SortFunction) { std::function<void(LVScope * Parent, LVSortFunction SortFunction)> Sort = [&](LVScope *Parent, LVSortFunction SortFunction) { - auto Traverse = [&](auto *Set, LVSortFunction SortFunction) { + auto Traverse = [&](auto &Set, LVSortFunction SortFunction) { if (Set) std::stable_sort(Set->begin(), Set->end(), SortFunction); }; @@ -877,7 +872,7 @@ bool LVScope::equalNumberOfChildren(const LVScope *Scope) const { } void LVScope::markMissingParents(const LVScope *Target, bool TraverseChildren) { - auto SetCompareState = [&](auto *Container) { + auto SetCompareState = [&](auto &Container) { if (Container) for (auto *Entry : *Container) Entry->setIsInCompare(); @@ -1356,8 +1351,7 @@ void LVScopeCompileUnit::addedElement(LVType *Type) { // Record unsuported DWARF tags. void LVScopeCompileUnit::addDebugTag(dwarf::Tag Target, LVOffset Offset) { - addItem<LVTagOffsetsMap, LVOffsetList, dwarf::Tag, LVOffset>(&DebugTags, - Target, Offset); + addItem<LVTagOffsetsMap, dwarf::Tag, LVOffset>(&DebugTags, Target, Offset); } // Record elements with invalid offsets. @@ -1390,8 +1384,7 @@ void LVScopeCompileUnit::addLineZero(LVLine *Line) { LVScope *Scope = Line->getParentScope(); LVOffset Offset = Scope->getOffset(); addInvalidOffset(Offset, Scope); - addItem<LVOffsetLinesMap, LVLines, LVOffset, LVLine *>(&LinesZero, Offset, - Line); + addItem<LVOffsetLinesMap, LVOffset, LVLine *>(&LinesZero, Offset, Line); } void LVScopeCompileUnit::printLocalNames(raw_ostream &OS, bool Full) const { @@ -1481,7 +1474,7 @@ void LVScopeCompileUnit::printWarnings(raw_ostream &OS, bool Full) const { PrintHeader(Header); for (LVOffsetLocationsMap::const_reference Entry : Map) { PrintElement(WarningOffsets, Entry.first); - for (const LVLocation *Location : *Entry.second) + for (const LVLocation *Location : Entry.second) OS << hexSquareString(Location->getOffset()) << " " << Location->getIntervalInfo() << "\n"; } @@ -1494,7 +1487,7 @@ void LVScopeCompileUnit::printWarnings(raw_ostream &OS, bool Full) const { OS << format("\n0x%02x", (unsigned)Entry.first) << ", " << dwarf::TagString(Entry.first) << "\n"; unsigned Count = 0; - for (const LVOffset &Offset : *Entry.second) + for (const LVOffset &Offset : Entry.second) PrintOffset(Count, Offset); OS << "\n"; } @@ -1519,7 +1512,7 @@ void LVScopeCompileUnit::printWarnings(raw_ostream &OS, bool Full) const { for (LVOffsetLinesMap::const_reference Entry : LinesZero) { PrintElement(WarningOffsets, Entry.first); unsigned Count = 0; - for (const LVLine *Line : *Entry.second) + for (const LVLine *Line : Entry.second) PrintOffset(Count, Line->getOffset()); OS << "\n"; } @@ -1795,6 +1788,8 @@ void LVScopeFunction::resolveReferences() { // DW_AT_external DW_FORM_flag_present // 00000070 DW_TAG_subprogram "bar" // DW_AT_specification DW_FORM_ref4 0x00000048 + // CodeView does not include any information at the class level to + // mark the member function as external. // If there is a reference linking the declaration and definition, mark // the definition as extern, to facilitate the logical view comparison. if (getHasReferenceSpecification()) { @@ -2030,6 +2025,28 @@ void LVScopeRoot::processRangeInformation() { } } +void LVScopeRoot::transformScopedName() { + // Recursively transform all names. + std::function<void(LVScope * Parent)> TraverseScope = [&](LVScope *Parent) { + auto Traverse = [&](const auto *Set) { + if (Set) + for (const auto &Entry : *Set) + Entry->setInnerComponent(); + }; + if (const LVScopes *Scopes = Parent->getScopes()) + for (LVScope *Scope : *Scopes) { + Scope->setInnerComponent(); + TraverseScope(Scope); + } + Traverse(Parent->getSymbols()); + Traverse(Parent->getTypes()); + Traverse(Parent->getLines()); + }; + + // Start traversing the scopes root and transform the element name. + TraverseScope(this); +} + bool LVScopeRoot::equals(const LVScope *Scope) const { return LVScope::equals(Scope); } diff --git a/llvm/lib/DebugInfo/LogicalView/Core/LVSupport.cpp b/llvm/lib/DebugInfo/LogicalView/Core/LVSupport.cpp index 9fa1f28eb089..42fb1142eb44 100644 --- a/llvm/lib/DebugInfo/LogicalView/Core/LVSupport.cpp +++ b/llvm/lib/DebugInfo/LogicalView/Core/LVSupport.cpp @@ -20,6 +20,12 @@ using namespace llvm::logicalview; #define DEBUG_TYPE "Support" +namespace { +// Unique string pool instance used by all logical readers. +LVStringPool StringPool; +} // namespace +LVStringPool &llvm::logicalview::getStringPool() { return StringPool; } + // Perform the following transformations to the given 'Path': // - all characters to lowercase. // - '\\' into '/' (Platform independent). @@ -54,3 +60,106 @@ std::string llvm::logicalview::flattenedFilePath(StringRef Path) { }; return Name; } + +using LexicalEntry = std::pair<size_t, size_t>; +using LexicalIndexes = SmallVector<LexicalEntry, 10>; + +static LexicalIndexes getAllLexicalIndexes(StringRef Name) { + if (Name.empty()) + return {}; + + size_t AngleCount = 0; + size_t ColonSeen = 0; + size_t Current = 0; + + LexicalIndexes Indexes; + +#ifndef NDEBUG + auto PrintLexicalEntry = [&]() { + LexicalEntry Entry = Indexes.back(); + llvm::dbgs() << formatv( + "'{0}:{1}', '{2}'\n", Entry.first, Entry.second, + Name.substr(Entry.first, Entry.second - Entry.first + 1)); + }; +#endif + + size_t Length = Name.size(); + for (size_t Index = 0; Index < Length; ++Index) { + LLVM_DEBUG({ + llvm::dbgs() << formatv("Index: '{0}', Char: '{1}'\n", Index, + Name[Index]); + }); + switch (Name[Index]) { + case '<': + ++AngleCount; + break; + case '>': + --AngleCount; + break; + case ':': + ++ColonSeen; + break; + } + if (ColonSeen == 2) { + if (!AngleCount) { + Indexes.push_back(LexicalEntry(Current, Index - 2)); + Current = Index + 1; + LLVM_DEBUG({ PrintLexicalEntry(); }); + } + ColonSeen = 0; + continue; + } + } + + // Store last component. + Indexes.push_back(LexicalEntry(Current, Length - 1)); + LLVM_DEBUG({ PrintLexicalEntry(); }); + return Indexes; +} + +LVLexicalComponent llvm::logicalview::getInnerComponent(StringRef Name) { + if (Name.empty()) + return {}; + + LexicalIndexes Indexes = getAllLexicalIndexes(Name); + if (Indexes.size() == 1) + return std::make_tuple(StringRef(), Name); + + LexicalEntry BeginEntry = Indexes.front(); + LexicalEntry EndEntry = Indexes[Indexes.size() - 2]; + StringRef Outer = + Name.substr(BeginEntry.first, EndEntry.second - BeginEntry.first + 1); + + LexicalEntry LastEntry = Indexes.back(); + StringRef Inner = + Name.substr(LastEntry.first, LastEntry.second - LastEntry.first + 1); + + return std::make_tuple(Outer, Inner); +} + +LVStringRefs llvm::logicalview::getAllLexicalComponents(StringRef Name) { + if (Name.empty()) + return {}; + + LexicalIndexes Indexes = getAllLexicalIndexes(Name); + LVStringRefs Components; + for (const LexicalEntry &Entry : Indexes) + Components.push_back( + Name.substr(Entry.first, Entry.second - Entry.first + 1)); + + return Components; +} + +std::string llvm::logicalview::getScopedName(const LVStringRefs &Components, + StringRef BaseName) { + if (Components.empty()) + return {}; + std::string Name(BaseName); + raw_string_ostream Stream(Name); + if (BaseName.size()) + Stream << "::"; + Stream << Components[0]; + for (LVStringRefs::size_type Index = 1; Index < Components.size(); ++Index) + Stream << "::" << Components[Index]; + return Name; +} diff --git a/llvm/lib/DebugInfo/LogicalView/Core/LVSymbol.cpp b/llvm/lib/DebugInfo/LogicalView/Core/LVSymbol.cpp index 82633fbc6b2e..4608fe20cb6d 100644 --- a/llvm/lib/DebugInfo/LogicalView/Core/LVSymbol.cpp +++ b/llvm/lib/DebugInfo/LogicalView/Core/LVSymbol.cpp @@ -66,10 +66,10 @@ void LVSymbol::addLocation(dwarf::Attribute Attr, LVAddress LowPC, LVAddress HighPC, LVUnsigned SectionOffset, uint64_t LocDescOffset, bool CallSiteLocation) { if (!Locations) - Locations = new LVAutoLocations(); + Locations = std::make_unique<LVLocations>(); // Create the location entry. - CurrentLocation = new LVLocationSymbol(); + CurrentLocation = getReader().createLocationSymbol(); CurrentLocation->setParent(this); CurrentLocation->setAttr(Attr); if (CallSiteLocation) @@ -82,10 +82,10 @@ void LVSymbol::addLocation(dwarf::Attribute Attr, LVAddress LowPC, } // Add a Location Record. -void LVSymbol::addLocationOperands(LVSmall Opcode, uint64_t Operand1, - uint64_t Operand2) { +void LVSymbol::addLocationOperands(LVSmall Opcode, + ArrayRef<uint64_t> Operands) { if (CurrentLocation) - CurrentLocation->addObject(Opcode, Operand1, Operand2); + CurrentLocation->addObject(Opcode, Operands); } // Add a Location Entry. @@ -97,15 +97,14 @@ void LVSymbol::addLocationConstant(dwarf::Attribute Attr, LVUnsigned Constant, /*SectionOffset=*/0, LocDescOffset); // Add records to Location Entry. - addLocationOperands(/*Opcode=*/LVLocationMemberOffset, - /*Operand1=*/Constant, /*Operand2=*/0); + addLocationOperands(/*Opcode=*/LVLocationMemberOffset, {Constant}); } LVLocations::iterator LVSymbol::addLocationGap(LVLocations::iterator Pos, LVAddress LowPC, LVAddress HighPC) { // Create a location entry for the gap. - LVLocation *Gap = new LVLocationSymbol(); + LVLocation *Gap = getReader().createLocationSymbol(); Gap->setParent(this); Gap->setAttr(dwarf::DW_AT_location); Gap->addObject(LowPC, HighPC, @@ -115,8 +114,7 @@ LVLocations::iterator LVSymbol::addLocationGap(LVLocations::iterator Pos, LVLocations::iterator Iter = Locations->insert(Pos, Gap); // Add gap to Location Entry. - Gap->addObject(/*op=*/dwarf::DW_OP_hi_user, - /*opd1=*/0, /*opd2=*/0); + Gap->addObject(dwarf::DW_OP_hi_user, {}); // Mark the entry as a gap. Gap->setIsGapEntry(); @@ -190,7 +188,7 @@ void LVSymbol::getLocations(LVLocations &LocationList) const { // Calculate coverage factor. void LVSymbol::calculateCoverage() { - if (!LVLocation::calculateCoverage(Locations, CoverageFactor, + if (!LVLocation::calculateCoverage(Locations.get(), CoverageFactor, CoveragePercentage)) { LVScope *Parent = getParentScope(); if (Parent->getIsInlinedFunction()) { @@ -444,6 +442,6 @@ void LVSymbol::printExtra(raw_ostream &OS, bool Full) const { Reference->printReference(OS, Full, const_cast<LVSymbol *>(this)); // Print location information. - LVLocation::print(Locations, OS, Full); + LVLocation::print(Locations.get(), OS, Full); } } diff --git a/llvm/lib/DebugInfo/LogicalView/Core/LVType.cpp b/llvm/lib/DebugInfo/LogicalView/Core/LVType.cpp index 3d32c34ee02a..28bccadce598 100644 --- a/llvm/lib/DebugInfo/LogicalView/Core/LVType.cpp +++ b/llvm/lib/DebugInfo/LogicalView/Core/LVType.cpp @@ -253,16 +253,10 @@ void LVType::getParameters(const LVTypes *Types, LVTypes *TypesParam, if (!Type->getIsTemplateParam()) continue; if (options().getAttributeArgument()) { - LVScope *Scope = nullptr; if (Type->getIsKindType()) - Type = Type->getTypeAsType(); - else { - if (Type->getIsKindScope()) { - Scope = Type->getTypeAsScope(); - Type = nullptr; - } - } - Type ? TypesParam->push_back(Type) : ScopesParam->push_back(Scope); + TypesParam->push_back(Type->getTypeAsType()); + else if (Type->getIsKindScope()) + ScopesParam->push_back(Type->getTypeAsScope()); } else TypesParam->push_back(Type); } @@ -330,6 +324,13 @@ LVElement *LVTypeDefinition::getUnderlyingType() { } void LVTypeDefinition::resolveExtra() { + // In the case of CodeView, the MSVC toolset generates a series of typedefs + // that refer to internal runtime structures, that we do not process. Those + // typedefs are marked as 'system'. They have an associated logical type, + // but the underlying type always is null. + if (getIsSystem()) + return; + // Set the reference to the typedef type. if (options().getAttributeUnderlying()) { setUnderlyingType(getUnderlyingType()); |
