Home | History | Annotate | Download | only in CodeGenCXX
      1 // RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o %t.ll -O1 -disable-llvm-optzns -fms-extensions -fstrict-vtable-pointers
      2 // RUN: %clang_cc1 %s -triple i686-pc-win32 -emit-llvm -o %t.ms.ll -O1 -disable-llvm-optzns -fms-extensions -fstrict-vtable-pointers
      3 // FIXME: Assume load should not require -fstrict-vtable-pointers
      4 
      5 // RUN: FileCheck --check-prefix=CHECK1 --input-file=%t.ll %s
      6 // RUN: FileCheck --check-prefix=CHECK2 --input-file=%t.ll %s
      7 // RUN: FileCheck --check-prefix=CHECK3 --input-file=%t.ll %s
      8 // RUN: FileCheck --check-prefix=CHECK4 --input-file=%t.ll %s
      9 // RUN: FileCheck --check-prefix=CHECK-MS --input-file=%t.ms.ll %s
     10 // RUN: FileCheck --check-prefix=CHECK6 --input-file=%t.ll %s
     11 // RUN: FileCheck --check-prefix=CHECK7 --input-file=%t.ll %s
     12 // RUN: FileCheck --check-prefix=CHECK8 --input-file=%t.ll %s
     13 // RUN: FileCheck --check-prefix=CHECK9 --input-file=%t.ll %s
     14 namespace test1 {
     15 
     16 struct A {
     17   A();
     18   virtual void foo();
     19 };
     20 
     21 struct B : A {
     22   virtual void foo();
     23 };
     24 
     25 void g(A *a) { a->foo(); }
     26 
     27 // CHECK1-LABEL: define void @_ZN5test14fooAEv()
     28 // CHECK1: call void @_ZN5test11AC1Ev(%"struct.test1::A"*
     29 // CHECK1: %[[VTABLE:.*]] = load i8**, i8*** %{{.*}}
     30 // CHECK1: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11AE, i32 0, i32 2)
     31 // CHECK1: call void @llvm.assume(i1 %[[CMP]])
     32 // CHECK1-LABEL: }
     33 
     34 void fooA() {
     35   A a;
     36   g(&a);
     37 }
     38 
     39 // CHECK1-LABEL: define void @_ZN5test14fooBEv()
     40 // CHECK1: call void @_ZN5test11BC1Ev(%"struct.test1::B"* %{{.*}})
     41 // CHECK1: %[[VTABLE:.*]] = load i8**, i8*** %{{.*}}
     42 // CHECK1: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11BE, i32 0, i32 2)
     43 // CHECK1: call void @llvm.assume(i1 %[[CMP]])
     44 // CHECK1-LABEL: }
     45 
     46 void fooB() {
     47   B b;
     48   g(&b);
     49 }
     50 // there should not be any assumes in the ctor that calls base ctor
     51 // CHECK1-LABEL: define linkonce_odr void @_ZN5test11BC2Ev(%"struct.test1::B"*
     52 // CHECK1-NOT: @llvm.assume(
     53 // CHECK1-LABEL: }
     54 }
     55 namespace test2 {
     56 struct A {
     57   A();
     58   virtual void foo();
     59 };
     60 
     61 struct B {
     62   B();
     63   virtual void bar();
     64 };
     65 
     66 struct C : A, B {
     67   C();
     68   virtual void foo();
     69 };
     70 void g(A *a) { a->foo(); }
     71 void h(B *b) { b->bar(); }
     72 
     73 // CHECK2-LABEL: define void @_ZN5test24testEv()
     74 // CHECK2: call void @_ZN5test21CC1Ev(%"struct.test2::C"*
     75 // CHECK2: %[[VTABLE:.*]] = load i8**, i8*** {{.*}}
     76 // CHECK2: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([6 x i8*], [6 x i8*]* @_ZTVN5test21CE, i32 0, i32 2)
     77 // CHECK2: call void @llvm.assume(i1 %[[CMP]])
     78 
     79 // CHECK2: %[[V2:.*]] = bitcast %"struct.test2::C"* %{{.*}} to i8*
     80 // CHECK2: %[[ADD_PTR:.*]] = getelementptr inbounds i8, i8* %[[V2]], i64 8
     81 // CHECK2: %[[V3:.*]] = bitcast i8* %[[ADD_PTR]] to i8***
     82 // CHECK2: %[[VTABLE2:.*]] = load i8**, i8*** %[[V3]]
     83 // CHECK2: %[[CMP2:.*]] = icmp eq i8** %[[VTABLE2]], getelementptr inbounds ([6 x i8*], [6 x i8*]* @_ZTVN5test21CE, i32 0, i32 5)
     84 // CHECK2: call void @llvm.assume(i1 %[[CMP2]])
     85 
     86 // CHECK2: call void @_ZN5test21gEPNS_1AE(
     87 // CHECK2-LABEL: }
     88 
     89 void test() {
     90   C c;
     91   g(&c);
     92   h(&c);
     93 }
     94 }
     95 
     96 namespace test3 {
     97 struct A {
     98   A();
     99 };
    100 
    101 struct B : A {
    102   B();
    103   virtual void foo();
    104 };
    105 
    106 struct C : virtual A, B {
    107   C();
    108   virtual void foo();
    109 };
    110 void g(B *a) { a->foo(); }
    111 
    112 // CHECK3-LABEL: define void @_ZN5test34testEv()
    113 // CHECK3: call void @_ZN5test31CC1Ev(%"struct.test3::C"*
    114 // CHECK3: %[[CMP:.*]] = icmp eq i8** %{{.*}}, getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTVN5test31CE, i32 0, i32 3)
    115 // CHECK3: call void @llvm.assume(i1 %[[CMP]])
    116 // CHECK3-LABLEL: }
    117 void test() {
    118   C c;
    119   g(&c);
    120 }
    121 } // test3
    122 
    123 namespace test4 {
    124 struct A {
    125   A();
    126   virtual void foo();
    127 };
    128 
    129 struct B : virtual A {
    130   B();
    131   virtual void foo();
    132 };
    133 struct C : B {
    134   C();
    135   virtual void foo();
    136 };
    137 
    138 void g(C *c) { c->foo(); }
    139 
    140 // CHECK4-LABEL: define void @_ZN5test44testEv()
    141 // CHECK4: call void @_ZN5test41CC1Ev(%"struct.test4::C"*
    142 // CHECK4: %[[VTABLE:.*]] = load i8**, i8*** %{{.*}}
    143 // CHECK4: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([5 x i8*], [5 x i8*]* @_ZTVN5test41CE, i32 0, i32 4)
    144 // CHECK4: call void @llvm.assume(i1 %[[CMP]]
    145 
    146 // CHECK4: %[[VTABLE2:.*]] = load i8**, i8*** %{{.*}}
    147 // CHECK4: %[[CMP2:.*]] = icmp eq i8** %[[VTABLE2]], getelementptr inbounds ([5 x i8*], [5 x i8*]* @_ZTVN5test41CE, i32 0, i32 4)
    148 // CHECK4: call void @llvm.assume(i1 %[[CMP2]])
    149 // CHECK4-LABEL: }
    150 
    151 void test() {
    152   C c;
    153   g(&c);
    154 }
    155 } // test4
    156 
    157 namespace testMS {
    158 
    159 struct __declspec(novtable) S {
    160   virtual void foo();
    161 };
    162 
    163 void g(S &s) { s.foo(); }
    164 
    165 // if struct has novtable specifier, then we can't generate assumes
    166 // CHECK-MS-LABEL: define void @"\01?test@testMS@@YAXXZ"()
    167 // CHECK-MS: call x86_thiscallcc %"struct.testMS::S"* @"\01??0S@testMS@@QAE@XZ"(
    168 // CHECK-MS-NOT: @llvm.assume
    169 // CHECK-MS-LABEL: }
    170 
    171 void test() {
    172   S s;
    173   g(s);
    174 }
    175 
    176 } // testMS
    177 
    178 namespace test6 {
    179 struct A {
    180   A();
    181   virtual void foo();
    182   virtual ~A() {}
    183 };
    184 struct B : A {
    185   B();
    186 };
    187 // FIXME: Because A's vtable is external, and no virtual functions are hidden,
    188 // it's safe to generate assumption loads.
    189 // CHECK6-LABEL: define void @_ZN5test61gEv()
    190 // CHECK6: call void @_ZN5test61AC1Ev(
    191 // CHECK6-NOT: call void @llvm.assume(
    192 
    193 // We can't emit assumption loads for B, because if we would refer to vtable
    194 // it would refer to functions that will not be able to find (like implicit
    195 // inline destructor).
    196 
    197 // CHECK6-LABEL:   call void @_ZN5test61BC1Ev(
    198 // CHECK6-NOT: call void @llvm.assume(
    199 // CHECK6-LABEL: }
    200 void g() {
    201   A *a = new A;
    202   B *b = new B;
    203 }
    204 }
    205 
    206 namespace test7 {
    207 // Because A's key function is defined here, vtable is generated in this TU
    208 // CHECK7: @_ZTVN5test71AE = unnamed_addr constant
    209 struct A {
    210   A();
    211   virtual void foo();
    212   virtual void bar();
    213 };
    214 void A::foo() {}
    215 
    216 // CHECK7-LABEL: define void @_ZN5test71gEv()
    217 // CHECK7: call void @_ZN5test71AC1Ev(
    218 // CHECK7: call void @llvm.assume(
    219 // CHECK7-LABEL: }
    220 void g() {
    221   A *a = new A();
    222   a->bar();
    223 }
    224 }
    225 
    226 namespace test8 {
    227 
    228 struct A {
    229   virtual void foo();
    230   virtual void bar();
    231 };
    232 
    233 // CHECK8-DAG: @_ZTVN5test81BE = available_externally unnamed_addr constant
    234 struct B : A {
    235   B();
    236   void foo();
    237   void bar();
    238 };
    239 
    240 // CHECK8-DAG: @_ZTVN5test81CE = linkonce_odr unnamed_addr constant
    241 struct C : A {
    242   C();
    243   void bar();
    244   void foo() {}
    245 };
    246 inline void C::bar() {}
    247 
    248 struct D : A {
    249   D();
    250   void foo();
    251   void inline bar();
    252 };
    253 void D::bar() {}
    254 
    255 // CHECK8-DAG: @_ZTVN5test81EE = linkonce_odr unnamed_addr constant
    256 struct E : A {
    257   E();
    258 };
    259 
    260 // CHECK8-LABEL: define void @_ZN5test81bEv()
    261 // CHECK8: call void @llvm.assume(
    262 // CHECK8-LABEL: }
    263 void b() {
    264   B b;
    265   b.bar();
    266 }
    267 
    268 // FIXME: C has inline virtual functions which prohibits as from generating
    269 // assumption loads, but because vtable is generated in this TU (key function
    270 // defined here) it would be correct to refer to it.
    271 // CHECK8-LABEL: define void @_ZN5test81cEv()
    272 // CHECK8-NOT: call void @llvm.assume(
    273 // CHECK8-LABEL: }
    274 void c() {
    275   C c;
    276   c.bar();
    277 }
    278 
    279 // FIXME: We could generate assumption loads here.
    280 // CHECK8-LABEL: define void @_ZN5test81dEv()
    281 // CHECK8-NOT: call void @llvm.assume(
    282 // CHECK8-LABEL: }
    283 void d() {
    284   D d;
    285   d.bar();
    286 }
    287 
    288 // CHECK8-LABEL: define void @_ZN5test81eEv()
    289 // CHECK8: call void @llvm.assume(
    290 // CHECK8-LABEL: }
    291 void e() {
    292   E e;
    293   e.bar();
    294 }
    295 }
    296 
    297 namespace test9 {
    298 
    299 struct S {
    300   S();
    301   __attribute__((visibility("hidden"))) virtual void doStuff();
    302 };
    303 
    304 // CHECK9-LABEL: define void @_ZN5test94testEv()
    305 // CHECK9-NOT: @llvm.assume(
    306 // CHECK9: }
    307 void test() {
    308   S *s = new S();
    309   s->doStuff();
    310   delete s;
    311 }
    312 }
    313 
    314