// clang-format off // REQUIRES: lld, x86 // RUN: %clang_cl --target=x86_64-windows-msvc -Od -Z7 -c /Fo%t.obj -- %s // RUN: lld-link -debug:full -nodefaultlib -entry:main %t.obj -out:%t.exe -pdb:%t.pdb // RUN: %lldb -f %t.exe -s \ // RUN: %p/Inputs/function-types-builtins.lldbinit | FileCheck %s // Test that we can display function signatures with simple builtin // and pointer types. We do this by using `target variable` in lldb // with global variables of type ptr-to-function or reference-to-function. // This technique in general allows us to exercise most of LLDB's type // system without a running process. // Define _fltused, since we're not linking against the MS C runtime, but use // floats. extern "C" int _fltused = 0; template struct MakeResult { static T result() { return T{}; } }; template struct MakeResult { static T& result() { static T t; return t; } }; template struct MakeResult { static T&& result() { static T t; return static_cast(t); } }; void nullary() {} template void unary(Arg) { } template Ret unaryret() { return MakeResult::result(); } template void binary(A1, A2) { } int varargs(int, int, ...) { return 0; } // Make sure to test every builtin type at least once for completeness. We // test these in the globals-fundamentals.cpp when they are the types of // variables but it's possible to imagine a situation where things behave // differently as function arguments or return values than they do with // global variables. // some interesting cases with argument types. auto aa = &unary; // CHECK: (void (*)(bool)) aa = {{.*}} auto ab = &unary; // CHECK: (void (*)(char)) ab = {{.*}} auto ac = &unary; // CHECK: (void (*)(signed char)) ac = {{.*}} auto ad = &unary; // CHECK: (void (*)(unsigned char)) ad = {{.*}} auto ae = &unary; // CHECK: (void (*)(char16_t)) ae = {{.*}} auto af = &unary; // CHECK: (void (*)(char32_t)) af = {{.*}} auto ag = &unary; // CHECK: (void (*)(wchar_t)) ag = {{.*}} auto ah = &unary; // CHECK: (void (*)(short)) ah = {{.*}} auto ai = &unary; // CHECK: (void (*)(unsigned short)) ai = {{.*}} auto aj = &unary; // CHECK: (void (*)(int)) aj = {{.*}} auto ak = &unary; // CHECK: (void (*)(unsigned int)) ak = {{.*}} auto al = &unary; // CHECK: (void (*)(long)) al = {{.*}} auto am = &unary; // CHECK: (void (*)(unsigned long)) am = {{.*}} auto an = &unary; // CHECK: (void (*)(long long)) an = {{.*}} auto ao = &unary; // CHECK: (void (*)(unsigned long long)) ao = {{.*}} auto aq = &unary; // CHECK: (void (*)(float)) aq = {{.*}} auto ar = &unary; // CHECK: (void (*)(double)) ar = {{.*}} auto as = &unary; // CHECK: (void (*)(int *)) as = {{.*}} auto at = &unary; // CHECK: (void (*)(int **)) at = {{.*}} auto au = &unary; // CHECK: (void (*)(int &)) au = {{.*}} auto av = &unary; // CHECK: (void (*)(int &&)) av = {{.*}} auto aw = &unary; // CHECK: (void (*)(const int *)) aw = {{.*}} auto ax = &unary; // CHECK: (void (*)(volatile int *)) ax = {{.*}} auto ay = &unary; // CHECK: (void (*)(const volatile int *)) ay = {{.*}} auto az = &unary; // CHECK: (void (*)(void *&)) az = {{.*}} auto aaa = &unary; // CHECK: (void (*)(int (&)[5])) aaa = {{.*}} auto aab = &unary; // CHECK: (void (*)(int (*)[5])) aab = {{.*}} auto aac = &unary; // CHECK: (void (*)(int (&&)[5])) aac = {{.*}} auto aad = &unary; // CHECK: (void (*)(int (*const)[5])) aad = {{.*}} // same test cases with return values, note we can't overload on return type // so we need to use a different instantiation each time. auto ra = &unaryret; // CHECK: (bool (*)()) ra = {{.*}} auto rb = &unaryret; // CHECK: (char (*)()) rb = {{.*}} auto rc = &unaryret; // CHECK: (signed char (*)()) rc = {{.*}} auto rd = &unaryret; // CHECK: (unsigned char (*)()) rd = {{.*}} auto re = &unaryret; // CHECK: (char16_t (*)()) re = {{.*}} auto rf = &unaryret; // CHECK: (char32_t (*)()) rf = {{.*}} auto rg = &unaryret; // CHECK: (wchar_t (*)()) rg = {{.*}} auto rh = &unaryret; // CHECK: (short (*)()) rh = {{.*}} auto ri = &unaryret; // CHECK: (unsigned short (*)()) ri = {{.*}} auto rj = &unaryret; // CHECK: (int (*)()) rj = {{.*}} auto rk = &unaryret; // CHECK: (unsigned int (*)()) rk = {{.*}} auto rl = &unaryret; // CHECK: (long (*)()) rl = {{.*}} auto rm = &unaryret; // CHECK: (unsigned long (*)()) rm = {{.*}} auto rn = &unaryret; // CHECK: (long long (*)()) rn = {{.*}} auto ro = &unaryret; // CHECK: (unsigned long long (*)()) ro = {{.*}} auto rq = &unaryret; // CHECK: (float (*)()) rq = {{.*}} auto rr = &unaryret; // CHECK: (double (*)()) rr = {{.*}} auto rs = &unaryret; // CHECK: (int *(*)()) rs = {{.*}} auto rt = &unaryret; // CHECK: (int **(*)()) rt = {{.*}} auto ru = &unaryret; // CHECK: (int &(*)()) ru = {{.*}} auto rv = &unaryret; // CHECK: (int &&(*)()) rv = {{.*}} auto rw = &unaryret; // CHECK: (const int *(*)()) rw = {{.*}} auto rx = &unaryret; // CHECK: (volatile int *(*)()) rx = {{.*}} auto ry = &unaryret; // CHECK: (const volatile int *(*)()) ry = {{.*}} auto rz = &unaryret; // CHECK: (void *&(*)()) rz = {{.*}} // FIXME: This output doesn't really look correct. It should probably be // formatting this as `int(&)[5] (*)()`. auto raa = &unaryret; // CHECK: (int (&(*)())[5]) raa = {{.*}} auto rab = &unaryret; // CHECK: (int (*(*)())[5]) rab = {{.*}} auto rac = &unaryret; // CHECK: (int (&&(*)())[5]) rac = {{.*}} auto rad = &unaryret; // CHECK: (int (*const (*)())[5]) rad = {{.*}} // Function references, we only need a couple of these since most of the // interesting cases are already tested. auto &ref = unary; // CHECK: (void (&)(bool)) ref = {{.*}} (&::ref = ) auto &ref2 = unary; // CHECK: (void (&)(volatile int *)) ref2 = {{.*}} (&::ref2 = ) auto &ref3 = varargs; // CHECK: (int (&)(int, int, ...)) ref3 = {{.*}} (&::ref3 = ) // Multiple arguments, as before, just something to make sure it works. auto binp = &binary; // CHECK: (void (*)(int *, const int *)) binp = {{.*}} auto &binr = binary; // CHECK: (void (&)(int *, const int *)) binr = {{.*}} (&::binr = ) // And finally, a function with no arguments. auto null = &nullary; // CHECK: (void (*)()) null = {{.*}} // FIXME: These currently don't work because clang-cl emits incorrect debug info // for std::nullptr_t. We should fix these in clang-cl. auto rae = &unaryret; // CHECK: (std::nullptr_t (*)()) rae = {{.*}} auto aae = &unary; // CHECK: (void (*)(std::nullptr_t)) aae = {{.*}} int main(int argc, char **argv) { return 0; }