As of recent, LLVM includes the bit-size as a `DW_AT_bit_size` (and as part of `DW_AT_name`) of `_BitInt`s in DWARF. This allows us to mark `_BitInt`s as "reconstitutable" when compiling with `-gsimple-template-names`. However, before doing so we need to make sure the `DWARFTypePrinter` can reconstruct template parameter values that have `_BitInt` type. This patch adds support for printing `DW_TAG_template_value_parameter`s that have `_BitInt` type. Since `-gsimple-template-names` only omits template parameters that are `<= 64` bit wide, we don't support `_BitInt`s larger than 64 bits.
277 lines
7.3 KiB
C++
277 lines
7.3 KiB
C++
#include <cstddef>
|
|
#include <cstdint>
|
|
template <typename... Ts> struct t1 {};
|
|
template <typename... Ts> struct t2;
|
|
struct udt {};
|
|
namespace ns {
|
|
struct udt {};
|
|
namespace inner {
|
|
template <typename T> struct ttp {};
|
|
struct udt {};
|
|
} // namespace inner
|
|
template <template <typename> class T> void ttp_user() {}
|
|
enum Enumeration : int { Enumerator1, Enumerator2, Enumerator3 = 1 };
|
|
enum class EnumerationClass { Enumerator1, Enumerator2, Enumerator3 = 1 };
|
|
enum : int { AnonEnum1, AnonEnum2, AnonEnum3 = 1 };
|
|
enum EnumerationSmall : unsigned char { kNeg = 0xff };
|
|
} // namespace ns
|
|
template <typename... Ts> void f1() {
|
|
t1<Ts...> v1;
|
|
t2<Ts...> *v2;
|
|
}
|
|
template <bool b, int i> void f2() {}
|
|
template <typename T, T... A> void f3() {}
|
|
template <typename T, unsigned = 3> void f4() {}
|
|
template <typename T, bool b = false> struct t3 {};
|
|
extern template class t3<int>;
|
|
template class t3<int>;
|
|
struct outer_class {
|
|
struct inner_class {};
|
|
};
|
|
int i = 3;
|
|
template <unsigned N> struct t4 {};
|
|
namespace {
|
|
struct t5 {};
|
|
enum LocalEnum { LocalEnum1 };
|
|
} // namespace
|
|
template <typename... T1, typename T2 = int> void f5() {}
|
|
template <typename T1, typename... T2> void f6() {}
|
|
struct t6 {
|
|
template <typename T> void operator<<(int) {}
|
|
template <typename T> void operator<(int) {}
|
|
template <typename T> void operator<=(int) {}
|
|
template <typename T = int> operator t1<float> *() { return nullptr; }
|
|
template <typename T> void operator-(int) {}
|
|
template <typename T> void operator*(int) {}
|
|
template <typename T> void operator/(int) {}
|
|
template <typename T> void operator%(int) {}
|
|
template <typename T> void operator^(int) {}
|
|
template <typename T> void operator&(int) {}
|
|
template <typename T> void operator|(int) {}
|
|
template <typename T> void operator~() {}
|
|
template <typename T> void operator!() {}
|
|
template <typename T> void operator=(int) {}
|
|
template <typename T> void operator>(int) {}
|
|
template <typename T> void operator,(int) {}
|
|
template <typename T> void operator()() {}
|
|
template <typename T> void operator[](int) {}
|
|
template <typename T> void operator<=>(int) {}
|
|
template <typename T> void *operator new(std::size_t, T) {
|
|
__builtin_unreachable();
|
|
}
|
|
template <typename T> void operator delete(void *, T) {}
|
|
template <typename T> void *operator new[](std::size_t, T) {
|
|
__builtin_unreachable();
|
|
}
|
|
template <typename T> void operator delete[](void *, T) {}
|
|
template <typename T> int operator co_await() { __builtin_unreachable(); }
|
|
};
|
|
void operator"" _suff(unsigned long long) {}
|
|
template <template <typename...> class T> void f7() {}
|
|
template <template <typename...> class T, typename T2> void f8() {}
|
|
template <typename T> struct t7;
|
|
using t7i = t7<int>;
|
|
template <typename T> struct __attribute__((__preferred_name__(t7i))) t7 {};
|
|
struct t8 {
|
|
void mem();
|
|
};
|
|
namespace ns {
|
|
inline namespace inl {
|
|
template <typename T> struct t9 {};
|
|
} // namespace inl
|
|
} // namespace ns
|
|
template <typename T> void (*f9())() { return nullptr; }
|
|
struct t10 {
|
|
template <typename T = void> t10() {}
|
|
};
|
|
|
|
template <typename T> void operator_not_really() {}
|
|
|
|
template <typename T, T... A> struct t11 {};
|
|
|
|
struct t12 {
|
|
t11<LocalEnum, LocalEnum1> v1;
|
|
};
|
|
|
|
template <decltype(ns::AnonEnum1)> void f10() {}
|
|
|
|
template <typename T, T V> void f11() {}
|
|
|
|
int main() {
|
|
struct {
|
|
} A;
|
|
auto L = [] {};
|
|
f1<int>();
|
|
f1<float>();
|
|
f1<bool>();
|
|
f1<double>();
|
|
f1<long>();
|
|
f1<short>();
|
|
f1<unsigned>();
|
|
f1<unsigned long long>();
|
|
f1<long long>();
|
|
f1<udt>();
|
|
f1<ns::udt>();
|
|
f1<ns::udt *>();
|
|
f1<ns::inner::udt>();
|
|
f1<t1<int>>();
|
|
f1<int, float>();
|
|
f1<int *>();
|
|
f1<int &>();
|
|
f1<int &&>();
|
|
f1<const int>();
|
|
f1<int[3]>();
|
|
f1<void>();
|
|
f1<outer_class::inner_class>();
|
|
f1<unsigned long>();
|
|
f2<true, 3>();
|
|
f3<ns::Enumeration, ns::Enumerator3, (ns::Enumeration)2>();
|
|
f3<ns::EnumerationClass, ns::EnumerationClass::Enumerator3,
|
|
(ns::EnumerationClass)2>();
|
|
f3<ns::EnumerationSmall, ns::kNeg>();
|
|
f3<decltype(ns::AnonEnum1), ns::AnonEnum3, (decltype(ns::AnonEnum1))2>();
|
|
f3<LocalEnum, LocalEnum1>();
|
|
f3<int *, &i>();
|
|
f3<int *, nullptr>();
|
|
t4<3> v2;
|
|
f3<unsigned long, 1>();
|
|
f3<unsigned long long, 1>();
|
|
f3<long, 1>();
|
|
f3<unsigned int, 1>();
|
|
f3<short, 1>();
|
|
f3<unsigned char, (char)0>();
|
|
f3<signed char, (char)0>();
|
|
f3<unsigned short, 1, 2>();
|
|
f3<char, 0, 1, 6, 7, 13, 14, 31, 32, 33, (char)127, (char)128>();
|
|
f3<__int128, ((__int128)9223372036854775807) * 2>();
|
|
f4<unsigned int>();
|
|
f1<t3<int>>();
|
|
f1<t3<t3<int>>>();
|
|
f1<decltype(L)>();
|
|
t3<decltype(L)> v1;
|
|
f1<t3<t3<decltype(L)>>>();
|
|
f1<int(float)>();
|
|
f1<void(...)>();
|
|
f1<void(int, ...)>();
|
|
f1<const int &>();
|
|
f1<const int *&>();
|
|
f1<t5>();
|
|
f1<decltype(nullptr)>();
|
|
f1<long *, long *>();
|
|
f1<long *, udt *>();
|
|
f1<void *const>();
|
|
f1<const void *const *>();
|
|
f1<void()>();
|
|
f1<void (*)()>();
|
|
f1<decltype(&L)>();
|
|
f1<decltype(A)>();
|
|
f1<decltype(&A)>();
|
|
f5<t1<int>>();
|
|
f5<>();
|
|
f6<t1<int>>();
|
|
f1<>();
|
|
f1<const void *, const void *>();
|
|
f1<t1<int *> *>();
|
|
f1<int *[]>();
|
|
t6 v6;
|
|
v6.operator<< <int>(1);
|
|
v6.operator< <int>(1);
|
|
v6.operator<= <int>(1);
|
|
v6.operator t1<float> *();
|
|
v6.operator- <int>(3);
|
|
v6.operator* <int>(3);
|
|
v6.operator/ <int>(3);
|
|
v6.operator% <int>(3);
|
|
v6.operator^ <int>(3);
|
|
v6.operator& <int>(3);
|
|
v6.operator| <int>(3);
|
|
v6.operator~ <int>();
|
|
v6.operator! <int>();
|
|
v6.operator= <int>(3);
|
|
v6.operator><int>(3);
|
|
v6.operator, <int>(3);
|
|
v6.operator()<int>();
|
|
v6.operator[]<int>(3);
|
|
v6.operator<=> <int>(3);
|
|
t6::operator new(0, 0);
|
|
t6::operator new[](0, 0);
|
|
t6::operator delete(nullptr, 0);
|
|
t6::operator delete[](nullptr, 0);
|
|
v6.operator co_await <int>();
|
|
42_suff;
|
|
struct t7 {};
|
|
f1<t7>();
|
|
f1<int (&)[3]>();
|
|
f1<int (*)[3]>();
|
|
f7<t1>();
|
|
f8<t1, int>();
|
|
using namespace ns;
|
|
ttp_user<inner::ttp>();
|
|
f1<int *, decltype(nullptr) *>();
|
|
t7i x;
|
|
f1<t7i>();
|
|
f7<ns::inl::t9>();
|
|
f1<_Atomic(int)>();
|
|
f1<int, long, volatile char>();
|
|
f1<__attribute__((__vector_size__(sizeof(int) * 2))) int>();
|
|
f1<int *const volatile>();
|
|
f1<const volatile void>();
|
|
f1<t1<decltype(L)>>();
|
|
t10 v3;
|
|
f1<void (::udt::*)() const>();
|
|
f1<void (::udt::*)() volatile &>();
|
|
f1<void (::udt::*)() const volatile &&>();
|
|
f9<int>();
|
|
f1<void (*const)()>();
|
|
f1<char const(&)[1]>();
|
|
f1<void() const &>();
|
|
f1<void() volatile &&>();
|
|
f1<void() const volatile>();
|
|
f1<int *const[1]>();
|
|
f1<int *const(&)[1]>();
|
|
f1<void (::udt::*const &)()>();
|
|
f1<void (*(int))(float)>();
|
|
f1<t1<int>[1]>();
|
|
f1<void (*)() noexcept>();
|
|
f1<void(decltype(A))>();
|
|
struct t8 {
|
|
decltype(A) m;
|
|
};
|
|
f1<void(t8, decltype(A))>();
|
|
f1<void(t8)>();
|
|
operator_not_really<int>();
|
|
t12 v4;
|
|
f11<_BitInt(3), 2>();
|
|
f11<const unsigned _BitInt(5), 2>();
|
|
f11<_BitInt(65), 2>();
|
|
f11<const unsigned _BitInt(65), 2>();
|
|
f1<void(t1<>, t1<>)>();
|
|
f1<int t1<>::*>();
|
|
void fcc() __attribute__((swiftcall));
|
|
f1<decltype(fcc)>();
|
|
int fnrt() __attribute__((noreturn));
|
|
f1<decltype(fnrt)>();
|
|
f10<ns::AnonEnum1>();
|
|
}
|
|
void t8::mem() {
|
|
struct t7 {};
|
|
f1<t7>();
|
|
f1<decltype(&t8::mem)>();
|
|
}
|
|
namespace complex_type_units {
|
|
void external_function();
|
|
namespace {
|
|
struct internal_type;
|
|
}
|
|
template <void (*)() = external_function> struct t2;
|
|
template <typename = t2<>> class t3 {};
|
|
template <typename = internal_type, typename = t3<>> struct t4 {};
|
|
struct t5 {
|
|
t4<> v1;
|
|
};
|
|
void f1() {
|
|
t5 v1;
|
|
t3<> v2;
|
|
}
|
|
} // namespace complex_type_units
|