Home | History | Annotate | Download | only in Layout
      1 // RUN: %clang_cc1 -fms-extensions -fexceptions -fcxx-exceptions -emit-llvm-only -triple x86_64-pc-win32 -fdump-record-layouts -fsyntax-only %s 2>&1 | FileCheck %s
      2 
      3 struct Base {
      4   virtual ~Base() {}
      5   virtual void BaseFunc() {}
      6 };
      7 
      8 #pragma vtordisp(0)
      9 
     10 struct Container {
     11   static void f() try {
     12     #pragma vtordisp(2)
     13     struct HasVtorDisp : virtual Base {
     14       virtual ~HasVtorDisp() {}
     15       virtual void Func() {}
     16     };
     17 
     18     int x[sizeof(HasVtorDisp)];
     19 
     20     // HasVtorDisp: vtordisp because of pragma right before it.
     21     //
     22     // CHECK: *** Dumping AST Record Layout
     23     // CHECK: *** Dumping AST Record Layout
     24     // CHECK-NEXT:          0 | struct HasVtorDisp
     25     // CHECK-NEXT:          0 |   (HasVtorDisp vftable pointer)
     26     // CHECK-NEXT:          8 |   (HasVtorDisp vbtable pointer)
     27     // CHECK-NEXT:         20 |   (vtordisp for vbase Base)
     28     // CHECK-NEXT:         24 |   struct Base (virtual base)
     29     // CHECK-NEXT:         24 |     (Base vftable pointer)
     30     // CHECK-NEXT:            | [sizeof=32, align=8,
     31     // CHECK-NEXT:            |  nvsize=16, nvalign=8]
     32   } catch (...) {
     33   }
     34 };
     35 
     36 struct NoVtorDisp1 : virtual Base {
     37   virtual ~NoVtorDisp1() {}
     38   virtual void Func() {}
     39 };
     40 
     41 int x1[sizeof(NoVtorDisp1)];
     42 
     43 // NoVtroDisp1: no vtordisp because of pragma disabling it.
     44 //
     45 // CHECK: *** Dumping AST Record Layout
     46 // CHECK-NEXT:          0 | struct NoVtorDisp1
     47 // CHECK-NEXT:          0 |   (NoVtorDisp1 vftable pointer)
     48 // CHECK-NEXT:          8 |   (NoVtorDisp1 vbtable pointer)
     49 // CHECK-NEXT:         16 |   struct Base (virtual base)
     50 // CHECK-NEXT:         16 |     (Base vftable pointer)
     51 // CHECK-NEXT:            | [sizeof=24, align=8,
     52 // CHECK-NEXT:            |  nvsize=16, nvalign=8]
     53 
     54 struct Container2 {
     55   static void f1() {
     56     // Local pragma #1 - must be disabled on exit from f1().
     57     #pragma vtordisp(push, 2)
     58     struct HasVtorDisp1 : virtual Base {
     59       virtual ~HasVtorDisp1() {}
     60       virtual void Func() {}
     61     };
     62 
     63     int x2[sizeof(HasVtorDisp1)];
     64 
     65     // HasVtorDisp1: vtordisp because of pragma right before it.
     66     //
     67     // CHECK: *** Dumping AST Record Layout
     68     // CHECK-NEXT:          0 | struct HasVtorDisp1
     69     // CHECK-NEXT:          0 |   (HasVtorDisp1 vftable pointer)
     70     // CHECK-NEXT:          8 |   (HasVtorDisp1 vbtable pointer)
     71     // CHECK-NEXT:         20 |   (vtordisp for vbase Base)
     72     // CHECK-NEXT:         24 |   struct Base (virtual base)
     73     // CHECK-NEXT:         24 |     (Base vftable pointer)
     74     // CHECK-NEXT:            | [sizeof=32, align=8,
     75     // CHECK-NEXT:            |  nvsize=16, nvalign=8]
     76 
     77     struct InnerContainer {
     78       static void g1() {
     79         struct HasVtorDisp2 : virtual Base {
     80           virtual ~HasVtorDisp2() {}
     81           virtual void Func() {}
     82         };
     83 
     84         int x3[sizeof(HasVtorDisp2)];
     85 
     86         // HasVtorDisp2: vtordisp because of vtordisp(2) in f1().
     87         //
     88         // CHECK: *** Dumping AST Record Layout
     89         // CHECK-NEXT:          0 | struct HasVtorDisp2
     90         // CHECK-NEXT:          0 |   (HasVtorDisp2 vftable pointer)
     91         // CHECK-NEXT:          8 |   (HasVtorDisp2 vbtable pointer)
     92         // CHECK-NEXT:         20 |   (vtordisp for vbase Base)
     93         // CHECK-NEXT:         24 |   struct Base (virtual base)
     94         // CHECK-NEXT:         24 |     (Base vftable pointer)
     95         // CHECK-NEXT:            | [sizeof=32, align=8,
     96         // CHECK-NEXT:            |  nvsize=16, nvalign=8]
     97 
     98         // Local pragma #2 - must be disabled on exit from g1().
     99         #pragma vtordisp(push, 0)
    100         struct NoVtorDisp2 : virtual Base {
    101           virtual ~NoVtorDisp2() {}
    102           virtual void Func() {}
    103         };
    104 
    105         int x4[sizeof(NoVtorDisp2)];
    106 
    107         // NoVtroDisp2: no vtordisp because of vtordisp(0) in g1().
    108         //
    109         // CHECK: *** Dumping AST Record Layout
    110         // CHECK-NEXT:          0 | struct NoVtorDisp2
    111         // CHECK-NEXT:          0 |   (NoVtorDisp2 vftable pointer)
    112         // CHECK-NEXT:          8 |   (NoVtorDisp2 vbtable pointer)
    113         // CHECK-NEXT:         16 |   struct Base (virtual base)
    114         // CHECK-NEXT:         16 |     (Base vftable pointer)
    115         // CHECK-NEXT:            | [sizeof=24, align=8,
    116         // CHECK-NEXT:            |  nvsize=16, nvalign=8]
    117       }
    118 
    119       static void g2() {
    120         struct HasVtorDisp3 : virtual Base {
    121           virtual ~HasVtorDisp3() {}
    122           virtual void Func() {}
    123         };
    124 
    125         int x5[sizeof(HasVtorDisp3)];
    126 
    127         // HasVtorDisp3: vtordisp because of vtordisp(2) in f1(),
    128         //               local vtordisp(0) in g1() is disabled.
    129         //
    130         // CHECK: *** Dumping AST Record Layout
    131         // CHECK-NEXT:          0 | struct HasVtorDisp3
    132         // CHECK-NEXT:          0 |   (HasVtorDisp3 vftable pointer)
    133         // CHECK-NEXT:          8 |   (HasVtorDisp3 vbtable pointer)
    134         // CHECK-NEXT:         20 |   (vtordisp for vbase Base)
    135         // CHECK-NEXT:         24 |   struct Base (virtual base)
    136         // CHECK-NEXT:         24 |     (Base vftable pointer)
    137         // CHECK-NEXT:            | [sizeof=32, align=8,
    138         // CHECK-NEXT:            |  nvsize=16, nvalign=8]
    139       }
    140     };
    141 
    142     struct HasVtorDisp4 : virtual Base {
    143       virtual ~HasVtorDisp4() {}
    144       virtual void Func() {}
    145     };
    146 
    147     int x6[sizeof(HasVtorDisp4)];
    148 
    149     // HasVtorDisp4: vtordisp because of vtordisp(2) in f1(),
    150     //               local vtordisp(0) in g1() is disabled,
    151     //               g2() has no pragmas - stack is not affected.
    152     //
    153     // CHECK: *** Dumping AST Record Layout
    154     // CHECK-NEXT:          0 | struct HasVtorDisp4
    155     // CHECK-NEXT:          0 |   (HasVtorDisp4 vftable pointer)
    156     // CHECK-NEXT:          8 |   (HasVtorDisp4 vbtable pointer)
    157     // CHECK-NEXT:         20 |   (vtordisp for vbase Base)
    158     // CHECK-NEXT:         24 |   struct Base (virtual base)
    159     // CHECK-NEXT:         24 |     (Base vftable pointer)
    160     // CHECK-NEXT:            | [sizeof=32, align=8,
    161     // CHECK-NEXT:            |  nvsize=16, nvalign=8]
    162 
    163     InnerContainer::g1();
    164     InnerContainer::g2();
    165   }
    166 
    167   static void f2() {
    168     struct NoVtorDisp3 : virtual Base {
    169       virtual ~NoVtorDisp3() {}
    170       virtual void Func() {}
    171     };
    172 
    173     int x7[sizeof(NoVtorDisp3)];
    174 
    175     // NoVtroDisp3: no vtordisp because of global pragma (0),
    176     //              local vtordisp(2) is disabled on exit from f1().
    177     //
    178     // CHECK: *** Dumping AST Record Layout
    179     // CHECK-NEXT:          0 | struct NoVtorDisp3
    180     // CHECK-NEXT:          0 |   (NoVtorDisp3 vftable pointer)
    181     // CHECK-NEXT:          8 |   (NoVtorDisp3 vbtable pointer)
    182     // CHECK-NEXT:         16 |   struct Base (virtual base)
    183     // CHECK-NEXT:         16 |     (Base vftable pointer)
    184     // CHECK-NEXT:            | [sizeof=24, align=8,
    185     // CHECK-NEXT:            |  nvsize=16, nvalign=8]
    186   }
    187 };
    188 
    189 struct Container3 {
    190   #pragma vtordisp(2)
    191   struct HasVtorDisp5 : virtual Base {
    192     virtual ~HasVtorDisp5() {}
    193     virtual void Func() {}
    194   };
    195 
    196   int x8[sizeof(HasVtorDisp5)];
    197 
    198   // HasVtorDisp5: vtordisp because of pragma right before it.
    199   //
    200   // CHECK: *** Dumping AST Record Layout
    201   // CHECK-NEXT:          0 | struct Container3::HasVtorDisp5
    202   // CHECK-NEXT:          0 |   (HasVtorDisp5 vftable pointer)
    203   // CHECK-NEXT:          8 |   (HasVtorDisp5 vbtable pointer)
    204   // CHECK-NEXT:         20 |   (vtordisp for vbase Base)
    205   // CHECK-NEXT:         24 |   struct Base (virtual base)
    206   // CHECK-NEXT:         24 |     (Base vftable pointer)
    207   // CHECK-NEXT:            | [sizeof=32, align=8,
    208   // CHECK-NEXT:            |  nvsize=16, nvalign=8]
    209 };
    210 
    211 int main() {
    212   Container::f();
    213   Container2::f1();
    214   Container2::f2();
    215   Container3 cont3;
    216   return 0;
    217 };
    218