Skip to content

Commit 8f91d9f

Browse files
authored
[cross-project-tests][DebugInfo] Make simplified-template-names test runnable on Darwin (#168725)
The test was failing on Darwin for two reasons: 1. `-fdebug-type-sections` is not a recognized flag on Darwin 2. We fail to reconstitute a name if the template parameter has a type that has a preferred_name. With LLDB tuning the type of such a parameter is a typedef, i.e., the preferred name. Without tuning it would be the canonical type that the typedef (possibly through a chain of typedefs) points to. This patch addresses (1) by splitting the `-fdebug-type-sections` tests into a separate file (and only mark that one `UNSUPPORTED`). Which means we can at least XFAIL the non-type-sections tests on Darwin. To fix (2) we might need to make the `DWARFTypePrinter` aware of non-canonical `DW_AT_type`s of template parameters.
1 parent e6fc654 commit 8f91d9f

File tree

4 files changed

+287
-360
lines changed

4 files changed

+287
-360
lines changed
Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
#include <cstddef>
2+
#include <cstdint>
3+
template <typename... Ts> struct t1 {};
4+
template <typename... Ts> struct t2;
5+
struct udt {};
6+
namespace ns {
7+
struct udt {};
8+
namespace inner {
9+
template <typename T> struct ttp {};
10+
struct udt {};
11+
} // namespace inner
12+
template <template <typename> class T> void ttp_user() {}
13+
enum Enumeration : int { Enumerator1, Enumerator2, Enumerator3 = 1 };
14+
enum class EnumerationClass { Enumerator1, Enumerator2, Enumerator3 = 1 };
15+
enum : int { AnonEnum1, AnonEnum2, AnonEnum3 = 1 };
16+
enum EnumerationSmall : unsigned char { kNeg = 0xff };
17+
} // namespace ns
18+
template <typename... Ts> void f1() {
19+
t1<Ts...> v1;
20+
t2<Ts...> *v2;
21+
}
22+
template <bool b, int i> void f2() {}
23+
template <typename T, T... A> void f3() {}
24+
template <typename T, unsigned = 3> void f4() {}
25+
template <typename T, bool b = false> struct t3 {};
26+
extern template class t3<int>;
27+
template class t3<int>;
28+
struct outer_class {
29+
struct inner_class {};
30+
};
31+
int i = 3;
32+
template <unsigned N> struct t4 {};
33+
namespace {
34+
struct t5 {};
35+
enum LocalEnum { LocalEnum1 };
36+
} // namespace
37+
template <typename... T1, typename T2 = int> void f5() {}
38+
template <typename T1, typename... T2> void f6() {}
39+
struct t6 {
40+
template <typename T> void operator<<(int) {}
41+
template <typename T> void operator<(int) {}
42+
template <typename T> void operator<=(int) {}
43+
template <typename T = int> operator t1<float> *() { return nullptr; }
44+
template <typename T> void operator-(int) {}
45+
template <typename T> void operator*(int) {}
46+
template <typename T> void operator/(int) {}
47+
template <typename T> void operator%(int) {}
48+
template <typename T> void operator^(int) {}
49+
template <typename T> void operator&(int) {}
50+
template <typename T> void operator|(int) {}
51+
template <typename T> void operator~() {}
52+
template <typename T> void operator!() {}
53+
template <typename T> void operator=(int) {}
54+
template <typename T> void operator>(int) {}
55+
template <typename T> void operator,(int) {}
56+
template <typename T> void operator()() {}
57+
template <typename T> void operator[](int) {}
58+
template <typename T> void operator<=>(int) {}
59+
template <typename T> void *operator new(std::size_t, T) {
60+
__builtin_unreachable();
61+
}
62+
template <typename T> void operator delete(void *, T) {}
63+
template <typename T> void *operator new[](std::size_t, T) {
64+
__builtin_unreachable();
65+
}
66+
template <typename T> void operator delete[](void *, T) {}
67+
template <typename T> int operator co_await() { __builtin_unreachable(); }
68+
};
69+
void operator"" _suff(unsigned long long) {}
70+
template <template <typename...> class T> void f7() {}
71+
template <template <typename...> class T, typename T2> void f8() {}
72+
template <typename T> struct t7;
73+
using t7i = t7<int>;
74+
template <typename T> struct __attribute__((__preferred_name__(t7i))) t7 {};
75+
struct t8 {
76+
void mem();
77+
};
78+
namespace ns {
79+
inline namespace inl {
80+
template <typename T> struct t9 {};
81+
} // namespace inl
82+
} // namespace ns
83+
template <typename T> void (*f9())() { return nullptr; }
84+
struct t10 {
85+
template <typename T = void> t10() {}
86+
};
87+
88+
template <typename T> void operator_not_really() {}
89+
90+
template <typename T, T... A> struct t11 {};
91+
92+
struct t12 {
93+
t11<LocalEnum, LocalEnum1> v1;
94+
};
95+
96+
template <decltype(ns::AnonEnum1)> void f10() {}
97+
98+
int main() {
99+
struct {
100+
} A;
101+
auto L = [] {};
102+
f1<int>();
103+
f1<float>();
104+
f1<bool>();
105+
f1<double>();
106+
f1<long>();
107+
f1<short>();
108+
f1<unsigned>();
109+
f1<unsigned long long>();
110+
f1<long long>();
111+
f1<udt>();
112+
f1<ns::udt>();
113+
f1<ns::udt *>();
114+
f1<ns::inner::udt>();
115+
f1<t1<int>>();
116+
f1<int, float>();
117+
f1<int *>();
118+
f1<int &>();
119+
f1<int &&>();
120+
f1<const int>();
121+
f1<int[3]>();
122+
f1<void>();
123+
f1<outer_class::inner_class>();
124+
f1<unsigned long>();
125+
f2<true, 3>();
126+
f3<ns::Enumeration, ns::Enumerator3, (ns::Enumeration)2>();
127+
f3<ns::EnumerationClass, ns::EnumerationClass::Enumerator3,
128+
(ns::EnumerationClass)2>();
129+
f3<ns::EnumerationSmall, ns::kNeg>();
130+
f3<decltype(ns::AnonEnum1), ns::AnonEnum3, (decltype(ns::AnonEnum1))2>();
131+
f3<LocalEnum, LocalEnum1>();
132+
f3<int *, &i>();
133+
f3<int *, nullptr>();
134+
t4<3> v2;
135+
f3<unsigned long, 1>();
136+
f3<unsigned long long, 1>();
137+
f3<long, 1>();
138+
f3<unsigned int, 1>();
139+
f3<short, 1>();
140+
f3<unsigned char, (char)0>();
141+
f3<signed char, (char)0>();
142+
f3<unsigned short, 1, 2>();
143+
f3<char, 0, 1, 6, 7, 13, 14, 31, 32, 33, (char)127, (char)128>();
144+
f3<__int128, ((__int128)9223372036854775807) * 2>();
145+
f4<unsigned int>();
146+
f1<t3<int>>();
147+
f1<t3<t3<int>>>();
148+
f1<decltype(L)>();
149+
t3<decltype(L)> v1;
150+
f1<t3<t3<decltype(L)>>>();
151+
f1<int(float)>();
152+
f1<void(...)>();
153+
f1<void(int, ...)>();
154+
f1<const int &>();
155+
f1<const int *&>();
156+
f1<t5>();
157+
f1<decltype(nullptr)>();
158+
f1<long *, long *>();
159+
f1<long *, udt *>();
160+
f1<void *const>();
161+
f1<const void *const *>();
162+
f1<void()>();
163+
f1<void (*)()>();
164+
f1<decltype(&L)>();
165+
f1<decltype(A)>();
166+
f1<decltype(&A)>();
167+
f5<t1<int>>();
168+
f5<>();
169+
f6<t1<int>>();
170+
f1<>();
171+
f1<const void *, const void *>();
172+
f1<t1<int *> *>();
173+
f1<int *[]>();
174+
t6 v6;
175+
v6.operator<< <int>(1);
176+
v6.operator< <int>(1);
177+
v6.operator<= <int>(1);
178+
v6.operator t1<float> *();
179+
v6.operator- <int>(3);
180+
v6.operator* <int>(3);
181+
v6.operator/ <int>(3);
182+
v6.operator% <int>(3);
183+
v6.operator^ <int>(3);
184+
v6.operator& <int>(3);
185+
v6.operator| <int>(3);
186+
v6.operator~ <int>();
187+
v6.operator! <int>();
188+
v6.operator= <int>(3);
189+
v6.operator><int>(3);
190+
v6.operator, <int>(3);
191+
v6.operator()<int>();
192+
v6.operator[]<int>(3);
193+
v6.operator<=> <int>(3);
194+
t6::operator new(0, 0);
195+
t6::operator new[](0, 0);
196+
t6::operator delete(nullptr, 0);
197+
t6::operator delete[](nullptr, 0);
198+
v6.operator co_await <int>();
199+
42_suff;
200+
struct t7 {};
201+
f1<t7>();
202+
f1<int (&)[3]>();
203+
f1<int (*)[3]>();
204+
f7<t1>();
205+
f8<t1, int>();
206+
using namespace ns;
207+
ttp_user<inner::ttp>();
208+
f1<int *, decltype(nullptr) *>();
209+
t7i x;
210+
f1<t7i>();
211+
f7<ns::inl::t9>();
212+
f1<_Atomic(int)>();
213+
f1<int, long, volatile char>();
214+
f1<__attribute__((__vector_size__(sizeof(int) * 2))) int>();
215+
f1<int *const volatile>();
216+
f1<const volatile void>();
217+
f1<t1<decltype(L)>>();
218+
t10 v3;
219+
f1<void (::udt::*)() const>();
220+
f1<void (::udt::*)() volatile &>();
221+
f1<void (::udt::*)() const volatile &&>();
222+
f9<int>();
223+
f1<void (*const)()>();
224+
f1<char const(&)[1]>();
225+
f1<void() const &>();
226+
f1<void() volatile &&>();
227+
f1<void() const volatile>();
228+
f1<int *const[1]>();
229+
f1<int *const(&)[1]>();
230+
f1<void (::udt::*const &)()>();
231+
f1<void (*(int))(float)>();
232+
f1<t1<int>[1]>();
233+
f1<void (*)() noexcept>();
234+
f1<void(decltype(A))>();
235+
struct t8 {
236+
decltype(A) m;
237+
};
238+
f1<void(t8, decltype(A))>();
239+
f1<void(t8)>();
240+
operator_not_really<int>();
241+
t12 v4;
242+
f1<_BitInt(3)>();
243+
f1<const unsigned _BitInt(5)>();
244+
f1<void(t1<>, t1<>)>();
245+
f1<int t1<>::*>();
246+
void fcc() __attribute__((swiftcall));
247+
f1<decltype(fcc)>();
248+
int fnrt() __attribute__((noreturn));
249+
f1<decltype(fnrt)>();
250+
f10<ns::AnonEnum1>();
251+
}
252+
void t8::mem() {
253+
struct t7 {};
254+
f1<t7>();
255+
f1<decltype(&t8::mem)>();
256+
}
257+
namespace complex_type_units {
258+
void external_function();
259+
namespace {
260+
struct internal_type;
261+
}
262+
template <void (*)() = external_function> struct t2;
263+
template <typename = t2<>> class t3 {};
264+
template <typename = internal_type, typename = t3<>> struct t4 {};
265+
struct t5 {
266+
t4<> v1;
267+
};
268+
void f1() {
269+
t5 v1;
270+
t3<> v2;
271+
}
272+
} // namespace complex_type_units
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// debug-types are not available for MachO.
2+
//
3+
// UNSUPPORTED: system-darwin
4+
//
5+
// RUN: %clang %target_itanium_abi_host_triple %p/Inputs/simplified_template_names.cpp -c -o - -gdwarf-4 -Xclang -gsimple-template-names=mangled -Xclang -debug-forward-template-params -std=c++20 -fdebug-types-section \
6+
// RUN: | llvm-dwarfdump --verify -
7+
//
8+
// RUN: %clang %target_itanium_abi_host_triple %p/Inputs/simplified_template_names.cpp -c -o - -gdwarf-5 -Xclang -gsimple-template-names=mangled -Xclang -debug-forward-template-params -std=c++20 -fdebug-types-section \
9+
// RUN: | llvm-dwarfdump --verify -

0 commit comments

Comments
 (0)