[llvm-pdbdump] Re-write the record layout code to be more resilient.

This reworks the way virtual bases are handled, and also the way
padding is detected across multiple levels of aggregates, producing
a much more accurate result.

llvm-svn: 301203
diff --git a/llvm/test/tools/llvm-pdbdump/Inputs/ComplexPaddingTest.cpp b/llvm/test/tools/llvm-pdbdump/Inputs/ComplexPaddingTest.cpp
new file mode 100644
index 0000000..44a4e30
--- /dev/null
+++ b/llvm/test/tools/llvm-pdbdump/Inputs/ComplexPaddingTest.cpp
@@ -0,0 +1,48 @@
+// Compile with "cl /c /Zi /GR- ComplexPaddingTest.cpp"
+// Link with "link ComplexPaddingTest.obj /debug /nodefaultlib /entry:main"
+
+#include <stdint.h>
+
+extern "C" using at_exit_handler = void();
+
+int atexit(at_exit_handler handler) { return 0; }
+
+struct TestVB {
+  static void operator delete(void *ptr, size_t sz) {}
+  virtual ~TestVB() {}
+  virtual void IntroFunction1() {}
+  int X;
+} A;
+
+struct TestNVB {
+  static void operator delete(void *ptr, size_t sz) {}
+  virtual ~TestNVB() {}
+  virtual void IntroFunction2() {}
+  int Y;
+} B;
+
+struct TestVBLayout
+    : public virtual TestVB,
+      public TestNVB {
+  static void operator delete(void *ptr, size_t sz) {}
+  int Z;
+} C;
+
+struct TestIVBBase : public virtual TestVB {
+  int A;
+} D;
+
+struct TestIVBDerived : public TestIVBBase {
+  int B;
+} E;
+
+struct TestIVBMergedDerived
+    : public virtual TestVB,
+      public TestIVBBase {
+  int B;
+} F;
+
+int main(int argc, char **argv) {
+
+  return 0;
+}
diff --git a/llvm/test/tools/llvm-pdbdump/Inputs/ComplexPaddingTest.pdb b/llvm/test/tools/llvm-pdbdump/Inputs/ComplexPaddingTest.pdb
new file mode 100644
index 0000000..093276b
--- /dev/null
+++ b/llvm/test/tools/llvm-pdbdump/Inputs/ComplexPaddingTest.pdb
Binary files differ
diff --git a/llvm/test/tools/llvm-pdbdump/class-layout.test b/llvm/test/tools/llvm-pdbdump/class-layout.test
index c0083d1..ef5eb49 100644
--- a/llvm/test/tools/llvm-pdbdump/class-layout.test
+++ b/llvm/test/tools/llvm-pdbdump/class-layout.test
@@ -36,9 +36,8 @@
 
 ; BASE_CLASS_D: ---TYPES---
 ; BASE_CLASS_D: class BaseClassTest::D [sizeof = 8]
-; BASE_CLASS_D-DAG: protected BaseClassTest::B
-; BASE_CLASS_D-DAG: private BaseClassTest::C
-; BASE_CLASS_D-DAG: protected virtual BaseClassTest::A
+; BASE_CLASS_D-NEXT: protected BaseClassTest::B
+; BASE_CLASS_D-NEXT: private BaseClassTest::C
 
 ; UDT_KIND_TEST: ---TYPES---
 ; UDT_KIND_TEST-DAG: union UdtKindTest::C [sizeof = 1] {}
diff --git a/llvm/test/tools/llvm-pdbdump/complex-padding-graphical.test b/llvm/test/tools/llvm-pdbdump/complex-padding-graphical.test
new file mode 100644
index 0000000..8288122
--- /dev/null
+++ b/llvm/test/tools/llvm-pdbdump/complex-padding-graphical.test
@@ -0,0 +1,53 @@
+; RUN: llvm-pdbdump pretty -classes -class-definitions=graphical \

+; RUN:     -include-types=Test %p/Inputs/ComplexPaddingTest.pdb > %t

+

+; RUN: FileCheck -input-file=%t %s -check-prefix=DIRECT_VB_ONLY

+; RUN: FileCheck -input-file=%t %s -check-prefix=DIRECT_VB_AND_NON_VB

+; RUN: FileCheck -input-file=%t %s -check-prefix=INDIRECT_VB

+; RUN: FileCheck -input-file=%t %s -check-prefix=INDIRECT_AND_DIRECT_VB

+

+

+; DIRECT_VB_ONLY:      struct TestIVBBase [sizeof = 16]

+; DIRECT_VB_ONLY-NEXT:   : public virtual TestVB {

+; DIRECT_VB_ONLY-NEXT:   vbptr +0x00 [sizeof=4]

+; DIRECT_VB_ONLY-NEXT:   data +0x04 [sizeof=4] int A

+; DIRECT_VB_ONLY-NEXT:   vbase +0x08 [sizeof=8] TestVB

+; DIRECT_VB_ONLY-NEXT:     vfptr +0x08 [sizeof=4]

+; DIRECT_VB_ONLY-NEXT:     data +0x0c [sizeof=4] int X

+; DIRECT_VB_ONLY-NEXT: }

+

+DIRECT_VB_AND_NON_VB:      struct TestVBLayout [sizeof = 24]

+DIRECT_VB_AND_NON_VB-NEXT:   : public TestNVB

+DIRECT_VB_AND_NON_VB-NEXT:   , public virtual TestVB {

+DIRECT_VB_AND_NON_VB-NEXT:   base +0x00 [sizeof=8] TestNVB

+DIRECT_VB_AND_NON_VB-NEXT:     vfptr +0x00 [sizeof=4]

+DIRECT_VB_AND_NON_VB-NEXT:     data +0x04 [sizeof=4] int Y

+DIRECT_VB_AND_NON_VB-NEXT:   vbptr +0x08 [sizeof=4]

+DIRECT_VB_AND_NON_VB-NEXT:   data +0x0c [sizeof=4] int Z

+DIRECT_VB_AND_NON_VB-NEXT:   vbase +0x10 [sizeof=8] TestVB

+DIRECT_VB_AND_NON_VB-NEXT:     vfptr +0x10 [sizeof=4]

+DIRECT_VB_AND_NON_VB-NEXT:     data +0x14 [sizeof=4] int X

+DIRECT_VB_AND_NON_VB-NEXT: }

+

+INDIRECT_VB:      struct TestIVBDerived [sizeof = 20]

+INDIRECT_VB-NEXT:   : public TestIVBBase {

+INDIRECT_VB-NEXT:   base +0x00 [sizeof=8] TestIVBBase

+INDIRECT_VB-NEXT:     vbptr +0x00 [sizeof=4]

+INDIRECT_VB-NEXT:     data +0x04 [sizeof=4] int A

+INDIRECT_VB-NEXT:   data +0x08 [sizeof=4] int B

+INDIRECT_VB-NEXT:   ivbase +0x0c [sizeof=8] TestVB

+INDIRECT_VB-NEXT:     vfptr +0x0c [sizeof=4]

+INDIRECT_VB-NEXT:     data +0x10 [sizeof=4] int X

+INDIRECT_VB-NEXT: }

+

+INDIRECT_AND_DIRECT_VB:      struct TestIVBMergedDerived [sizeof = 20]

+INDIRECT_AND_DIRECT_VB-NEXT:   : public TestIVBBase

+INDIRECT_AND_DIRECT_VB-NEXT:   , public virtual TestVB {

+INDIRECT_AND_DIRECT_VB-NEXT:   base +0x00 [sizeof=8] TestIVBBase

+INDIRECT_AND_DIRECT_VB-NEXT:     vbptr +0x00 [sizeof=4]

+INDIRECT_AND_DIRECT_VB-NEXT:     data +0x04 [sizeof=4] int A

+INDIRECT_AND_DIRECT_VB-NEXT:   data +0x08 [sizeof=4] int B

+INDIRECT_AND_DIRECT_VB-NEXT:   vbase +0x0c [sizeof=8] TestVB

+INDIRECT_AND_DIRECT_VB-NEXT:     vfptr +0x0c [sizeof=4]

+INDIRECT_AND_DIRECT_VB-NEXT:     data +0x10 [sizeof=4] int X

+INDIRECT_AND_DIRECT_VB-NEXT: }

diff --git a/llvm/test/tools/llvm-pdbdump/simple-padding-graphical.test b/llvm/test/tools/llvm-pdbdump/simple-padding-graphical.test
index aacb0a3..222349e 100644
--- a/llvm/test/tools/llvm-pdbdump/simple-padding-graphical.test
+++ b/llvm/test/tools/llvm-pdbdump/simple-padding-graphical.test
@@ -71,7 +71,6 @@
 
 ; VFPTR:      struct SimplePadVfptr [sizeof = 8] {
 ; VFPTR-NEXT:   vfptr +0x00 [sizeof=4]
-; VFPTR-NEXT:     [0] &SimplePadVfptr::~SimplePadVfptr
 ; VFPTR-NEXT:   data +0x04 [sizeof=4] int X
 ; VFPTR-NEXT: }
 
@@ -89,15 +88,15 @@
 ; MULTIPLE_INHERIT2:      SimplePadMultiInherit2 [sizeof = 16]
 ; MULTIPLE_INHERIT2-NEXT:   : public SimplePadFields1
 ; MULTIPLE_INHERIT2-NEXT:   , public SimplePadFields2 {
-; MULTIPLE_INHERIT2-NEXT:   base +0x00 [sizeof=4] SimplePadFields1
+; MULTIPLE_INHERIT2-NEXT:   base +0x00 [sizeof=3] SimplePadFields1
 ; MULTIPLE_INHERIT2-NEXT:     data +0x00 [sizeof=1] char A
 ; MULTIPLE_INHERIT2-NEXT:     data +0x01 [sizeof=1] char B
 ; MULTIPLE_INHERIT2-NEXT:     data +0x02 [sizeof=1] char C
-; MULTIPLE_INHERIT2-NEXT:     <padding> (1 bytes)
-; MULTIPLE_INHERIT2-NEXT:   base +0x04 [sizeof=8] SimplePadFields2
+; MULTIPLE_INHERIT2-NEXT:   <padding> (1 bytes)
+; MULTIPLE_INHERIT2-NEXT:   base +0x04 [sizeof=5] SimplePadFields2
 ; MULTIPLE_INHERIT2-NEXT:     data +0x04 [sizeof=4] int Y
 ; MULTIPLE_INHERIT2-NEXT:     data +0x08 [sizeof=1] char X
-; MULTIPLE_INHERIT2-NEXT:     <padding> (3 bytes)
+; MULTIPLE_INHERIT2-NEXT:   <padding> (3 bytes)
 ; MULTIPLE_INHERIT2-NEXT:   data +0x0c [sizeof=4] int X
 ; MULTIPLE_INHERIT2-NEXT: }
 
diff --git a/llvm/test/tools/llvm-pdbdump/simple-padding-text.test b/llvm/test/tools/llvm-pdbdump/simple-padding-text.test
deleted file mode 100644
index b33af56..0000000
--- a/llvm/test/tools/llvm-pdbdump/simple-padding-text.test
+++ /dev/null
@@ -1,94 +0,0 @@
-; RUN: llvm-pdbdump pretty -classes -class-definitions=layout-members \
-; RUN:     -include-types=SimplePad %p/Inputs/SimplePaddingTest.pdb > %t
-
-; RUN: FileCheck -input-file=%t %s -check-prefix=NO_PADDING
-; RUN: FileCheck -input-file=%t %s -check-prefix=UNION
-; RUN: FileCheck -input-file=%t %s -check-prefix=NESTED_UNION
-; RUN: FileCheck -input-file=%t %s -check-prefix=PAD_FROM_FIELDS1
-; RUN: FileCheck -input-file=%t %s -check-prefix=PAD_FROM_FIELDS2
-; RUN: FileCheck -input-file=%t %s -check-prefix=NO_PAD_IN_BASE
-; RUN: FileCheck -input-file=%t %s -check-prefix=PAD_IN_DERIVED
-; RUN: FileCheck -input-file=%t %s -check-prefix=EMPTY_BASE
-; RUN: FileCheck -input-file=%t %s -check-prefix=VFPTR
-; RUN: FileCheck -input-file=%t %s -check-prefix=MULTIPLE_INHERIT
-; RUN: FileCheck -input-file=%t %s -check-prefix=MULTIPLE_INHERIT2
-; RUN: FileCheck -input-file=%t %s -check-prefix=DEEP_INHERIT
-; RUN: FileCheck -input-file=%t %s -check-prefix=AGGREGATE
-
-; NO_PADDING:      struct SimplePadNoPadding [sizeof = 8] {
-; NO_PADDING-NEXT:   data +0x00 [sizeof=4] int X
-; NO_PADDING-NEXT:   data +0x04 [sizeof=4] int Y
-; NO_PADDING-NEXT: }
-
-; UNION:      struct SimplePadUnion [sizeof = 16] {
-; UNION-NEXT:   data +0x00 [sizeof=4] int X
-; UNION-NEXT:   data +0x00 [sizeof=8] __int64 Y
-; UNION-NEXT:   data +0x00 [sizeof=16] SimplePadUnion::
-; UNION-NEXT: }
-
-; NESTED_UNION:      struct {{SimplePadUnion::.*}} [sizeof = 16] {
-; NESTED_UNION-NEXT:   data +0x00 [sizeof=4] int X
-; NESTED_UNION-NEXT:   <padding> (4 bytes)
-; NESTED_UNION-NEXT:   data +0x08 [sizeof=8] __int64 Y
-; NESTED_UNION-NEXT: }
-
-; PAD_FROM_FIELDS1:      struct SimplePadFields1 [sizeof = 4] {
-; PAD_FROM_FIELDS1-NEXT:   data +0x00 [sizeof=1] char A
-; PAD_FROM_FIELDS1-NEXT:   data +0x01 [sizeof=1] char B
-; PAD_FROM_FIELDS1-NEXT:   data +0x02 [sizeof=1] char C
-; PAD_FROM_FIELDS1-NEXT:   <padding> (1 bytes)
-; PAD_FROM_FIELDS1-NEXT: }
-
-; PAD_FROM_FIELDS2:      struct SimplePadFields2 [sizeof = 8] {
-; PAD_FROM_FIELDS2-NEXT:   data +0x00 [sizeof=4] int Y
-; PAD_FROM_FIELDS2-NEXT:   data +0x04 [sizeof=1] char X
-; PAD_FROM_FIELDS2-NEXT:   <padding> (3 bytes)
-; PAD_FROM_FIELDS2-NEXT: }
-
-; NO_PAD_IN_BASE:      struct SimplePadBase [sizeof = 4] {
-; NO_PAD_IN_BASE-NEXT:   data +0x00 [sizeof=4] int X
-; NO_PAD_IN_BASE-NEXT: }
-
-; PAD_IN_DERIVED:      struct SimplePadDerived [sizeof = 16]
-; PAD_IN_DERIVED-NEXT:   public SimplePadBase {
-; PAD_IN_DERIVED-NEXT:   <padding> (4 bytes)
-; PAD_IN_DERIVED-NEXT:   data +0x08 [sizeof=8] __int64 Y
-; PAD_IN_DERIVED-NEXT: }
-
-; EMPTY_BASE:      struct SimplePadEmpty [sizeof = 8]
-; EMPTY_BASE-NEXT:   : public SimplePadEmptyBase1
-; EMPTY_BASE-NEXT:   , public SimplePadEmptyBase2 {
-; EMPTY_BASE-NEXT:   <padding> (2 bytes)
-; EMPTY_BASE-NEXT:   data +0x04 [sizeof=4] int X
-; EMPTY_BASE-NEXT: }
-
-; VFPTR:      struct SimplePadVfptr [sizeof = 8] {
-; VFPTR-NEXT:   vfptr +0x00 [sizeof=4]
-; VFPTR-NEXT:   data +0x04 [sizeof=4] int X
-; VFPTR-NEXT: }
-
-; MULTIPLE_INHERIT:      struct SimplePadMultiInherit [sizeof = 8]
-; MULTIPLE_INHERIT-NEXT:   : public NonEmptyBase1
-; MULTIPLE_INHERIT-NEXT:   , public NonEmptyBase2 {
-; MULTIPLE_INHERIT-NEXT:   <padding> (2 bytes)
-; MULTIPLE_INHERIT-NEXT:   data +0x04 [sizeof=4] int X
-; MULTIPLE_INHERIT-NEXT: }
-
-; MULTIPLE_INHERIT2:      SimplePadMultiInherit2 [sizeof = 16]
-; MULTIPLE_INHERIT2-NEXT:   : public SimplePadFields1
-; MULTIPLE_INHERIT2-NEXT:   , public SimplePadFields2 {
-; MULTIPLE_INHERIT2-NEXT:   data +0x0c [sizeof=4] int X
-; MULTIPLE_INHERIT2-NEXT: }
-
-; DEEP_INHERIT:      struct SimplePadTwoLevelInherit [sizeof = 16]
-; DEEP_INHERIT-NEXT:   : public OneLevelInherit {
-; DEEP_INHERIT-NEXT:   <padding> (4 bytes)
-; DEEP_INHERIT-NEXT:   data +0x08 [sizeof=8] __int64 Z
-; DEEP_INHERIT-NEXT: }
-
-
-; AGGREGATE:      struct SimplePadAggregate [sizeof = 8] {
-; AGGREGATE-NEXT:   data +0x00 [sizeof=1] NonEmptyBase1 X
-; AGGREGATE-NEXT:   <padding> (3 bytes)
-; AGGREGATE-NEXT:   data +0x04 [sizeof=4] int Y
-; AGGREGATE-NEXT: }