This revision was automatically updated to reflect the committed changes.
Closed by commit rL345629: [NativePDB] Add support for dumping global variables 
of class type. (authored by zturner, committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D53822?vs=171537&id=171755#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D53822

Files:
  lldb/trunk/lit/SymbolFile/NativePDB/Inputs/globals-classes.lldbinit
  lldb/trunk/lit/SymbolFile/NativePDB/global-classes.cpp
  lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
  lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
  lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
  lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h

Index: lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
===================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
@@ -59,6 +59,8 @@
 
 lldb::AccessType TranslateMemberAccess(llvm::codeview::MemberAccess access);
 llvm::codeview::TypeIndex GetFieldListIndex(llvm::codeview::CVType cvt);
+llvm::codeview::TypeIndex
+LookThroughModifierRecord(llvm::codeview::CVType modifier);
 
 llvm::StringRef DropNameScope(llvm::StringRef name);
 
Index: lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
===================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
@@ -170,6 +170,8 @@
                              const llvm::codeview::EnumRecord &er);
   lldb::TypeSP CreateTagType(PdbSymUid type_uid,
                              const llvm::codeview::UnionRecord &ur);
+  lldb::TypeSP CreateArrayType(PdbSymUid type_uid,
+                               const llvm::codeview::ArrayRecord &ar);
   lldb::TypeSP
   CreateClassStructUnion(PdbSymUid type_uid, llvm::StringRef name, size_t size,
                          clang::TagTypeKind ttk,
Index: lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
===================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
@@ -343,6 +343,13 @@
   }
 }
 
+TypeIndex lldb_private::npdb::LookThroughModifierRecord(CVType modifier) {
+  lldbassert(modifier.kind() == LF_MODIFIER);
+  ModifierRecord mr;
+  llvm::cantFail(TypeDeserializer::deserializeAs<ModifierRecord>(modifier, mr));
+  return mr.ModifiedType;
+}
+
 llvm::StringRef lldb_private::npdb::DropNameScope(llvm::StringRef name) {
   // Not all PDB names can be parsed with CPlusPlusNameParser.
   // E.g. it fails on names containing `anonymous namespace'.
Index: lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
===================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -391,9 +391,7 @@
   // If this is an LF_MODIFIER, look through it to get the kind that it
   // modifies.  Note that it's not possible to have an LF_MODIFIER that
   // modifies another LF_MODIFIER, although this would handle that anyway.
-  ModifierRecord mr;
-  llvm::cantFail(TypeDeserializer::deserializeAs<ModifierRecord>(cvt, mr));
-  return GetPdbSymType(tpi, mr.ModifiedType);
+  return GetPdbSymType(tpi, LookThroughModifierRecord(cvt));
 }
 
 static clang::TagTypeKind TranslateUdtKind(const TagRecord &cr) {
@@ -775,6 +773,25 @@
       lldb_private::Type::eResolveStateForward);
 }
 
+TypeSP SymbolFileNativePDB::CreateArrayType(PdbSymUid type_uid,
+                                            const ArrayRecord &ar) {
+  TypeSP element_type = GetOrCreateType(ar.ElementType);
+  uint64_t element_count = ar.Size / element_type->GetByteSize();
+
+  CompilerType element_ct = element_type->GetFullCompilerType();
+
+  CompilerType array_ct =
+      m_clang->CreateArrayType(element_ct, element_count, false);
+
+  Declaration decl;
+  TypeSP array_sp = std::make_shared<lldb_private::Type>(
+      type_uid.toOpaqueId(), m_clang->GetSymbolFile(), ConstString(), ar.Size,
+      nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
+      array_ct, lldb_private::Type::eResolveStateFull);
+  array_sp->SetEncodingType(element_type.get());
+  return array_sp;
+}
+
 TypeSP SymbolFileNativePDB::CreateType(PdbSymUid type_uid) {
   const PdbTypeSymId &tsid = type_uid.asTypeSym();
   TypeIndex index(tsid.index);
@@ -817,6 +834,12 @@
     return CreateTagType(type_uid, ur);
   }
 
+  if (cvt.kind() == LF_ARRAY) {
+    ArrayRecord ar;
+    llvm::cantFail(TypeDeserializer::deserializeAs<ArrayRecord>(cvt, ar));
+    return CreateArrayType(type_uid, ar);
+  }
+
   return nullptr;
 }
 
@@ -1442,6 +1465,25 @@
   auto types_iter = m_types.find(uid.toOpaqueId());
   lldbassert(types_iter != m_types.end());
 
+  if (cvt.kind() == LF_MODIFIER) {
+    TypeIndex unmodified_type = LookThroughModifierRecord(cvt);
+    cvt = m_index->tpi().getType(unmodified_type);
+    // LF_MODIFIERS usually point to forward decls, so this is the one case
+    // where we won't have been able to resolve a forward decl to a full decl
+    // earlier on.  So we need to do that now.
+    if (IsForwardRefUdt(cvt)) {
+      llvm::Expected<TypeIndex> expected_full_ti =
+          m_index->tpi().findFullDeclForForwardRef(unmodified_type);
+      if (!expected_full_ti) {
+        llvm::consumeError(expected_full_ti.takeError());
+        return false;
+      }
+      cvt = m_index->tpi().getType(*expected_full_ti);
+      lldbassert(!IsForwardRefUdt(cvt));
+      unmodified_type = *expected_full_ti;
+    }
+    uid = PdbSymUid::makeTypeSymId(uid.tag(), unmodified_type, false);
+  }
   TypeIndex field_list_ti = GetFieldListIndex(cvt);
   CVType field_list_cvt = m_index->tpi().getType(field_list_ti);
   if (field_list_cvt.kind() != LF_FIELDLIST)
Index: lldb/trunk/lit/SymbolFile/NativePDB/Inputs/globals-classes.lldbinit
===================================================================
--- lldb/trunk/lit/SymbolFile/NativePDB/Inputs/globals-classes.lldbinit
+++ lldb/trunk/lit/SymbolFile/NativePDB/Inputs/globals-classes.lldbinit
@@ -0,0 +1,14 @@
+settings set auto-one-line-summaries false
+
+target variable -T ClassWithPaddingInstance
+target variable -T ClassNoPaddingInstance
+target variable -T DC
+target variable -T EBOC
+target variable -T PBC
+
+target variable -T UnnamedClassInstance
+
+target variable -T PointersInstance
+target variable -T ReferencesInstance
+
+quit
\ No newline at end of file
Index: lldb/trunk/lit/SymbolFile/NativePDB/global-classes.cpp
===================================================================
--- lldb/trunk/lit/SymbolFile/NativePDB/global-classes.cpp
+++ lldb/trunk/lit/SymbolFile/NativePDB/global-classes.cpp
@@ -0,0 +1,275 @@
+// clang-format off
+// REQUIRES: lld
+
+// Test that we can display tag types.
+// RUN: clang-cl /Z7 /GS- /GR- /c -Xclang -fkeep-static-consts /Fo%t.obj -- %s
+// RUN: lld-link /DEBUG /nodefaultlib /entry:main /OUT:%t.exe /PDB:%t.pdb -- %t.obj
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb -f %t.exe -s \
+// RUN:     %p/Inputs/globals-classes.lldbinit | FileCheck %s
+
+enum class EnumType : unsigned {
+  A = 1,
+  B = 2
+};
+
+class ClassNoPadding {
+  /* [ 0] */ unsigned char a = 86;
+  /* [ 1] */ char b = 'a';
+  /* [ 2] */ bool c = false;
+  /* [ 3] */ bool d = true;
+  /* [ 4] */ short e = -1234;
+  /* [ 6] */ unsigned short f = 8123;
+  /* [ 8] */ unsigned int g = 123908;
+  /* [12] */ int h = -890234;
+  /* [16] */ unsigned long i = 2908234;
+  /* [20] */ long j = 7234890;
+  /* [24] */ float k = 908234.12392;
+  /* [28] */ EnumType l = EnumType::A;
+  /* [32] */ double m = 23890.897423;
+  /* [40] */ unsigned long long n = 23490782;
+  /* [48] */ long long o = -923409823;
+  /* [56] */ int p[5] = { 2, 3, 5, 8, 13 };
+};
+
+class ClassWithPadding {
+  /* [ 0] */ char a = '0';
+  //         char padding[1];
+  /* [ 2] */ short b = 50;
+  /* [ 4] */ char c[2] = { '0', '1' };
+  //         char padding[2];
+  /* [ 8] */ int d = 100;
+  /* [12] */ char e = '0';
+  //         char padding[3];
+  /* [16] */ int f = 200;
+  //         char padding[4];
+  /* [24] */ long long g = 300;
+  /* [32] */ char h[3] = { '0', '1', '2' };
+  //         char padding[5];
+  /* [40] */ long long i = 400;
+  /* [48] */ char j[2] = { '0', '1' };
+  //         char padding[6];
+  /* [56] */ long long k = 500;
+  /* [64] */ char l = '0';
+  //         char padding[7];
+  /* [72] */ long long m = 600;
+} ;
+
+struct EmptyBase {};
+
+template<typename T>
+struct BaseClass {
+  constexpr BaseClass(int N)
+    : BaseMember(N) {}
+
+  int BaseMember;
+};
+
+struct DerivedClass : public BaseClass<int> {
+  constexpr DerivedClass(int Base, int Derived)
+    : BaseClass(Base), DerivedMember(Derived) {}
+
+  int DerivedMember;
+};
+
+struct EBO : public EmptyBase {
+  constexpr EBO(int N) : Member(N) {}
+  int Member;
+};
+
+struct PaddedBases : public BaseClass<char>, public BaseClass<short>, BaseClass<int> {
+  constexpr PaddedBases(char CH, short S, int N, long long D)
+    : BaseClass<char>(CH), BaseClass<short>(S), BaseClass<int>(N), DerivedMember(D) {}
+  long long DerivedMember;
+};
+
+struct Statics {
+  static char a;
+  static bool b;
+  static short c;
+  static unsigned short d;
+  static unsigned int e;
+  static int f;
+  static unsigned long g;
+  static long h;
+  static float i;
+  static EnumType j;
+  static double k;
+  static unsigned long long l;
+  static long long m;
+};
+
+char Statics::a = 'a';
+bool Statics::b = true;
+short Statics::c = 1234;
+unsigned short Statics::d = 2345;
+unsigned int Statics::e = 3456;
+int Statics::f = 4567;
+unsigned long Statics::g = 5678;
+long Statics::h = 6789;
+float Statics::i = 7890.1234;
+EnumType Statics::j = EnumType::A;
+double Statics::k = 8901.2345;
+unsigned long long Statics::l = 9012345;
+long long Statics::m = 1234567;
+
+
+struct Pointers {
+  void *a = nullptr;
+  char *b = &Statics::a;
+  bool *c = &Statics::b;
+  short *e = &Statics::c;
+  unsigned short *f = &Statics::d;
+  unsigned int *g = &Statics::e;
+  int *h = &Statics::f;
+  unsigned long *i = &Statics::g;
+  long *j = &Statics::h;
+  float *k = &Statics::i;
+  EnumType *l = &Statics::j;
+  double *m = &Statics::k;
+  unsigned long long *n = &Statics::l;
+  long long *o = &Statics::m;
+};
+
+struct References {
+  char &a = Statics::a;
+  bool &b = Statics::b;
+  short &c = Statics::c;
+  unsigned short &d = Statics::d;
+  unsigned int &e = Statics::e;
+  int &f = Statics::f;
+  unsigned long &g = Statics::g;
+  long &h = Statics::h;
+  float &i = Statics::i;
+  EnumType &j = Statics::j;
+  double &k = Statics::k;
+  unsigned long long &l = Statics::l;
+  long long &m = Statics::m;
+};
+
+
+constexpr ClassWithPadding ClassWithPaddingInstance;
+// CHECK:      (lldb) target variable -T ClassWithPaddingInstance
+// CHECK-NEXT: (const ClassWithPadding) ClassWithPaddingInstance = {
+// CHECK-NEXT:   (char) a = '0'
+// CHECK-NEXT:   (short) b = 50
+// CHECK-NEXT:   (char [2]) c = "01"
+// CHECK-NEXT:   (int) d = 100
+// CHECK-NEXT:   (char) e = '0'
+// CHECK-NEXT:   (int) f = 200
+// CHECK-NEXT:   (long long) g = 300
+// CHECK-NEXT:   (char [3]) h = "012"
+// CHECK-NEXT:   (long long) i = 400
+// CHECK-NEXT:   (char [2]) j = "01"
+// CHECK-NEXT:   (long long) k = 500
+// CHECK-NEXT:   (char) l = '0'
+// CHECK-NEXT:   (long long) m = 600
+// CHECK-NEXT: }
+
+constexpr ClassNoPadding ClassNoPaddingInstance;
+// CHECK:      (lldb) target variable -T ClassNoPaddingInstance
+// CHECK-NEXT: (const ClassNoPadding) ClassNoPaddingInstance = {
+// CHECK-NEXT:   (unsigned char) a = 'V'
+// CHECK-NEXT:   (char) b = 'a'
+// CHECK-NEXT:   (bool) c = false
+// CHECK-NEXT:   (bool) d = true
+// CHECK-NEXT:   (short) e = -1234
+// CHECK-NEXT:   (unsigned short) f = 8123
+// CHECK-NEXT:   (unsigned int) g = 123908
+// CHECK-NEXT:   (int) h = -890234
+// CHECK-NEXT:   (unsigned long) i = 2908234
+// CHECK-NEXT:   (long) j = 7234890
+// CHECK-NEXT:   (float) k = 908234.125
+// CHECK-NEXT:   (EnumType) l = A
+// CHECK-NEXT:   (double) m = 23890.897422999999
+// CHECK-NEXT:   (unsigned long long) n = 23490782
+// CHECK-NEXT:     (long long) o = -923409823
+// CHECK-NEXT:     (int [5]) p = {
+// CHECK-NEXT:       (int) [0] = 2
+// CHECK-NEXT:       (int) [1] = 3
+// CHECK-NEXT:       (int) [2] = 5
+// CHECK-NEXT:       (int) [3] = 8
+// CHECK-NEXT:       (int) [4] = 13
+// CHECK-NEXT:     }
+// CHECK-NEXT:   }
+
+constexpr DerivedClass DC(10, 20);
+// CHECK:      (lldb) target variable -T DC
+// CHECK-NEXT: (const DerivedClass) DC = {
+// CHECK-NEXT:   (BaseClass<int>) BaseClass<int> = {
+// CHECK-NEXT:     (int) BaseMember = 10
+// CHECK-NEXT:   }
+// CHECK-NEXT:   (int) DerivedMember = 20
+// CHECK-NEXT: }
+
+constexpr EBO EBOC(20);
+// CHECK:      (lldb) target variable -T EBOC
+// CHECK-NEXT: (const EBO) EBOC = {
+// CHECK-NEXT:   (int) Member = 20
+// CHECK-NEXT: }
+
+constexpr PaddedBases PBC('a', 12, 120, 1200);
+// CHECK:      (lldb) target variable -T PBC
+// CHECK-NEXT: (const PaddedBases) PBC = {
+// CHECK-NEXT:   (BaseClass<char>) BaseClass<char> = {
+// CHECK-NEXT:     (int) BaseMember = 97
+// CHECK-NEXT:   }
+// CHECK-NEXT:   (BaseClass<short>) BaseClass<short> = {
+// CHECK-NEXT:     (int) BaseMember = 12
+// CHECK-NEXT:   }
+// CHECK-NEXT:   (BaseClass<int>) BaseClass<int> = {
+// CHECK-NEXT:     (int) BaseMember = 120
+// CHECK-NEXT:   }
+// CHECK-NEXT:   (long long) DerivedMember = 1200
+// CHECK-NEXT: }
+
+constexpr struct {
+  int x = 12;
+  EBO EBOC{ 42 };
+} UnnamedClassInstance;
+// CHECK:      (lldb) target variable -T UnnamedClassInstance
+// CHECK-NEXT: (const <unnamed-type-UnnamedClassInstance>) UnnamedClassInstance = {
+// CHECK-NEXT:   (int) x = 12
+// CHECK-NEXT:   (EBO) EBOC = {
+// CHECK-NEXT:     (int) Member = 42
+// CHECK-NEXT:   }
+// CHECK-NEXT: }
+
+constexpr Pointers PointersInstance;
+// CHECK:      (lldb) target variable -T PointersInstance
+// CHECK-NEXT: (const Pointers) PointersInstance = {
+// CHECK-NEXT:   (void *) a = {{.*}}
+// CHECK-NEXT:   (char *) b = {{.*}}
+// CHECK-NEXT:   (bool *) c = {{.*}}
+// CHECK-NEXT:   (short *) e = {{.*}}
+// CHECK-NEXT:   (unsigned short *) f = {{.*}}
+// CHECK-NEXT:   (unsigned int *) g = {{.*}}
+// CHECK-NEXT:   (int *) h = {{.*}}
+// CHECK-NEXT:   (unsigned long *) i = {{.*}}
+// CHECK-NEXT:   (long *) j = {{.*}}
+// CHECK-NEXT:   (float *) k = {{.*}}
+// CHECK-NEXT:   (EnumType *) l = {{.*}}
+// CHECK-NEXT:   (double *) m = {{.*}}
+// CHECK-NEXT:   (unsigned long long *) n = {{.*}}
+// CHECK-NEXT:   (long long *) o = {{.*}}
+// CHECK-NEXT: }
+constexpr References ReferencesInstance;
+// CHECK:      (lldb) target variable -T ReferencesInstance
+// CHECK-NEXT: (const References) ReferencesInstance = {
+// CHECK-NEXT:   (char &) a = {{.*}}
+// CHECK-NEXT:   (bool &) b = {{.*}}
+// CHECK-NEXT:   (short &) c = {{.*}}
+// CHECK-NEXT:   (unsigned short &) d = {{.*}}
+// CHECK-NEXT:   (unsigned int &) e = {{.*}}
+// CHECK-NEXT:   (int &) f = {{.*}}
+// CHECK-NEXT:   (unsigned long &) g = {{.*}}
+// CHECK-NEXT:   (long &) h = {{.*}}
+// CHECK-NEXT:   (float &) i = {{.*}}
+// CHECK-NEXT:   (EnumType &) j = {{.*}}
+// CHECK-NEXT:   (double &) k = {{.*}}
+// CHECK-NEXT:   (unsigned long long &) l = {{.*}}
+// CHECK-NEXT:   (long long &) m = {{.*}}
+// CHECK-NEXT: }
+
+int main(int argc, char **argv) {
+  return 0;
+}
\ No newline at end of file
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to