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
| // clang-format off
// REQUIRES: lld
// Test that we can display function signatures with class types.
// 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-classes.lldbinit | FileCheck %s
// This is just some unimportant helpers needed so that we can get reference and
// rvalue-reference types into return values.
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);
}
};
template<typename R>
R nullary() { return MakeResult<R>::result(); }
template<typename R, typename A, typename B>
R three(A a, B b) { return MakeResult<R>::result(); }
template<typename R, typename A, typename B, typename C>
R four(A a, B b, C c) { return MakeResult<R>::result(); }
struct S {};
class C {};
union U {};
enum E {};
namespace A {
namespace B {
// NS::NS
struct S { };
}
struct C {
// NS::Struct
struct S {};
};
}
struct B {
struct A {
// Struct::Struct
struct S {};
};
};
// clang (incorrectly) doesn't emit debug information for outer classes
// unless they are instantiated. They should also be emitted if there
// is an inner class which is instantiated.
A::C ForceInstantiateAC;
B ForceInstantiateB;
B::A ForceInstantiateBA;
template<typename T>
struct TC {};
// const and volatile modifiers
auto a = &four<S, C*, U&, E&&>;
// CHECK: (S (*)(C *, U &, E &&)) a = {{.*}}
auto b = &four<E, const S*, const C&, const U&&>;
// CHECK: (E (*)(const S *, const C &, const U &&)) b = {{.*}}
auto c = &four<U, volatile E*, volatile S&, volatile C&&>;
// CHECK: (U (*)(volatile E *, volatile S &, volatile C &&)) c = {{.*}}
auto d = &four<C, const volatile U*, const volatile E&, const volatile S&&>;
// CHECK: (C (*)(const volatile U *, const volatile E &, const volatile S &&)) d = {{.*}}
// classes nested in namespaces and inner classes
auto e = &three<A::B::S*, B::A::S*, A::C::S&>;
// CHECK: (A::B::S *(*)(B::A::S *, A::C::S &)) e = {{.*}}
auto f = &three<A::C::S&, A::B::S*, B::A::S*>;
// CHECK: (A::C::S &(*)(A::B::S *, B::A::S *)) f = {{.*}}
auto g = &three<B::A::S*, A::C::S&, A::B::S*>;
// CHECK: (B::A::S *(*)(A::C::S &, A::B::S *)) g = {{.*}}
// parameter types that are themselves template instantiations.
auto h = &four<TC<void>, TC<int>, TC<TC<int>>, TC<A::B::S>>;
// CHECK: (TC<void> (*)(TC<int>, TC<TC<int>>, TC<A::B::S>)) h = {{.*}}
auto i = &nullary<A::B::S>;
// CHECK: (A::B::S (*)()) i = {{.*}}
// Make sure we can handle types that don't have complete debug info.
struct Incomplete;
auto incomplete = &three<Incomplete*, Incomplete**, const Incomplete*>;
// CHECK: (Incomplete *(*)(Incomplete **, const Incomplete *)) incomplete = {{.*}}
// CHECK: TranslationUnitDecl {{.*}}
// CHECK: |-CXXRecordDecl {{.*}} class C
// CHECK: |-CXXRecordDecl {{.*}} union U
// CHECK: |-EnumDecl {{.*}} E
// CHECK: |-CXXRecordDecl {{.*}} struct S
// CHECK: |-VarDecl {{.*}} a 'S (*)(C *, U &, E &&)'
// CHECK: |-VarDecl {{.*}} b 'E (*)(const S *, const C &, const U &&)'
// CHECK: |-VarDecl {{.*}} c 'U (*)(volatile E *, volatile S &, volatile C &&)'
// CHECK: |-VarDecl {{.*}} d 'C (*)(const volatile U *, const volatile E &, const volatile S &&)'
// CHECK: |-CXXRecordDecl {{.*}} struct B
// CHECK: | `-CXXRecordDecl {{.*}} struct A
// CHECK: | `-CXXRecordDecl {{.*}} struct S
// CHECK: |-NamespaceDecl {{.*}} A
// CHECK: | |-CXXRecordDecl {{.*}} struct C
// CHECK: | | `-CXXRecordDecl {{.*}} struct S
// CHECK: | `-NamespaceDecl {{.*}} B
// CHECK: | `-CXXRecordDecl {{.*}} struct S
// CHECK: |-VarDecl {{.*}} e 'A::B::S *(*)(B::A::S *, A::C::S &)'
// CHECK: |-VarDecl {{.*}} f 'A::C::S &(*)(A::B::S *, B::A::S *)'
// CHECK: |-VarDecl {{.*}} g 'B::A::S *(*)(A::C::S &, A::B::S *)'
// CHECK: |-CXXRecordDecl {{.*}} struct TC<int>
// CHECK: |-CXXRecordDecl {{.*}} struct TC<TC<int>>
// CHECK: |-CXXRecordDecl {{.*}} struct TC<A::B::S>
// CHECK: |-CXXRecordDecl {{.*}} struct TC<void>
// CHECK: |-VarDecl {{.*}} h 'TC<void> (*)(TC<int>, TC<TC<int>>, TC<A::B::S>)'
// CHECK: |-VarDecl {{.*}} i 'A::B::S (*)()'
// CHECK: |-CXXRecordDecl {{.*}} struct Incomplete
// CHECK: `-VarDecl {{.*}} incomplete 'Incomplete *(*)(Incomplete **, const Incomplete *)'
int main(int argc, char **argv) {
return 0;
}
|