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