Bug 93085 - ICE in get_class_binding_direct and alias_ctad_tweaks, with C++20 NTTP + CTAD + alias template
Summary: ICE in get_class_binding_direct and alias_ctad_tweaks, with C++20 NTTP + CTAD...
Status: ASSIGNED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 10.0
: P3 normal
Target Milestone: ---
Assignee: Jason Merrill
URL:
Keywords: ice-on-valid-code
Depends on:
Blocks:
 
Reported: 2019-12-28 03:04 UTC by Arthur O'Dwyer
Modified: 2021-04-14 18:59 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2020-01-21 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Arthur O'Dwyer 2019-12-28 03:04:10 UTC
// https://godbolt.org/z/KhiNKJ
template<template<class> class A>
struct G {
    template<class T> using B = A<T>;
    template<B> static int foo();
    int x = foo<42>();
};

test.cc:5:21: internal compiler error: in get_class_binding_direct, at cp/name-lookup.c:1221
    5 |     int x = foo<42>();
      |                     ^


And here's a second ICE in the same general area...

// https://godbolt.org/z/W3Fgku
template<template<class> class A>
struct G {
    template<class... T> using B = A<T...>;
    template<B> int foo();
    int x = foo<42>();
};
template<class T> struct A { constexpr A(T) {} };
G<A> g;

test.cc: In instantiation of 'constexpr G<A>::G()':
test.cc:8:6:   required from here
test.cc:5:20: internal compiler error: in alias_ctad_tweaks, at cp/pt.c:28181
    5 |     int x = foo<42>();
      |             ~~~~~~~^~

Both of these are ice-on-valid-code, as far as I'm aware (relative to the C++2a draft). Bug #91365 is related.
Comment 1 Martin Liška 2020-01-21 14:32:42 UTC
Confirmed, is it a valid code or not?
Comment 2 Johel Ernesto Guerrero Peña 2020-10-17 23:57:14 UTC
Invalid because it passes (a) type template argument(s) to a template template parameter.
Comment 3 Arthur O'Dwyer 2020-10-18 00:11:54 UTC
Re comment 2: My original test code was "invalid-code", but here's one I believe to be "valid-code" in C++20.

// https://godbolt.org/z/dqcWeq
template<template<class> class A>
struct G {
    template<class T> using B = A<T>;
    template<B> static int foo();
    template<int> static int foo();
    int x = foo<42>();  // OK
};

test.cc:7:21: internal compiler error: in get_class_binding_direct, at cp/name-lookup.c:1238
    7 |     int x = foo<42>();  // OK
      |                     ^

====
If you change the `<B>` to an `<A>`, the ICE disappears, but GCC still gives a bogus error at template-definition time:

// https://godbolt.org/z/Tjrnzv
template<template<class> class A>
struct G {
    template<class T> using B = A<T>;
    template<A> static int foo();    // #1
    template<int> static int foo();  // #2
    int x = foo<42>();  // OK
};

test.cc:7:21: error: call of overloaded 'foo()' is ambiguous
    7 |     int x = foo<42>();  // OK
      |                     ^

GCC shouldn't even be trying to resolve `foo<42>()` until `G` has been instantiated; and once `G` has been instantiated with some specific `A`, this call may or may not be ambiguous (depending on whether it's possible to deduce the template arguments to foo #1 or not).
Comment 4 Johel Ernesto Guerrero Peña 2020-10-18 00:46:46 UTC
> GCC shouldn't even be trying to resolve `foo<42>()` until `G` has been instantiated.

That's right. I came across this bug report when reporting such an issue: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97476.
Comment 5 Jason Merrill 2021-04-10 06:14:31 UTC
The ICEs are fixed, I want to address the second testcase in comment #3.
Comment 6 CVS Commits 2021-04-12 21:30:26 UTC
The master branch has been updated by Jason Merrill <jason@gcc.gnu.org>:

https://gcc.gnu.org/g:84081e2c6bd43a6790f751755865cf4227adac7c

commit r11-8137-g84081e2c6bd43a6790f751755865cf4227adac7c
Author: Jason Merrill <jason@redhat.com>
Date:   Sat Apr 10 02:10:32 2021 -0400

    c++: premature overload resolution [PR93085]
    
    We can't resolve the call to foo<42> before instantiation of G, because the
    template parameter of #1 has dependent type.  But we were missing that in
    our dependency check, because the tree walk of DECL_TEMPLATE_PARMS doesn't
    look into the types of template parameters.  So look at them directly.
    
    gcc/cp/ChangeLog:
    
            PR c++/93085
            * pt.c (uses_outer_template_parms): Handle non-type and template
            template parameters specifically.
    
    gcc/testsuite/ChangeLog:
    
            PR c++/93085
            * g++.dg/template/dependent-tmpl1.C: New test.
Comment 7 CVS Commits 2021-04-14 18:59:31 UTC
The master branch has been updated by Jason Merrill <jason@gcc.gnu.org>:

https://gcc.gnu.org/g:00a2774923c1dc5666cd26bb9b8c37b1b7dd689d

commit r11-8182-g00a2774923c1dc5666cd26bb9b8c37b1b7dd689d
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Apr 14 14:14:31 2021 -0400

    c++: premature overload resolution redux [PR100078]
    
    My patch for PR93085 didn't consider that a default template argument can
    also make a template dependent.
    
    gcc/cp/ChangeLog:
    
            PR c++/100078
            PR c++/93085
            * pt.c (uses_outer_template_parms): Also look at default
            template argument.
    
    gcc/testsuite/ChangeLog:
    
            PR c++/100078
            * g++.dg/template/dependent-tmpl2.C: New test.