On 8/27/25 5:22 AM, Jakub Jelinek wrote:
On Tue, Aug 26, 2025 at 12:26:17AM +0200, Jakub Jelinek wrote:
Unfortunately that version (unlike the previous one) regresses:
...
UNRESOLVED: std/ranges/access/rend.cc  -std=gnu++26 compilation failed to 
produce executable

Will try to investigate what's going on tomorrow^H^H^Htoday.

Took a while to reduce, -std=c++2{0,3,6}:

template <typename T>
struct remove_reference { using type = __remove_reference (T); };
template <typename> bool A;
template <typename T> constexpr bool A<T &> = true;
template <typename T> void foo (typename remove_reference <T>::type);
template <typename T, typename U>
concept B = requires (T x, U) { x; };
template <typename T, typename U>
concept C = B<T, U>;
template <typename T>
concept D = A<T>;
struct E {};
template <typename T>
concept F = requires (T &x) { { 0 } -> C<decltype (E {} (foo<T> (x)))>; };
template <typename T>
concept G = requires(T &x) { { x } -> C<decltype (E {} (foo<T> (x)))>; };
struct H {
   template <D T>
   void operator () (T &&) { if (F<T>) if (G<T>) ; }
} h;
struct I {};

void
bar ()
{
   I r;
   h (r);
}

When current_function_decl is the H::operator (), the PARM_DECL x
from concept F = requires (T &x) has NULL DECL_CONTEXT for which
uses_template_parms returns false, so with:
+             /* Parameters of non-templates map to themselves (e.g. in
+                expansion statement body).  */
+             if (!uses_template_parms (DECL_CONTEXT (t)))
+               RETURN (t);
+
we return t rather than doing what we were before:
               /* This can happen for a parameter name used later in a function
                  declaration (such as in a late-specified return type).  Just
                  make a dummy decl, since it's only used for its type.  */
               gcc_assert (cp_unevaluated_operand);
               r = tsubst_decl (t, args, complain);
               /* Give it the template pattern as its context; its true context
                  hasn't been instantiated yet and this is good enough for
                  mangling.  */
               DECL_CONTEXT (r) = DECL_CONTEXT (t);
Now, in expansion stmt bodies we can have unevaluated operands, so doing
              if (cp_unevaluated_oeprand)
                {
                  r = tsubst_decl (t, args, complain);
                  DECL_CONTEXT (r) = DECL_CONTEXT (t);
                }
              else if (!uses_template_parms (DECL_CONTEXT (t)))
                RETURN (t);
              else
                gcc_unreachable ();
would be wrong.  Guess
              if (DECL_CONTEXT (t)
                  && !uses_template_parms (DECL_CONTEXT (t)))
                RETURN (t);
would fix these ICEs, shall I go with that

Sounds good.

, or the original expansion stmt
body check, or something else?

        Jakub


Reply via email to