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