On Wed, Dec 11, 2024 at 10:19 AM Patrick Palka <ppa...@redhat.com> wrote:
>
> On Wed, 27 Nov 2024, Patrick Palka wrote:
>
> > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK
> > for trunk/14/13?
>
> Ping.

Ping.

>
> It occurred to me that another way to fix this PR might be to tweak the
> overload set pruning (for non-dependent calls) to un-specialize the
> selected function template specialization if it turned out to be dependent:
>
> diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
> index efa748c7dc8..08d05209f44 100644
> --- a/gcc/cp/semantics.cc
> +++ b/gcc/cp/semantics.cc
> @@ -3311,6 +3311,13 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, 
> bool disallow_virtual,
>             /* Our original callee wasn't wrapped in an ADDR_EXPR,
>                so strip this ADDR_EXPR added by build_over_call.  */
>             sel_fn = TREE_OPERAND (sel_fn, 0);
> +         if (TREE_CODE (sel_fn) == FUNCTION_DECL
> +             && type_dependent_expression_p (sel_fn)
> +             && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (sel_fn)))
> +           {
> +             sel_fn = ovl_make (DECL_TI_TEMPLATE (sel_fn));
> +             sel_fn = lookup_template_function (fns, ...);
> +           }
>           orig_fn = sel_fn;
>         }
>
> But IMHO this should be impossible in the first place -- if an
> unresolved overload set is deemed non-dependent then any specialization
> selected by overload resolution should be deemed non-dependent as
> well.  Or conversely if overload resolution yielded a dependent
> specialization then the unresolved overload set should be considered
> dependent.
>
> >
> > -- >8 --
> >
> > Here we end up ICEing at instantiation time for the call to
> > f<local_static> ultimately because we wrongly consider the call to be
> > non-dependent, and so we specialize f ahead of time and then get
> > confused when fully substituting this specialization.
> >
> > The call is dependent due to [temp.dep.temp]/3 and we miss that because
> > function template-id arguments aren't coerced until overload resolution,
> > and so the local static template argument lacks an implicit cast to
> > reference type that value_dependent_expression_p looks for before
> > considering dependence of the address.  Other kinds of template-ids aren't
> > affected since they're coerced ahead of time.
> >
> > So when considering dependence of a function template-id, we need to
> > conservatively consider dependence of the address of each argument (if
> > applicable).
> >
> >       PR c++/117792
> >
> > gcc/cp/ChangeLog:
> >
> >       * pt.cc (type_dependent_expression_p): Consider the dependence
> >       of the address of each template argument of a function
> >       template-id.
> >
> > gcc/testsuite/ChangeLog:
> >
> >       * g++.dg/cpp1z/nontype7.C: New test.
> > ---
> >  gcc/cp/pt.cc                          | 10 ++++++++--
> >  gcc/testsuite/g++.dg/cpp1z/nontype7.C | 22 ++++++++++++++++++++++
> >  2 files changed, 30 insertions(+), 2 deletions(-)
> >  create mode 100644 gcc/testsuite/g++.dg/cpp1z/nontype7.C
> >
> > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> > index 564e368ff43..2f2ec39b083 100644
> > --- a/gcc/cp/pt.cc
> > +++ b/gcc/cp/pt.cc
> > @@ -28864,9 +28864,15 @@ type_dependent_expression_p (tree expression)
> >
> >        if (TREE_CODE (expression) == TEMPLATE_ID_EXPR)
> >       {
> > -       if (any_dependent_template_arguments_p
> > -           (TREE_OPERAND (expression, 1)))
> > +       tree args = TREE_OPERAND (expression, 1);
> > +       if (any_dependent_template_arguments_p (args))
> >           return true;
> > +       /* Arguments of a function template-id aren't necessarily coerced
> > +          yet so we must conservatively assume that the address (and not
> > +          just value) of the argument matters as per [temp.dep.temp]/3.  */
> > +       for (tree arg : tree_vec_range (args))
> > +         if (has_value_dependent_address (arg))
> > +           return true;
> >         expression = TREE_OPERAND (expression, 0);
> >         if (identifier_p (expression))
> >           return true;
> > diff --git a/gcc/testsuite/g++.dg/cpp1z/nontype7.C 
> > b/gcc/testsuite/g++.dg/cpp1z/nontype7.C
> > new file mode 100644
> > index 00000000000..b03c643c987
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/cpp1z/nontype7.C
> > @@ -0,0 +1,22 @@
> > +// PR c++/117792
> > +// { dg-do compile { target c++17 } }
> > +
> > +template<const int& N, class T>
> > +void f(T) { }
> > +
> > +template<int, class T>
> > +void f(...) = delete;
> > +
> > +template<const int& N> int v;
> > +
> > +template<const int& N> struct A { static const int value = 0; };
> > +
> > +template<class T>
> > +void g() {
> > +  static const int local_static = 0;
> > +  auto x = v<local_static>; // OK
> > +  auto y = A<local_static>::value; // OK
> > +  f<local_static>(0); // ICE
> > +}
> > +
> > +template void g<int>();
> > --
> > 2.47.1.313.gcc01bad4a9
> >
> >

Reply via email to