aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-10-25 21:59:45 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-10-25 21:59:45 +0000
commit0848333c398d1ddd9f4e3b60cccef6a1b2698f78 (patch)
tree40d57eb6d12a7baae0f04998f060e4675516029d
parentd2e7d20dc7a3c9b9d0b2e0b8e3266bf57416fa21 (diff)
Add a more direct test for r166661.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@166727 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--test/CodeGenCXX/catch-undef-behavior.cpp48
1 files changed, 42 insertions, 6 deletions
diff --git a/test/CodeGenCXX/catch-undef-behavior.cpp b/test/CodeGenCXX/catch-undef-behavior.cpp
index bfe716847e..2765c6f4f1 100644
--- a/test/CodeGenCXX/catch-undef-behavior.cpp
+++ b/test/CodeGenCXX/catch-undef-behavior.cpp
@@ -26,9 +26,7 @@ struct S {
// CHECK: @_Z13member_access
void member_access(S *p) {
- // (1) Check 'p' is appropriately sized and aligned for member access.
-
- // FIXME: Check vptr is for 'S' or a class derived from 'S'.
+ // (1a) Check 'p' is appropriately sized and aligned for member access.
// CHECK: icmp ne {{.*}}, null
@@ -39,6 +37,36 @@ void member_access(S *p) {
// CHECK-NEXT: %[[MISALIGN:.*]] = and i64 %[[PTRINT]], 7
// CHECK-NEXT: icmp eq i64 %[[MISALIGN]], 0
+ // (1b) Check that 'p' actually points to an 'S'.
+
+ // CHECK: %[[VPTRADDR:.*]] = bitcast {{.*}} to i64*
+ // CHECK-NEXT: %[[VPTR:.*]] = load i64* %[[VPTRADDR]]
+ //
+ // hash_16_bytes:
+ //
+ // If this number changes, it indicates that either the mangled name of ::S
+ // has changed, or that LLVM's hashing function has changed. The latter case
+ // is OK if the hashing function is still stable.
+ // CHECK-NEXT: xor i64 -4030275160588942838, %[[VPTR]]
+ // CHECK-NEXT: mul i64 {{.*}}, -7070675565921424023
+ // CHECK-NEXT: lshr i64 {{.*}}, 47
+ // CHECK-NEXT: xor i64
+ // CHECK-NEXT: xor i64 %[[VPTR]]
+ // CHECK-NEXT: mul i64 {{.*}}, -7070675565921424023
+ // CHECK-NEXT: lshr i64 {{.*}}, 47
+ // CHECK-NEXT: xor i64
+ // CHECK-NEXT: %[[HASH:.*]] = mul i64 {{.*}}, -7070675565921424023
+ //
+ // Check the hash against the table:
+ //
+ // CHECK-NEXT: %[[IDX:.*]] = and i64 %{{.*}}, 127
+ // CHECK-NEXT: getelementptr inbounds [128 x i64]* @__ubsan_vptr_type_cache, i32 0, i64 %[[IDX]]
+ // CHECK-NEXT: %[[CACHEVAL:.*]] = load i64*
+ // CHECK-NEXT: icmp eq i64 %[[CACHEVAL]], %[[HASH]]
+ // CHECK-NEXT: br i1
+
+ // CHECK: call void @__ubsan_handle_dynamic_type_cache_miss({{.*}}, i64 %{{.*}}, i64 %[[HASH]])
+
// (2) Check 'p->b' is appropriately sized and aligned for a load.
// FIXME: Suppress this in the trivial case of a member access, because we
@@ -52,9 +80,7 @@ void member_access(S *p) {
// CHECK-NEXT: icmp eq i64 %[[MISALIGN]], 0
int k = p->b;
- // (3) Check 'p' is appropriately sized and aligned for member function call.
-
- // FIXME: Check vptr is for 'S' or a class derived from 'S'.
+ // (3a) Check 'p' is appropriately sized and aligned for member function call.
// CHECK: icmp ne {{.*}}, null
@@ -64,6 +90,16 @@ void member_access(S *p) {
// CHECK: %[[PTRINT:.*]] = ptrtoint
// CHECK-NEXT: %[[MISALIGN:.*]] = and i64 %[[PTRINT]], 7
// CHECK-NEXT: icmp eq i64 %[[MISALIGN]], 0
+
+ // (3b) Check that 'p' actually points to an 'S'
+
+ // CHECK: load i64*
+ // CHECK-NEXT: xor i64 -4030275160588942838,
+ // [...]
+ // CHECK: getelementptr inbounds [128 x i64]* @__ubsan_vptr_type_cache, i32 0, i64 %
+ // CHECK: br i1
+ // CHECK: call void @__ubsan_handle_dynamic_type_cache_miss({{.*}}, i64 %{{.*}}, i64 %{{.*}})
+
k = p->f();
}