LCOV - code coverage report
Current view: top level - lib/DebugInfo/PDB/Native - NativeTypeEnum.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 144 149 96.6 %
Date: 2018-10-20 13:21:21 Functions: 33 35 94.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- NativeTypeEnum.cpp - info about enum type ----------------*- 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 "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
      11             : 
      12             : #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
      13             : #include "llvm/DebugInfo/CodeView/TypeRecord.h"
      14             : #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
      15             : #include "llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h"
      16             : #include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
      17             : #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
      18             : #include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
      19             : #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
      20             : #include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
      21             : 
      22             : #include "llvm/Support/FormatVariadic.h"
      23             : 
      24             : #include <cassert>
      25             : 
      26             : using namespace llvm;
      27             : using namespace llvm::codeview;
      28             : using namespace llvm::pdb;
      29             : 
      30             : namespace {
      31             : // Yea, this is a pretty terrible class name.  But if we have an enum:
      32             : //
      33             : // enum Foo {
      34             : //  A,
      35             : //  B
      36             : // };
      37             : //
      38             : // then A and B are the "enumerators" of the "enum" Foo.  And we need
      39             : // to enumerate them.
      40           0 : class NativeEnumEnumEnumerators : public IPDBEnumSymbols, TypeVisitorCallbacks {
      41             : public:
      42             :   NativeEnumEnumEnumerators(NativeSession &Session,
      43             :                             const NativeTypeEnum &ClassParent);
      44             : 
      45             :   uint32_t getChildCount() const override;
      46             :   std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override;
      47             :   std::unique_ptr<PDBSymbol> getNext() override;
      48             :   void reset() override;
      49             : 
      50             : private:
      51             :   Error visitKnownMember(CVMemberRecord &CVM,
      52             :                          EnumeratorRecord &Record) override;
      53             :   Error visitKnownMember(CVMemberRecord &CVM,
      54             :                          ListContinuationRecord &Record) override;
      55             : 
      56             :   NativeSession &Session;
      57             :   const NativeTypeEnum &ClassParent;
      58             :   std::vector<EnumeratorRecord> Enumerators;
      59             :   Optional<TypeIndex> ContinuationIndex;
      60             :   uint32_t Index = 0;
      61             : };
      62             : } // namespace
      63             : 
      64          45 : NativeEnumEnumEnumerators::NativeEnumEnumEnumerators(
      65          45 :     NativeSession &Session, const NativeTypeEnum &ClassParent)
      66          90 :     : Session(Session), ClassParent(ClassParent) {
      67          90 :   TpiStream &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream());
      68             :   LazyRandomTypeCollection &Types = Tpi.typeCollection();
      69             : 
      70          45 :   ContinuationIndex = ClassParent.getEnumRecord().FieldList;
      71          90 :   while (ContinuationIndex) {
      72          90 :     CVType FieldList = Types.getType(*ContinuationIndex);
      73             :     assert(FieldList.kind() == LF_FIELDLIST);
      74             :     ContinuationIndex.reset();
      75          90 :     cantFail(visitMemberRecordStream(FieldList.data(), *this));
      76             :   }
      77          45 : }
      78             : 
      79         178 : Error NativeEnumEnumEnumerators::visitKnownMember(CVMemberRecord &CVM,
      80             :                                                   EnumeratorRecord &Record) {
      81         178 :   Enumerators.push_back(Record);
      82         178 :   return Error::success();
      83             : }
      84             : 
      85           0 : Error NativeEnumEnumEnumerators::visitKnownMember(
      86             :     CVMemberRecord &CVM, ListContinuationRecord &Record) {
      87           0 :   ContinuationIndex = Record.ContinuationIndex;
      88           0 :   return Error::success();
      89             : }
      90             : 
      91          22 : uint32_t NativeEnumEnumEnumerators::getChildCount() const {
      92         846 :   return Enumerators.size();
      93             : }
      94             : 
      95             : std::unique_ptr<PDBSymbol>
      96         178 : NativeEnumEnumEnumerators::getChildAtIndex(uint32_t Index) const {
      97         178 :   if (Index >= getChildCount())
      98             :     return nullptr;
      99             : 
     100         356 :   SymIndexId Id = Session.getSymbolCache()
     101         356 :                       .getOrCreateFieldListMember<NativeSymbolEnumerator>(
     102             :                           ClassParent.getEnumRecord().FieldList, Index,
     103         178 :                           ClassParent, Enumerators[Index]);
     104         356 :   return Session.getSymbolCache().getSymbolById(Id);
     105             : }
     106             : 
     107         223 : std::unique_ptr<PDBSymbol> NativeEnumEnumEnumerators::getNext() {
     108         446 :   if (Index >= getChildCount())
     109             :     return nullptr;
     110             : 
     111         178 :   return getChildAtIndex(Index++);
     112             : }
     113             : 
     114           0 : void NativeEnumEnumEnumerators::reset() { Index = 0; }
     115             : 
     116          50 : NativeTypeEnum::NativeTypeEnum(NativeSession &Session, SymIndexId Id,
     117          50 :                                TypeIndex Index, EnumRecord Record)
     118             :     : NativeRawSymbol(Session, PDB_SymType::Enum, Id), Index(Index),
     119          50 :       Record(std::move(Record)) {}
     120             : 
     121           2 : NativeTypeEnum::NativeTypeEnum(NativeSession &Session, SymIndexId Id,
     122             :                                NativeTypeEnum &UnmodifiedType,
     123           2 :                                codeview::ModifierRecord Modifier)
     124             :     : NativeRawSymbol(Session, PDB_SymType::Enum, Id),
     125           2 :       UnmodifiedType(&UnmodifiedType), Modifiers(std::move(Modifier)) {}
     126             : 
     127         104 : NativeTypeEnum::~NativeTypeEnum() {}
     128             : 
     129          23 : void NativeTypeEnum::dump(raw_ostream &OS, int Indent,
     130             :                           PdbSymbolIdField ShowIdFields,
     131             :                           PdbSymbolIdField RecurseIdFields) const {
     132          23 :   NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
     133             : 
     134          23 :   dumpSymbolField(OS, "baseType", static_cast<uint32_t>(getBuiltinType()),
     135             :                   Indent);
     136          46 :   dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session,
     137             :                     PdbSymbolIdField::LexicalParent, ShowIdFields,
     138             :                     RecurseIdFields);
     139          23 :   dumpSymbolField(OS, "name", getName(), Indent);
     140          23 :   dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session,
     141             :                     PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields);
     142          23 :   if (Modifiers.hasValue())
     143           1 :     dumpSymbolIdField(OS, "unmodifiedTypeId", getUnmodifiedTypeId(), Indent,
     144           1 :                       Session, PdbSymbolIdField::UnmodifiedType, ShowIdFields,
     145             :                       RecurseIdFields);
     146          23 :   dumpSymbolField(OS, "length", getLength(), Indent);
     147          23 :   dumpSymbolField(OS, "constructor", hasConstructor(), Indent);
     148          23 :   dumpSymbolField(OS, "constType", isConstType(), Indent);
     149          23 :   dumpSymbolField(OS, "hasAssignmentOperator", hasAssignmentOperator(), Indent);
     150          23 :   dumpSymbolField(OS, "hasCastOperator", hasCastOperator(), Indent);
     151          23 :   dumpSymbolField(OS, "hasNestedTypes", hasNestedTypes(), Indent);
     152          23 :   dumpSymbolField(OS, "overloadedOperator", hasOverloadedOperator(), Indent);
     153          23 :   dumpSymbolField(OS, "isInterfaceUdt", isInterfaceUdt(), Indent);
     154          23 :   dumpSymbolField(OS, "intrinsic", isIntrinsic(), Indent);
     155          23 :   dumpSymbolField(OS, "nested", isNested(), Indent);
     156          23 :   dumpSymbolField(OS, "packed", isPacked(), Indent);
     157          23 :   dumpSymbolField(OS, "isRefUdt", isRefUdt(), Indent);
     158          23 :   dumpSymbolField(OS, "scoped", isScoped(), Indent);
     159          23 :   dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
     160          23 :   dumpSymbolField(OS, "isValueUdt", isValueUdt(), Indent);
     161          23 :   dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
     162          23 : }
     163             : 
     164             : std::unique_ptr<IPDBEnumSymbols>
     165          45 : NativeTypeEnum::findChildren(PDB_SymType Type) const {
     166          45 :   if (Type != PDB_SymType::Data)
     167             :     return llvm::make_unique<NullEnumerator<PDBSymbol>>();
     168             : 
     169             :   const NativeTypeEnum *ClassParent = nullptr;
     170          45 :   if (!Modifiers)
     171             :     ClassParent = this;
     172             :   else
     173           1 :     ClassParent = UnmodifiedType;
     174          45 :   return llvm::make_unique<NativeEnumEnumEnumerators>(Session, *ClassParent);
     175             : }
     176             : 
     177         110 : PDB_SymType NativeTypeEnum::getSymTag() const { return PDB_SymType::Enum; }
     178             : 
     179          24 : PDB_BuiltinType NativeTypeEnum::getBuiltinType() const {
     180          24 :   if (UnmodifiedType)
     181           1 :     return UnmodifiedType->getBuiltinType();
     182             : 
     183          46 :   Session.getSymbolCache().findSymbolByTypeIndex(Record->getUnderlyingType());
     184             : 
     185          23 :   codeview::TypeIndex Underlying = Record->getUnderlyingType();
     186             : 
     187             :   // This indicates a corrupt record.
     188          23 :   if (!Underlying.isSimple() ||
     189             :       Underlying.getSimpleMode() != SimpleTypeMode::Direct) {
     190             :     return PDB_BuiltinType::None;
     191             :   }
     192             : 
     193             :   switch (Underlying.getSimpleKind()) {
     194             :   case SimpleTypeKind::Boolean128:
     195             :   case SimpleTypeKind::Boolean64:
     196             :   case SimpleTypeKind::Boolean32:
     197             :   case SimpleTypeKind::Boolean16:
     198             :   case SimpleTypeKind::Boolean8:
     199             :     return PDB_BuiltinType::Bool;
     200             :   case SimpleTypeKind::NarrowCharacter:
     201             :   case SimpleTypeKind::UnsignedCharacter:
     202             :   case SimpleTypeKind::SignedCharacter:
     203             :     return PDB_BuiltinType::Char;
     204             :   case SimpleTypeKind::WideCharacter:
     205             :     return PDB_BuiltinType::WCharT;
     206             :   case SimpleTypeKind::Character16:
     207             :     return PDB_BuiltinType::Char16;
     208             :   case SimpleTypeKind::Character32:
     209             :     return PDB_BuiltinType::Char32;
     210             :   case SimpleTypeKind::Int128:
     211             :   case SimpleTypeKind::Int128Oct:
     212             :   case SimpleTypeKind::Int16:
     213             :   case SimpleTypeKind::Int16Short:
     214             :   case SimpleTypeKind::Int32:
     215             :   case SimpleTypeKind::Int32Long:
     216             :   case SimpleTypeKind::Int64:
     217             :   case SimpleTypeKind::Int64Quad:
     218             :     return PDB_BuiltinType::Int;
     219             :   case SimpleTypeKind::UInt128:
     220             :   case SimpleTypeKind::UInt128Oct:
     221             :   case SimpleTypeKind::UInt16:
     222             :   case SimpleTypeKind::UInt16Short:
     223             :   case SimpleTypeKind::UInt32:
     224             :   case SimpleTypeKind::UInt32Long:
     225             :   case SimpleTypeKind::UInt64:
     226             :   case SimpleTypeKind::UInt64Quad:
     227             :     return PDB_BuiltinType::UInt;
     228             :   case SimpleTypeKind::HResult:
     229             :     return PDB_BuiltinType::HResult;
     230             :   case SimpleTypeKind::Complex16:
     231             :   case SimpleTypeKind::Complex32:
     232             :   case SimpleTypeKind::Complex32PartialPrecision:
     233             :   case SimpleTypeKind::Complex64:
     234             :   case SimpleTypeKind::Complex80:
     235             :   case SimpleTypeKind::Complex128:
     236             :     return PDB_BuiltinType::Complex;
     237             :   case SimpleTypeKind::Float16:
     238             :   case SimpleTypeKind::Float32:
     239             :   case SimpleTypeKind::Float32PartialPrecision:
     240             :   case SimpleTypeKind::Float48:
     241             :   case SimpleTypeKind::Float64:
     242             :   case SimpleTypeKind::Float80:
     243             :   case SimpleTypeKind::Float128:
     244             :     return PDB_BuiltinType::Float;
     245             :   default:
     246             :     return PDB_BuiltinType::None;
     247             :   }
     248             :   llvm_unreachable("Unreachable");
     249             : }
     250             : 
     251          24 : SymIndexId NativeTypeEnum::getUnmodifiedTypeId() const {
     252          24 :   return UnmodifiedType ? UnmodifiedType->getSymIndexId() : 0;
     253             : }
     254             : 
     255          24 : bool NativeTypeEnum::hasConstructor() const {
     256          24 :   if (UnmodifiedType)
     257           1 :     return UnmodifiedType->hasConstructor();
     258             : 
     259          23 :   return bool(Record->getOptions() &
     260          23 :               codeview::ClassOptions::HasConstructorOrDestructor);
     261             : }
     262             : 
     263          24 : bool NativeTypeEnum::hasAssignmentOperator() const {
     264          24 :   if (UnmodifiedType)
     265           1 :     return UnmodifiedType->hasAssignmentOperator();
     266             : 
     267          23 :   return bool(Record->getOptions() &
     268          23 :               codeview::ClassOptions::HasOverloadedAssignmentOperator);
     269             : }
     270             : 
     271          24 : bool NativeTypeEnum::hasNestedTypes() const {
     272          24 :   if (UnmodifiedType)
     273           1 :     return UnmodifiedType->hasNestedTypes();
     274             : 
     275          23 :   return bool(Record->getOptions() &
     276          23 :               codeview::ClassOptions::ContainsNestedClass);
     277             : }
     278             : 
     279          24 : bool NativeTypeEnum::isIntrinsic() const {
     280          24 :   if (UnmodifiedType)
     281           1 :     return UnmodifiedType->isIntrinsic();
     282             : 
     283          46 :   return bool(Record->getOptions() & codeview::ClassOptions::Intrinsic);
     284             : }
     285             : 
     286          24 : bool NativeTypeEnum::hasCastOperator() const {
     287          24 :   if (UnmodifiedType)
     288           1 :     return UnmodifiedType->hasCastOperator();
     289             : 
     290          23 :   return bool(Record->getOptions() &
     291          23 :               codeview::ClassOptions::HasConversionOperator);
     292             : }
     293             : 
     294          48 : uint64_t NativeTypeEnum::getLength() const {
     295          48 :   if (UnmodifiedType)
     296           2 :     return UnmodifiedType->getLength();
     297             : 
     298          92 :   const auto Id = Session.getSymbolCache().findSymbolByTypeIndex(
     299             :       Record->getUnderlyingType());
     300             :   const auto UnderlyingType =
     301          46 :       Session.getConcreteSymbolById<PDBSymbolTypeBuiltin>(Id);
     302          46 :   return UnderlyingType ? UnderlyingType->getLength() : 0;
     303             : }
     304             : 
     305          80 : std::string NativeTypeEnum::getName() const {
     306          80 :   if (UnmodifiedType)
     307           3 :     return UnmodifiedType->getName();
     308             : 
     309             :   return Record->getName();
     310             : }
     311             : 
     312          24 : bool NativeTypeEnum::isNested() const {
     313          24 :   if (UnmodifiedType)
     314           1 :     return UnmodifiedType->isNested();
     315             : 
     316          46 :   return bool(Record->getOptions() & codeview::ClassOptions::Nested);
     317             : }
     318             : 
     319          24 : bool NativeTypeEnum::hasOverloadedOperator() const {
     320          24 :   if (UnmodifiedType)
     321           1 :     return UnmodifiedType->hasOverloadedOperator();
     322             : 
     323          23 :   return bool(Record->getOptions() &
     324          23 :               codeview::ClassOptions::HasOverloadedOperator);
     325             : }
     326             : 
     327          24 : bool NativeTypeEnum::isPacked() const {
     328          24 :   if (UnmodifiedType)
     329           1 :     return UnmodifiedType->isPacked();
     330             : 
     331          46 :   return bool(Record->getOptions() & codeview::ClassOptions::Packed);
     332             : }
     333             : 
     334          24 : bool NativeTypeEnum::isScoped() const {
     335          24 :   if (UnmodifiedType)
     336           1 :     return UnmodifiedType->isScoped();
     337             : 
     338          46 :   return bool(Record->getOptions() & codeview::ClassOptions::Scoped);
     339             : }
     340             : 
     341         314 : SymIndexId NativeTypeEnum::getTypeId() const {
     342         314 :   if (UnmodifiedType)
     343           1 :     return UnmodifiedType->getTypeId();
     344             : 
     345         626 :   return Session.getSymbolCache().findSymbolByTypeIndex(
     346         313 :       Record->getUnderlyingType());
     347             : }
     348             : 
     349          23 : bool NativeTypeEnum::isRefUdt() const { return false; }
     350             : 
     351          23 : bool NativeTypeEnum::isValueUdt() const { return false; }
     352             : 
     353          23 : bool NativeTypeEnum::isInterfaceUdt() const { return false; }
     354             : 
     355          24 : bool NativeTypeEnum::isConstType() const {
     356          24 :   if (!Modifiers)
     357             :     return false;
     358           2 :   return ((Modifiers->getModifiers() & ModifierOptions::Const) !=
     359           2 :           ModifierOptions::None);
     360             : }
     361             : 
     362          24 : bool NativeTypeEnum::isVolatileType() const {
     363          24 :   if (!Modifiers)
     364             :     return false;
     365           2 :   return ((Modifiers->getModifiers() & ModifierOptions::Volatile) !=
     366           2 :           ModifierOptions::None);
     367             : }
     368             : 
     369          24 : bool NativeTypeEnum::isUnalignedType() const {
     370          24 :   if (!Modifiers)
     371             :     return false;
     372           2 :   return ((Modifiers->getModifiers() & ModifierOptions::Unaligned) !=
     373           2 :           ModifierOptions::None);
     374             : }
     375             : 
     376         178 : const NativeTypeBuiltin &NativeTypeEnum::getUnderlyingBuiltinType() const {
     377         178 :   if (UnmodifiedType)
     378             :     return UnmodifiedType->getUnderlyingBuiltinType();
     379             : 
     380         178 :   return Session.getSymbolCache().getNativeSymbolById<NativeTypeBuiltin>(
     381         178 :       getTypeId());
     382             : }

Generated by: LCOV version 1.13