Skip to content

Commit f57d0e2

Browse files
committed
DWARF Simplified Template Names: Narrow down the handling for operator overloads
Actually we can, for now, remove the explicit "operator" handling entirely - since clang currently won't try to flag any of these as rebuildable. That seems like a reasonable state for now, but it could be narrowed down to only apply to conversion operators, most likely - but would need more nuance for op> and op>> since they would be incorrectly flagged as already having their template arguments (due to the trailing '>').
1 parent d24a0e8 commit f57d0e2

File tree

3 files changed

+12080
-14
lines changed

3 files changed

+12080
-14
lines changed

cross-project-tests/debuginfo-tests/clang_llvm_roundtrip/simplified_template_names.cpp

Lines changed: 93 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
// RUN: %clang %target_itanium_abi_host_triple %s -c -o - -g -Xclang -gsimple-template-names=mangled -Xclang -debug-forward-template-params \
1+
// RUN: %clang %target_itanium_abi_host_triple %s -c -o - -g -Xclang -gsimple-template-names=mangled -Xclang -debug-forward-template-params -std=c++20 \
22
// RUN: | llvm-dwarfdump --verify -
3+
#include <cstdint>
34
template<typename ...Ts>
45
struct t1 {
56
};
@@ -67,7 +68,70 @@ struct t6 {
6768
operator t1<float>*() {
6869
return nullptr;
6970
}
71+
template<typename T>
72+
void operator-(int) {
73+
}
74+
template<typename T>
75+
void operator*(int) {
76+
}
77+
template<typename T>
78+
void operator/(int) {
79+
}
80+
template<typename T>
81+
void operator%(int) {
82+
}
83+
template<typename T>
84+
void operator^(int) {
85+
}
86+
template<typename T>
87+
void operator&(int) {
88+
}
89+
template<typename T>
90+
void operator|(int) {
91+
}
92+
template<typename T>
93+
void operator~() {
94+
}
95+
template<typename T>
96+
void operator!() {
97+
}
98+
template<typename T>
99+
void operator=(int) {
100+
}
101+
template<typename T>
102+
void operator>(int) {
103+
}
104+
template<typename T>
105+
void operator,(int) {
106+
}
107+
template<typename T>
108+
void operator()() {
109+
}
110+
template<typename T>
111+
void operator[](int) {
112+
}
113+
template<typename T>
114+
void operator<=>(int) {
115+
}
116+
template<typename T>
117+
void* operator new(std::size_t, T) {
118+
__builtin_unreachable();
119+
}
120+
template<typename T>
121+
void operator delete(void*, T) {
122+
}
123+
template<typename T>
124+
void* operator new[](std::size_t, T) {
125+
__builtin_unreachable();
126+
}
127+
template<typename T>
128+
void operator delete[](void*, T) {
129+
}
130+
template<typename T>
131+
int operator co_await() { __builtin_unreachable(); }
132+
70133
};
134+
void operator"" _suff(unsigned long long) {}
71135
template<template<typename...> class T> void f7() { }
72136
template<template<typename...> class T, typename T2> void f8() { }
73137
template<typename T>
@@ -94,6 +158,11 @@ struct t10 {
94158
template<typename T = void>
95159
t10() { }
96160
};
161+
162+
template<typename T>
163+
void operator_not_really() {
164+
}
165+
97166
int main() {
98167
struct { } A;
99168
auto L = []{};
@@ -127,7 +196,7 @@ int main() {
127196
f3<decltype(ns::AnonEnum1), ns::AnonEnum3, (decltype(ns::AnonEnum1))2>();
128197
f3<int*, &i>();
129198
f3<int*, nullptr>();
130-
// t4<3> v2;
199+
t4<3> v2;
131200
f3<unsigned long, 1>();
132201
f3<unsigned long long, 1>();
133202
f3<long, 1>();
@@ -169,6 +238,27 @@ int main() {
169238
v6.operator< <int>(1);
170239
v6.operator<= <int>(1);
171240
v6.operator t1<float>*();
241+
v6.operator- <int>(3);
242+
v6.operator* <int>(3);
243+
v6.operator/ <int>(3);
244+
v6.operator% <int>(3);
245+
v6.operator^ <int>(3);
246+
v6.operator& <int>(3);
247+
v6.operator| <int>(3);
248+
v6.operator~ <int>();
249+
v6.operator! <int>();
250+
v6.operator= <int>(3);
251+
v6.operator> <int>(3);
252+
v6.operator, <int>(3);
253+
v6.operator() <int>();
254+
v6.operator[] <int>(3);
255+
v6.operator<=> <int>(3);
256+
t6::operator new(0, 0);
257+
t6::operator new[](0, 0);
258+
t6::operator delete(nullptr, 0);
259+
t6::operator delete[](nullptr, 0);
260+
v6.operator co_await<int>();
261+
42_suff;
172262
struct t7 { };
173263
f1<t7>();
174264
f1<int(&)[3]>();
@@ -207,6 +297,7 @@ int main() {
207297
struct t8 { decltype(A) m; };
208298
f1<void(t8, decltype(A))>();
209299
f1<void(t8)>();
300+
operator_not_really<int>();
210301
}
211302
void t8::mem() {
212303
struct t7 { };

llvm/lib/DebugInfo/DWARF/DWARFDie.cpp

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -305,18 +305,19 @@ struct DWARFTypePrinter {
305305
} else
306306
EndedWithTemplate = Name.endswith(">");
307307
OS << Name;
308-
// FIXME: This needs to be a bit more narrow, it would fail to
309-
// reconstitute a non-operator overload that is a template, like
310-
// "operator_thing<int>"
311-
if (!Name.endswith(">") && !Name.startswith("operator")) {
312-
if (appendTemplateParameters(D)) {
313-
if (EndedWithTemplate)
314-
OS << ' ';
315-
OS << '>';
316-
EndedWithTemplate = true;
317-
Word = true;
318-
}
319-
}
308+
// This check would be insufficient for operator overloads like
309+
// "operator>>" - but for now Clang doesn't try to simplify them, so this
310+
// is OK. Add more nuanced operator overload handling here if/when needed.
311+
if (Name.endswith(">"))
312+
break;
313+
if (!appendTemplateParameters(D))
314+
break;
315+
316+
if (EndedWithTemplate)
317+
OS << ' ';
318+
OS << '>';
319+
EndedWithTemplate = true;
320+
Word = true;
320321
break;
321322
}
322323
}

0 commit comments

Comments
 (0)