Commit 308d9cda by Marek Polacek Committed by Marek Polacek

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
parent 4497d88f
...@@ -5,6 +5,11 @@ ...@@ -5,6 +5,11 @@
out if performing the maybe-rvalue overload resolution and a conversion out if performing the maybe-rvalue overload resolution and a conversion
function is getting called. 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> 2018-09-05 Pádraig Brady <p@draigbrady.com>
PR c++/87185 PR c++/87185
......
...@@ -63,6 +63,8 @@ static tree lookup_destructor (tree, tree, tree, tsubst_flags_t); ...@@ -63,6 +63,8 @@ static tree lookup_destructor (tree, tree, tree, tsubst_flags_t);
static void error_args_num (location_t, tree, bool); static void error_args_num (location_t, tree, bool);
static int convert_arguments (tree, vec<tree, va_gc> **, tree, int, static int convert_arguments (tree, vec<tree, va_gc> **, tree, int,
tsubst_flags_t); 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 /* Do `exp = require_complete_type (exp);' to make sure exp
does not have an incomplete type. (That includes void types.) does not have an incomplete type. (That includes void types.)
...@@ -9071,6 +9073,15 @@ maybe_warn_about_returning_address_of_local (tree retval) ...@@ -9071,6 +9073,15 @@ maybe_warn_about_returning_address_of_local (tree retval)
STRIP_NOPS (whats_returned); 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) if (TREE_CODE (whats_returned) != ADDR_EXPR)
return false; return false;
whats_returned = TREE_OPERAND (whats_returned, 0); whats_returned = TREE_OPERAND (whats_returned, 0);
...@@ -9136,6 +9147,23 @@ decl_in_std_namespace_p (tree decl) ...@@ -9136,6 +9147,23 @@ decl_in_std_namespace_p (tree decl)
&& DECL_NAMESPACE_STD_P (decl_namespace_context (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. */ /* Returns true if FN, a CALL_EXPR, is a call to std::move. */
static bool static bool
......
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> 2018-09-05 Cesar Philippidis <cesar@codesourcery.com>
Bernd Schmidt <bernds_cb1@t-online.de> Bernd Schmidt <bernds_cb1@t-online.de>
......
// 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" }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment