mirror of
git://gcc.gnu.org/git/gcc.git
synced 2024-12-30 15:45:42 +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;
|
||||
|
||||
|
100
gcc/cp/typeck.c
100
gcc/cp/typeck.c
@ -7204,24 +7204,48 @@ c_expand_return (retval)
|
||||
expand_return (retval);
|
||||
return;
|
||||
}
|
||||
|
||||
/* 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
|
||||
{
|
||||
retval = convert_for_initialization
|
||||
(NULL_TREE, valtype, retval, LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING,
|
||||
"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;
|
||||
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. */
|
||||
@ -7268,54 +7292,6 @@ c_expand_return (retval)
|
||||
&& !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.
|
||||
(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
|
||||
|
Loading…
Reference in New Issue
Block a user