diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2017-12-18 20:11:37 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2017-12-18 20:11:37 +0000 |
| commit | 461a67fa15370a9ec88f8f8a240bf7c123bb2029 (patch) | |
| tree | 6942083d7d56bba40ec790a453ca58ad3baf6832 /test/CodeGenCXX/ubsan-type-checks.cpp | |
| parent | 75c3240472ba6ac2669ee72ca67eb72d4e2851fc (diff) | |
Notes
Diffstat (limited to 'test/CodeGenCXX/ubsan-type-checks.cpp')
| -rw-r--r-- | test/CodeGenCXX/ubsan-type-checks.cpp | 51 |
1 files changed, 50 insertions, 1 deletions
diff --git a/test/CodeGenCXX/ubsan-type-checks.cpp b/test/CodeGenCXX/ubsan-type-checks.cpp index 786d049dfb56a..e53ab2466e733 100644 --- a/test/CodeGenCXX/ubsan-type-checks.cpp +++ b/test/CodeGenCXX/ubsan-type-checks.cpp @@ -1,6 +1,8 @@ // RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=alignment | FileCheck %s -check-prefixes=ALIGN,COMMON // RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=null | FileCheck %s -check-prefixes=NULL,COMMON // RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=object-size | FileCheck %s -check-prefixes=OBJSIZE,COMMON +// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=null,vptr | FileCheck %s -check-prefixes=VPTR +// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=vptr | FileCheck %s -check-prefixes=VPTR_NO_NULL struct A { // COMMON-LABEL: define linkonce_odr void @_ZN1A10do_nothingEv @@ -24,13 +26,60 @@ struct B { // NULL: icmp ne %struct.B* %{{.*}}, null, !nosanitize // OBJSIZE-NOT: call i64 @llvm.objectsize + // OBJSIZE: ret void } }; -void force_irgen() { +struct Animal { + virtual const char *speak() = 0; +}; + +struct Cat : Animal { + const char *speak() override { return "meow"; } +}; + +struct Dog : Animal { + const char *speak() override { return "woof"; } +}; + +// VPTR-LABEL: define void @_Z12invalid_castP3Cat +void invalid_cast(Cat *cat = nullptr) { + // If -fsanitize=null is available, we'll reuse its check: + // + // VPTR: [[ICMP:%.*]] = icmp ne %struct.Dog* {{.*}}, null + // VPTR-NEXT: br i1 [[ICMP]] + // VPTR: call void @__ubsan_handle_type_mismatch + // VPTR-NOT: icmp ne %struct.Dog* {{.*}}, null + // VPTR: br i1 [[ICMP]] + // VPTR: call void @__ubsan_handle_dynamic_type_cache_miss + // + // Fall back to the vptr sanitizer's null check when -fsanitize=null isn't + // available. + // + // VPTR_NO_NULL-NOT: call void @__ubsan_handle_type_mismatch + // VPTR_NO_NULL: [[ICMP:%.*]] = icmp ne %struct.Dog* {{.*}}, null + // VPTR_NO_NULL-NEXT: br i1 [[ICMP]] + // VPTR_NO_NULL: call void @__ubsan_handle_dynamic_type_cache_miss + auto *badDog = reinterpret_cast<Dog *>(cat); + badDog->speak(); +} + +// VPTR_NO_NULL-LABEL: define void @_Z13invalid_cast2v +void invalid_cast2() { + // We've got a pointer to an alloca, so there's no run-time null check needed. + // VPTR_NO_NULL-NOT: call void @__ubsan_handle_type_mismatch + // VPTR_NO_NULL: call void @__ubsan_handle_dynamic_type_cache_miss + Cat cat; + cat.speak(); +} + +int main() { A a; a.do_nothing(); B b; b.do_nothing(); + + invalid_cast(); + return 0; } |
