mirror of https://github.com/microsoft/clang.git
86 lines
2.7 KiB
C++
86 lines
2.7 KiB
C++
// 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
|
|
void do_nothing() {
|
|
// ALIGN-NOT: ptrtoint %struct.A* %{{.*}} to i64, !nosanitize
|
|
|
|
// NULL: icmp ne %struct.A* %{{.*}}, null, !nosanitize
|
|
|
|
// OBJSIZE-NOT: call i64 @llvm.objectsize
|
|
}
|
|
};
|
|
|
|
struct B {
|
|
int x;
|
|
|
|
// COMMON-LABEL: define linkonce_odr void @_ZN1B10do_nothingEv
|
|
void do_nothing() {
|
|
// ALIGN: ptrtoint %struct.B* %{{.*}} to i64, !nosanitize
|
|
// ALIGN: and i64 %{{.*}}, 3, !nosanitize
|
|
|
|
// NULL: icmp ne %struct.B* %{{.*}}, null, !nosanitize
|
|
|
|
// OBJSIZE-NOT: call i64 @llvm.objectsize
|
|
// OBJSIZE: ret void
|
|
}
|
|
};
|
|
|
|
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;
|
|
}
|