We were complaining about a function with deduced return type in C++11 mode, but leaving it alone and then assuming it couldn't have happened later. Fixed by removing that assumption.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit 94709718a2b25596677385adbf8a298c621ff8d0 Author: Jason Merrill <ja...@redhat.com> Date: Fri Feb 10 15:40:21 2017 -0500 PR c++/77790 - ICE with auto function in C++11 mode * decl.c (undeduced_auto_decl): Remove C++14 limitation. (require_deduced_type): Add complain parm, return bool. * cp-tree.h: Adjust. * decl2.c (mark_used): Use require_deduced_type. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index a410926..0146332 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5909,7 +5909,7 @@ extern tree reshape_init (tree, tree, tsubst_flags_t); extern tree next_initializable_field (tree); extern tree fndecl_declared_return_type (tree); extern bool undeduced_auto_decl (tree); -extern void require_deduced_type (tree); +extern bool require_deduced_type (tree, tsubst_flags_t = tf_warning_or_error); extern tree finish_case_label (location_t, tree, tree); extern tree cxx_maybe_build_cleanup (tree, tsubst_flags_t); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 734a6c7..2292a3a 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -16138,24 +16138,29 @@ fndecl_declared_return_type (tree fn) return TREE_TYPE (TREE_TYPE (fn)); } -/* Returns true iff DECL was declared with an auto return type and it has +/* Returns true iff DECL was declared with an auto type and it has not yet been deduced to a real type. */ bool undeduced_auto_decl (tree decl) { - if (cxx_dialect < cxx14) + if (cxx_dialect < cxx11) return false; return type_uses_auto (TREE_TYPE (decl)); } /* Complain if DECL has an undeduced return type. */ -void -require_deduced_type (tree decl) +bool +require_deduced_type (tree decl, tsubst_flags_t complain) { if (undeduced_auto_decl (decl)) - error ("use of %qD before deduction of %<auto%>", decl); + { + if (complain & tf_error) + error ("use of %qD before deduction of %<auto%>", decl); + return false; + } + return true; } #include "gt-cp-decl.h" diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index cecb6a1..efc0b0e 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -5084,12 +5084,9 @@ mark_used (tree decl, tsubst_flags_t complain) || DECL_LANG_SPECIFIC (decl) == NULL || DECL_THUNK_P (decl)) { - if (!processing_template_decl && type_uses_auto (TREE_TYPE (decl))) - { - if (complain & tf_error) - error ("use of %qD before deduction of %<auto%>", decl); - return false; - } + if (!processing_template_decl + && !require_deduced_type (decl, complain)) + return false; return true; } @@ -5117,12 +5114,8 @@ mark_used (tree decl, tsubst_flags_t complain) && uses_template_parms (DECL_TI_ARGS (decl))) return true; - if (undeduced_auto_decl (decl)) - { - if (complain & tf_error) - error ("use of %qD before deduction of %<auto%>", decl); - return false; - } + if (!require_deduced_type (decl, complain)) + return false; /* If we don't need a value, then we don't need to synthesize DECL. */ if (cp_unevaluated_operand || in_discarded_stmt) diff --git a/gcc/testsuite/g++.dg/cpp0x/auto41.C b/gcc/testsuite/g++.dg/cpp0x/auto41.C index b1551e2..a1065af 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto41.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto41.C @@ -2,4 +2,4 @@ // { dg-do compile { target c++11 } } auto foo(); // { dg-error "auto" "" { target { ! c++14 } } } -auto fp = foo; // { dg-error "auto" "" { target c++14 } } +auto fp = foo; // { dg-error "auto" } diff --git a/gcc/testsuite/g++.dg/cpp1y/auto-fn35.C b/gcc/testsuite/g++.dg/cpp1y/auto-fn35.C new file mode 100644 index 0000000..a408174 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/auto-fn35.C @@ -0,0 +1,11 @@ +// PR c++/77790 +// { dg-do compile { target c++11 } } + +template < typename S > struct A +{ + // { dg-error "" "" { target c++11_only } .+1 } + template < typename T > static auto f () { return 0; } + template < class U = decltype (f < S > ()) > int g () { return 0; } +}; + +auto a = A < int > {}.g ();