https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119736
Bug ID: 119736
Summary: rejected/ICEs when non type template parameter used as
an argument to a const ref non type template parameter
Product: gcc
Version: 15.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: waffl3x at gcc dot gnu.org
Target Milestone: ---
https://godbolt.org/z/aE7xEnzzq
```
template<int const& R> struct takes_static_ref {};
template<int Data>
struct make_static_ref {
static constexpr auto const& ref = Data;
};
using ice = takes_static_ref<make_static_ref<42>::ref>;
```
https://godbolt.org/z/EEjMj9ab4
```
template<int const& R>
void takes_static_ref_f() {}
template<int Data>
struct make_static_ref {
static constexpr auto const& ref = Data;
};
template void takes_static_ref_f<make_static_ref<42>::ref>();
```
This only triggers in C++17 and up, I am fairly certain this is valid
code but it doesn't seem like it was ever accepted in GCC, it's just
the ICE that is new.
All the cases beyond here are not regressions, but I do believe they
are all valid code.
https://godbolt.org/z/qG66n6Mse
```
template<int const& R> struct takes_static_ref {};
template<int Data>
struct make_static_ref {
using direct = takes_static_ref<Data>;
static constexpr auto const& ref = Data;
using from_member = takes_static_ref<ref>;
};
using direct = make_static_ref<42>::direct;
using from_member = make_static_ref<42>::from_member;
```
And finally these are what should be a fairly exhaustive list of cases,
the ones you would expect to work still work and are just included to
illustrate that the problematic cases are probably valid C++ code.
https://godbolt.org/z/7KabYPqTr
```
template<int const& R> struct takes_static_ref {};
template<int V> struct takes_value {};
template<int const& R>
void takes_static_ref_f() {}
template<int Data>
struct make_static_ref {
static constexpr int const& ref = Data;
};
template<int Data>
inline constexpr const auto& make_static_ref_inline = Data;
inline int my_global_var = 42;
using with_global = takes_static_ref<my_global_var>;
template void takes_static_ref_f<my_global_var>();
struct S {
inline static int my_static_member = 42;
using with_static_member = takes_static_ref<my_static_member>;
};
using with_static_member = takes_static_ref<S::my_static_member>;
template void takes_static_ref_f<S::my_static_member>();
void f()
{
static int my_static_var = 42;
takes_static_ref<my_static_var> with_local_static;
takes_static_ref_f<my_static_var>();
static constexpr auto data_0 = make_static_ref<42>::ref;
static constexpr auto data_1 = make_static_ref_inline<42>;
static constexpr auto const& data_ref_0 = make_static_ref<42>::ref;
static constexpr auto const& data_ref_1 = make_static_ref_inline<42>;
takes_value<data_ref_0> v_0;
takes_value<data_ref_1> v_1;
takes_static_ref<data_ref_0> r_0;
takes_static_ref<data_ref_1> r_1;
takes_static_ref_f<data_ref_0>();
takes_static_ref_f<data_ref_1>();
}
using sr_0 = takes_value<make_static_ref<42>::ref>;
using sr_1 = takes_value<make_static_ref_inline<42>>;
using sr_0 = takes_static_ref<make_static_ref<42>::ref>;
using sr_1 = takes_static_ref<make_static_ref_inline<42>>;
template void takes_static_ref_f<make_static_ref<42>::ref>();
template void takes_static_ref_f<make_static_ref_inline<42>>();
```