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