aboutsummaryrefslogtreecommitdiff
path: root/clang/test/CodeGenCXX/member-function-pointers.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2012-02-15 01:22:51 +0000
committerJohn McCall <rjmccall@apple.com>2012-02-15 01:22:51 +0000
commitc62bb3914260c9b864dcf88e8a12ee645f5368da (patch)
tree7128c79cc1a2fea3a832f3b1505b2bcadf6e48b6 /clang/test/CodeGenCXX/member-function-pointers.cpp
parent4dd0963d56096eb3de1b6beaa5deee57be384e95 (diff)
downloadllvm-c62bb3914260c9b864dcf88e8a12ee645f5368da.zip
llvm-c62bb3914260c9b864dcf88e8a12ee645f5368da.tar.gz
llvm-c62bb3914260c9b864dcf88e8a12ee645f5368da.tar.bz2
Split reinterpret_casts of member pointers out from CK_BitCast; this
is general goodness because representations of member pointers are not always equivalent across member pointer types on all ABIs (even though this isn't really standard-endorsed). Take advantage of the new information to teach IR-generation how to do these reinterprets in constant initializers. Make sure this works when intermingled with hierarchy conversions (although this is not part of our motivating use case). Doing this in the constant-evaluator would probably have been better, but that would require a *lot* of extra structure in the representation of constant member pointers: you'd really have to track an arbitrary chain of hierarchy conversions and reinterpretations in order to get this right. Ultimately, this seems less complex. I also wasn't quite sure how to extend the constant evaluator to handle foldings that we don't actually want to treat as extended constant expressions. llvm-svn: 150551
Diffstat (limited to 'clang/test/CodeGenCXX/member-function-pointers.cpp')
-rw-r--r--clang/test/CodeGenCXX/member-function-pointers.cpp40
1 files changed, 40 insertions, 0 deletions
diff --git a/clang/test/CodeGenCXX/member-function-pointers.cpp b/clang/test/CodeGenCXX/member-function-pointers.cpp
index 5ce5fbf..2417aa4 100644
--- a/clang/test/CodeGenCXX/member-function-pointers.cpp
+++ b/clang/test/CodeGenCXX/member-function-pointers.cpp
@@ -28,6 +28,16 @@ void (C::*pc2)() = &C::f;
// CHECK: @pc3 = global { i64, i64 } { i64 1, i64 0 }, align 8
void (A::*pc3)() = &A::vf1;
+// Tests for test10.
+// CHECK: @_ZN6test101aE = global { i64, i64 } { i64 ptrtoint (void (%"struct.test10::A"*)* @_ZN6test101A3fooEv to i64), i64 0 }, align 8
+// CHECK: @_ZN6test101bE = global { i64, i64 } { i64 ptrtoint (void (%"struct.test10::A"*)* @_ZN6test101A3fooEv to i64), i64 8 }, align 8
+// CHECK: @_ZN6test101cE = global { i64, i64 } { i64 ptrtoint (void (%"struct.test10::A"*)* @_ZN6test101A3fooEv to i64), i64 8 }, align 8
+// CHECK: @_ZN6test101dE = global { i64, i64 } { i64 ptrtoint (void (%"struct.test10::A"*)* @_ZN6test101A3fooEv to i64), i64 16 }, align 8
+// CHECK-LP32: @_ZN6test101aE = global { i32, i32 } { i32 ptrtoint (void (%"struct.test10::A"*)* @_ZN6test101A3fooEv to i32), i32 0 }, align 4
+// CHECK-LP32: @_ZN6test101bE = global { i32, i32 } { i32 ptrtoint (void (%"struct.test10::A"*)* @_ZN6test101A3fooEv to i32), i32 4 }, align 4
+// CHECK-LP32: @_ZN6test101cE = global { i32, i32 } { i32 ptrtoint (void (%"struct.test10::A"*)* @_ZN6test101A3fooEv to i32), i32 4 }, align 4
+// CHECK-LP32: @_ZN6test101dE = global { i32, i32 } { i32 ptrtoint (void (%"struct.test10::A"*)* @_ZN6test101A3fooEv to i32), i32 8 }, align 4
+
void f() {
// CHECK: store { i64, i64 } zeroinitializer, { i64, i64 }* @pa
pa = 0;
@@ -232,3 +242,33 @@ namespace test9 {
static S array[] = { (fooptr) &B::foo };
}
}
+
+// rdar://problem/10815683 - Verify that we can emit reinterprets of
+// member pointers as constant initializers. For added trickiness,
+// we also add some non-trivial adjustments.
+namespace test10 {
+ struct A {
+ int nonEmpty;
+ void foo();
+ };
+ struct B : public A {
+ virtual void requireNonZeroAdjustment();
+ };
+ struct C {
+ int nonEmpty;
+ };
+ struct D : public C {
+ virtual void requireNonZeroAdjustment();
+ };
+
+ // Non-ARM tests at top of file.
+ void (A::*a)() = &A::foo;
+ void (B::*b)() = (void (B::*)()) &A::foo;
+ void (C::*c)() = (void (C::*)()) (void (B::*)()) &A::foo;
+ void (D::*d)() = (void (C::*)()) (void (B::*)()) &A::foo;
+}
+// It's not that the offsets are doubled on ARM, it's that they're left-shifted by 1.
+// CHECK-ARM: @_ZN6test101aE = global { i32, i32 } { i32 ptrtoint (void (%"struct.test10::A"*)* @_ZN6test101A3fooEv to i32), i32 0 }, align 4
+// CHECK-ARM: @_ZN6test101bE = global { i32, i32 } { i32 ptrtoint (void (%"struct.test10::A"*)* @_ZN6test101A3fooEv to i32), i32 8 }, align 4
+// CHECK-ARM: @_ZN6test101cE = global { i32, i32 } { i32 ptrtoint (void (%"struct.test10::A"*)* @_ZN6test101A3fooEv to i32), i32 8 }, align 4
+// CHECK-ARM: @_ZN6test101dE = global { i32, i32 } { i32 ptrtoint (void (%"struct.test10::A"*)* @_ZN6test101A3fooEv to i32), i32 16 }, align 4