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.
12 template<typename T>
13 struct MakeResult {
resultMakeResult14 static T result() {
15 return T{};
16 }
17 };
18
19 template<typename T>
20 struct MakeResult<T&> {
resultMakeResult21 static T& result() {
22 static T t;
23 return t;
24 }
25 };
26
27 template<typename T>
28 struct MakeResult<T&&> {
resultMakeResult29 static T&& result() {
30 static T t;
31 return static_cast<T&&>(t);
32 }
33 };
34
35
36 template<typename R>
nullary()37 R nullary() { return MakeResult<R>::result(); }
38
39 template<typename R, typename A, typename B>
three(A a,B b)40 R three(A a, B b) { return MakeResult<R>::result(); }
41
42 template<typename R, typename A, typename B, typename C>
four(A a,B b,C c)43 R four(A a, B b, C c) { return MakeResult<R>::result(); }
44
45 struct S {};
46 class C {};
47 union U {};
48 enum E {};
49
50 namespace A {
51 namespace B {
52 // NS::NS
53 struct S { };
54 }
55
56 struct C {
57 // NS::Struct
58 struct S {};
59 };
60 }
61
62 struct 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.
72 A::C ForceInstantiateAC;
73 B ForceInstantiateB;
74 B::A ForceInstantiateBA;
75
76 template<typename T>
77 struct TC {};
78
79 // const and volatile modifiers
80 auto a = &four<S, C*, U&, E&&>;
81 // CHECK: (S (*)(C *, U &, E &&)) a = {{.*}}
82 auto b = &four<E, const S*, const C&, const U&&>;
83 // CHECK: (E (*)(const S *, const C &, const U &&)) b = {{.*}}
84 auto c = &four<U, volatile E*, volatile S&, volatile C&&>;
85 // CHECK: (U (*)(volatile E *, volatile S &, volatile C &&)) c = {{.*}}
86 auto 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
91 auto e = &three<A::B::S*, B::A::S*, A::C::S&>;
92 // CHECK: (A::B::S *(*)(B::A::S *, A::C::S &)) e = {{.*}}
93 auto f = &three<A::C::S&, A::B::S*, B::A::S*>;
94 // CHECK: (A::C::S &(*)(A::B::S *, B::A::S *)) f = {{.*}}
95 auto 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.
99 auto 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
102 auto 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.
107 struct Incomplete;
108 auto 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
main(int argc,char ** argv)140 int main(int argc, char **argv) {
141 return 0;
142 }
143