188 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			188 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
| // RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 %s -emit-llvm -o - | FileCheck %s
 | |
| 
 | |
| namespace Test1 {
 | |
|   struct A {
 | |
|     virtual int f() final;
 | |
|   };
 | |
| 
 | |
|   // CHECK-LABEL: define i32 @_ZN5Test11fEPNS_1AE
 | |
|   int f(A *a) {
 | |
|     // CHECK: call i32 @_ZN5Test11A1fEv
 | |
|     return a->f();
 | |
|   }
 | |
| }
 | |
| 
 | |
| namespace Test2 {
 | |
|   struct A final {
 | |
|     virtual int f();
 | |
|   };
 | |
| 
 | |
|   // CHECK-LABEL: define i32 @_ZN5Test21fEPNS_1AE
 | |
|   int f(A *a) {
 | |
|     // CHECK: call i32 @_ZN5Test21A1fEv
 | |
|     return a->f();
 | |
|   }
 | |
| }
 | |
| 
 | |
| namespace Test3 {
 | |
|   struct A {
 | |
|     virtual int f();
 | |
|   };
 | |
| 
 | |
|   struct B final : A { };
 | |
| 
 | |
|   // CHECK-LABEL: define i32 @_ZN5Test31fEPNS_1BE
 | |
|   int f(B *b) {
 | |
|     // CHECK: call i32 @_ZN5Test31A1fEv
 | |
|     return b->f();
 | |
|   }
 | |
| 
 | |
|   // CHECK-LABEL: define i32 @_ZN5Test31fERNS_1BE
 | |
|   int f(B &b) {
 | |
|     // CHECK: call i32 @_ZN5Test31A1fEv
 | |
|     return b.f();
 | |
|   }
 | |
| 
 | |
|   // CHECK-LABEL: define i32 @_ZN5Test31fEPv
 | |
|   int f(void *v) {
 | |
|     // CHECK: call i32 @_ZN5Test31A1fEv
 | |
|     return static_cast<B*>(v)->f();
 | |
|   }
 | |
| }
 | |
| 
 | |
| namespace Test4 {
 | |
|   struct A {
 | |
|     virtual void f();
 | |
|   };
 | |
| 
 | |
|   struct B final : A {
 | |
|     virtual void f();
 | |
|   };
 | |
| 
 | |
|   // CHECK-LABEL: define void @_ZN5Test41fEPNS_1BE
 | |
|   void f(B* d) {
 | |
|     // CHECK: call void @_ZN5Test41B1fEv
 | |
|     static_cast<A*>(d)->f();
 | |
|   }
 | |
| }
 | |
| 
 | |
| namespace Test5 {
 | |
|   struct A {
 | |
|     virtual void f();
 | |
|   };
 | |
| 
 | |
|   struct B : A {
 | |
|     virtual void f();
 | |
|   };
 | |
| 
 | |
|   struct C final : B {
 | |
|   };
 | |
| 
 | |
|   // CHECK-LABEL: define void @_ZN5Test51fEPNS_1CE
 | |
|   void f(C* d) {
 | |
|     // FIXME: It should be possible to devirtualize this case, but that is
 | |
|     // not implemented yet.
 | |
|     // CHECK: getelementptr
 | |
|     // CHECK-NEXT: %[[FUNC:.*]] = load
 | |
|     // CHECK-NEXT: call void %[[FUNC]]
 | |
|     static_cast<A*>(d)->f();
 | |
|   }
 | |
| }
 | |
| 
 | |
| namespace Test6 {
 | |
|   struct A {
 | |
|     virtual ~A();
 | |
|   };
 | |
| 
 | |
|   struct B : public A {
 | |
|     virtual ~B();
 | |
|   };
 | |
| 
 | |
|   struct C {
 | |
|     virtual ~C();
 | |
|   };
 | |
| 
 | |
|   struct D final : public C, public B {
 | |
|   };
 | |
| 
 | |
|   // CHECK-LABEL: define void @_ZN5Test61fEPNS_1DE
 | |
|   void f(D* d) {
 | |
|     // CHECK: call void @_ZN5Test61DD1Ev
 | |
|     static_cast<A*>(d)->~A();
 | |
|   }
 | |
| }
 | |
| 
 | |
| namespace Test7 {
 | |
|   struct foo {
 | |
|     virtual void g() {}
 | |
|   };
 | |
| 
 | |
|   struct bar {
 | |
|     virtual int f() { return 0; }
 | |
|   };
 | |
| 
 | |
|   struct zed final : public foo, public bar {
 | |
|     int z;
 | |
|     virtual int f() {return z;}
 | |
|   };
 | |
| 
 | |
|   // CHECK-LABEL: define i32 @_ZN5Test71fEPNS_3zedE
 | |
|   int f(zed *z) {
 | |
|     // CHECK: alloca
 | |
|     // CHECK-NEXT: store
 | |
|     // CHECK-NEXT: load
 | |
|     // CHECK-NEXT: call i32 @_ZN5Test73zed1fEv
 | |
|     // CHECK-NEXT: ret
 | |
|     return static_cast<bar*>(z)->f();
 | |
|   }
 | |
| }
 | |
| 
 | |
| namespace Test8 {
 | |
|   struct A { virtual ~A() {} };
 | |
|   struct B {
 | |
|     int b;
 | |
|     virtual int foo() { return b; }
 | |
|   };
 | |
|   struct C final : A, B {  };
 | |
|   // CHECK-LABEL: define i32 @_ZN5Test84testEPNS_1CE
 | |
|   int test(C *c) {
 | |
|     // CHECK: %[[THIS:.*]] = phi
 | |
|     // CHECK-NEXT: call i32 @_ZN5Test81B3fooEv(%"struct.Test8::B"* %[[THIS]])
 | |
|     return static_cast<B*>(c)->foo();
 | |
|   }
 | |
| }
 | |
| 
 | |
| namespace Test9 {
 | |
|   struct A {
 | |
|     int a;
 | |
|   };
 | |
|   struct B {
 | |
|     int b;
 | |
|   };
 | |
|   struct C : public B, public A {
 | |
|   };
 | |
|   struct RA {
 | |
|     virtual A *f() {
 | |
|       return 0;
 | |
|     }
 | |
|   };
 | |
|   struct RC final : public RA {
 | |
|     virtual C *f() {
 | |
|       C *x = new C();
 | |
|       x->a = 1;
 | |
|       x->b = 2;
 | |
|       return x;
 | |
|     }
 | |
|   };
 | |
|   // CHECK: define {{.*}} @_ZN5Test91fEPNS_2RCE
 | |
|   A *f(RC *x) {
 | |
|     // FIXME: It should be possible to devirtualize this case, but that is
 | |
|     // not implemented yet.
 | |
|     // CHECK: getelementptr
 | |
|     // CHECK-NEXT: %[[FUNC:.*]] = load
 | |
|     // CHECK-NEXT: bitcast
 | |
|     // CHECK-NEXT: = call {{.*}} %[[FUNC]]
 | |
|     return static_cast<RA*>(x)->f();
 | |
|   }
 | |
| }
 |