aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2018-08-03 18:38:13 +0000
committerDavid Malcolm <dmalcolm@gcc.gnu.org>2018-08-03 18:38:13 +0000
commitbc31a87ac791bc6e733405b1539fbd710c92813e (patch)
tree7f272d1d2161125dd562b5c1f25dd467eb8fcf7a /gcc
parent2e2bd24b7c8ede398669d61852d962498889942a (diff)
downloadgcc-bc31a87ac791bc6e733405b1539fbd710c92813e.zip
gcc-bc31a87ac791bc6e733405b1539fbd710c92813e.tar.gz
gcc-bc31a87ac791bc6e733405b1539fbd710c92813e.tar.bz2
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 <jwakely@redhat.com> From-SVN: r263298
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/decl.c33
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/pr85523.C88
4 files changed, 134 insertions, 2 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 17f9821..90af73d 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,12 @@
+2018-08-03 David Malcolm <dmalcolm@redhat.com>
+ Jonathan Wakely <jwakely@redhat.com>
+
+ * 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 <jason@redhat.com>
PR c++/86706
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 1206ddb..cf216a1 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 ba0c4c6..0b61339 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2018-08-03 David Malcolm <dmalcolm@redhat.com>
+ Jonathan Wakely <jwakely@redhat.com>
+
+ PR c++/85523
+ * g++.dg/pr85523.C: New test.
+
2018-08-03 Bogdan Harjoc <harjoc@gmail.com>
PR c/86690
diff --git a/gcc/testsuite/g++.dg/pr85523.C b/gcc/testsuite/g++.dg/pr85523.C
new file mode 100644
index 0000000..9cd939b
--- /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 "" } */
+};