Commit c1bc6829 by Jason Merrill Committed by Jason Merrill

typeck.c (c_expand_return): Always convert_for_initialization before checking…

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
parent fa8b6024
Wed Sep 3 11:09:25 1997 Jason Merrill <jason@yorick.cygnus.com> 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 * pt.c (type_unification): If strict and the function parm doesn't
use template parms, just compare types. use template parms, just compare types.
......
...@@ -321,7 +321,9 @@ int flag_memoize_lookups; int flag_save_memoized_contexts; ...@@ -321,7 +321,9 @@ int flag_memoize_lookups; int flag_save_memoized_contexts;
int write_virtuals; 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; int flag_elide_constructors;
......
...@@ -7204,25 +7204,49 @@ c_expand_return (retval) ...@@ -7204,25 +7204,49 @@ c_expand_return (retval)
expand_return (retval); expand_return (retval);
return; 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 /* Now deal with possible C++ hair:
could lose when being inlined by another caller. (GCC can't (1) Compute the return value.
read the function return register in an inline function when (2) If there are aggregate values with destructors which
the return value is being ignored). */ must be cleaned up, clean them (taking care
if (result && TYPE_MODE (TREE_TYPE (tmp_result)) != BLKmode) not to clobber the return value).
tmp_result = 0; (3) If an X(X&) constructor is defined, the return
value must be returned via that. */
/* convert to reference now, so we can give error if we if (retval == result
return an reference to a non-lvalue. */ || DECL_CONSTRUCTOR_P (current_function_decl))
/* It's already done for us. */;
else if (TREE_TYPE (retval) == void_type_node)
{
pedwarn ("return of void value in function returning non-void");
expand_expr_stmt (retval);
retval = 0;
}
else
{
retval = convert_for_initialization retval = convert_for_initialization
(tmp_result, valtype, retval, LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING, (NULL_TREE, valtype, retval, LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING,
"return", NULL_TREE, 0); "return", NULL_TREE, 0);
if (retval == error_mark_node)
{
/* Avoid warning about control reaching end of function. */
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 /* Sort through common things to see what it is
we are returning. */ we are returning. */
whats_returned = retval; whats_returned = retval;
...@@ -7268,54 +7292,6 @@ c_expand_return (retval) ...@@ -7268,54 +7292,6 @@ c_expand_return (retval)
&& !TREE_PUBLIC (whats_returned)) && !TREE_PUBLIC (whats_returned))
cp_warning_at ("address of local variable `%D' returned", 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.
(2) If there are aggregate values with destructors which
must be cleaned up, clean them (taking care
not to clobber the return value).
(3) If an X(X&) constructor is defined, the return
value must be returned via that. */
if (retval == result
|| DECL_CONSTRUCTOR_P (current_function_decl))
/* It's already done for us. */;
else if (TREE_TYPE (retval) == void_type_node)
{
pedwarn ("return of void value in function returning non-void");
expand_expr_stmt (retval);
retval = 0;
}
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));
if (retval == error_mark_node)
{
/* Avoid warning about control reaching end of function. */
expand_null_return ();
return;
}
} }
if (retval != NULL_TREE if (retval != NULL_TREE
......
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