xref: /llvm-project/lldb/test/Shell/SymbolFile/NativePDB/function-types-classes.cpp (revision cf3464bbb796d492bcd4e764ada945304e0c874f)
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: %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 {
14   static T result() {
15     return T{};
16   }
17 };
18 
19 template<typename T>
20 struct MakeResult<T&> {
21   static T& result() {
22     static T t;
23     return t;
24   }
25 };
26 
27 template<typename T>
28 struct MakeResult<T&&> {
29   static T&& result() {
30     static T t;
31     return static_cast<T&&>(t);
32   }
33 };
34 
35 
36 template<typename R>
37 R nullary() { return MakeResult<R>::result(); }
38 
39 template<typename R, typename A, typename B>
40 R three(A a, B b) { return MakeResult<R>::result(); }
41 
42 template<typename R, typename A, typename B, typename 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 
140 int main(int argc, char **argv) {
141   return 0;
142 }
143