mirror of
git://gcc.gnu.org/git/gcc.git
synced 2024-12-21 08:03:41 +08:00
typeck.c (c_expand_return): Always convert_for_initialization before checking for returning a pointer to local.
* typeck.c (c_expand_return): Always convert_for_initialization before checking for returning a pointer to local. From-SVN: r15064
This commit is contained in:
parent
fa8b602464
commit
c1bc6829b4
@ -1,5 +1,8 @@
|
||||
Wed Sep 3 11:09:25 1997 Jason Merrill <jason@yorick.cygnus.com>
|
||||
|
||||
* typeck.c (c_expand_return): Always convert_for_initialization
|
||||
before checking for returning a pointer to local.
|
||||
|
||||
* pt.c (type_unification): If strict and the function parm doesn't
|
||||
use template parms, just compare types.
|
||||
|
||||
|
@ -321,7 +321,9 @@ int flag_memoize_lookups; int flag_save_memoized_contexts;
|
||||
|
||||
int write_virtuals;
|
||||
|
||||
/* Nonzero means we should attempt to elide constructors when possible. */
|
||||
/* Nonzero means we should attempt to elide constructors when possible.
|
||||
FIXME: This flag is obsolete, and should be torn out along with the
|
||||
old overloading code. */
|
||||
|
||||
int flag_elide_constructors;
|
||||
|
||||
|
146
gcc/cp/typeck.c
146
gcc/cp/typeck.c
@ -7204,79 +7204,6 @@ c_expand_return (retval)
|
||||
expand_return (retval);
|
||||
return;
|
||||
}
|
||||
/* Add some useful error checking for C++. */
|
||||
else if (TREE_CODE (valtype) == REFERENCE_TYPE)
|
||||
{
|
||||
tree whats_returned;
|
||||
tree tmp_result = result;
|
||||
|
||||
/* Don't initialize directly into a non-BLKmode retval, since that
|
||||
could lose when being inlined by another caller. (GCC can't
|
||||
read the function return register in an inline function when
|
||||
the return value is being ignored). */
|
||||
if (result && TYPE_MODE (TREE_TYPE (tmp_result)) != BLKmode)
|
||||
tmp_result = 0;
|
||||
|
||||
/* convert to reference now, so we can give error if we
|
||||
return an reference to a non-lvalue. */
|
||||
retval = convert_for_initialization
|
||||
(tmp_result, valtype, retval, LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING,
|
||||
"return", NULL_TREE, 0);
|
||||
|
||||
/* Sort through common things to see what it is
|
||||
we are returning. */
|
||||
whats_returned = retval;
|
||||
if (TREE_CODE (whats_returned) == COMPOUND_EXPR)
|
||||
{
|
||||
whats_returned = TREE_OPERAND (whats_returned, 1);
|
||||
if (TREE_CODE (whats_returned) == ADDR_EXPR)
|
||||
whats_returned = TREE_OPERAND (whats_returned, 0);
|
||||
}
|
||||
while (TREE_CODE (whats_returned) == CONVERT_EXPR
|
||||
|| TREE_CODE (whats_returned) == NOP_EXPR)
|
||||
whats_returned = TREE_OPERAND (whats_returned, 0);
|
||||
if (TREE_CODE (whats_returned) == ADDR_EXPR)
|
||||
{
|
||||
whats_returned = TREE_OPERAND (whats_returned, 0);
|
||||
while (TREE_CODE (whats_returned) == NEW_EXPR
|
||||
|| TREE_CODE (whats_returned) == TARGET_EXPR)
|
||||
{
|
||||
/* Get the target. */
|
||||
whats_returned = TREE_OPERAND (whats_returned, 0);
|
||||
warning ("returning reference to temporary");
|
||||
}
|
||||
}
|
||||
|
||||
if (TREE_CODE (whats_returned) == VAR_DECL && DECL_NAME (whats_returned))
|
||||
{
|
||||
if (TEMP_NAME_P (DECL_NAME (whats_returned)))
|
||||
warning ("reference to non-lvalue returned");
|
||||
else if (! TREE_STATIC (whats_returned)
|
||||
&& IDENTIFIER_LOCAL_VALUE (DECL_NAME (whats_returned))
|
||||
&& !TREE_PUBLIC (whats_returned))
|
||||
cp_warning_at ("reference to local variable `%D' returned", whats_returned);
|
||||
}
|
||||
}
|
||||
else if (TREE_CODE (retval) == ADDR_EXPR)
|
||||
{
|
||||
tree whats_returned = TREE_OPERAND (retval, 0);
|
||||
|
||||
if (TREE_CODE (whats_returned) == VAR_DECL
|
||||
&& DECL_NAME (whats_returned)
|
||||
&& IDENTIFIER_LOCAL_VALUE (DECL_NAME (whats_returned))
|
||||
&& !TREE_STATIC (whats_returned)
|
||||
&& !TREE_PUBLIC (whats_returned))
|
||||
cp_warning_at ("address of local variable `%D' returned", whats_returned);
|
||||
}
|
||||
else if (TREE_CODE (retval) == VAR_DECL)
|
||||
{
|
||||
if (TREE_CODE (TREE_TYPE (retval)) == ARRAY_TYPE
|
||||
&& DECL_NAME (retval)
|
||||
&& IDENTIFIER_LOCAL_VALUE (DECL_NAME (retval))
|
||||
&& !TREE_STATIC (retval)
|
||||
&& !TREE_PUBLIC (retval))
|
||||
cp_warning_at ("address of local array `%D' returned", retval);
|
||||
}
|
||||
|
||||
/* Now deal with possible C++ hair:
|
||||
(1) Compute the return value.
|
||||
@ -7297,18 +7224,9 @@ c_expand_return (retval)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We already did this above for refs, don't do it again. */
|
||||
if (TREE_CODE (valtype) != REFERENCE_TYPE)
|
||||
retval = convert_for_initialization
|
||||
(NULL_TREE, valtype, retval, LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING,
|
||||
"return", NULL_TREE, 0);
|
||||
|
||||
/* We can't initialize a register from a NEW_EXPR. */
|
||||
if (! current_function_returns_struct
|
||||
&& TREE_CODE (retval) == TARGET_EXPR
|
||||
&& TREE_CODE (TREE_OPERAND (retval, 1)) == NEW_EXPR)
|
||||
retval = build (COMPOUND_EXPR, TREE_TYPE (retval), retval,
|
||||
TREE_OPERAND (retval, 0));
|
||||
retval = convert_for_initialization
|
||||
(NULL_TREE, valtype, retval, LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING,
|
||||
"return", NULL_TREE, 0);
|
||||
|
||||
if (retval == error_mark_node)
|
||||
{
|
||||
@ -7316,6 +7234,64 @@ c_expand_return (retval)
|
||||
expand_null_return ();
|
||||
return;
|
||||
}
|
||||
|
||||
/* We can't initialize a register from a NEW_EXPR. */
|
||||
else if (! current_function_returns_struct
|
||||
&& TREE_CODE (retval) == TARGET_EXPR
|
||||
&& TREE_CODE (TREE_OPERAND (retval, 1)) == NEW_EXPR)
|
||||
retval = build (COMPOUND_EXPR, TREE_TYPE (retval), retval,
|
||||
TREE_OPERAND (retval, 0));
|
||||
|
||||
/* Add some useful error checking for C++. */
|
||||
else if (TREE_CODE (valtype) == REFERENCE_TYPE)
|
||||
{
|
||||
tree whats_returned;
|
||||
|
||||
/* Sort through common things to see what it is
|
||||
we are returning. */
|
||||
whats_returned = retval;
|
||||
if (TREE_CODE (whats_returned) == COMPOUND_EXPR)
|
||||
{
|
||||
whats_returned = TREE_OPERAND (whats_returned, 1);
|
||||
if (TREE_CODE (whats_returned) == ADDR_EXPR)
|
||||
whats_returned = TREE_OPERAND (whats_returned, 0);
|
||||
}
|
||||
while (TREE_CODE (whats_returned) == CONVERT_EXPR
|
||||
|| TREE_CODE (whats_returned) == NOP_EXPR)
|
||||
whats_returned = TREE_OPERAND (whats_returned, 0);
|
||||
if (TREE_CODE (whats_returned) == ADDR_EXPR)
|
||||
{
|
||||
whats_returned = TREE_OPERAND (whats_returned, 0);
|
||||
while (TREE_CODE (whats_returned) == NEW_EXPR
|
||||
|| TREE_CODE (whats_returned) == TARGET_EXPR)
|
||||
{
|
||||
/* Get the target. */
|
||||
whats_returned = TREE_OPERAND (whats_returned, 0);
|
||||
warning ("returning reference to temporary");
|
||||
}
|
||||
}
|
||||
|
||||
if (TREE_CODE (whats_returned) == VAR_DECL && DECL_NAME (whats_returned))
|
||||
{
|
||||
if (TEMP_NAME_P (DECL_NAME (whats_returned)))
|
||||
warning ("reference to non-lvalue returned");
|
||||
else if (! TREE_STATIC (whats_returned)
|
||||
&& IDENTIFIER_LOCAL_VALUE (DECL_NAME (whats_returned))
|
||||
&& !TREE_PUBLIC (whats_returned))
|
||||
cp_warning_at ("reference to local variable `%D' returned", whats_returned);
|
||||
}
|
||||
}
|
||||
else if (TREE_CODE (retval) == ADDR_EXPR)
|
||||
{
|
||||
tree whats_returned = TREE_OPERAND (retval, 0);
|
||||
|
||||
if (TREE_CODE (whats_returned) == VAR_DECL
|
||||
&& DECL_NAME (whats_returned)
|
||||
&& IDENTIFIER_LOCAL_VALUE (DECL_NAME (whats_returned))
|
||||
&& !TREE_STATIC (whats_returned)
|
||||
&& !TREE_PUBLIC (whats_returned))
|
||||
cp_warning_at ("address of local variable `%D' returned", whats_returned);
|
||||
}
|
||||
}
|
||||
|
||||
if (retval != NULL_TREE
|
||||
|
Loading…
Reference in New Issue
Block a user