Created attachment 44897 [details] g++-8 SFINAE Error Test Case The following (reduced) code example uses SFINAE to discern argument types in a visitor pattern. The original bug report is here: https://github.com/tim-janik/beast/issues/72#issuecomment-432874963 It works well under clang-6 and g++-7.3. With g++-8.1.1 (and reportedly g++-8.2.1) a template substitution failure during a method presence check on std::string is promoted to an error, even though a std::false_type substitution variant exists that should be picked up instead. Not only do other compiler (versions) compile this correctly, but duplicating a seemingly unrelated static_assert in the code also "remedies" the g++-8 treatment of the failure as error, tested via -DWITHASSERT below. EXPECTED: $ g++ --version g++ (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0 $ g++ -std=gnu++14 -Wall -O2 aidavisit.cc && ./a.out visit_string: some_string="A std::string" BUGGY BEHAVIOUR: $ g++ --version g++ (GCC) 8.1.1 20180712 (Red Hat 8.1.1-5) $ g++ -std=gnu++14 -Wall -O2 aidavisit.cc && ./a.out aidavisit.cc:19:77: error: 'class std::__cxx11::basic_string<char>' has no member named '__aida_visit__' $ g++ -std=gnu++14 -Wall -O2 aidavisit.cc -DWITHASSERT && ./a.out visit_string: some_string="A std::string"
This regressed with r258824 PR c++/78489 - wrong SFINAE behavior. PR c++/84489 * pt.c (type_unification_real): Don't defer substitution failure.
GCC 8.3 has been released.
Author: jason Date: Mon Mar 25 18:27:08 2019 New Revision: 269921 URL: https://gcc.gnu.org/viewcvs?rev=269921&root=gcc&view=rev Log: PR c++/87748 - substitution failure error with decltype. This issue is similar to PR 87480; in both cases we were doing non-dependent substitution with processing_template_decl set, leading to member access expressions seeming still instantiation-dependent, and therefore decltype not being simplified to its actual type. And as in that PR, the fix is to clear processing_template_decl while substituting a default template argument. * pt.c (most_specialized_partial_spec): Clear processing_template_decl. Added: trunk/gcc/testsuite/g++.dg/cpp0x/sfinae64.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/pt.c
Fixed on trunk so far.
*** Bug 90080 has been marked as a duplicate of this bug. ***
Another reproducer from PR 90080: struct false_type { static constexpr bool value = false; }; struct true_type { static constexpr bool value = true; }; template<bool, typename = void> struct enable_if { }; template<typename T> struct enable_if<true, T> { using type = T; }; template<typename T> T&& declval(); template<typename T, typename U, typename = U> struct is_static_castable : false_type {}; template<typename T, typename U> struct is_static_castable<T, U, decltype(static_cast<U>(declval<T>()))> : true_type {}; template<typename To, typename From, typename enable_if<is_static_castable<From*, To*>::value, int>::type = 0> To* safePtrCast(From* from) { return static_cast<To*>(from); } template<typename To, typename From, typename enable_if<!is_static_castable<From*, To*>::value, int>::type = 0> To* safePtrCast(From* from) { return dynamic_cast<To*>(from); } struct BarBase{ virtual ~BarBase() = default;}; struct Bar : virtual BarBase{}; Bar* foo(BarBase* b){ return safePtrCast<Bar>(b); } 90080.cc: In instantiation of ‘struct is_static_castable<BarBase*, Bar*, Bar*>’: 90080.cc:21:57: required by substitution of ‘template<class To, class From, typename enable_if<(! is_static_castable<From*, To*>::value), int>::type <anonymous> > To* safePtrCast(From*) [with To = Bar; From = BarBase; typename enable_if<(! is_static_castable<From*, To*>::value), int>::type <anonymous> = <missing>]’ 90080.cc:31:30: required from here 90080.cc:12:42: error: cannot convert from pointer to base class ‘BarBase’ to pointer to derived class ‘Bar’ because the base is virtual 12 | struct is_static_castable<T, U, decltype(static_cast<U>(declval<T>()))> : true_type | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ 90080.cc:12:42: error: cannot convert from pointer to base class ‘BarBase’ to pointer to derived class ‘Bar’ because the base is virtual 90080.cc: In instantiation of ‘To* safePtrCast(From*) [with To = Bar; From = BarBase; typename enable_if<is_static_castable<From*, To*>::value, int>::type <anonymous> = 0]’: 90080.cc:31:30: required from here 90080.cc:18:12: error: cannot convert from pointer to base class ‘BarBase’ to pointer to derived class ‘Bar’ because the base is virtual 18 | return static_cast<To*>(from); | ^~~~~~~~~~~~~~~~~~~~~~
The releases/gcc-8 branch has been updated by Jason Merrill <jason@gcc.gnu.org>: https://gcc.gnu.org/g:ac5e28911abdfb8d9bf6bea980223e199bbcf28d commit r8-10070-gac5e28911abdfb8d9bf6bea980223e199bbcf28d Author: Jason Merrill <jason@redhat.com> Date: Tue Feb 25 21:29:03 2020 -0500 PR c++/87748 - substitution failure error with decltype. This issue is similar to PR 87480; in both cases we were doing non-dependent substitution with processing_template_decl set, leading to member access expressions seeming still instantiation-dependent, and therefore decltype not being simplified to its actual type. And as in that PR, the fix is to clear processing_template_decl while substituting a default template argument. gcc/cp/ChangeLog 2020-02-25 Jason Merrill <jason@redhat.com> PR c++/87748 - substitution failure error with decltype. * pt.c (most_specialized_partial_spec): Clear processing_template_decl.
Fixed for 8.4.