Commit abe80e6d by Richard Kenner

(c_expand_return): Refine check for returning pointer to local

variable to allow subtracting a pointer from it.

From-SVN: r8837
parent da6f15cd
/* Build expressions with type checking for C compiler. /* Build expressions with type checking for C compiler.
Copyright (C) 1987, 88, 91, 92, 93, 1994 Free Software Foundation, Inc. Copyright (C) 1987, 88, 91, 92, 93, 94, 1995 Free Software Foundation, Inc.
This file is part of GNU CC. This file is part of GNU CC.
...@@ -6348,25 +6348,50 @@ c_expand_return (retval) ...@@ -6348,25 +6348,50 @@ c_expand_return (retval)
/* Strip any conversions, additions, and subtractions, and see if /* Strip any conversions, additions, and subtractions, and see if
we are returning the address of a local variable. Warn if so. */ we are returning the address of a local variable. Warn if so. */
while (TREE_CODE (inner) == NOP_EXPR while (1)
|| TREE_CODE (inner) == NON_LVALUE_EXPR
|| TREE_CODE (inner) == CONVERT_EXPR
|| TREE_CODE (inner) == PLUS_EXPR
|| TREE_CODE (inner) == MINUS_EXPR)
inner = TREE_OPERAND (inner, 0);
if (TREE_CODE (inner) == ADDR_EXPR)
{ {
inner = TREE_OPERAND (inner, 0); switch (TREE_CODE (inner))
{
case NOP_EXPR: case NON_LVALUE_EXPR: case CONVERT_EXPR:
case PLUS_EXPR:
inner = TREE_OPERAND (inner, 0);
continue;
case MINUS_EXPR:
/* If the second operand of the MINUS_EXPR has a pointer
type (or is converted from it), this may be valid, so
don't give a warning. */
{
tree op1 = TREE_OPERAND (inner, 1);
while (! POINTER_TYPE_P (TREE_TYPE (op1))
&& (TREE_CODE (op1) == NOP_EXPR
|| TREE_CODE (op1) == NON_LVALUE_EXPR
|| TREE_CODE (op1) == CONVERT_EXPR))
op1 = TREE_OPERAND (op1, 0);
if (POINTER_TYPE_P (TREE_TYPE (op1)))
break;
while (TREE_CODE_CLASS (TREE_CODE (inner)) == 'r') inner = TREE_OPERAND (inner, 0);
inner = TREE_OPERAND (inner, 0); continue;
}
case ADDR_EXPR:
inner = TREE_OPERAND (inner, 0);
if (TREE_CODE (inner) == VAR_DECL while (TREE_CODE_CLASS (TREE_CODE (inner)) == 'r')
&& ! DECL_EXTERNAL (inner) inner = TREE_OPERAND (inner, 0);
&& ! TREE_STATIC (inner)
&& DECL_CONTEXT (inner) == current_function_decl) if (TREE_CODE (inner) == VAR_DECL
warning ("function returns address of local variable"); && ! DECL_EXTERNAL (inner)
&& ! TREE_STATIC (inner)
&& DECL_CONTEXT (inner) == current_function_decl)
warning ("function returns address of local variable");
break;
}
break;
} }
t = build (MODIFY_EXPR, TREE_TYPE (res), res, t); t = build (MODIFY_EXPR, TREE_TYPE (res), res, t);
......
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