reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
  194
  195
  196
  197
  198
  199
  200
  201
  202
  203
  204
  205
  206
  207
  208
  209
  210
  211
  212
  213
  214
  215
  216
  217
  218
// clang-format off
// REQUIRES: lld

// RUN: %build --compiler=clang-cl --nodefaultlib -o %t.exe -- %s 
// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %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<typename T>
struct MakeResult {
  static T result() {
    return T{};
  }
};

template<typename T>
struct MakeResult<T&> {
  static T& result() {
    static T t;
    return t;
  }
};

template<typename T>
struct MakeResult<T&&> {
  static T&& result() {
    static T t;
    return static_cast<T&&>(t);
  }
};


void nullary() {}

template<typename Arg>
void unary(Arg) { }

template<typename Ret, int N>
Ret unaryret() { return MakeResult<Ret>::result(); }

template<typename A1, typename A2>
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<bool>;
// CHECK: (void (*)(bool)) aa = {{.*}}
auto ab = &unary<char>;
// CHECK: (void (*)(char)) ab = {{.*}}
auto ac = &unary<signed char>;
// CHECK: (void (*)(signed char)) ac = {{.*}}
auto ad = &unary<unsigned char>;
// CHECK: (void (*)(unsigned char)) ad = {{.*}}
auto ae = &unary<char16_t>;
// CHECK: (void (*)(char16_t)) ae = {{.*}}
auto af = &unary<char32_t>;
// CHECK: (void (*)(char32_t)) af = {{.*}}
auto ag = &unary<wchar_t>;
// CHECK: (void (*)(wchar_t)) ag = {{.*}}
auto ah = &unary<short>;
// CHECK: (void (*)(short)) ah = {{.*}}
auto ai = &unary<unsigned short>;
// CHECK: (void (*)(unsigned short)) ai = {{.*}}
auto aj = &unary<int>;
// CHECK: (void (*)(int)) aj = {{.*}}
auto ak = &unary<unsigned int>;
// CHECK: (void (*)(unsigned int)) ak = {{.*}}
auto al = &unary<long>;
// CHECK: (void (*)(long)) al = {{.*}}
auto am = &unary<unsigned long>;
// CHECK: (void (*)(unsigned long)) am = {{.*}}
auto an = &unary<long long>;
// CHECK: (void (*)(long long)) an = {{.*}}
auto ao = &unary<unsigned long long>;
// CHECK: (void (*)(unsigned long long)) ao = {{.*}}
auto aq = &unary<float>;
// CHECK: (void (*)(float)) aq = {{.*}}
auto ar = &unary<double>;
// CHECK: (void (*)(double)) ar = {{.*}}

auto as = &unary<int*>;
// CHECK: (void (*)(int *)) as = {{.*}}
auto at = &unary<int**>;
// CHECK: (void (*)(int **)) at = {{.*}}
auto au = &unary<int&>;
// CHECK: (void (*)(int &)) au = {{.*}}
auto av = &unary<int&&>;
// CHECK: (void (*)(int &&)) av = {{.*}}
auto aw = &unary<const int*>;
// CHECK: (void (*)(const int *)) aw = {{.*}}
auto ax = &unary<volatile int*>;
// CHECK: (void (*)(volatile int *)) ax = {{.*}}
auto ay = &unary<const volatile int*>;
// CHECK: (void (*)(const volatile int *)) ay = {{.*}}
auto az = &unary<void*&>;
// CHECK: (void (*)(void *&)) az = {{.*}}
auto aaa = &unary<int(&)[5]>;
// CHECK: (void (*)(int (&)[5])) aaa = {{.*}}
auto aab = &unary<int(*)[5]>;
// CHECK: (void (*)(int (*)[5])) aab = {{.*}}
auto aac = &unary<int(&&)[5]>;
// CHECK: (void (*)(int (&&)[5])) aac = {{.*}}
auto aad = &unary<int(*const)[5]>;
// CHECK: (void (*)(int (*)[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<bool, 0>;
// CHECK: (bool (*)()) ra = {{.*}}
auto rb = &unaryret<char, 1>;
// CHECK: (char (*)()) rb = {{.*}}
auto rc = &unaryret<signed char, 2>;
// CHECK: (signed char (*)()) rc = {{.*}}
auto rd = &unaryret<unsigned char, 3>;
// CHECK: (unsigned char (*)()) rd = {{.*}}
auto re = &unaryret<char16_t, 4>;
// CHECK: (char16_t (*)()) re = {{.*}}
auto rf = &unaryret<char32_t, 5>;
// CHECK: (char32_t (*)()) rf = {{.*}}
auto rg = &unaryret<wchar_t, 6>;
// CHECK: (wchar_t (*)()) rg = {{.*}}
auto rh = &unaryret<short, 7>;
// CHECK: (short (*)()) rh = {{.*}}
auto ri = &unaryret<unsigned short, 8>;
// CHECK: (unsigned short (*)()) ri = {{.*}}
auto rj = &unaryret<int, 9>;
// CHECK: (int (*)()) rj = {{.*}}
auto rk = &unaryret<unsigned int, 10>;
// CHECK: (unsigned int (*)()) rk = {{.*}}
auto rl = &unaryret<long, 11>;
// CHECK: (long (*)()) rl = {{.*}}
auto rm = &unaryret<unsigned long, 12>;
// CHECK: (unsigned long (*)()) rm = {{.*}}
auto rn = &unaryret<long long, 13>;
// CHECK: (long long (*)()) rn = {{.*}}
auto ro = &unaryret<unsigned long long, 14>;
// CHECK: (unsigned long long (*)()) ro = {{.*}}
auto rq = &unaryret<float, 15>;
// CHECK: (float (*)()) rq = {{.*}}
auto rr = &unaryret<double, 16>;
// CHECK: (double (*)()) rr = {{.*}}

auto rs = &unaryret<int*, 17>;
// CHECK: (int *(*)()) rs = {{.*}}
auto rt = &unaryret<int**, 18>;
// CHECK: (int **(*)()) rt = {{.*}}
auto ru = &unaryret<int&, 19>;
// CHECK: (int &(*)()) ru = {{.*}}
auto rv = &unaryret<int&&, 20>;
// CHECK: (int &&(*)()) rv = {{.*}}
auto rw = &unaryret<const int*, 21>;
// CHECK: (const int *(*)()) rw = {{.*}}
auto rx = &unaryret<volatile int*, 22>;
// CHECK: (volatile int *(*)()) rx = {{.*}}
auto ry = &unaryret<const volatile int*, 23>;
// CHECK: (const volatile int *(*)()) ry = {{.*}}
auto rz = &unaryret<void*&, 24>;
// CHECK: (void *&(*)()) rz = {{.*}}

// FIXME: This output doesn't really look correct.  It should probably be
// formatting this as `int(&)[5] (*)()`.
auto raa = &unaryret<int(&)[5], 25>;
// CHECK: (int (&(*)())[5]) raa = {{.*}}
auto rab = &unaryret<int(*)[5], 26>;
// CHECK: (int (*(*)())[5]) rab = {{.*}}
auto rac = &unaryret<int(&&)[5], 27>;
// CHECK: (int (&&(*)())[5]) rac = {{.*}}
auto rad = &unaryret<int(*const)[5], 28>;
// 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<bool>;
// CHECK: (void (&)(bool)) ref = {{.*}} (&::ref = <no summary available>)
auto &ref2 = unary<volatile int*>;
// CHECK: (void (&)(volatile int *)) ref2 = {{.*}} (&::ref2 = <no summary available>)
auto &ref3 = varargs;
// CHECK: (int (&)(int, int, ...)) ref3 = {{.*}} (&::ref3 = <no summary available>)

// Multiple arguments, as before, just something to make sure it works.
auto binp = &binary<int*, const int*>;
// CHECK: (void (*)(int *, const int *)) binp = {{.*}}
auto &binr = binary<int*, const int*>;
// CHECK: (void (&)(int *, const int *)) binr = {{.*}} (&::binr = <no summary available>)

// 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<decltype(nullptr), 29>;
// CHECK: (nullptr_t (*)()) rae = {{.*}}
auto aae = &unary<decltype(nullptr)>;
// CHECK: (void (*)(nullptr_t)) aae = {{.*}}

int main(int argc, char **argv) {
  return 0;
}