From: Richard Kenner Date: Sat, 28 Jan 1995 20:14:09 +0000 (-0500) Subject: (c_expand_return): Refine check for returning pointer to local X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=abe80e6df576bbb5c1f6bcc545c0546f80056f59;p=gcc.git (c_expand_return): Refine check for returning pointer to local variable to allow subtracting a pointer from it. From-SVN: r8837 --- diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index b295be74fc3..ceabea89835 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -1,5 +1,5 @@ /* 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. @@ -6348,25 +6348,50 @@ c_expand_return (retval) /* Strip any conversions, additions, and subtractions, and see if we are returning the address of a local variable. Warn if so. */ - while (TREE_CODE (inner) == NOP_EXPR - || 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) + while (1) { - 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 - && ! DECL_EXTERNAL (inner) - && ! TREE_STATIC (inner) - && DECL_CONTEXT (inner) == current_function_decl) - warning ("function returns address of local variable"); + while (TREE_CODE_CLASS (TREE_CODE (inner)) == 'r') + inner = TREE_OPERAND (inner, 0); + + if (TREE_CODE (inner) == VAR_DECL + && ! 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);