Hi,

in grokdeclarator the checks on the return type do nothing useful in case of late-specified return type because they happen too early, before splice_late_return_type is called. A straightforward way to solve the problem involves separating the checks themselves to a new check_function_return_type and calling it again only in case splice_late_return_type actually spliced the late return type (in that case, we should also consistently update type_quals).

As a side issue, if we want to use good and consistent locations for the error messages (the testcase below checks that too), we need a fall back to input_location for typespec_loc, because otherwise an UNKNOWN_LOCATION is used for the error messages of testcases like lambda-syntax1.C and pr60190.C.

Tested x86_64-linux.

Thanks, Paolo.

/////////////////////

/cp
2017-06-25  Paolo Carlini  <paolo.carl...@oracle.com>

        PR c++/65775
        * decl.c (check_function_return_type): New.
        (grokdeclarator): Use the latter; if declspecs->locations[ds_type_spec]
        is UNKNOWN_LOCATION fall back to input_location.

/testsuite
2017-06-25  Paolo Carlini  <paolo.carl...@oracle.com>

        PR c++/65775
        * g++.dg/cpp0x/trailing14.C: New.
Index: testsuite/g++.dg/cpp0x/trailing14.C
===================================================================
--- testsuite/g++.dg/cpp0x/trailing14.C (revision 0)
+++ testsuite/g++.dg/cpp0x/trailing14.C (working copy)
@@ -0,0 +1,15 @@
+// PR c++/65775
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wignored-qualifiers" }
+
+using Qi = int const volatile;
+Qi q1();           // { dg-warning "1: type qualifiers ignored" }
+auto q2() -> Qi;   // { dg-warning "1: type qualifiers ignored" }
+
+using Fi = int();
+Fi f1();           // { dg-error "1: 'f1' declared as function returning a 
function" }
+auto f2() -> Fi;   // { dg-error "1: 'f2' declared as function returning a 
function" }
+
+using Ai = int[5];
+Ai a1();           // { dg-error "1: 'a1' declared as function returning an 
array" }
+auto a2() -> Ai;   // { dg-error "1: 'a2' declared as function returning an 
array" }
Index: cp/decl.c
===================================================================
--- cp/decl.c   (revision 249632)
+++ cp/decl.c   (working copy)
@@ -9789,7 +9789,43 @@ mark_inline_variable (tree decl)
     }
 }
 
+/* If TYPE has TYPE_QUALS != TYPE_UNQUALIFIED issue a warning controlled by
+   -Wignored-qualifiers and clear TYPE_QUALS to avoid cascading diagnostics.
+   If TYPE is not valid, issue an error message and return error_mark_node,
+   otherwise return TYPE itself.  */
 
+static tree
+check_function_return_type (tree type, int& type_quals,
+                           const char* name, location_t loc)
+{
+  if (type_quals != TYPE_UNQUALIFIED)
+    {
+      if (SCALAR_TYPE_P (type) || VOID_TYPE_P (type))
+       warning_at (loc, OPT_Wignored_qualifiers, "type "
+                   "qualifiers ignored on function return type");
+
+      /* We now know that the TYPE_QUALS don't apply to the
+        decl, but to its return type.  */
+      type_quals = TYPE_UNQUALIFIED;
+    }
+
+  /* Error about some types functions can't return.  */
+
+  if (TREE_CODE (type) == FUNCTION_TYPE)
+    {
+      error_at (loc, "%qs declared as function returning a function", name);
+      return error_mark_node;
+    }
+
+  if (TREE_CODE (type) == ARRAY_TYPE)
+    {
+      error_at (loc, "%qs declared as function returning an array", name);
+      return error_mark_node;
+    }
+
+  return type;
+}
+
 /* Assign a typedef-given name to a class or enumeration type declared
    as anonymous at first.  This was split out of grokdeclarator
    because it is also used in libcc1.  */
@@ -9993,6 +10029,8 @@ grokdeclarator (const cp_declarator *declarator,
                                                      declspecs->locations);
   if (typespec_loc == UNKNOWN_LOCATION)
     typespec_loc = declspecs->locations[ds_type_spec];
+  if (typespec_loc == UNKNOWN_LOCATION)
+    typespec_loc = input_location;
 
   /* Look inside a declarator for the name being declared
      and get it as a string, for an error message.  */
@@ -10828,31 +10866,10 @@ grokdeclarator (const cp_declarator *declarator,
            /* Declaring a function type.
               Make sure we have a valid type for the function to return.  */
 
-           if (type_quals != TYPE_UNQUALIFIED)
-             {
-               if (SCALAR_TYPE_P (type) || VOID_TYPE_P (type))
-                 {
-                   warning_at (typespec_loc, OPT_Wignored_qualifiers, "type "
-                               "qualifiers ignored on function return type");
-                 }
-               /* We now know that the TYPE_QUALS don't apply to the
-                  decl, but to its return type.  */
-               type_quals = TYPE_UNQUALIFIED;
-             }
+           if (check_function_return_type (type, type_quals, name, 
typespec_loc)
+               == error_mark_node)
+             return error_mark_node;
 
-           /* Error about some types functions can't return.  */
-
-           if (TREE_CODE (type) == FUNCTION_TYPE)
-             {
-               error ("%qs declared as function returning a function", name);
-               return error_mark_node;
-             }
-           if (TREE_CODE (type) == ARRAY_TYPE)
-             {
-               error ("%qs declared as function returning an array", name);
-               return error_mark_node;
-             }
-
            input_location = declspecs->locations[ds_type_spec];
            abstract_virtuals_error (ACU_RETURN, type);
            input_location = saved_loc;
@@ -10959,7 +10976,17 @@ grokdeclarator (const cp_declarator *declarator,
              return error_mark_node;
 
            if (late_return_type)
-             late_return_type_p = true;
+             {
+               late_return_type_p = true;
+               if (type == late_return_type)
+                 {
+                   type_quals = cp_type_quals (type);
+                   if (check_function_return_type (type, type_quals,
+                                                   name, typespec_loc)
+                       == error_mark_node)
+                     return error_mark_node;
+                 }
+             }
 
            if (ctype == NULL_TREE
                && decl_context == FIELD

Reply via email to