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:
Jason Merrill 1997-09-03 20:01:18 +00:00 committed by Jason Merrill
parent fa8b602464
commit c1bc6829b4
3 changed files with 67 additions and 86 deletions

View File

@ -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.

View File

@ -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;

View File

@ -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