// RUN: %clang_cc1 -emit-llvm-only -triple i686-pc-win32 -fdump-record-layouts -cxx-abi microsoft %s 2>&1 \
// RUN:            | FileCheck %s

#pragma pack(push, 8)

class B {
public:
  virtual void b(){}
  int b_field;
protected:
private:
};

class A : public B {
public:
  int a_field;
  virtual void a(){}
  char one;
protected:
private:
};

class D {
public:
  virtual void b(){}
  double a;
};

class C : public virtual A, 
          public D, public B {
public:
  double c1_field;
  int c2_field;
  double c3_field;
  int c4_field;
  virtual void foo(){}
  virtual void bar(){}
protected:
private:
};

struct BaseStruct
{
    BaseStruct(){}
    double v0;
    float v1;
    C fg;
};

struct DerivedStruct : public BaseStruct {
  int x;
};

struct G
{
    int g_field;
};

struct H : public G, 
           public virtual D
{
};

struct I : public virtual D
{
  virtual ~I(){}
  double q;
};

struct K
{
  int k;
};

struct L
{
  int l;
};

struct M : public virtual K
{
  int m;
};

struct N : public L, public M
{
  virtual void f(){}
};

struct O : public H, public G {
  virtual void fo(){}
};

struct P : public M, public virtual L {
  int p;
};

struct R {};

class IA {
public:
  virtual ~IA(){}
  virtual void ia() = 0;
};

class ICh : public virtual IA {
public:
  virtual ~ICh(){}
  virtual void ia(){}
  virtual void iCh(){}
};

struct f {
  virtual int asd() {return -90;}
};

struct s : public virtual f {
  virtual ~s(){}
  int r;
  virtual int asd() {return -9;}
};

struct sd : virtual s, virtual ICh {
  virtual ~sd(){}
  int q;
  char y;
  virtual int asd() {return -1;}
};
struct AV { 
  virtual void foo(); 
};
struct BV : AV { 
};
struct CV : virtual BV { 
  CV(); 
  virtual void foo(); 
};
struct DV : BV {
};
struct EV : CV, DV {
};
#pragma pack(pop)

// This needs only for building layouts. 
// Without this clang doesn`t dump record layouts.
int main() {
  // This avoid "Can't yet mangle constructors!" for MS ABI.
  C* c;
  c->foo();
  DerivedStruct* v;
  H* g;
  BaseStruct* u;
  I* i;
  N* n;
  O* o;
  P* p;
  R* r;
  sd *h;
  EV *j;
  return 0;
}

// CHECK:       0 | class D
// CHECK-NEXT:  0 |   (D vftable pointer)
// CHECK-NEXT:  8 |   double a

// CHECK-NEXT: sizeof=16, dsize=16, align=8
// CHECK-NEXT: nvsize=16, nvalign=8

// CHECK: %class.D = type { i32 (...)**, double }

// CHECK:       0 | class B
// CHECK-NEXT:  0 |   (B vftable pointer)
// CHECK-NEXT:  4 |   int b_field

// CHECK-NEXT: sizeof=8, dsize=8, align=4
// CHECK-NEXT: nvsize=8, nvalign=4

// CHECK: %class.B = type { i32 (...)**, i32 }

// CHECK:       0 | class A
// CHECK-NEXT:  0 |   class B (primary base)
// CHECK-NEXT:  0 |     (B vftable pointer)
// CHECK-NEXT:  4 |     int b_field
// CHECK-NEXT:  8 |   int a_field
// CHECK-NEXT: 12 |   char one

// CHECK-NEXT: sizeof=16, dsize=16, align=4
// CHECK-NEXT: nvsize=16, nvalign=4

// CHECK:       0 | class C
// CHECK-NEXT:  0 |   class D (primary base)
// CHECK-NEXT:  0 |     (D vftable pointer)
// CHECK-NEXT:  8 |     double a
// CHECK-NEXT: 16 |   class B (base)
// CHECK-NEXT: 16 |     (B vftable pointer)
// CHECK-NEXT: 20 |     int b_field
// CHECK-NEXT: 24 |   (C vbtable pointer)
// CHECK-NEXT: 32 |   double c1_field
// CHECK-NEXT: 40 |   int c2_field
// CHECK-NEXT: 48 |   double c3_field
// CHECK-NEXT: 56 |   int c4_field
// CHECK-NEXT: 64 |   class A (virtual base)
// CHECK-NEXT: 64 |     class B (primary base)
// CHECK-NEXT: 64 |       (B vftable pointer)
// CHECK-NEXT: 68 |       int b_field
// CHECK-NEXT: 72 |     int a_field
// CHECK-NEXT: 76 |     char one

// CHECK-NEXT: sizeof=80, dsize=80, align=8
// CHECK-NEXT: nvsize=64, nvalign=8

// CHECK: %class.A = type { %class.B, i32, i8 }

// CHECK: %class.C = type { %class.D, %class.B, i32*, double, i32, double, i32, [4 x i8], %class.A }
// CHECK: %class.C.base = type { %class.D, %class.B, i32*, double, i32, double, i32 }

// CHECK:       0 | struct BaseStruct
// CHECK-NEXT:  0 |   double v0
// CHECK-NEXT:  8 |   float v1
// CHECK-NEXT: 16 |   class C fg
// CHECK-NEXT: 16 |     class D (primary base)
// CHECK-NEXT: 16 |       (D vftable pointer)
// CHECK-NEXT: 24 |       double a
// CHECK-NEXT: 32 |     class B (base)
// CHECK-NEXT: 32 |       (B vftable pointer)
// CHECK-NEXT: 36 |       int b_field
// CHECK-NEXT: 40 |     (C vbtable pointer)
// CHECK-NEXT: 48 |     double c1_field
// CHECK-NEXT: 56 |     int c2_field
// CHECK-NEXT: 64 |     double c3_field
// CHECK-NEXT: 72 |     int c4_field
// CHECK-NEXT: 80 |     class A (virtual base)
// CHECK-NEXT: 80 |       class B (primary base)
// CHECK-NEXT: 80 |         (B vftable pointer)
// CHECK-NEXT: 84 |         int b_field
// CHECK-NEXT: 88 |       int a_field
// CHECK-NEXT: 92 |       char one

// CHECK-NEXT: sizeof=80, dsize=80, align=8
// CHECK-NEXT: nvsize=64, nvalign=8

// CHECK: sizeof=96, dsize=96, align=8
// CHECK-NEXT: nvsize=96, nvalign=8

// CHECK: %struct.BaseStruct = type { double, float, %class.C }

// CHECK:       0 | struct DerivedStruct
// CHECK-NEXT:  0 |   struct BaseStruct (base)
// CHECK-NEXT:  0 |     double v0
// CHECK-NEXT:  8 |     float v1
// CHECK-NEXT: 16 |     class C fg
// CHECK-NEXT: 16 |       class D (primary base)
// CHECK-NEXT: 16 |         (D vftable pointer)
// CHECK-NEXT: 24 |         double a
// CHECK-NEXT: 32 |       class B (base)
// CHECK-NEXT: 32 |         (B vftable pointer)
// CHECK-NEXT: 36 |         int b_field
// CHECK-NEXT: 40 |       (C vbtable pointer)
// CHECK-NEXT: 48 |       double c1_field
// CHECK-NEXT: 56 |       int c2_field
// CHECK-NEXT: 64 |       double c3_field
// CHECK-NEXT: 72 |       int c4_field
// CHECK-NEXT: 80 |       class A (virtual base)
// CHECK-NEXT: 80 |         class B (primary base)
// CHECK-NEXT: 80 |           (B vftable pointer)
// CHECK-NEXT: 84 |           int b_field
// CHECK-NEXT: 88 |         int a_field
// CHECK-NEXT: 92 |         char one
// CHECK-NEXT: sizeof=80, dsize=80, align=8
// CHECK-NEXT: nvsize=64, nvalign=8

// CHECK: 96 |   int x
// CHECK-NEXT: sizeof=104, dsize=104, align=8
// CHECK-NEXT: nvsize=104, nvalign=8

// CHECK: %struct.DerivedStruct = type { %struct.BaseStruct, i32 }

// CHECK:      0 | struct G
// CHECK-NEXT: 0 |   int g_field
// CHECK-NEXT: sizeof=4, dsize=4, align=4
// CHECK-NEXT: nvsize=4, nvalign=4

// CHECK:       0 | struct H
// CHECK-NEXT:  0 |   struct G (base)
// CHECK-NEXT:  0 |     int g_field
// CHECK-NEXT:  4 |   (H vbtable pointer)
// CHECK-NEXT:  8 |   class D (virtual base)
// CHECK-NEXT:  8 |     (D vftable pointer)
// CHECK-NEXT: 16 |     double a
// CHECK-NEXT: sizeof=24, dsize=24, align=8
// CHECK-NEXT: nvsize=8, nvalign=4

// CHECK: %struct.H = type { %struct.G, i32*, %class.D }

// CHECK:       0 | struct I
// CHECK-NEXT:  0 |   (I vftable pointer)
// CHECK-NEXT:  8 |   (I vbtable pointer)
// CHECK-NEXT: 16 |   double q
// CHECK-NEXT: 24 |   class D (virtual base)
// CHECK-NEXT: 24 |     (D vftable pointer)
// CHECK-NEXT: 32 |     double a
// CHECK-NEXT: sizeof=40, dsize=40, align=8
// CHECK-NEXT: nvsize=24, nvalign=8

// CHECK: %struct.I = type { i32 (...)**, [4 x i8], i32*, double, %class.D }
// CHECK: %struct.I.base = type { i32 (...)**, [4 x i8], i32*, double }

// CHECK:       0 | struct L
// CHECK-NEXT:  0 |   int l
// CHECK-NEXT: sizeof=4, dsize=4, align=4
// CHECK-NEXT: nvsize=4, nvalign=4

// CHECK:       0 | struct K
// CHECK-NEXT:  0 |   int k
// CHECK-NEXT: sizeof=4, dsize=4, align=4
// CHECK-NEXT: nvsize=4, nvalign=4

// CHECK:       0 | struct M
// CHECK-NEXT:  0 |   (M vbtable pointer)
// CHECK-NEXT:  4 |   int m
// CHECK-NEXT:  8 |   struct K (virtual base)
// CHECK-NEXT:  8 |     int k
// CHECK-NEXT: sizeof=12, dsize=12, align=4

//CHECK: %struct.M = type { i32*, i32, %struct.K }
//CHECK: %struct.M.base = type { i32*, i32 }

// CHECK:       0 | struct N
// CHECK-NEXT:  4 |   struct L (base)
// CHECK-NEXT:  4 |     int l
// CHECK-NEXT:  8 |   struct M (base)
// CHECK-NEXT:  8 |     (M vbtable pointer)
// CHECK-NEXT: 12 |     int m
// CHECK-NEXT:  0 |   (N vftable pointer)
// CHECK-NEXT: 16 |   struct K (virtual base)
// CHECK-NEXT: 16 |     int k
// CHECK-NEXT: sizeof=20, dsize=20, align=4
// CHECK-NEXT: nvsize=16, nvalign=4

//CHECK: %struct.N = type { i32 (...)**, %struct.L, %struct.M.base, %struct.K }

// FIXME: MSVC place struct H at offset 8.
// CHECK:       0 | struct O
// CHECK-NEXT:  4 |   struct H (base)
// CHECK-NEXT:  4 |     struct G (base)
// CHECK-NEXT:  4 |       int g_field
// CHECK-NEXT:  8 |     (H vbtable pointer)
// CHECK-NEXT: 12 |   struct G (base)
// CHECK-NEXT: 12 |     int g_field
// CHECK-NEXT:  0 |   (O vftable pointer)
// CHECK-NEXT: 16 |   class D (virtual base)
// CHECK-NEXT: 16 |     (D vftable pointer)
// CHECK-NEXT: 24 |     double a
// CHECK-NEXT: sizeof=32, dsize=32, align=8
// CHECK-NEXT: nvsize=16, nvalign=4

//CHECK: %struct.O = type { i32 (...)**, %struct.H.base, %struct.G, %class.D }
//CHECK: %struct.O.base = type { i32 (...)**, %struct.H.base, %struct.G }

// CHECK:       0 | struct P
// CHECK-NEXT:  0 |   struct M (base)
// CHECK-NEXT:  0 |     (M vbtable pointer)
// CHECK-NEXT:  4 |     int m
// CHECK-NEXT:  8 |   int p
// CHECK-NEXT: 12 |   struct K (virtual base)
// CHECK-NEXT: 12 |     int k
// CHECK-NEXT: 16 |   struct L (virtual base)
// CHECK-NEXT: 16 |     int l
// CHECK-NEXT: sizeof=20, dsize=20, align=4
// CHECK-NEXT: nvsize=12, nvalign=4

//CHECK: %struct.P = type { %struct.M.base, i32, %struct.K, %struct.L }

// CHECK:       0 | struct R (empty)
// CHECK-NEXT:  sizeof=1, dsize=0, align=1
// CHECK-NEXT:  nvsize=0, nvalign=1

//CHECK: %struct.R = type { i8 }

// CHECK:       0 | struct f
// CHECK-NEXT:  0 |   (f vftable pointer)
// CHECK-NEXT: sizeof=4, dsize=4, align=4
// CHECK-NEXT: nvsize=4, nvalign=4

// CHECK:       0 | struct s
// CHECK-NEXT:  0 |   (s vftable pointer)
// CHECK-NEXT:  4 |   (s vbtable pointer)
// CHECK-NEXT:  8 |   int r
// CHECK-NEXT: 12 |   (vtordisp for vbase f)
// CHECK-NEXT: 16 |   struct f (virtual base)
// CHECK-NEXT: 16 |     (f vftable pointer)
// CHECK-NEXT: sizeof=20, dsize=20, align=4
// CHECK-NEXT: nvsize=12, nvalign=4

// CHECK:       0 | class IA
// CHECK-NEXT:  0 |   (IA vftable pointer)
// CHECK-NEXT:  sizeof=4, dsize=4, align=4
// CHECK-NEXT:  nvsize=4, nvalign=4
	
// CHECK:       0 | class ICh
// CHECK-NEXT:  0 |   (ICh vftable pointer)
// CHECK-NEXT:  4 |   (ICh vbtable pointer)
// CHECK-NEXT:  8 |   (vtordisp for vbase IA)
// CHECK-NEXT: 12 |   class IA (virtual base)
// CHECK-NEXT: 12 |     (IA vftable pointer)
// CHECK-NEXT: sizeof=16, dsize=16, align=4
// CHECK-NEXT: nvsize=8, nvalign=4

// CHECK:       0 | struct sd
// CHECK-NEXT:  0 |   (sd vbtable pointer)
// CHECK-NEXT:  4 |   int q
// CHECK-NEXT:  8 |   char y
// CHECK-NEXT: 12 |   (vtordisp for vbase f)
// CHECK-NEXT: 16 |   struct f (virtual base)
// CHECK-NEXT: 16 |     (f vftable pointer)
// CHECK-NEXT: 20 |   struct s (virtual base)
// CHECK-NEXT: 20 |     (s vftable pointer)
// CHECK-NEXT: 24 |     (s vbtable pointer)
// CHECK-NEXT: 28 |     int r
// CHECK-NEXT: 32 |   (vtordisp for vbase IA)
// CHECK-NEXT: 36 |   class IA (virtual base)
// CHECK-NEXT: 36 |     (IA vftable pointer)
// CHECK-NEXT: 40 |   class ICh (virtual base)
// CHECK-NEXT: 40 |     (ICh vftable pointer)
// CHECK-NEXT: 44 |     (ICh vbtable pointer)
// CHECK-NEXT: sizeof=48, dsize=48, align=4
// CHECK-NEXT: nvsize=12, nvalign=4

// CHECK: %struct.f = type { i32 (...)** }
// CHECK: %struct.s = type { i32 (...)**, i32*, i32, [4 x i8], %struct.f }
// CHECK: %class.IA = type { i32 (...)** }
// CHECK: %class.ICh = type { i32 (...)**, i32*, [4 x i8], %class.IA }
// CHECK: %struct.sd = type { i32*, i32, i8, [7 x i8], %struct.f, %struct.s.base, [4 x i8], %class.IA, %class.ICh.base }

// CHECK:       0 | struct AV
// CHECK-NEXT:  0 |   (AV vftable pointer)
// CHECK-NEXT: sizeof=4, dsize=4, align=4
// CHECK-NEXT: nvsize=4, nvalign=4


// CHECK:       0 | struct BV
// CHECK-NEXT:  0 |   struct AV (primary base)
// CHECK-NEXT:  0 |     (AV vftable pointer)
// CHECK-NEXT: sizeof=4, dsize=4, align=4
// CHECK-NEXT: nvsize=4, nvalign=4


// CHECK:       0 | struct CV
// CHECK-NEXT:  0 |   (CV vbtable pointer)
// CHECK-NEXT:  4 |   (vtordisp for vbase BV)
// CHECK-NEXT:  8 |   struct BV (virtual base)
// CHECK-NEXT:  8 |     struct AV (primary base)
// CHECK-NEXT:  8 |       (AV vftable pointer)
// CHECK-NEXT: sizeof=12, dsize=12, align=4
// CHECK-NEXT: nvsize=4, nvalign=4

// CHECK: %struct.AV = type { i32 (...)** }
// CHECK: %struct.BV = type { %struct.AV }
// CHECK: %struct.CV = type { i32*, [4 x i8], %struct.BV }
// CHECK: %struct.CV.base = type { i32* }

// CHECK:       0 | struct DV
// CHECK-NEXT:  0 |   struct BV (primary base)
// CHECK-NEXT:  0 |     struct AV (primary base)
// CHECK-NEXT:  0 |       (AV vftable pointer)
// CHECK-NEXT: sizeof=4, dsize=4, align=4
// CHECK-NEXT: nvsize=4, nvalign=4

// CHECK: %struct.DV = type { %struct.BV }

// CHECK:       0 | struct EV
// CHECK-NEXT:  4 |   struct CV (base)
// CHECK-NEXT:  4 |     (CV vbtable pointer)
// CHECK-NEXT:  0 |   struct DV (primary base)
// CHECK-NEXT:  0 |     struct BV (primary base)
// CHECK-NEXT:  0 |       struct AV (primary base)
// CHECK-NEXT:  0 |         (AV vftable pointer)
// CHECK-NEXT:  8 |   (vtordisp for vbase BV)
// CHECK-NEXT: 12 |   struct BV (virtual base)
// CHECK-NEXT: 12 |     struct AV (primary base)
// CHECK-NEXT: 12 |       (AV vftable pointer)
// CHECK-NEXT: sizeof=16, dsize=16, align=4
// CHECK-NEXT: nvsize=8, nvalign=4

// CHECK: %struct.EV = type { %struct.DV, %struct.CV.base, [4 x i8], %struct.BV }
// CHECK: %struct.EV.base = type { %struct.DV, %struct.CV.base }

// Overriding a method means that all the vbases containing that
// method need a vtordisp.
namespace test1 {
  struct A { virtual void foo(); };
  struct B : A {};
  struct C : virtual A, virtual B { C(); virtual void foo(); };
  void test() { C *c; }

// CHECK:        0 | struct test1::C
// CHECK-NEXT:   0 |   (C vbtable pointer)
// CHECK-NEXT:   4 |   (vtordisp for vbase A)
// CHECK-NEXT:   8 |   struct test1::A (virtual base)
// CHECK-NEXT:   8 |     (A vftable pointer)
// CHECK-NEXT:  12 |   (vtordisp for vbase B)
// CHECK-NEXT:  16 |   struct test1::B (virtual base)
// CHECK-NEXT:  16 |     struct test1::A (primary base)
// CHECK-NEXT:  16 |       (A vftable pointer)
// CHECK-NEXT:  sizeof=20, dsize=20, align=4
// CHECK-NEXT:  nvsize=4, nvalign=4
}
