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

Reply via email to