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

Reply via email to