* [C++ Patch] PR 65775 ("Late-specified return type bypasses return type checks (qualified, function, array)")
@ 2017-06-25 21:12 Paolo Carlini
2017-06-26 0:18 ` Paolo Carlini
0 siblings, 1 reply; 3+ messages in thread
From: Paolo Carlini @ 2017-06-25 21:12 UTC (permalink / raw)
To: gcc-patches; +Cc: Jason Merrill
[-- Attachment #1: Type: text/plain, Size: 836 bytes --]
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.
/////////////////////
[-- Attachment #2: CL_65775 --]
[-- Type: text/plain, Size: 357 bytes --]
/cp
2017-06-25 Paolo Carlini <paolo.carlini@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.carlini@oracle.com>
PR c++/65775
* g++.dg/cpp0x/trailing14.C: New.
[-- Attachment #3: patch_65775 --]
[-- Type: text/plain, Size: 4562 bytes --]
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
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [C++ Patch] PR 65775 ("Late-specified return type bypasses return type checks (qualified, function, array)")
2017-06-25 21:12 [C++ Patch] PR 65775 ("Late-specified return type bypasses return type checks (qualified, function, array)") Paolo Carlini
@ 2017-06-26 0:18 ` Paolo Carlini
2017-06-30 22:50 ` Jason Merrill
0 siblings, 1 reply; 3+ messages in thread
From: Paolo Carlini @ 2017-06-26 0:18 UTC (permalink / raw)
To: gcc-patches; +Cc: Jason Merrill
[-- Attachment #1: Type: text/plain, Size: 182 bytes --]
... in fact, simply moving the checks forward, past the
splice_late_return_type call, appears to work fine. I'm finishing
testing the below.
Thanks!
Paolo.
/////////////////////
[-- Attachment #2: CL_65775_2 --]
[-- Type: text/plain, Size: 382 bytes --]
/cp
2017-06-25 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/65775
* decl.c (grokdeclarator): Move checks on function return type after
the splice_late_return_type call; if declspecs->locations[ds_type_spec]
is UNKNOWN_LOCATION fall back to input_location.
/testsuite
2017-06-25 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/65775
* g++.dg/cpp0x/trailing14.C: New.
[-- Attachment #3: patch_65775_2 --]
[-- Type: text/plain, Size: 3732 bytes --]
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)
@@ -9993,6 +9993,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. */
@@ -10825,34 +10827,8 @@ grokdeclarator (const cp_declarator *declarator,
tree arg_types;
int funcdecl_p;
- /* Declaring a function type.
- Make sure we have a valid type for the function to return. */
+ /* Declaring a function type. */
- 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;
- }
-
- /* 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,8 +10935,36 @@ grokdeclarator (const cp_declarator *declarator,
return error_mark_node;
if (late_return_type)
- late_return_type_p = true;
+ {
+ late_return_type_p = true;
+ type_quals = cp_type_quals (type);
+ }
+ 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;
+ }
+
+ /* Error about some types functions can't return. */
+
+ if (TREE_CODE (type) == FUNCTION_TYPE)
+ {
+ error_at (typespec_loc, "%qs declared as function returning "
+ "a function", name);
+ return error_mark_node;
+ }
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ error_at (typespec_loc, "%qs declared as function returning "
+ "an array", name);
+ return error_mark_node;
+ }
+
if (ctype == NULL_TREE
&& decl_context == FIELD
&& funcdecl_p
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [C++ Patch] PR 65775 ("Late-specified return type bypasses return type checks (qualified, function, array)")
2017-06-26 0:18 ` Paolo Carlini
@ 2017-06-30 22:50 ` Jason Merrill
0 siblings, 0 replies; 3+ messages in thread
From: Jason Merrill @ 2017-06-30 22:50 UTC (permalink / raw)
To: Paolo Carlini; +Cc: gcc-patches
OK.
On Sun, Jun 25, 2017 at 8:18 PM, Paolo Carlini <paolo.carlini@oracle.com> wrote:
> ... in fact, simply moving the checks forward, past the
> splice_late_return_type call, appears to work fine. I'm finishing testing
> the below.
>
> Thanks!
> Paolo.
>
> /////////////////////
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2017-06-30 22:50 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-25 21:12 [C++ Patch] PR 65775 ("Late-specified return type bypasses return type checks (qualified, function, array)") Paolo Carlini
2017-06-26 0:18 ` Paolo Carlini
2017-06-30 22:50 ` Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).