teak-llvm/clang/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp
Rafael Espindola 49e860b248 During codegen of a virtual call we would extract any casts in the expression
to see if we had an underlying final class or method, but we would then
use the cast type to do the call, resulting in a direct call to the wrong
method.

llvm-svn: 159212
2012-06-26 17:45:31 +00:00

110 lines
1.7 KiB
C++

// RUN: %clang_cc1 -std=c++11 %s -emit-llvm -o - | FileCheck %s
namespace Test1 {
struct A {
virtual int f() final;
};
// CHECK: define i32 @_ZN5Test11fEPNS_1AE
int f(A *a) {
// CHECK: call i32 @_ZN5Test11A1fEv
return a->f();
}
}
namespace Test2 {
struct A final {
virtual int f();
};
// CHECK: 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: define i32 @_ZN5Test31fEPNS_1BE
int f(B *b) {
// CHECK: call i32 @_ZN5Test31A1fEv
return b->f();
}
// CHECK: define i32 @_ZN5Test31fERNS_1BE
int f(B &b) {
// CHECK: call i32 @_ZN5Test31A1fEv
return b.f();
}
// CHECK: 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: 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: define void @_ZN5Test51fEPNS_1CE
void f(C* d) {
// CHECK: call void @_ZN5Test51B1fEv
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: define void @_ZN5Test61fEPNS_1DE
void f(D* d) {
// CHECK: call void @_ZN5Test61DD1Ev
static_cast<A*>(d)->~A();
}
}