1// clang-format off
2// REQUIRES: lld, x86
3
4// RUN: %clang_cl --target=x86_64-windows-msvc -Od -Z7 -c /Fo%t.obj -- %s
5// RUN: lld-link -debug:full -nodefaultlib -entry:main %t.obj -out:%t.exe -pdb:%t.pdb
6// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
7// RUN: %p/Inputs/function-types-builtins.lldbinit | FileCheck %s
8
9// Test that we can display function signatures with simple builtin
10// and pointer types. We do this by using `target variable` in lldb
11// with global variables of type ptr-to-function or reference-to-function.
12// This technique in general allows us to exercise most of LLDB's type
13// system without a running process.
14
15// Define _fltused, since we're not linking against the MS C runtime, but use
16// floats.
17extern "C" int _fltused = 0;
18
19template<typename T>
20struct MakeResult {
21 static T result() {
22 return T{};
23 }
24};
25
26template<typename T>
27struct MakeResult<T&> {
28 static T& result() {
29 static T t;
30 return t;
31 }
32};
33
34template<typename T>
35struct MakeResult<T&&> {
36 static T&& result() {
37 static T t;
38 return static_cast<T&&>(t);
39 }
40};
41
42
43void nullary() {}
44
45template<typename Arg>
46void unary(Arg) { }
47
48template<typename Ret, int N>
49Ret unaryret() { return MakeResult<Ret>::result(); }
50
51template<typename A1, typename A2>
52void binary(A1, A2) { }
53
54int varargs(int, int, ...) { return 0; }
55
56// Make sure to test every builtin type at least once for completeness. We
57// test these in the globals-fundamentals.cpp when they are the types of
58// variables but it's possible to imagine a situation where things behave
59// differently as function arguments or return values than they do with
60// global variables.
61
62// some interesting cases with argument types.
63auto aa = &unary<bool>;
64// CHECK: (void (*)(bool)) aa = {{.*}}
65auto ab = &unary<char>;
66// CHECK: (void (*)(char)) ab = {{.*}}
67auto ac = &unary<signed char>;
68// CHECK: (void (*)(signed char)) ac = {{.*}}
69auto = &unary<unsigned char>;
70// CHECK: (void (*)(unsigned char)) ad = {{.*}}
71auto ae = &unary<char16_t>;
72// CHECK: (void (*)(char16_t)) ae = {{.*}}
73auto af = &unary<char32_t>;
74// CHECK: (void (*)(char32_t)) af = {{.*}}
75auto ag = &unary<wchar_t>;
76// CHECK: (void (*)(wchar_t)) ag = {{.*}}
77auto ah = &unary<short>;
78// CHECK: (void (*)(short)) ah = {{.*}}
79auto ai = &unary<unsigned short>;
80// CHECK: (void (*)(unsigned short)) ai = {{.*}}
81auto aj = &unary<int>;
82// CHECK: (void (*)(int)) aj = {{.*}}
83auto ak = &unary<unsigned int>;
84// CHECK: (void (*)(unsigned int)) ak = {{.*}}
85auto al = &unary<long>;
86// CHECK: (void (*)(long)) al = {{.*}}
87auto am = &unary<unsigned long>;
88// CHECK: (void (*)(unsigned long)) am = {{.*}}
89auto an = &unary<long long>;
90// CHECK: (void (*)(long long)) an = {{.*}}
91auto ao = &unary<unsigned long long>;
92// CHECK: (void (*)(unsigned long long)) ao = {{.*}}
93auto aq = &unary<float>;
94// CHECK: (void (*)(float)) aq = {{.*}}
95auto ar = &unary<double>;
96// CHECK: (void (*)(double)) ar = {{.*}}
97
98auto as = &unary<int*>;
99// CHECK: (void (*)(int *)) as = {{.*}}
100auto at = &unary<int**>;
101// CHECK: (void (*)(int **)) at = {{.*}}
102auto au = &unary<int&>;
103// CHECK: (void (*)(int &)) au = {{.*}}
104auto av = &unary<int&&>;
105// CHECK: (void (*)(int &&)) av = {{.*}}
106auto aw = &unary<const int*>;
107// CHECK: (void (*)(const int *)) aw = {{.*}}
108auto ax = &unary<volatile int*>;
109// CHECK: (void (*)(volatile int *)) ax = {{.*}}
110auto ay = &unary<const volatile int*>;
111// CHECK: (void (*)(const volatile int *)) ay = {{.*}}
112auto az = &unary<void*&>;
113// CHECK: (void (*)(void *&)) az = {{.*}}
114auto aaa = &unary<int(&)[5]>;
115// CHECK: (void (*)(int (&)[5])) aaa = {{.*}}
116auto aab = &unary<int(*)[5]>;
117// CHECK: (void (*)(int (*)[5])) aab = {{.*}}
118auto aac = &unary<int(&&)[5]>;
119// CHECK: (void (*)(int (&&)[5])) aac = {{.*}}
120auto aad = &unary<int(*const)[5]>;
121// CHECK: (void (*)(int (*const)[5])) aad = {{.*}}
122
123
124// same test cases with return values, note we can't overload on return type
125// so we need to use a different instantiation each time.
126auto ra = &unaryret<bool, 0>;
127// CHECK: (bool (*)()) ra = {{.*}}
128auto rb = &unaryret<char, 1>;
129// CHECK: (char (*)()) rb = {{.*}}
130auto rc = &unaryret<signed char, 2>;
131// CHECK: (signed char (*)()) rc = {{.*}}
132auto rd = &unaryret<unsigned char, 3>;
133// CHECK: (unsigned char (*)()) rd = {{.*}}
134auto re = &unaryret<char16_t, 4>;
135// CHECK: (char16_t (*)()) re = {{.*}}
136auto rf = &unaryret<char32_t, 5>;
137// CHECK: (char32_t (*)()) rf = {{.*}}
138auto rg = &unaryret<wchar_t, 6>;
139// CHECK: (wchar_t (*)()) rg = {{.*}}
140auto rh = &unaryret<short, 7>;
141// CHECK: (short (*)()) rh = {{.*}}
142auto ri = &unaryret<unsigned short, 8>;
143// CHECK: (unsigned short (*)()) ri = {{.*}}
144auto rj = &unaryret<int, 9>;
145// CHECK: (int (*)()) rj = {{.*}}
146auto rk = &unaryret<unsigned int, 10>;
147// CHECK: (unsigned int (*)()) rk = {{.*}}
148auto rl = &unaryret<long, 11>;
149// CHECK: (long (*)()) rl = {{.*}}
150auto rm = &unaryret<unsigned long, 12>;
151// CHECK: (unsigned long (*)()) rm = {{.*}}
152auto rn = &unaryret<long long, 13>;
153// CHECK: (long long (*)()) rn = {{.*}}
154auto ro = &unaryret<unsigned long long, 14>;
155// CHECK: (unsigned long long (*)()) ro = {{.*}}
156auto rq = &unaryret<float, 15>;
157// CHECK: (float (*)()) rq = {{.*}}
158auto rr = &unaryret<double, 16>;
159// CHECK: (double (*)()) rr = {{.*}}
160
161auto rs = &unaryret<int*, 17>;
162// CHECK: (int *(*)()) rs = {{.*}}
163auto rt = &unaryret<int**, 18>;
164// CHECK: (int **(*)()) rt = {{.*}}
165auto ru = &unaryret<int&, 19>;
166// CHECK: (int &(*)()) ru = {{.*}}
167auto rv = &unaryret<int&&, 20>;
168// CHECK: (int &&(*)()) rv = {{.*}}
169auto rw = &unaryret<const int*, 21>;
170// CHECK: (const int *(*)()) rw = {{.*}}
171auto rx = &unaryret<volatile int*, 22>;
172// CHECK: (volatile int *(*)()) rx = {{.*}}
173auto ry = &unaryret<const volatile int*, 23>;
174// CHECK: (const volatile int *(*)()) ry = {{.*}}
175auto rz = &unaryret<void*&, 24>;
176// CHECK: (void *&(*)()) rz = {{.*}}
177
178// FIXME: This output doesn't really look correct. It should probably be
179// formatting this as `int(&)[5] (*)()`.
180auto raa = &unaryret<int(&)[5], 25>;
181// CHECK: (int (&(*)())[5]) raa = {{.*}}
182auto rab = &unaryret<int(*)[5], 26>;
183// CHECK: (int (*(*)())[5]) rab = {{.*}}
184auto rac = &unaryret<int(&&)[5], 27>;
185// CHECK: (int (&&(*)())[5]) rac = {{.*}}
186auto rad = &unaryret<int(*const)[5], 28>;
187// CHECK: (int (*const (*)())[5]) rad = {{.*}}
188
189
190
191// Function references, we only need a couple of these since most of the
192// interesting cases are already tested.
193auto &ref = unary<bool>;
194// CHECK: (void (&)(bool)) ref = {{.*}} (&::ref = <no summary available>)
195auto &ref2 = unary<volatile int*>;
196// CHECK: (void (&)(volatile int *)) ref2 = {{.*}} (&::ref2 = <no summary available>)
197auto &ref3 = varargs;
198// CHECK: (int (&)(int, int, ...)) ref3 = {{.*}} (&::ref3 = <no summary available>)
199
200// Multiple arguments, as before, just something to make sure it works.
201auto binp = &binary<int*, const int*>;
202// CHECK: (void (*)(int *, const int *)) binp = {{.*}}
203auto &binr = binary<int*, const int*>;
204// CHECK: (void (&)(int *, const int *)) binr = {{.*}} (&::binr = <no summary available>)
205
206// And finally, a function with no arguments.
207auto null = &nullary;
208// CHECK: (void (*)()) null = {{.*}}
209
210// FIXME: These currently don't work because clang-cl emits incorrect debug info
211// for std::nullptr_t. We should fix these in clang-cl.
212auto rae = &unaryret<decltype(nullptr), 29>;
213// CHECK: (std::nullptr_t (*)()) rae = {{.*}}
214auto aae = &unary<decltype(nullptr)>;
215// CHECK: (void (*)(std::nullptr_t)) aae = {{.*}}
216
217int main(int argc, char **argv) {
218 return 0;
219}
220

source code of lldb/test/Shell/SymbolFile/NativePDB/function-types-builtins.cpp