Bug 78489 - [8 Regression] Substitution failure does not happen in lexical order for NTTP declarations.
Summary: [8 Regression] Substitution failure does not happen in lexical order for NTTP...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 7.0
: P3 normal
Target Milestone: 8.0
Assignee: Jason Merrill
URL:
Keywords: rejects-valid
Depends on:
Blocks:
 
Reported: 2016-11-23 08:38 UTC by Eric Fiselier
Modified: 2018-03-23 22:05 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work: 5.5.0
Known to fail: 6.4.0, 7.3.0, 8.0.1
Last reconfirmed: 2018-03-23 00:00:00


Attachments
reproducer2.cpp (373 bytes, text/plain)
2018-03-22 22:05 UTC, Eric Fiselier
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Eric Fiselier 2016-11-23 08:38:35 UTC
When substitution failure occurs in the declaration of a NTTP GCC
will incorrectly continue to perform substitution on later template
parameters. This is incorrect since substitution should occur in
lexical order. Note that this does not occur when the substitution
happens in the declaration of a type template parameter.


Reproducer:
// g++ -std=c++1z test.cpp
template <bool Pred, class T> struct enable_if { typedef T type; };
template <class T> struct enable_if<false, T> {};

template <int Idx> struct blows_up { static_assert(Idx != Idx, ""); };

template <int Idx,
           // substitution should fail here
          typename enable_if<Idx != Idx, int>::type = 0,
          // GCC evaluates this statement
          class = typename blows_up<Idx>::type 
>
void Foo() {}

template <int Idx,
          // Substitution correctly fails here.
          class = typename enable_if<Idx != Idx, int>::type,
          class = typename blows_up<Idx>::type // OK. Not evaluated
>
constexpr void Bar() {}
// Check the constructor in as SFINAE context
template <int I> constexpr auto test(int) -> decltype((Foo<I>(), true)) { return true; }
template <int>   constexpr bool test(long) { return false; }

template <int I> constexpr auto test_bar(int) -> decltype((Bar<I>(), true)) { return true; }
template <int>   constexpr bool test_bar(long) { return false; }

static_assert(!test<3>(0), ""); // Blows up
static_assert(!test_bar<4>(0), ""); // OK.
Comment 1 Eric Fiselier 2016-11-23 08:39:14 UTC
Substitution
Comment 2 Eric Fiselier 2018-03-22 22:05:43 UTC
Created attachment 43737 [details]
reproducer2.cpp

Another reproducer: This one is a regression from 7.3
https://godbolt.org/g/UEti9f

Could somebody please take a look at this?
Comment 3 Jonathan Wakely 2018-03-23 12:01:59 UTC
GCC 5.x compiled this without error.
Comment 4 Jonathan Wakely 2018-03-23 12:10:13 UTC
This started to fail with r223301

        DR 1391
        * pt.c (type_unification_real): Check convertibility here.
        (unify_one_argument): Not here.
Comment 5 Jonathan Wakely 2018-03-23 12:22:06 UTC
(In reply to Eric Fiselier from comment #2)
> Created attachment 43737 [details]
> reproducer2.cpp
> 
> Another reproducer: This one is a regression from 7.3
> https://godbolt.org/g/UEti9f
> 
> Could somebody please take a look at this?

This one started to fail on trunk with r258039

        PR c++/84489 - dependent default template argument
    
        * pt.c (type_unification_real): Handle early substitution failure.
    
That fix has just been backported to the 6 and 7 branches, and so also fails with the tip of those branches.
Comment 6 Jason Merrill 2018-03-23 12:57:41 UTC
Author: jason
Date: Fri Mar 23 12:57:09 2018
New Revision: 258802

URL: https://gcc.gnu.org/viewcvs?rev=258802&root=gcc&view=rev
Log:
	PR c++/78489 - Substitution in wrong order

	PR c++/84489
	* pt.c (type_unification_real): Revert last two changes.

Removed:
    branches/gcc-6-branch/gcc/testsuite/g++.dg/cpp0x/alias-decl-63.C
    branches/gcc-6-branch/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg7.C
Modified:
    branches/gcc-6-branch/gcc/cp/ChangeLog
    branches/gcc-6-branch/gcc/cp/pt.c
Comment 7 Jason Merrill 2018-03-23 14:40:41 UTC
Author: jason
Date: Fri Mar 23 14:40:06 2018
New Revision: 258814

URL: https://gcc.gnu.org/viewcvs?rev=258814&root=gcc&view=rev
Log:
	PR c++/78489 - Substitution in wrong order

	PR c++/84489
	* pt.c (type_unification_real): Revert last two changes.

Added:
    branches/gcc-7-branch/gcc/testsuite/g++.dg/cpp0x/sfinae60.C
Removed:
    branches/gcc-7-branch/gcc/testsuite/g++.dg/cpp0x/alias-decl-63.C
    branches/gcc-7-branch/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg7.C
Modified:
    branches/gcc-7-branch/gcc/cp/ChangeLog
    branches/gcc-7-branch/gcc/cp/pt.c
Comment 8 Jason Merrill 2018-03-23 22:04:22 UTC
Author: jason
Date: Fri Mar 23 22:03:51 2018
New Revision: 258824

URL: https://gcc.gnu.org/viewcvs?rev=258824&root=gcc&view=rev
Log:
	PR c++/78489 - wrong SFINAE behavior.

	PR c++/84489
	* pt.c (type_unification_real): Don't defer substitution failure.

Added:
    trunk/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg4a.C
    trunk/gcc/testsuite/g++.dg/cpp0x/sfinae60.C
    trunk/gcc/testsuite/g++.dg/cpp0x/sfinae61.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/pt.c
Comment 9 Jason Merrill 2018-03-23 22:05:30 UTC
Fixed for GCC 8.