From bc31a87ac791bc6e733405b1539fbd710c92813e Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Fri, 3 Aug 2018 18:38:13 +0000 Subject: [PATCH] Add fix-it hint for missing return statement in assignment operators (PR c++/85523) gcc/cp/ChangeLog: PR c++/85523 * decl.c: Include "gcc-rich-location.h". (add_return_star_this_fixit): New function. (finish_function): When warning about missing return statements in functions returning non-void, add a "return *this;" fix-it hint for assignment operators. gcc/testsuite/ChangeLog: PR c++/85523 * g++.dg/pr85523.C: New test. Co-Authored-By: Jonathan Wakely From-SVN: r263298 --- gcc/cp/ChangeLog | 9 ++++ gcc/cp/decl.c | 33 ++++++++++++- gcc/testsuite/ChangeLog | 6 +++ gcc/testsuite/g++.dg/pr85523.C | 88 ++++++++++++++++++++++++++++++++++ 4 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/pr85523.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 17f9821b939..90af73d4810 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2018-08-03 David Malcolm + Jonathan Wakely + + * decl.c: Include "gcc-rich-location.h". + (add_return_star_this_fixit): New function. + (finish_function): When warning about missing return statements in + functions returning non-void, add a "return *this;" fix-it hint for + assignment operators. + 2018-08-03 Jason Merrill PR c++/86706 diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 1206ddb3abe..cf216a1a960 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -15710,6 +15710,22 @@ maybe_save_function_definition (tree fun) register_constexpr_fundef (fun, DECL_SAVED_TREE (fun)); } +/* Attempt to add a fix-it hint to RICHLOC suggesting the insertion + of "return *this;" immediately before its location, using FNDECL's + first statement (if any) to give the indentation, if appropriate. */ + +static void +add_return_star_this_fixit (gcc_rich_location *richloc, tree fndecl) +{ + location_t indent = UNKNOWN_LOCATION; + tree stmts = expr_first (DECL_SAVED_TREE (fndecl)); + if (stmts) + indent = EXPR_LOCATION (stmts); + richloc->add_fixit_insert_formatted ("return *this;", + richloc->get_loc (), + indent); +} + /* Finish up a function declaration and compile that function all the way to assembler language output. The free the storage for the function definition. INLINE_P is TRUE if we just @@ -15903,8 +15919,21 @@ finish_function (bool inline_p) && !DECL_DESTRUCTOR_P (fndecl) && targetm.warn_func_return (fndecl)) { - warning (OPT_Wreturn_type, - "no return statement in function returning non-void"); + gcc_rich_location richloc (input_location); + /* Potentially add a "return *this;" fix-it hint for + assignment operators. */ + if (IDENTIFIER_ASSIGN_OP_P (DECL_NAME (fndecl))) + { + tree valtype = TREE_TYPE (DECL_RESULT (fndecl)); + if (TREE_CODE (valtype) == REFERENCE_TYPE + && same_type_ignoring_top_level_qualifiers_p + (TREE_TYPE (valtype), TREE_TYPE (current_class_ref))) + if (global_dc->option_enabled (OPT_Wreturn_type, + global_dc->option_state)) + add_return_star_this_fixit (&richloc, fndecl); + } + warning_at (&richloc, OPT_Wreturn_type, + "no return statement in function returning non-void"); TREE_NO_WARNING (fndecl) = 1; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ba0c4c6ef5d..0b61339a0b4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2018-08-03 David Malcolm + Jonathan Wakely + + PR c++/85523 + * g++.dg/pr85523.C: New test. + 2018-08-03 Bogdan Harjoc PR c/86690 diff --git a/gcc/testsuite/g++.dg/pr85523.C b/gcc/testsuite/g++.dg/pr85523.C new file mode 100644 index 00000000000..9cd939be54d --- /dev/null +++ b/gcc/testsuite/g++.dg/pr85523.C @@ -0,0 +1,88 @@ +/* { dg-options "-fdiagnostics-show-caret" } */ + +/* Verify that we emit a "return *this;" fix-it hint for + a missing return in an assignment operator. */ + +struct s1 { + s1& operator=(const s1&) { } // { dg-warning "no return statement in function returning non-void" } + /* { dg-begin-multiline-output "" } + s1& operator=(const s1&) { } + ^ + return *this; + { dg-end-multiline-output "" } */ +}; + +/* Likewise for +=. */ + +struct s2 { + s2& operator+=(const s2&) {} // { dg-warning "no return statement in function returning non-void" } + /* { dg-begin-multiline-output "" } + s2& operator+=(const s2&) {} + ^ + return *this; + { dg-end-multiline-output "" } */ +}; + +/* No warning for "void" return. */ + +struct s3 { + void operator=(const s3&) { } +}; + +/* We shouldn't issue the fix-it hint if the return type isn't right. */ + +struct s4 { + int operator=(int) { } // { dg-warning "no return statement in function returning non-void" } + /* { dg-begin-multiline-output "" } + int operator=(int) { } + ^ + { dg-end-multiline-output "" } */ +}; + +/* Example of a multi-line fix-it hint. */ + +struct s5 { + int i; + s5& operator=(const s5& z) { + i = z.i; + } // { dg-warning "no return statement in function returning non-void" } + /* { dg-begin-multiline-output "" } ++ return *this; + } + ^ + { dg-end-multiline-output "" } */ +}; + +/* Example of a multi-line fix-it hint with other statements. */ + +extern void log (const char *); +struct s6 { + int i; + s6& operator=(const s6& z) { + log ("operator=\n"); + i = z.i; + } // { dg-warning "no return statement in function returning non-void" } + /* { dg-begin-multiline-output "" } ++ return *this; + } + ^ + { dg-end-multiline-output "" } */ +}; + +/* Another example of a multi-line fix-it hint with other statements. */ + +struct s7 { + int i; + s7& operator=(const s6& z) { + if (z.i) + log ("operator=\n"); + else + log ("operator=\n"); + i = z.i; + } // { dg-warning "no return statement in function returning non-void" } + /* { dg-begin-multiline-output "" } ++ return *this; + } + ^ + { dg-end-multiline-output "" } */ +}; -- 2.30.2