brintos

brintos / llvm-project-archived public Read only

0
0
Text · 17.5 KiB · c5ce69f Raw
570 lines · cpp
1// RUN: %clang_cc1 -fno-rtti -emit-llvm -fdump-vtable-layouts %s -o %t.ll -triple=i386-pc-win32 > %t2// RUN: FileCheck %s < %t3// RUN: FileCheck --check-prefix=MANGLING %s < %t.ll4 5// For now, just make sure x86_64 doesn't crash.6// RUN: %clang_cc1 -fno-rtti -emit-llvm-only -fdump-vtable-layouts %s -triple=x86_64-pc-win32 > /dev/null7 8struct V1 {9  virtual void f();10  virtual ~V1();11};12 13struct V2 {14  virtual void f();15  virtual ~V2();16  int v;17};18 19struct Z {20  virtual void g();21  virtual ~Z();22  int x;23};24 25struct V3 : Z, V2 {26};27 28struct V4 : Z, V1, V2 {29  int y;30};31 32void use_somewhere_else(void*);33 34namespace simple {35// In case of a single-layer virtual inheritance, the "this" adjustment for a36// virtual method is done statically:37//   struct A {38//     virtual void f();  // Expects "(A*)this" in ECX39//   };40//   struct B : virtual A {41//     virtual void f();  // Expects "(char*)(B*)this + 12" in ECX42//     virtual ~B();      // Might call f()43//   };44//45// If a class overrides a virtual function of its base and has a non-trivial46// ctor/dtor that call(s) the virtual function (or may escape "this" to some47// code that might call it), a virtual adjustment might be needed in case the48// current class layout and the most derived class layout are different.49// This is done using vtordisp thunks.50//51// A simple vtordisp{x,y} thunk for Method@Class is something like:52//   sub  ecx, [ecx+x]  // apply the vtordisp adjustment53//   sub  ecx, y        // apply the subobject adjustment, if needed.54//   jmp Method@Class55 56struct A : virtual V1 {57  // CHECK-LABEL: VFTable for 'V1' in 'simple::A' (2 entries).58  // CHECK-NEXT: 0 | void simple::A::f()59  // CHECK-NEXT:     [this adjustment: vtordisp at -4, 0 non-virtual]60  // CHECK-NEXT: 1 | simple::A::~A() [scalar deleting]61  // CHECK-NEXT:     [this adjustment: vtordisp at -4, 0 non-virtual]62 63  // CHECK-LABEL: Thunks for 'simple::A::~A()' (1 entry).64  // CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, 0 non-virtual]65 66  // CHECK-LABEL: Thunks for 'void simple::A::f()' (1 entry).67  // CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, 0 non-virtual]68 69  virtual void f();70  // MANGLING-DAG: @"?f@A@simple@@$4PPPPPPPM@A@AEXXZ"71 72  virtual ~A();73  // MANGLING-DAG: @"??_EA@simple@@$4PPPPPPPM@A@AEPAXI@Z"74};75 76A a;77void use(A *obj) { obj->f(); }78 79struct B : virtual V3 {80  // CHECK-LABEL: VFTable for 'Z' in 'V3' in 'simple::B' (2 entries).81  // CHECK-NEXT: 0 | void Z::g()82  // CHECK-NEXT: 1 | simple::B::~B() [scalar deleting]83  // CHECK-NEXT:     [this adjustment: vtordisp at -4, 0 non-virtual]84 85  // CHECK-LABEL: Thunks for 'simple::B::~B()' (1 entry).86  // CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, 0 non-virtual]87 88  // CHECK-LABEL: VFTable for 'V2' in 'V3' in 'simple::B' (2 entries).89  // CHECK-NEXT: 0 | void simple::B::f()90  // CHECK-NEXT:     [this adjustment: vtordisp at -12, 0 non-virtual]91  // CHECK-NEXT: 1 | simple::B::~B() [scalar deleting]92  // CHECK-NEXT:     [this adjustment: vtordisp at -12, -8 non-virtual]93 94  // CHECK-LABEL: Thunks for 'simple::B::~B()' (1 entry).95  // CHECK-NEXT: 0 | [this adjustment: vtordisp at -12, -8 non-virtual]96 97  // CHECK-LABEL: Thunks for 'void simple::B::f()' (1 entry).98  // CHECK-NEXT: 0 | [this adjustment: vtordisp at -12, 0 non-virtual]99 100  // FIXME: The vtordisp thunk should only get emitted for a constructor101  // if "this" leaves scope.102  B() { use_somewhere_else(this); }103 104  virtual void f();105  // MANGLING-DAG: @"?f@B@simple@@$4PPPPPPPE@A@AEXXZ"106 107  // Has an implicit destructor.108  // MANGLING-DAG: @"??_EB@simple@@$4PPPPPPPE@7AEPAXI@Z"109  // MANGLING-DAG: @"??_EB@simple@@$4PPPPPPPM@A@AEPAXI@Z"110};111 112B b;113void use(B *obj) { obj->f(); }114 115struct C : virtual V4 {116  // CHECK-LABEL: VFTable for 'Z' in 'V4' in 'simple::C' (2 entries).117  // CHECK-NEXT: 0 | void Z::g()118  // CHECK-NEXT: 1 | simple::C::~C() [scalar deleting]119  // CHECK-NEXT:     [this adjustment: vtordisp at -4, 0 non-virtual]120 121  // CHECK-LABEL: Thunks for 'simple::C::~C()' (1 entry).122  // CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, 0 non-virtual]123 124  // CHECK-LABEL: VFTable for 'V1' in 'V4' in 'simple::C' (2 entries).125  // CHECK-NEXT: 0 | void simple::C::f()126  // CHECK-NEXT:     [this adjustment: vtordisp at -12, 0 non-virtual]127  // CHECK-NEXT: 1 | simple::C::~C() [scalar deleting]128  // CHECK-NEXT:     [this adjustment: vtordisp at -12, -8 non-virtual]129 130  // CHECK-LABEL: Thunks for 'simple::C::~C()' (1 entry).131  // CHECK-NEXT: 0 | [this adjustment: vtordisp at -12, -8 non-virtual]132 133  // CHECK-LABEL: Thunks for 'void simple::C::f()' (1 entry).134  // CHECK-NEXT: 0 | [this adjustment: vtordisp at -12, 0 non-virtual]135 136  // CHECK-LABEL: VFTable for 'V2' in 'V4' in 'simple::C' (2 entries).137  // CHECK-NEXT: 0 | void simple::C::f()138  // CHECK-NEXT:     [this adjustment: vtordisp at -16, -4 non-virtual]139  // CHECK-NEXT: 1 | simple::C::~C() [scalar deleting]140  // CHECK-NEXT:     [this adjustment: vtordisp at -16, -12 non-virtual]141 142  // CHECK-LABEL: Thunks for 'simple::C::~C()' (1 entry).143  // CHECK-NEXT: 0 | [this adjustment: vtordisp at -16, -12 non-virtual]144 145  // CHECK-LABEL: Thunks for 'void simple::C::f()' (1 entry).146  // CHECK-NEXT: 0 | [this adjustment: vtordisp at -16, -4 non-virtual]147 148  int x;149  virtual void f();150  // MANGLING-DAG: @"?f@C@simple@@$4PPPPPPPA@3AEXXZ"151  // MANGLING-DAG: @"?f@C@simple@@$4PPPPPPPE@A@AEXXZ"152  virtual ~C();153  // MANGLING-DAG: @"??_EC@simple@@$4PPPPPPPA@M@AEPAXI@Z"154  // MANGLING-DAG: @"??_EC@simple@@$4PPPPPPPE@7AEPAXI@Z"155  // MANGLING-DAG: @"??_EC@simple@@$4PPPPPPPM@A@AEPAXI@Z"156};157 158C c;159void use(C *obj) { obj->f(); }160 161class D : B {162  // CHECK-LABEL: VFTable for 'V2' in 'V3' in 'simple::B' in 'simple::D' (2 entries).163  // CHECK-NEXT: 0 | void simple::B::f()164  // CHECK-NEXT:     [this adjustment: vtordisp at -12, -4 non-virtual]165  // CHECK-NEXT: 1 | simple::D::~D() [scalar deleting]166  // CHECK-NEXT:     [this adjustment: vtordisp at -12, -8 non-virtual]167  D();168  int z;169 170  // MANGLING-DAG: @"?f@B@simple@@$4PPPPPPPE@3AEXXZ"171};172 173D::D() {}174 175struct E : V3 {176  virtual void f();177};178 179struct F : virtual E {180  // CHECK-LABEL: VFTable for 'Z' in 'V3' in 'simple::E' in 'simple::F' (2 entries).181  // CHECK-NEXT:   0 | void simple::F::g()182  // CHECK-NEXT:       [this adjustment: vtordisp at -4, 0 non-virtual]183  // CHECK-NEXT:   1 | simple::F::~F() [scalar deleting]184  // CHECK-NEXT:       [this adjustment: vtordisp at -4, 0 non-virtual]185 186  // CHECK-LABEL: VFTable for 'V2' in 'V3' in 'simple::E' in 'simple::F' (2 entries).187  // CHECK-NEXT:   0 | void simple::E::f()188  // CHECK-NEXT:   1 | simple::F::~F() [scalar deleting]189  // CHECK-NEXT:       [this adjustment: vtordisp at -12, -8 non-virtual]190 191  F();192  virtual void g();  // Force a vtordisp.193  int f;194 195  // MANGLING-DAG: @"?g@F@simple@@$4PPPPPPPM@A@AEXXZ"{{.*}}??_EF@simple@@$4PPPPPPPM@A@AEPAXI@Z196  // MANGLING-DAG: ?f@E@simple@@UAEXXZ{{.*}}??_EF@simple@@$4PPPPPPPE@7AEPAXI@Z197};198 199F::F() {}200 201struct G : F {202  // CHECK-LABEL: VFTable for 'Z' in 'V3' in 'simple::E' in 'simple::F' in 'simple::G' (2 entries).203  // CHECK-NEXT:   0 | void simple::F::g()204  // CHECK-NEXT:       [this adjustment: vtordisp at -4, -4 non-virtual]205  // CHECK-NEXT:   1 | simple::G::~G() [scalar deleting]206  // CHECK-NEXT:       [this adjustment: vtordisp at -4, 0 non-virtual]207 208  // CHECK-LABEL: VFTable for 'V2' in 'V3' in 'simple::E' in 'simple::F' in 'simple::G' (2 entries).209  // CHECK-NEXT:   0 | void simple::E::f()210  // CHECK-NEXT:   1 | simple::G::~G() [scalar deleting]211  // CHECK-NEXT:       [this adjustment: vtordisp at -12, -8 non-virtual]212 213  G();214  int g;215 216  // MANGLING-DAG: @"?g@F@simple@@$4PPPPPPPM@3AEXXZ"{{.*}}@"??_EG@simple@@$4PPPPPPPM@A@AEPAXI@Z"217  // MANGLING-DAG: @"?f@E@simple@@UAEXXZ"{{.*}}@"??_EG@simple@@$4PPPPPPPE@7AEPAXI@Z"218};219 220G::G() {}221}222 223namespace extended {224// If a virtual function requires vtordisp adjustment and the final overrider225// is defined in another virtual base of the most derived class,226// we need to know two vbase offsets.227// In this case, we should use the extended form of vtordisp thunks, called228// vtordispex thunks.229//230// vtordispex{x,y,z,w} thunk for Method@Class is something like:231//   sub  ecx, [ecx+z]  // apply the vtordisp adjustment232//   sub  ecx, x        // jump to the vbptr of the most derived class233//   mov  eax, [ecx]    // load the vbtable address234//   add  ecx, [eax+y]  // lookup the final overrider's vbase offset235//   add  ecx, w        // apphy the subobject offset if needed236//   jmp Method@Class237 238struct A : virtual simple::A {239  // CHECK-LABEL: VFTable for 'V1' in 'simple::A' in 'extended::A' (2 entries).240  // CHECK-NEXT: 0 | void simple::A::f()241  // CHECK-NEXT:     [this adjustment: vtordisp at -4, vbptr at 8 to the left,242  // CHECK-NEXT:      vboffset at 8 in the vbtable, 8 non-virtual]243  // CHECK-NEXT: 1 | extended::A::~A() [scalar deleting]244  // CHECK-NEXT:     [this adjustment: vtordisp at -4, 0 non-virtual]245 246  // CHECK-LABEL: Thunks for 'void simple::A::f()' (1 entry).247  // CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, vbptr at 8 to the left,248  // CHECK-NEXT:      vboffset at 8 in the vbtable, 8 non-virtual]249 250  // `vtordispex{8,8,4294967292,8}'251  // MANGLING-DAG: @"?f@A@simple@@$R477PPPPPPPM@7AEXXZ"252 253  virtual ~A();254  // vtordisp{4294967292,0}255  // MANGLING-DAG: @"??_EA@extended@@$4PPPPPPPM@A@AEPAXI@Z"256};257 258A a;259void use(A *obj) { delete obj; }260 261struct B : virtual simple::A {262  // This class has an implicit dtor.  Vdtors don't require vtordispex thunks263  // as the most derived class always has an implicit dtor,264  // which is a final overrider.265 266  // CHECK-LABEL: VFTable for 'V1' in 'simple::A' in 'extended::B' (2 entries).267  //  ...268  // CHECK: 1 | extended::B::~B() [scalar deleting]269  // CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual]270 271  // CHECK-LABEL: Thunks for 'void simple::A::f()' (1 entry).272  // CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, vbptr at 8 to the left,273  // CHECK-NEXT:      vboffset at 8 in the vbtable, 8 non-virtual]274 275  // vtordisp{4294967292,0}276  // MANGLING-DAG: @"??_EB@extended@@$4PPPPPPPM@A@AEPAXI@Z"277};278 279B b;280void use(B *obj) { delete obj; }281 282struct C : virtual simple::A {283  // CHECK-LABEL: VFTable for 'V1' in 'simple::A' in 'extended::C' (2 entries).284  // CHECK-NEXT: 0 | void simple::A::f()285  // CHECK-NEXT:     [this adjustment: vtordisp at -4, vbptr at 12 to the left,286  // CHECK-NEXT:      vboffset at 8 in the vbtable, 8 non-virtual]287 288  // CHECK-LABEL: Thunks for 'void simple::A::f()' (1 entry).289  // CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, vbptr at 12 to the left,290  // CHECK-NEXT:      vboffset at 8 in the vbtable, 8 non-virtual]291 292  // `vtordispex{12,8,4294967292,8}'293  // MANGLING-DAG: @"?f@A@simple@@$R4M@7PPPPPPPM@7AEXXZ"294  int x;295  virtual ~C();296  // MANGLING-DAG: @"??_EC@extended@@$4PPPPPPPM@A@AEPAXI@Z"297};298 299C c;300void use(C *obj) { delete obj; }301 302struct D : virtual V2 {303  virtual void f();304  virtual ~D();305  int x;306};307 308struct E : virtual D {309  // CHECK-LABEL: VFTable for 'V2' in 'extended::D' in 'extended::E' (2 entries).310  // CHECK-NEXT: 0 | void extended::D::f()311  // CHECK-NEXT:     [this adjustment: vtordisp at -4, vbptr at 8 to the left,312  // CHECK-NEXT:      vboffset at 8 in the vbtable, 12 non-virtual]313 314  // CHECK-LABEL: Thunks for 'void extended::D::f()' (1 entry).315  // CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, vbptr at 8 to the left,316  // CHECK-NEXT:      vboffset at 8 in the vbtable, 12 non-virtual]317 318  // `vtordispex{8,8,4294967292,12}'319  // MANGLING-DAG: @"?f@D@extended@@$R477PPPPPPPM@M@AEXXZ"320 321  virtual ~E();322  // MANGLING-DAG: @"??_EE@extended@@$4PPPPPPPM@A@AEPAXI@Z"323};324 325E e;326void use(E *obj) { delete obj; } 327 328struct F : virtual Z, virtual D {329  // CHECK-LABEL: VFTable for 'V2' in 'extended::D' in 'extended::F' (2 entries).330  // CHECK-NEXT: 0 | void extended::D::f()331  // CHECK-NEXT:     [this adjustment: vtordisp at -4, vbptr at 20 to the left,332  // CHECK-NEXT:      vboffset at 12 in the vbtable, 12 non-virtual]333 334  // CHECK-LABEL: Thunks for 'void extended::D::f()' (1 entry).335  // CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, vbptr at 20 to the left,336  // CHECK-NEXT:      vboffset at 12 in the vbtable, 12 non-virtual]337 338  // `vtordispex{20,12,4294967292,12}'339  // MANGLING-DAG: @"?f@D@extended@@$R4BE@M@PPPPPPPM@M@AEXXZ"340  int x;341  virtual ~F();342  // MANGLING-DAG: @"??_EF@extended@@$4PPPPPPPM@M@AEPAXI@Z"343};344 345F f;346void use(F *obj) { delete obj; }347 348struct G : virtual simple::A {349  // CHECK-LABEL: VFTable for 'extended::G' (1 entry).350  // CHECK-NEXT: 0 | void extended::G::g()351 352  // CHECK-LABEL: VFTable for 'V1' in 'simple::A' in 'extended::G' (2 entries).353  // CHECK-NEXT: 0 | void simple::A::f()354  // CHECK-NEXT:     [this adjustment: vtordisp at -4, vbptr at 8 to the left,355  // CHECK-NEXT:      vboffset at 8 in the vbtable, 8 non-virtual]356  // CHECK-NEXT: 1 | extended::G::~G() [scalar deleting]357  // CHECK-NEXT:     [this adjustment: vtordisp at -4, 0 non-virtual]358 359  // CHECK-LABEL: Thunks for 'void simple::A::f()' (1 entry).360  // CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, vbptr at 8 to the left,361  // CHECK-NEXT:      vboffset at 8 in the vbtable, 8 non-virtual]362 363  // Emits a G's own vfptr, thus moving the vbptr in the layout.364  virtual void g();365 366  virtual ~G();367  // vtordisp{4294967292,0}368  // MANGLING-DAG: @"??_EG@extended@@$4PPPPPPPM@A@AEPAXI@Z"369};370 371G g;372void use(G *obj) { obj->g(); }373 374struct H : Z, A {375  // CHECK-LABEL: VFTable for 'Z' in 'extended::H' (2 entries).376  // CHECK-NEXT: 0 | void Z::g()377  // CHECK-NEXT: 1 | extended::H::~H() [scalar deleting]378 379  // CHECK-LABEL: VFTable for 'V1' in 'simple::A' in 'extended::A' in 'extended::H' (2 entries).380  // CHECK-NEXT: 0 | void simple::A::f()381  // CHECK-NEXT:     [this adjustment: vtordisp at -4, vbptr at 8 to the left,382  // CHECK-NEXT:      vboffset at 8 in the vbtable, 8 non-virtual]383 384  // CHECK-LABEL: Thunks for 'void simple::A::f()' (1 entry).385  // CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, vbptr at 8 to the left,386  // CHECK-NEXT:      vboffset at 8 in the vbtable, 8 non-virtual]387 388  // MANGLING-DAG: @"?f@A@simple@@$R477PPPPPPPM@7AEXXZ"389  // MANGLING-DAG: @"??_EH@extended@@$4PPPPPPPM@BA@AEPAXI@Z"390};391 392H h;393void use(H *obj) { delete obj; }394}395 396namespace pr17738 {397// These classes should have vtordispex thunks but MSVS CL miscompiles them.398// Just do the right thing.399 400struct A : virtual simple::B {401  // CHECK-LABEL: VFTable for 'V2' in 'V3' in 'simple::B' in 'pr17738::A' (2 entries).402  // CHECK-NEXT: 0 | void simple::B::f()403  // CHECK-NEXT:     [this adjustment: vtordisp at -12, vbptr at 20 to the left,404  // CHECK-NEXT:      vboffset at 8 in the vbtable, 16 non-virtual]405 406  // CHECK-LABEL: Thunks for 'void simple::B::f()' (1 entry).407  // CHECK-NEXT: 0 | [this adjustment: vtordisp at -12, vbptr at 20 to the left,408  // CHECK-NEXT:      vboffset at 8 in the vbtable, 16 non-virtual]409 410  // MANGLING-DAG: @"?f@B@simple@@$R4BE@7PPPPPPPE@BA@AEXXZ"411  int a;412  virtual ~A();413};414 415A a;416void use(A *obj) { delete obj; }417}418 419namespace pr19408 {420// In this test, the vptr used to vcall D::f() is located in the A vbase.421// The offset of A in different in C and D, so the D vtordisp thunk should422// adjust "this" so C::f gets the right value.423struct A {424  A();425  virtual void f();426  int a;427};428 429struct B : virtual A {430  B();431  int b;432};433 434struct C : B {435  C();436  virtual void f();437  int c;438};439 440struct D : C {441  // CHECK-LABEL: VFTable for 'pr19408::A' in 'pr19408::B' in 'pr19408::C' in 'pr19408::D' (1 entry).442  // CHECK-NEXT:   0 | void pr19408::C::f()443  // CHECK-NEXT:       [this adjustment: vtordisp at -4, -4 non-virtual]444 445  // MANGLING-DAG: @"?f@C@pr19408@@$4PPPPPPPM@3AEXXZ"446  D();447  int d;448};449 450D::D() {}451}452 453namespace access {454struct A {455  virtual ~A();456protected:457  virtual void prot();458private:459  virtual void priv();460};461 462struct B : virtual A {463  virtual ~B();464protected:465  virtual void prot();466  // MANGLING-DAG: @"?prot@B@access@@$2PPPPPPPM@A@AEXXZ"467private:468  virtual void priv();469  // MANGLING-DAG: @"?priv@B@access@@$0PPPPPPPM@A@AEXXZ"470};471 472B b;473 474struct C : virtual B {475  virtual ~C();476 477  // MANGLING-DAG: @"?prot@B@access@@$R277PPPPPPPM@7AEXXZ"478  // MANGLING-DAG: @"?priv@B@access@@$R077PPPPPPPM@7AEXXZ"479};480 481C c;482}483 484namespace pr19505 {485struct A {486  virtual void f();487  virtual void z();488};489 490struct B : A {491  virtual void f();492};493 494struct C : A, B {495  virtual void g();496};497 498struct X : B, virtual C {499  X() {}500  virtual void g();501 502  // CHECK-LABEL: VFTable for 'pr19505::A' in 'pr19505::B' in 'pr19505::C' in 'pr19505::X' (2 entries).503  // CHECK-NEXT:   0 | void pr19505::B::f()504  // CHECK-NEXT:   1 | void pr19505::A::z()505 506  // MANGLING-DAG: @"??_7X@pr19505@@6BB@1@@" = {{.*}}@"?f@B@pr19505@@UAEXXZ"507} x;508 509void build_vftable(X *obj) { obj->g(); }510}511 512namespace pr19506 {513struct A {514  virtual void f();515  virtual void g();516};517 518struct B : A {519  virtual void f();520};521 522struct C : B {};523 524struct X : C, virtual B {525  virtual void g();526  X() {}527 528  // CHECK-LABEL: VFTable for 'pr19506::A' in 'pr19506::B' in 'pr19506::X' (2 entries).529  // CHECK-NEXT:   0 | void pr19506::B::f()530  // CHECK-NEXT:   1 | void pr19506::X::g()531  // CHECK-NEXT:       [this adjustment: vtordisp at -4, -12 non-virtual]532 533  // MANGLING-DAG: @"??_7X@pr19506@@6BB@1@@" = {{.*}}@"?f@B@pr19506@@UAEXXZ"534} x;535 536void build_vftable(X *obj) { obj->g(); }537}538 539namespace pr19519 {540// VS2013 CL miscompiles this, just make sure we don't regress.541 542struct A {543  virtual void f();544  virtual void g();545};546 547struct B : virtual A {548  virtual void f();549  B();550};551 552struct C : virtual A {553  virtual void g();554};555 556struct X : B, C {557  X();558 559  // CHECK-LABEL: VFTable for 'pr19519::A' in 'pr19519::B' in 'pr19519::X' (2 entries).560  // CHECK-NEXT:   0 | void pr19519::B::f()561  // CHECK-NEXT:       [this adjustment: vtordisp at -4, -4 non-virtual]562  // CHECK-NEXT:   1 | void pr19519::C::g()563  // CHECK-NEXT:       [this adjustment: vtordisp at -4, -4 non-virtual]564 565  // MANGLING-DAG: @"??_7X@pr19519@@6B@" = {{.*}}@"?g@C@pr19519@@$4PPPPPPPM@3AEXXZ"566};567 568X::X() {}569}570