1// clang-format off
2// REQUIRES: lld, x86
3
4// Test that we can display function signatures with class types.
5// RUN: %clang_cl --target=x86_64-windows-msvc -Od -Z7 -c /Fo%t.obj -- %s
6// RUN: lld-link -debug:full -nodefaultlib -entry:main %t.obj -out:%t.exe -pdb:%t.pdb
7// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
8// RUN: %p/Inputs/function-types-classes.lldbinit | FileCheck %s
9
10// This is just some unimportant helpers needed so that we can get reference and
11// rvalue-reference types into return values.
12template<typename T>
13struct MakeResult {
14 static T result() {
15 return T{};
16 }
17};
18
19template<typename T>
20struct MakeResult<T&> {
21 static T& result() {
22 static T t;
23 return t;
24 }
25};
26
27template<typename T>
28struct MakeResult<T&&> {
29 static T&& result() {
30 static T t;
31 return static_cast<T&&>(t);
32 }
33};
34
35
36template<typename R>
37R nullary() { return MakeResult<R>::result(); }
38
39template<typename R, typename A, typename B>
40R three(A a, B b) { return MakeResult<R>::result(); }
41
42template<typename R, typename A, typename B, typename C>
43R four(A a, B b, C c) { return MakeResult<R>::result(); }
44
45struct S {};
46class C {};
47union U {};
48enum E {};
49
50namespace A {
51 namespace B {
52 // NS::NS
53 struct S { };
54 }
55
56 struct C {
57 // NS::Struct
58 struct S {};
59 };
60}
61
62struct B {
63 struct A {
64 // Struct::Struct
65 struct S {};
66 };
67};
68
69// clang (incorrectly) doesn't emit debug information for outer classes
70// unless they are instantiated. They should also be emitted if there
71// is an inner class which is instantiated.
72A::C ForceInstantiateAC;
73B ForceInstantiateB;
74B::A ForceInstantiateBA;
75
76template<typename T>
77struct TC {};
78
79// const and volatile modifiers
80auto a = &four<S, C*, U&, E&&>;
81// CHECK: (S (*)(C *, U &, E &&)) a = {{.*}}
82auto b = &four<E, const S*, const C&, const U&&>;
83// CHECK: (E (*)(const S *, const C &, const U &&)) b = {{.*}}
84auto c = &four<U, volatile E*, volatile S&, volatile C&&>;
85// CHECK: (U (*)(volatile E *, volatile S &, volatile C &&)) c = {{.*}}
86auto d = &four<C, const volatile U*, const volatile E&, const volatile S&&>;
87// CHECK: (C (*)(const volatile U *, const volatile E &, const volatile S &&)) d = {{.*}}
88
89// classes nested in namespaces and inner classes
90
91auto e = &three<A::B::S*, B::A::S*, A::C::S&>;
92// CHECK: (A::B::S *(*)(B::A::S *, A::C::S &)) e = {{.*}}
93auto f = &three<A::C::S&, A::B::S*, B::A::S*>;
94// CHECK: (A::C::S &(*)(A::B::S *, B::A::S *)) f = {{.*}}
95auto g = &three<B::A::S*, A::C::S&, A::B::S*>;
96// CHECK: (B::A::S *(*)(A::C::S &, A::B::S *)) g = {{.*}}
97
98// parameter types that are themselves template instantiations.
99auto h = &four<TC<void>, TC<int>, TC<TC<int>>, TC<A::B::S>>;
100// CHECK: (TC<void> (*)(TC<int>, TC<TC<int>>, TC<A::B::S>)) h = {{.*}}
101
102auto i = &nullary<A::B::S>;
103// CHECK: (A::B::S (*)()) i = {{.*}}
104
105
106// Make sure we can handle types that don't have complete debug info.
107struct Incomplete;
108auto incomplete = &three<Incomplete*, Incomplete**, const Incomplete*>;
109// CHECK: (Incomplete *(*)(Incomplete **, const Incomplete *)) incomplete = {{.*}}
110
111// CHECK: TranslationUnitDecl {{.*}}
112// CHECK: |-CXXRecordDecl {{.*}} class C
113// CHECK: |-CXXRecordDecl {{.*}} union U
114// CHECK: |-EnumDecl {{.*}} E
115// CHECK: |-CXXRecordDecl {{.*}} struct S
116// CHECK: |-VarDecl {{.*}} a 'S (*)(C *, U &, E &&)'
117// CHECK: |-VarDecl {{.*}} b 'E (*)(const S *, const C &, const U &&)'
118// CHECK: |-VarDecl {{.*}} c 'U (*)(volatile E *, volatile S &, volatile C &&)'
119// CHECK: |-VarDecl {{.*}} d 'C (*)(const volatile U *, const volatile E &, const volatile S &&)'
120// CHECK: |-CXXRecordDecl {{.*}} struct B
121// CHECK: | `-CXXRecordDecl {{.*}} struct A
122// CHECK: | `-CXXRecordDecl {{.*}} struct S
123// CHECK: |-NamespaceDecl {{.*}} A
124// CHECK: | |-CXXRecordDecl {{.*}} struct C
125// CHECK: | | `-CXXRecordDecl {{.*}} struct S
126// CHECK: | `-NamespaceDecl {{.*}} B
127// CHECK: | `-CXXRecordDecl {{.*}} struct S
128// CHECK: |-VarDecl {{.*}} e 'A::B::S *(*)(B::A::S *, A::C::S &)'
129// CHECK: |-VarDecl {{.*}} f 'A::C::S &(*)(A::B::S *, B::A::S *)'
130// CHECK: |-VarDecl {{.*}} g 'B::A::S *(*)(A::C::S &, A::B::S *)'
131// CHECK: |-CXXRecordDecl {{.*}} struct TC<int>
132// CHECK: |-CXXRecordDecl {{.*}} struct TC<TC<int>>
133// CHECK: |-CXXRecordDecl {{.*}} struct TC<A::B::S>
134// CHECK: |-CXXRecordDecl {{.*}} struct TC<void>
135// CHECK: |-VarDecl {{.*}} h 'TC<void> (*)(TC<int>, TC<TC<int>>, TC<A::B::S>)'
136// CHECK: |-VarDecl {{.*}} i 'A::B::S (*)()'
137// CHECK: |-CXXRecordDecl {{.*}} struct Incomplete
138// CHECK: `-VarDecl {{.*}} incomplete 'Incomplete *(*)(Incomplete **, const Incomplete *)'
139
140int main(int argc, char **argv) {
141 return 0;
142}
143

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