1// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -emit-llvm %s -fstrict-vtable-pointers -O1 -o - -disable-llvm-optzns | FileCheck %s
2
3struct A {
4  virtual void foo();
5};
6
7struct D : A {
8  void foo();
9};
10
11// CHECK-LABEL: define void @_Z21testExternallyVisiblev()
12void testExternallyVisible() {
13  A *a = new A;
14
15  // CHECK: load {{.*}} !invariant.group ![[A_MD:[0-9]+]]
16  a->foo();
17
18  D *d = new D;
19  // CHECK: call void @_ZN1DC1Ev(
20  // CHECK: load {{.*}} !invariant.group ![[D_MD:[0-9]+]]
21  d->foo();
22  A *a2 = d;
23  // CHECK: load {{.*}} !invariant.group ![[A_MD]]
24  a2->foo();
25}
26// CHECK-LABEL: }
27
28namespace {
29
30struct B {
31  virtual void bar();
32};
33
34struct C : B {
35  void bar();
36};
37
38}
39
40// CHECK-LABEL: define void @_Z21testInternallyVisibleb(
41void testInternallyVisible(bool p) {
42  B *b = new B;
43  // CHECK: = load {{.*}}, !invariant.group ![[B_MD:[0-9]+]]
44  b->bar();
45
46  // CHECK: call void @_ZN12_GLOBAL__N_11CC1Ev(
47  C *c = new C;
48  // CHECK: = load {{.*}}, !invariant.group ![[C_MD:[0-9]+]]
49  c->bar();
50}
51
52// Checking A::A()
53// CHECK-LABEL: define linkonce_odr void @_ZN1AC2Ev(
54// CHECK: store {{.*}}, !invariant.group ![[A_MD]]
55// CHECK-LABEL: }
56
57// Checking D::D()
58// CHECK-LABEL: define linkonce_odr void @_ZN1DC2Ev(
59// CHECK:  = call i8* @llvm.invariant.group.barrier(i8*
60// CHECK:  call void @_ZN1AC2Ev(%struct.A*
61// CHECK: store {{.*}} !invariant.group ![[D_MD]]
62
63// Checking B::B()
64// CHECK-LABEL: define internal void @_ZN12_GLOBAL__N_11BC2Ev(
65// CHECK:  store {{.*}}, !invariant.group ![[B_MD]]
66
67// Checking C::C()
68// CHECK-LABEL: define internal void @_ZN12_GLOBAL__N_11CC2Ev(
69// CHECK:  store {{.*}}, !invariant.group ![[C_MD]]
70
71// CHECK: ![[A_MD]] = !{!"_ZTS1A"}
72// CHECK: ![[D_MD]] = !{!"_ZTS1D"}
73// CHECK: ![[B_MD]] = distinct !{}
74// CHECK: ![[C_MD]] = distinct !{}
75