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.
Substitution
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?
GCC 5.x compiled this without error.
This started to fail with r223301 DR 1391 * pt.c (type_unification_real): Check convertibility here. (unify_one_argument): Not here.
(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.
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
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
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
Fixed for GCC 8.