xref: /llvm-project/clang/test/CodeGen/attr-noundef.cpp (revision 9ad72df55cb74b29193270c28f6974d2af8e0b71)
1 // RUN: %clang_cc1 -triple x86_64-gnu-linux -x c++ -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-INTEL
2 // RUN: %clang_cc1 -triple aarch64-gnu-linux -x c++ -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-AARCH
3 // RUN: %clang_cc1 -triple x86_64-gnu-linux -x c++ -emit-llvm -fsanitize-memory-param-retval %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-INTEL
4 // RUN: %clang_cc1 -triple aarch64-gnu-linux -x c++ -emit-llvm -fsanitize-memory-param-retval %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-AARCH
5 
6 // no-sanitize-memory-param-retval does NOT conflict with enable-noundef-analysis
7 // RUN: %clang_cc1 -triple x86_64-gnu-linux -x c++ -emit-llvm -fno-sanitize-memory-param-retval %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-INTEL
8 
9 //************ Passing structs by value
10 // TODO: No structs may currently be marked noundef
11 
12 namespace check_structs {
13 struct Trivial {
14   int a;
15 };
16 Trivial ret_trivial() { return {}; }
17 void pass_trivial(Trivial e) {}
18 // CHECK-INTEL: [[DEF:define( dso_local)?]] i32 @{{.*}}ret_trivial
19 // CHECK-AARCH: [[DEF:define( dso_local)?]] i32 @{{.*}}ret_trivial
20 // CHECK-INTEL: [[DEF]] void @{{.*}}pass_trivial{{.*}}(i32 %
21 // CHECK-AARCH: [[DEF]] void @{{.*}}pass_trivial{{.*}}(i64 %
22 
23 struct NoCopy {
24   int a;
25   NoCopy(NoCopy &) = delete;
26 };
27 NoCopy ret_nocopy() { return {}; }
28 void pass_nocopy(NoCopy e) {}
29 // CHECK: [[DEF]] void @{{.*}}ret_nocopy{{.*}}(ptr dead_on_unwind noalias writable sret({{[^)]+}}) align 4 %
30 // CHECK: [[DEF]] void @{{.*}}pass_nocopy{{.*}}(ptr noundef %
31 
32 struct Huge {
33   int a[1024];
34 };
35 Huge ret_huge() { return {}; }
36 void pass_huge(Huge h) {}
37 // CHECK: [[DEF]] void @{{.*}}ret_huge{{.*}}(ptr dead_on_unwind noalias writable sret({{[^)]+}}) align 4 %
38 // CHECK: [[DEF]] void @{{.*}}pass_huge{{.*}}(ptr noundef
39 } // namespace check_structs
40 
41 //************ Passing unions by value
42 // No unions may be marked noundef
43 
44 namespace check_unions {
45 union Trivial {
46   int a;
47 };
48 Trivial ret_trivial() { return {}; }
49 void pass_trivial(Trivial e) {}
50 // CHECK-INTEL: [[DEF]] i32 @{{.*}}ret_trivial
51 // CHECK-AARCH: [[DEF]] i32 @{{.*}}ret_trivial
52 // CHECK-INTEL: [[DEF]] void @{{.*}}pass_trivial{{.*}}(i32 %
53 // CHECK-AARCH: [[DEF]] void @{{.*}}pass_trivial{{.*}}(i64 %
54 
55 union NoCopy {
56   int a;
57   NoCopy(NoCopy &) = delete;
58 };
59 NoCopy ret_nocopy() { return {}; }
60 void pass_nocopy(NoCopy e) {}
61 // CHECK: [[DEF]] void @{{.*}}ret_nocopy{{.*}}(ptr dead_on_unwind noalias writable sret({{[^)]+}}) align 4 %
62 // CHECK: [[DEF]] void @{{.*}}pass_nocopy{{.*}}(ptr noundef %
63 } // namespace check_unions
64 
65 //************ Passing `this` pointers
66 // `this` pointer must always be defined
67 
68 namespace check_this {
69 struct Object {
70   int data[];
71 
72   Object() {
73     this->data[0] = 0;
74   }
75   int getData() {
76     return this->data[0];
77   }
78   Object *getThis() {
79     return this;
80   }
81 };
82 
83 void use_object() {
84   Object obj;
85   obj.getData();
86   obj.getThis();
87 }
88 // CHECK: define linkonce_odr void @{{.*}}Object{{.*}}(ptr noundef nonnull align 4 dereferenceable(1) %
89 // CHECK: define linkonce_odr noundef i32 @{{.*}}Object{{.*}}getData{{.*}}(ptr noundef nonnull align 4 dereferenceable(1) %
90 // CHECK: define linkonce_odr noundef ptr @{{.*}}Object{{.*}}getThis{{.*}}(ptr noundef nonnull align 4 dereferenceable(1) %
91 } // namespace check_this
92 
93 //************ Passing vector types
94 
95 namespace check_vecs {
96 typedef int __attribute__((vector_size(12))) i32x3;
97 i32x3 ret_vec() {
98   return {};
99 }
100 void pass_vec(i32x3 v) {
101 }
102 
103 // CHECK: [[DEF]] noundef <3 x i32> @{{.*}}ret_vec{{.*}}()
104 // CHECK-INTEL: [[DEF]] void @{{.*}}pass_vec{{.*}}(<3 x i32> noundef %
105 // CHECK-AARCH: [[DEF]] void @{{.*}}pass_vec{{.*}}(<4 x i32> %
106 } // namespace check_vecs
107 
108 //************ Passing exotic types
109 // Function/Array pointers, Function member / Data member pointers, nullptr_t, ExtInt types
110 
111 namespace check_exotic {
112 struct Object {
113   int mfunc();
114   int mdata;
115 };
116 typedef int Object::*mdptr;
117 typedef int (Object::*mfptr)();
118 typedef decltype(nullptr) nullptr_t;
119 typedef int (*arrptr)[32];
120 typedef int (*fnptr)(int);
121 
122 arrptr ret_arrptr() {
123   return nullptr;
124 }
125 fnptr ret_fnptr() {
126   return nullptr;
127 }
128 mdptr ret_mdptr() {
129   return nullptr;
130 }
131 mfptr ret_mfptr() {
132   return nullptr;
133 }
134 nullptr_t ret_npt() {
135   return nullptr;
136 }
137 void pass_npt(nullptr_t t) {
138 }
139 _BitInt(3) ret_BitInt() {
140   return 0;
141 }
142 void pass_BitInt(_BitInt(3) e) {
143 }
144 void pass_large_BitInt(_BitInt(127) e) {
145 }
146 
147 // Pointers to arrays/functions are always noundef
148 // CHECK: [[DEF]] noundef ptr @{{.*}}ret_arrptr{{.*}}()
149 // CHECK: [[DEF]] noundef ptr @{{.*}}ret_fnptr{{.*}}()
150 
151 // Pointers to members are never noundef
152 // CHECK: [[DEF]] i64 @{{.*}}ret_mdptr{{.*}}()
153 // CHECK-INTEL: [[DEF]] { i64, i64 } @{{.*}}ret_mfptr{{.*}}()
154 // CHECK-AARCH: [[DEF]] [2 x i64] @{{.*}}ret_mfptr{{.*}}()
155 
156 // nullptr_t is never noundef
157 // CHECK: [[DEF]] ptr @{{.*}}ret_npt{{.*}}()
158 // CHECK: [[DEF]] void @{{.*}}pass_npt{{.*}}(ptr %
159 
160 // CHECK-INTEL: [[DEF]] noundef signext i3 @{{.*}}ret_BitInt{{.*}}()
161 // CHECK-AARCH: [[DEF]] noundef i3 @{{.*}}ret_BitInt{{.*}}()
162 // CHECK-INTEL: [[DEF]] void @{{.*}}pass_BitInt{{.*}}(i3 noundef signext %
163 // CHECK-AARCH: [[DEF]] void @{{.*}}pass_BitInt{{.*}}(i3 noundef %
164 // CHECK-INTEL: [[DEF]] void @{{.*}}pass_large_BitInt{{.*}}(i64 noundef %{{.*}}, i64 noundef %
165 // CHECK-AARCH: [[DEF]] void @{{.*}}pass_large_BitInt{{.*}}(i127 noundef %
166 } // namespace check_exotic
167