Ping. On Wed, Jun 24, 2020 at 07:27:14PM -0400, Marek Polacek via Gcc-patches wrote: > This is an ICE-on-invalid but I've been seeing it when reducing > various testcases, so it's more important for me than usually. > > splice_late_return_type now checks that if we've seen a late return > type, the function return type was auto. That's a fair assumption > but grokdeclarator/cdk_function wasn't giving errors for function > pointers and similar. So we want to perform various checks not only > when funcdecl_p || inner_declarator == NULL. But only give the > !late_return_type errors when funcdecl_p, to accept e.g. > > auto (*fp)() = f; > > in C++11. Here's a diff -w to ease the review: > > --- a/gcc/cp/decl.c > +++ b/gcc/cp/decl.c > @@ -12102,14 +12102,9 @@ grokdeclarator (const cp_declarator *declarator, > > /* Handle a late-specified return type. */ > tree late_return_type = declarator->u.function.late_return_type; > - if (funcdecl_p > - /* This is the case e.g. for > - using T = auto () -> int. */ > - || inner_declarator == NULL) > - { > if (tree auto_node = type_uses_auto (type)) > { > - if (!late_return_type) > + if (!late_return_type && funcdecl_p) > { > if (current_class_type > && LAMBDA_TYPE_P (current_class_type)) > @@ -12201,7 +12196,6 @@ grokdeclarator (const cp_declarator *declarator, > "type specifier", name); > return error_mark_node; > } > - } > type = splice_late_return_type (type, late_return_type); > if (type == error_mark_node) > return error_mark_node; > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? > > gcc/cp/ChangeLog: > > PR c++/95820 > * decl.c (grokdeclarator) <case cdk_function>: Check also > pointers/references/... to functions. > > gcc/testsuite/ChangeLog: > > PR c++/95820 > * g++.dg/cpp1y/auto-fn58.C: New test. > --- > gcc/cp/decl.c | 166 ++++++++++++------------- > gcc/testsuite/g++.dg/cpp1y/auto-fn58.C | 13 ++ > 2 files changed, 93 insertions(+), 86 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/cpp1y/auto-fn58.C > > diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c > index 3afad5ca805..a9ec328c498 100644 > --- a/gcc/cp/decl.c > +++ b/gcc/cp/decl.c > @@ -12102,106 +12102,100 @@ grokdeclarator (const cp_declarator *declarator, > > /* Handle a late-specified return type. */ > tree late_return_type = declarator->u.function.late_return_type; > - if (funcdecl_p > - /* This is the case e.g. for > - using T = auto () -> int. */ > - || inner_declarator == NULL) > + if (tree auto_node = type_uses_auto (type)) > { > - if (tree auto_node = type_uses_auto (type)) > + if (!late_return_type && funcdecl_p) > { > - if (!late_return_type) > + if (current_class_type > + && LAMBDA_TYPE_P (current_class_type)) > + /* OK for C++11 lambdas. */; > + else if (cxx_dialect < cxx14) > { > - if (current_class_type > - && LAMBDA_TYPE_P (current_class_type)) > - /* OK for C++11 lambdas. */; > - else if (cxx_dialect < cxx14) > - { > - error_at (typespec_loc, "%qs function uses " > - "%<auto%> type specifier without " > - "trailing return type", name); > - inform (typespec_loc, > - "deduced return type only available " > - "with %<-std=c++14%> or %<-std=gnu++14%>"); > - } > - else if (virtualp) > - { > - error_at (typespec_loc, "virtual function " > - "cannot have deduced return type"); > - virtualp = false; > - } > + error_at (typespec_loc, "%qs function uses " > + "%<auto%> type specifier without " > + "trailing return type", name); > + inform (typespec_loc, > + "deduced return type only available " > + "with %<-std=c++14%> or %<-std=gnu++14%>"); > } > - else if (!is_auto (type) && sfk != sfk_conversion) > + else if (virtualp) > { > - error_at (typespec_loc, "%qs function with trailing " > - "return type has %qT as its type rather " > - "than plain %<auto%>", name, type); > - return error_mark_node; > + error_at (typespec_loc, "virtual function " > + "cannot have deduced return type"); > + virtualp = false; > } > - else if (is_auto (type) && AUTO_IS_DECLTYPE (type)) > + } > + else if (!is_auto (type) && sfk != sfk_conversion) > + { > + error_at (typespec_loc, "%qs function with trailing " > + "return type has %qT as its type rather " > + "than plain %<auto%>", name, type); > + return error_mark_node; > + } > + else if (is_auto (type) && AUTO_IS_DECLTYPE (type)) > + { > + if (funcdecl_p) > + error_at (typespec_loc, > + "%qs function with trailing return type " > + "has %<decltype(auto)%> as its type " > + "rather than plain %<auto%>", name); > + else > + error_at (typespec_loc, > + "invalid use of %<decltype(auto)%>"); > + return error_mark_node; > + } > + tree tmpl = CLASS_PLACEHOLDER_TEMPLATE (auto_node); > + if (!tmpl) > + if (tree late_auto = type_uses_auto (late_return_type)) > + tmpl = CLASS_PLACEHOLDER_TEMPLATE (late_auto); > + if (tmpl && funcdecl_p) > + { > + if (!dguide_name_p (unqualified_id)) > { > - if (funcdecl_p) > - error_at (typespec_loc, > - "%qs function with trailing return type " > - "has %<decltype(auto)%> as its type " > - "rather than plain %<auto%>", name); > - else > - error_at (typespec_loc, > - "invalid use of %<decltype(auto)%>"); > + error_at (declarator->id_loc, "deduced class " > + "type %qD in function return type", > + DECL_NAME (tmpl)); > + inform (DECL_SOURCE_LOCATION (tmpl), > + "%qD declared here", tmpl); > return error_mark_node; > } > - tree tmpl = CLASS_PLACEHOLDER_TEMPLATE (auto_node); > - if (!tmpl) > - if (tree late_auto = type_uses_auto (late_return_type)) > - tmpl = CLASS_PLACEHOLDER_TEMPLATE (late_auto); > - if (tmpl && funcdecl_p) > + else if (!late_return_type) > { > - if (!dguide_name_p (unqualified_id)) > - { > - error_at (declarator->id_loc, "deduced class " > - "type %qD in function return type", > - DECL_NAME (tmpl)); > - inform (DECL_SOURCE_LOCATION (tmpl), > - "%qD declared here", tmpl); > - return error_mark_node; > - } > - else if (!late_return_type) > - { > - error_at (declarator->id_loc, "deduction guide " > - "for %qT must have trailing return " > - "type", TREE_TYPE (tmpl)); > - inform (DECL_SOURCE_LOCATION (tmpl), > - "%qD declared here", tmpl); > - return error_mark_node; > - } > - else if (CLASS_TYPE_P (late_return_type) > - && CLASSTYPE_TEMPLATE_INFO (late_return_type) > - && (CLASSTYPE_TI_TEMPLATE (late_return_type) > - == tmpl)) > - /* OK */; > - else > - error ("trailing return type %qT of deduction guide " > - "is not a specialization of %qT", > - late_return_type, TREE_TYPE (tmpl)); > + error_at (declarator->id_loc, "deduction guide " > + "for %qT must have trailing return " > + "type", TREE_TYPE (tmpl)); > + inform (DECL_SOURCE_LOCATION (tmpl), > + "%qD declared here", tmpl); > + return error_mark_node; > } > - } > - else if (late_return_type > - && sfk != sfk_conversion) > - { > - if (late_return_type == error_mark_node) > - return error_mark_node; > - if (cxx_dialect < cxx11) > - /* Not using maybe_warn_cpp0x because this should > - always be an error. */ > - error_at (typespec_loc, > - "trailing return type only available " > - "with %<-std=c++11%> or %<-std=gnu++11%>"); > + else if (CLASS_TYPE_P (late_return_type) > + && CLASSTYPE_TEMPLATE_INFO (late_return_type) > + && (CLASSTYPE_TI_TEMPLATE (late_return_type) > + == tmpl)) > + /* OK */; > else > - error_at (typespec_loc, "%qs function with trailing " > - "return type not declared with %<auto%> " > - "type specifier", name); > - return error_mark_node; > + error ("trailing return type %qT of deduction guide " > + "is not a specialization of %qT", > + late_return_type, TREE_TYPE (tmpl)); > } > } > + else if (late_return_type > + && sfk != sfk_conversion) > + { > + if (late_return_type == error_mark_node) > + return error_mark_node; > + if (cxx_dialect < cxx11) > + /* Not using maybe_warn_cpp0x because this should > + always be an error. */ > + error_at (typespec_loc, > + "trailing return type only available " > + "with %<-std=c++11%> or %<-std=gnu++11%>"); > + else > + error_at (typespec_loc, "%qs function with trailing " > + "return type not declared with %<auto%> " > + "type specifier", name); > + return error_mark_node; > + } > type = splice_late_return_type (type, late_return_type); > if (type == error_mark_node) > return error_mark_node; > diff --git a/gcc/testsuite/g++.dg/cpp1y/auto-fn58.C > b/gcc/testsuite/g++.dg/cpp1y/auto-fn58.C > new file mode 100644 > index 00000000000..8c4f24ccc74 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp1y/auto-fn58.C > @@ -0,0 +1,13 @@ > +// PR c++/95820 > +// { dg-do compile { target c++14 } } > + > +auto (*a)() -> bool = nullptr; > +int (*b)() -> bool = nullptr; // { dg-error "function with trailing return > type" } > +int (**c)() -> bool = nullptr; // { dg-error "function with trailing return > type" } > +int (&d)() -> bool = nullptr; // { dg-error "function with trailing return > type" } > +int (*&e)() -> bool = nullptr; // { dg-error "function with trailing return > type" } > +int (f[])() -> bool = nullptr; // { dg-error "function with trailing return > type" } > +auto* (*g)() -> bool = nullptr; // { dg-error "function with trailing return > type" } > +decltype(auto) (*h)() -> bool = nullptr; // { dg-error "invalid use" } > +decltype(auto)* (*i)() -> bool = nullptr; // { dg-error "function with > trailing return type" } > +decltype(auto)& (*j)() -> bool = nullptr; // { dg-error "function with > trailing return type" } > > base-commit: ef6506e23691a72e1e724977e8ee8b9f3db74015 > -- > Marek Polacek • Red Hat, Inc. • 300 A St, Boston, MA >
Marek