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>>(); ```