From: Richard Henderson Date: Sat, 31 Jul 1999 01:13:08 +0000 (-0700) Subject: c-typeck.c (initializer_constant_valid_p): Move ... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=7e8176d77891d6bfb95844e3918690ccbfcc7b71;p=gcc.git c-typeck.c (initializer_constant_valid_p): Move ... * c-typeck.c (initializer_constant_valid_p): Move ... * c-common.c (initializer_constant_valid_p): ... here. Use FOO_TYPE_P instead of tests against TREE_CODE. Allow subtraction of label addresses. * c-common.h (initializer_constant_valid_p): Declare. * c-tree.h (initializer_constant_valid_p): Remove. From-SVN: r28349 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 75de1b3b84c..55dd80940af 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +1999-07-30 Richard Henderson + + * c-typeck.c (initializer_constant_valid_p): Move ... + * c-common.c (initializer_constant_valid_p): ... here. Use + FOO_TYPE_P instead of tests against TREE_CODE. Allow subtraction + of label addresses. + * c-common.h (initializer_constant_valid_p): Declare. + * c-tree.h (initializer_constant_valid_p): Remove. + Fri Jul 30 16:33:42 1999 Mathias Froehlich * config/i386/sol2-c1.asm: Align the stack. diff --git a/gcc/c-common.c b/gcc/c-common.c index 4c083de60f6..137d1d3d9f3 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -3767,3 +3767,159 @@ build_va_arg (expr, type) { return build1 (VA_ARG_EXPR, type, expr); } + +/* Return nonzero if VALUE is a valid constant-valued expression + for use in initializing a static variable; one that can be an + element of a "constant" initializer. + + Return null_pointer_node if the value is absolute; + if it is relocatable, return the variable that determines the relocation. + We assume that VALUE has been folded as much as possible; + therefore, we do not need to check for such things as + arithmetic-combinations of integers. */ + +tree +initializer_constant_valid_p (value, endtype) + tree value; + tree endtype; +{ + switch (TREE_CODE (value)) + { + case CONSTRUCTOR: + if ((TREE_CODE (TREE_TYPE (value)) == UNION_TYPE + || TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE) + && TREE_CONSTANT (value) + && CONSTRUCTOR_ELTS (value)) + return + initializer_constant_valid_p (TREE_VALUE (CONSTRUCTOR_ELTS (value)), + endtype); + + return TREE_STATIC (value) ? null_pointer_node : 0; + + case INTEGER_CST: + case REAL_CST: + case STRING_CST: + case COMPLEX_CST: + return null_pointer_node; + + case ADDR_EXPR: + return TREE_OPERAND (value, 0); + + case NON_LVALUE_EXPR: + return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype); + + case CONVERT_EXPR: + case NOP_EXPR: + /* Allow conversions between pointer types. */ + if (POINTER_TYPE_P (TREE_TYPE (value)) + && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0)))) + return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype); + + /* Allow conversions between real types. */ + if (FLOAT_TYPE_P (TREE_TYPE (value)) + && FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0)))) + return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype); + + /* Allow length-preserving conversions between integer types. */ + if (INTEGRAL_TYPE_P (TREE_TYPE (value)) + && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0))) + && (TYPE_PRECISION (TREE_TYPE (value)) + == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0))))) + return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype); + + /* Allow conversions between other integer types only if + explicit value. */ + if (INTEGRAL_TYPE_P (TREE_TYPE (value)) + && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0)))) + { + tree inner = initializer_constant_valid_p (TREE_OPERAND (value, 0), + endtype); + if (inner == null_pointer_node) + return null_pointer_node; + break; + } + + /* Allow (int) &foo provided int is as wide as a pointer. */ + if (INTEGRAL_TYPE_P (TREE_TYPE (value)) + && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0))) + && (TYPE_PRECISION (TREE_TYPE (value)) + >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0))))) + return initializer_constant_valid_p (TREE_OPERAND (value, 0), + endtype); + + /* Likewise conversions from int to pointers, but also allow + conversions from 0. */ + if (POINTER_TYPE_P (TREE_TYPE (value)) + && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0)))) + { + if (integer_zerop (TREE_OPERAND (value, 0))) + return null_pointer_node; + else if (TYPE_PRECISION (TREE_TYPE (value)) + <= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))) + return initializer_constant_valid_p (TREE_OPERAND (value, 0), + endtype); + } + + /* Allow conversions to union types if the value inside is okay. */ + if (TREE_CODE (TREE_TYPE (value)) == UNION_TYPE) + return initializer_constant_valid_p (TREE_OPERAND (value, 0), + endtype); + break; + + case PLUS_EXPR: + if (! INTEGRAL_TYPE_P (endtype) + || TYPE_PRECISION (endtype) >= POINTER_SIZE) + { + tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0), + endtype); + tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1), + endtype); + /* If either term is absolute, use the other terms relocation. */ + if (valid0 == null_pointer_node) + return valid1; + if (valid1 == null_pointer_node) + return valid0; + } + break; + + case MINUS_EXPR: + if (! INTEGRAL_TYPE_P (endtype) + || TYPE_PRECISION (endtype) >= POINTER_SIZE) + { + tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0), + endtype); + tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1), + endtype); + /* Win if second argument is absolute. */ + if (valid1 == null_pointer_node) + return valid0; + /* Win if both arguments have the same relocation. + Then the value is absolute. */ + if (valid0 == valid1) + return null_pointer_node; + } + + /* Support differences between labels. */ + if (INTEGRAL_TYPE_P (endtype)) + { + tree op0, op1; + op0 = TREE_OPERAND (value, 0); + op1 = TREE_OPERAND (value, 1); + STRIP_NOPS (op0); + STRIP_NOPS (op1); + + if (TREE_CODE (op0) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (op0, 0)) == LABEL_DECL + && TREE_CODE (op1) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (op1, 0)) == LABEL_DECL) + return null_pointer_node; + } + break; + + default: + break; + } + + return 0; +} + diff --git a/gcc/c-common.h b/gcc/c-common.h index ec4a556a2e4..ab0cdecbd37 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -190,3 +190,5 @@ extern tree builtin_function PROTO((const char *, tree, enum built_in_function extern void c_common_nodes_and_builtins PROTO((int, int, int)); extern tree build_va_arg PROTO((tree, tree)); + +extern tree initializer_constant_valid_p PROTO((tree, tree)); diff --git a/gcc/c-tree.h b/gcc/c-tree.h index 1db0790a1c8..8e5aa73ac26 100644 --- a/gcc/c-tree.h +++ b/gcc/c-tree.h @@ -282,7 +282,6 @@ extern tree build_compound_expr PROTO((tree)); extern tree build_c_cast PROTO((tree, tree)); extern tree build_modify_expr PROTO((tree, enum tree_code, tree)); -extern tree initializer_constant_valid_p PROTO((tree, tree)); extern void store_init_value PROTO((tree, tree)); extern void error_init PROTO((const char *)); extern void pedwarn_init PROTO((const char *)); diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 18b82109ed5..6d4c7df75fe 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -4246,145 +4246,6 @@ warn_for_assignment (msgid, opname, function, argnum) pedwarn (msgid, opname); } -/* Return nonzero if VALUE is a valid constant-valued expression - for use in initializing a static variable; one that can be an - element of a "constant" initializer. - - Return null_pointer_node if the value is absolute; - if it is relocatable, return the variable that determines the relocation. - We assume that VALUE has been folded as much as possible; - therefore, we do not need to check for such things as - arithmetic-combinations of integers. */ - -tree -initializer_constant_valid_p (value, endtype) - tree value; - tree endtype; -{ - switch (TREE_CODE (value)) - { - case CONSTRUCTOR: - if ((TREE_CODE (TREE_TYPE (value)) == UNION_TYPE - || TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE) - && TREE_CONSTANT (value) - && CONSTRUCTOR_ELTS (value)) - return - initializer_constant_valid_p (TREE_VALUE (CONSTRUCTOR_ELTS (value)), - endtype); - - return TREE_STATIC (value) ? null_pointer_node : 0; - - case INTEGER_CST: - case REAL_CST: - case STRING_CST: - case COMPLEX_CST: - return null_pointer_node; - - case ADDR_EXPR: - return TREE_OPERAND (value, 0); - - case NON_LVALUE_EXPR: - return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype); - - case CONVERT_EXPR: - case NOP_EXPR: - /* Allow conversions between pointer types. */ - if (TREE_CODE (TREE_TYPE (value)) == POINTER_TYPE - && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == POINTER_TYPE) - return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype); - - /* Allow conversions between real types. */ - if (TREE_CODE (TREE_TYPE (value)) == REAL_TYPE - && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == REAL_TYPE) - return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype); - - /* Allow length-preserving conversions between integer types. */ - if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE - && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE - && (TYPE_PRECISION (TREE_TYPE (value)) - == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0))))) - return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype); - - /* Allow conversions between other integer types only if - explicit value. */ - if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE - && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE) - { - tree inner = initializer_constant_valid_p (TREE_OPERAND (value, 0), - endtype); - if (inner == null_pointer_node) - return null_pointer_node; - return 0; - } - - /* Allow (int) &foo provided int is as wide as a pointer. */ - if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE - && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == POINTER_TYPE - && (TYPE_PRECISION (TREE_TYPE (value)) - >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0))))) - return initializer_constant_valid_p (TREE_OPERAND (value, 0), - endtype); - - /* Likewise conversions from int to pointers, but also allow - conversions from 0. */ - if (TREE_CODE (TREE_TYPE (value)) == POINTER_TYPE - && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE) - { - if (integer_zerop (TREE_OPERAND (value, 0))) - return null_pointer_node; - else if (TYPE_PRECISION (TREE_TYPE (value)) - <= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))) - return initializer_constant_valid_p (TREE_OPERAND (value, 0), - endtype); - } - - /* Allow conversions to union types if the value inside is okay. */ - if (TREE_CODE (TREE_TYPE (value)) == UNION_TYPE) - return initializer_constant_valid_p (TREE_OPERAND (value, 0), - endtype); - return 0; - - case PLUS_EXPR: - if (TREE_CODE (endtype) == INTEGER_TYPE - && TYPE_PRECISION (endtype) < POINTER_SIZE) - return 0; - { - tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0), - endtype); - tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1), - endtype); - /* If either term is absolute, use the other terms relocation. */ - if (valid0 == null_pointer_node) - return valid1; - if (valid1 == null_pointer_node) - return valid0; - return 0; - } - - case MINUS_EXPR: - if (TREE_CODE (endtype) == INTEGER_TYPE - && TYPE_PRECISION (endtype) < POINTER_SIZE) - return 0; - { - tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0), - endtype); - tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1), - endtype); - /* Win if second argument is absolute. */ - if (valid1 == null_pointer_node) - return valid0; - /* Win if both arguments have the same relocation. - Then the value is absolute. */ - if (valid0 == valid1) - return null_pointer_node; - return 0; - } - - default: - return 0; - } -} - /* If VALUE is a compound expr all of whose expressions are constant, then return its value. Otherwise, return error_mark_node.