diff options
author | Marek Polacek <polacek@redhat.com> | 2018-09-06 00:38:13 +0000 |
---|---|---|
committer | Marek Polacek <mpolacek@gcc.gnu.org> | 2018-09-06 00:38:13 +0000 |
commit | 308d9cda32faed5d49ce3d0732b4ff465c423300 (patch) | |
tree | 8c35a937933ae3e55c78546616653aa06d11b0e0 /gcc | |
parent | 4497d88fe2cbf9d8210485e68123a9abac693297 (diff) | |
download | gcc-308d9cda32faed5d49ce3d0732b4ff465c423300.zip gcc-308d9cda32faed5d49ce3d0732b4ff465c423300.tar.gz gcc-308d9cda32faed5d49ce3d0732b4ff465c423300.tar.bz2 |
PR c++/86982, -Wreturn-local-addr and std::move and std::forward.
* typeck.c (maybe_warn_about_returning_address_of_local): Handle calls
to std::move or std::forward.
(is_std_forward_p): New function.
* g++.dg/warn/Wreturn-local-addr-5.C: New test.
From-SVN: r264139
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 28 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/warn/Wreturn-local-addr-5.C | 8 |
4 files changed, 46 insertions, 0 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b4ec9f4..d5879f8 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -5,6 +5,11 @@ out if performing the maybe-rvalue overload resolution and a conversion function is getting called. + PR c++/86982, -Wreturn-local-addr and std::move and std::forward. + * typeck.c (maybe_warn_about_returning_address_of_local): Handle calls + to std::move or std::forward. + (is_std_forward_p): New function. + 2018-09-05 Pádraig Brady <p@draigbrady.com> PR c++/87185 diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 84cf4c4..9fa4c16 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -63,6 +63,8 @@ static tree lookup_destructor (tree, tree, tree, tsubst_flags_t); static void error_args_num (location_t, tree, bool); static int convert_arguments (tree, vec<tree, va_gc> **, tree, int, tsubst_flags_t); +static bool is_std_move_p (tree); +static bool is_std_forward_p (tree); /* Do `exp = require_complete_type (exp);' to make sure exp does not have an incomplete type. (That includes void types.) @@ -9071,6 +9073,15 @@ maybe_warn_about_returning_address_of_local (tree retval) STRIP_NOPS (whats_returned); } + /* As a special case, we handle a call to std::move or std::forward. */ + if (TREE_CODE (whats_returned) == CALL_EXPR + && (is_std_move_p (whats_returned) + || is_std_forward_p (whats_returned))) + { + tree arg = CALL_EXPR_ARG (whats_returned, 0); + return maybe_warn_about_returning_address_of_local (arg); + } + if (TREE_CODE (whats_returned) != ADDR_EXPR) return false; whats_returned = TREE_OPERAND (whats_returned, 0); @@ -9136,6 +9147,23 @@ decl_in_std_namespace_p (tree decl) && DECL_NAMESPACE_STD_P (decl_namespace_context (decl))); } +/* Returns true if FN, a CALL_EXPR, is a call to std::forward. */ + +static bool +is_std_forward_p (tree fn) +{ + /* std::forward only takes one argument. */ + if (call_expr_nargs (fn) != 1) + return false; + + tree fndecl = cp_get_callee_fndecl_nofold (fn); + if (!decl_in_std_namespace_p (fndecl)) + return false; + + tree name = DECL_NAME (fndecl); + return name && id_equal (name, "forward"); +} + /* Returns true if FN, a CALL_EXPR, is a call to std::move. */ static bool diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5ccc244..e22ede0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2018-09-05 Marek Polacek <polacek@redhat.com> + + PR c++/86982, -Wreturn-local-addr and std::move and std::forward. + * g++.dg/warn/Wreturn-local-addr-5.C: New test. + 2018-09-05 Cesar Philippidis <cesar@codesourcery.com> Bernd Schmidt <bernds_cb1@t-online.de> diff --git a/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-5.C b/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-5.C new file mode 100644 index 0000000..7609627 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-5.C @@ -0,0 +1,8 @@ +// PR c++/86982 +// { dg-do compile { target c++11 } } + +#include <utility> + +int&& f() { int i = 0; return std::move(i); } // { dg-warning "reference to local variable" } +int&& g() { int i = 0; return std::forward<int>(i); } // { dg-warning "reference to local variable" } +int&& h() { long l = 0; return std::forward<int>(l); } // { dg-warning "reference to temporary" } |