xref: /llvm-project/clang/test/CodeGenCXX/ubsan-type-checks.cpp (revision 1b9a6e58a8b831193c9e5e733f881aabe0d2d06b)
1 // RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=alignment | FileCheck %s -check-prefixes=ALIGN,COMMON
2 // RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=null | FileCheck %s -check-prefixes=NULL,COMMON
3 // RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=object-size | FileCheck %s -check-prefixes=OBJSIZE,COMMON
4 // RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=null,vptr | FileCheck %s -check-prefixes=VPTR
5 // RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=vptr | FileCheck %s -check-prefixes=VPTR_NO_NULL
6 
7 struct A {
8   // COMMON-LABEL: define linkonce_odr void @_ZN1A10do_nothingEv
do_nothingA9   void do_nothing() {
10     // ALIGN-NOT: ptrtoint ptr %{{.*}} to i64, !nosanitize
11 
12     // NULL: icmp ne ptr %{{.*}}, null, !nosanitize
13 
14     // OBJSIZE-NOT: call i64 @llvm.objectsize
15   }
16 };
17 
18 struct B {
19   int x;
20 
21   // COMMON-LABEL: define linkonce_odr void @_ZN1B10do_nothingEv
do_nothingB22   void do_nothing() {
23     // ALIGN: ptrtoint ptr %{{.*}} to i64, !nosanitize
24     // ALIGN: and i64 %{{.*}}, 3, !nosanitize
25 
26     // NULL: icmp ne ptr %{{.*}}, null, !nosanitize
27 
28     // OBJSIZE-NOT: call i64 @llvm.objectsize
29     // OBJSIZE: ret void
30   }
31 };
32 
33 struct Animal {
34   virtual const char *speak() = 0;
35 };
36 
37 struct Cat : Animal {
speakCat38   const char *speak() override { return "meow"; }
39 };
40 
41 struct Dog : Animal {
speakDog42   const char *speak() override { return "woof"; }
43 };
44 
45 // VPTR-LABEL: define{{.*}} void @_Z12invalid_castP3Cat
invalid_cast(Cat * cat=nullptr)46 void invalid_cast(Cat *cat = nullptr) {
47   // If -fsanitize=null is available, we'll reuse its check:
48   //
49   // VPTR: [[ICMP:%.*]] = icmp ne ptr {{.*}}, null
50   // VPTR-NEXT: br i1 [[ICMP]]
51   // VPTR: call void @__ubsan_handle_type_mismatch
52   // VPTR-NOT: icmp ne ptr {{.*}}, null
53   // VPTR: br i1 [[ICMP]]
54   // VPTR: call void @__ubsan_handle_dynamic_type_cache_miss
55   //
56   // Fall back to the vptr sanitizer's null check when -fsanitize=null isn't
57   // available.
58   //
59   // VPTR_NO_NULL-NOT: call void @__ubsan_handle_type_mismatch
60   // VPTR_NO_NULL: [[ICMP:%.*]] = icmp ne ptr {{.*}}, null
61   // VPTR_NO_NULL-NEXT: br i1 [[ICMP]]
62   // VPTR_NO_NULL: call void @__ubsan_handle_dynamic_type_cache_miss
63   auto *badDog = reinterpret_cast<Dog *>(cat);
64   badDog->speak();
65 }
66 
67 // VPTR_NO_NULL-LABEL: define{{.*}} void @_Z13invalid_cast2v
invalid_cast2()68 void invalid_cast2() {
69   // We've got a pointer to an alloca, so there's no run-time null check needed.
70   // VPTR_NO_NULL-NOT: call void @__ubsan_handle_type_mismatch
71   // VPTR_NO_NULL: call void @__ubsan_handle_dynamic_type_cache_miss
72   Cat cat;
73   cat.speak();
74 }
75 
main()76 int main() {
77   A a;
78   a.do_nothing();
79 
80   B b;
81   b.do_nothing();
82 
83   invalid_cast();
84   return 0;
85 }
86