| /* Build expressions with type checking for C compiler. |
| Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, |
| 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. |
| |
| This file is part of GCC. |
| |
| GCC is free software; you can redistribute it and/or modify it under |
| the terms of the GNU General Public License as published by the Free |
| Software Foundation; either version 2, or (at your option) any later |
| version. |
| |
| GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
| WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GCC; see the file COPYING. If not, write to the Free |
| Software Foundation, 59 Temple Place - Suite 330, Boston, MA |
| 02111-1307, USA. */ |
| |
| |
| /* This file is part of the C front end. |
| It contains routines to build C expressions given their operands, |
| including computing the types of the result, C-specific error checks, |
| and some optimization. |
| |
| There are also routines to build RETURN_STMT nodes and CASE_STMT nodes, |
| and to process initializations in declarations (since they work |
| like a strange sort of assignment). */ |
| |
| #include "config.h" |
| #include "system.h" |
| #include "coretypes.h" |
| #include "tm.h" |
| #include "rtl.h" |
| #include "tree.h" |
| #include "c-tree.h" |
| #include "tm_p.h" |
| #include "flags.h" |
| #include "output.h" |
| #include "expr.h" |
| #include "toplev.h" |
| #include "intl.h" |
| #include "ggc.h" |
| #include "target.h" |
| |
| /* Nonzero if we've already printed a "missing braces around initializer" |
| message within this initializer. */ |
| static int missing_braces_mentioned; |
| |
| static int require_constant_value; |
| static int require_constant_elements; |
| |
| static tree qualify_type (tree, tree); |
| static int same_translation_unit_p (tree, tree); |
| static int tagged_types_tu_compatible_p (tree, tree, int); |
| static int comp_target_types (tree, tree, int); |
| static int function_types_compatible_p (tree, tree, int); |
| static int type_lists_compatible_p (tree, tree, int); |
| static tree decl_constant_value_for_broken_optimization (tree); |
| static tree default_function_array_conversion (tree); |
| static tree lookup_field (tree, tree); |
| static tree convert_arguments (tree, tree, tree, tree); |
| static tree pointer_diff (tree, tree); |
| static tree unary_complex_lvalue (enum tree_code, tree, int); |
| static void pedantic_lvalue_warning (enum tree_code); |
| static tree internal_build_compound_expr (tree, int); |
| static tree convert_for_assignment (tree, tree, const char *, tree, tree, |
| int); |
| static void warn_for_assignment (const char *, const char *, tree, int); |
| static tree valid_compound_expr_initializer (tree, tree); |
| static void push_string (const char *); |
| static void push_member_name (tree); |
| static void push_array_bounds (int); |
| static int spelling_length (void); |
| static char *print_spelling (char *); |
| static void warning_init (const char *); |
| static tree digest_init (tree, tree, int); |
| static void output_init_element (tree, tree, tree, int); |
| static void output_pending_init_elements (int); |
| static int set_designator (int); |
| static void push_range_stack (tree); |
| static void add_pending_init (tree, tree); |
| static void set_nonincremental_init (void); |
| static void set_nonincremental_init_from_string (tree); |
| static tree find_init_member (tree); |
| |
| /* Do `exp = require_complete_type (exp);' to make sure exp |
| does not have an incomplete type. (That includes void types.) */ |
| |
| tree |
| require_complete_type (tree value) |
| { |
| tree type = TREE_TYPE (value); |
| |
| if (value == error_mark_node || type == error_mark_node) |
| return error_mark_node; |
| |
| /* First, detect a valid value with a complete type. */ |
| if (COMPLETE_TYPE_P (type)) |
| return value; |
| |
| c_incomplete_type_error (value, type); |
| return error_mark_node; |
| } |
| |
| /* Print an error message for invalid use of an incomplete type. |
| VALUE is the expression that was used (or 0 if that isn't known) |
| and TYPE is the type that was invalid. */ |
| |
| void |
| c_incomplete_type_error (tree value, tree type) |
| { |
| const char *type_code_string; |
| |
| /* Avoid duplicate error message. */ |
| if (TREE_CODE (type) == ERROR_MARK) |
| return; |
| |
| if (value != 0 && (TREE_CODE (value) == VAR_DECL |
| || TREE_CODE (value) == PARM_DECL)) |
| error ("`%s' has an incomplete type", |
| IDENTIFIER_POINTER (DECL_NAME (value))); |
| else |
| { |
| retry: |
| /* We must print an error message. Be clever about what it says. */ |
| |
| switch (TREE_CODE (type)) |
| { |
| case RECORD_TYPE: |
| type_code_string = "struct"; |
| break; |
| |
| case UNION_TYPE: |
| type_code_string = "union"; |
| break; |
| |
| case ENUMERAL_TYPE: |
| type_code_string = "enum"; |
| break; |
| |
| case VOID_TYPE: |
| error ("invalid use of void expression"); |
| return; |
| |
| case ARRAY_TYPE: |
| if (TYPE_DOMAIN (type)) |
| { |
| if (TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL) |
| { |
| error ("invalid use of flexible array member"); |
| return; |
| } |
| type = TREE_TYPE (type); |
| goto retry; |
| } |
| error ("invalid use of array with unspecified bounds"); |
| return; |
| |
| default: |
| abort (); |
| } |
| |
| if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) |
| error ("invalid use of undefined type `%s %s'", |
| type_code_string, IDENTIFIER_POINTER (TYPE_NAME (type))); |
| else |
| /* If this type has a typedef-name, the TYPE_NAME is a TYPE_DECL. */ |
| error ("invalid use of incomplete typedef `%s'", |
| IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)))); |
| } |
| } |
| |
| /* Given a type, apply default promotions wrt unnamed function |
| arguments and return the new type. */ |
| |
| tree |
| c_type_promotes_to (tree type) |
| { |
| if (TYPE_MAIN_VARIANT (type) == float_type_node) |
| return double_type_node; |
| |
| if (c_promoting_integer_type_p (type)) |
| { |
| /* Preserve unsignedness if not really getting any wider. */ |
| if (TREE_UNSIGNED (type) |
| && (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))) |
| return unsigned_type_node; |
| return integer_type_node; |
| } |
| |
| return type; |
| } |
| |
| /* Return a variant of TYPE which has all the type qualifiers of LIKE |
| as well as those of TYPE. */ |
| |
| static tree |
| qualify_type (tree type, tree like) |
| { |
| return c_build_qualified_type (type, |
| TYPE_QUALS (type) | TYPE_QUALS (like)); |
| } |
| |
| /* Return the common type of two types. |
| We assume that comptypes has already been done and returned 1; |
| if that isn't so, this may crash. In particular, we assume that qualifiers |
| match. |
| |
| This is the type for the result of most arithmetic operations |
| if the operands have the given two types. */ |
| |
| tree |
| common_type (tree t1, tree t2) |
| { |
| enum tree_code code1; |
| enum tree_code code2; |
| tree attributes; |
| |
| /* Save time if the two types are the same. */ |
| |
| if (t1 == t2) return t1; |
| |
| /* If one type is nonsense, use the other. */ |
| if (t1 == error_mark_node) |
| return t2; |
| if (t2 == error_mark_node) |
| return t1; |
| |
| /* Merge the attributes. */ |
| attributes = (*targetm.merge_type_attributes) (t1, t2); |
| |
| /* Treat an enum type as the unsigned integer type of the same width. */ |
| |
| if (TREE_CODE (t1) == ENUMERAL_TYPE) |
| t1 = c_common_type_for_size (TYPE_PRECISION (t1), 1); |
| if (TREE_CODE (t2) == ENUMERAL_TYPE) |
| t2 = c_common_type_for_size (TYPE_PRECISION (t2), 1); |
| |
| code1 = TREE_CODE (t1); |
| code2 = TREE_CODE (t2); |
| |
| /* If one type is complex, form the common type of the non-complex |
| components, then make that complex. Use T1 or T2 if it is the |
| required type. */ |
| if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE) |
| { |
| tree subtype1 = code1 == COMPLEX_TYPE ? TREE_TYPE (t1) : t1; |
| tree subtype2 = code2 == COMPLEX_TYPE ? TREE_TYPE (t2) : t2; |
| tree subtype = common_type (subtype1, subtype2); |
| |
| if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype) |
| return build_type_attribute_variant (t1, attributes); |
| else if (code2 == COMPLEX_TYPE && TREE_TYPE (t2) == subtype) |
| return build_type_attribute_variant (t2, attributes); |
| else |
| return build_type_attribute_variant (build_complex_type (subtype), |
| attributes); |
| } |
| |
| switch (code1) |
| { |
| case INTEGER_TYPE: |
| case REAL_TYPE: |
| /* If only one is real, use it as the result. */ |
| |
| if (code1 == REAL_TYPE && code2 != REAL_TYPE) |
| return build_type_attribute_variant (t1, attributes); |
| |
| if (code2 == REAL_TYPE && code1 != REAL_TYPE) |
| return build_type_attribute_variant (t2, attributes); |
| |
| /* Both real or both integers; use the one with greater precision. */ |
| |
| if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2)) |
| return build_type_attribute_variant (t1, attributes); |
| else if (TYPE_PRECISION (t2) > TYPE_PRECISION (t1)) |
| return build_type_attribute_variant (t2, attributes); |
| |
| /* Same precision. Prefer longs to ints even when same size. */ |
| |
| if (TYPE_MAIN_VARIANT (t1) == long_unsigned_type_node |
| || TYPE_MAIN_VARIANT (t2) == long_unsigned_type_node) |
| { |
| t1 = build_qualified_type (long_unsigned_type_node, |
| TYPE_QUALS (t1)); |
| return build_type_attribute_variant (t1, attributes); |
| } |
| |
| if (TYPE_MAIN_VARIANT (t1) == long_integer_type_node |
| || TYPE_MAIN_VARIANT (t2) == long_integer_type_node) |
| { |
| tree ntype; |
| |
| /* But preserve unsignedness from the other type, |
| since long cannot hold all the values of an unsigned int. */ |
| if (TREE_UNSIGNED (t1) || TREE_UNSIGNED (t2)) |
| ntype = long_unsigned_type_node; |
| else |
| ntype = long_integer_type_node; |
| |
| ntype = build_qualified_type (ntype, TYPE_QUALS (t1)); |
| return build_type_attribute_variant (ntype, attributes); |
| } |
| |
| /* Likewise, prefer long double to double even if same size. */ |
| if (TYPE_MAIN_VARIANT (t1) == long_double_type_node |
| || TYPE_MAIN_VARIANT (t2) == long_double_type_node) |
| { |
| t1 = build_qualified_type (long_double_type_node, |
| TYPE_QUALS (t1)); |
| return build_type_attribute_variant (t1, attributes); |
| } |
| |
| /* Otherwise prefer the unsigned one. */ |
| |
| if (TREE_UNSIGNED (t1)) |
| return build_type_attribute_variant (t1, attributes); |
| else |
| return build_type_attribute_variant (t2, attributes); |
| |
| case POINTER_TYPE: |
| /* For two pointers, do this recursively on the target type, |
| and combine the qualifiers of the two types' targets. */ |
| /* This code was turned off; I don't know why. |
| But ANSI C specifies doing this with the qualifiers. |
| So I turned it on again. */ |
| { |
| tree pointed_to_1 = TREE_TYPE (t1); |
| tree pointed_to_2 = TREE_TYPE (t2); |
| tree target = common_type (TYPE_MAIN_VARIANT (pointed_to_1), |
| TYPE_MAIN_VARIANT (pointed_to_2)); |
| t1 = build_pointer_type (c_build_qualified_type |
| (target, |
| TYPE_QUALS (pointed_to_1) | |
| TYPE_QUALS (pointed_to_2))); |
| return build_type_attribute_variant (t1, attributes); |
| } |
| |
| case ARRAY_TYPE: |
| { |
| tree elt = common_type (TREE_TYPE (t1), TREE_TYPE (t2)); |
| /* Save space: see if the result is identical to one of the args. */ |
| if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1)) |
| return build_type_attribute_variant (t1, attributes); |
| if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2)) |
| return build_type_attribute_variant (t2, attributes); |
| /* Merge the element types, and have a size if either arg has one. */ |
| t1 = build_array_type (elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2)); |
| return build_type_attribute_variant (t1, attributes); |
| } |
| |
| case FUNCTION_TYPE: |
| /* Function types: prefer the one that specified arg types. |
| If both do, merge the arg types. Also merge the return types. */ |
| { |
| tree valtype = common_type (TREE_TYPE (t1), TREE_TYPE (t2)); |
| tree p1 = TYPE_ARG_TYPES (t1); |
| tree p2 = TYPE_ARG_TYPES (t2); |
| int len; |
| tree newargs, n; |
| int i; |
| |
| /* Save space: see if the result is identical to one of the args. */ |
| if (valtype == TREE_TYPE (t1) && ! TYPE_ARG_TYPES (t2)) |
| return build_type_attribute_variant (t1, attributes); |
| if (valtype == TREE_TYPE (t2) && ! TYPE_ARG_TYPES (t1)) |
| return build_type_attribute_variant (t2, attributes); |
| |
| /* Simple way if one arg fails to specify argument types. */ |
| if (TYPE_ARG_TYPES (t1) == 0) |
| { |
| t1 = build_function_type (valtype, TYPE_ARG_TYPES (t2)); |
| return build_type_attribute_variant (t1, attributes); |
| } |
| if (TYPE_ARG_TYPES (t2) == 0) |
| { |
| t1 = build_function_type (valtype, TYPE_ARG_TYPES (t1)); |
| return build_type_attribute_variant (t1, attributes); |
| } |
| |
| /* If both args specify argument types, we must merge the two |
| lists, argument by argument. */ |
| |
| pushlevel (0); |
| declare_parm_level (); |
| |
| len = list_length (p1); |
| newargs = 0; |
| |
| for (i = 0; i < len; i++) |
| newargs = tree_cons (NULL_TREE, NULL_TREE, newargs); |
| |
| n = newargs; |
| |
| for (; p1; |
| p1 = TREE_CHAIN (p1), p2 = TREE_CHAIN (p2), n = TREE_CHAIN (n)) |
| { |
| /* A null type means arg type is not specified. |
| Take whatever the other function type has. */ |
| if (TREE_VALUE (p1) == 0) |
| { |
| TREE_VALUE (n) = TREE_VALUE (p2); |
| goto parm_done; |
| } |
| if (TREE_VALUE (p2) == 0) |
| { |
| TREE_VALUE (n) = TREE_VALUE (p1); |
| goto parm_done; |
| } |
| |
| /* Given wait (union {union wait *u; int *i} *) |
| and wait (union wait *), |
| prefer union wait * as type of parm. */ |
| if (TREE_CODE (TREE_VALUE (p1)) == UNION_TYPE |
| && TREE_VALUE (p1) != TREE_VALUE (p2)) |
| { |
| tree memb; |
| for (memb = TYPE_FIELDS (TREE_VALUE (p1)); |
| memb; memb = TREE_CHAIN (memb)) |
| if (comptypes (TREE_TYPE (memb), TREE_VALUE (p2), |
| COMPARE_STRICT)) |
| { |
| TREE_VALUE (n) = TREE_VALUE (p2); |
| if (pedantic) |
| pedwarn ("function types not truly compatible in ISO C"); |
| goto parm_done; |
| } |
| } |
| if (TREE_CODE (TREE_VALUE (p2)) == UNION_TYPE |
| && TREE_VALUE (p2) != TREE_VALUE (p1)) |
| { |
| tree memb; |
| for (memb = TYPE_FIELDS (TREE_VALUE (p2)); |
| memb; memb = TREE_CHAIN (memb)) |
| if (comptypes (TREE_TYPE (memb), TREE_VALUE (p1), |
| COMPARE_STRICT)) |
| { |
| TREE_VALUE (n) = TREE_VALUE (p1); |
| if (pedantic) |
| pedwarn ("function types not truly compatible in ISO C"); |
| goto parm_done; |
| } |
| } |
| TREE_VALUE (n) = common_type (TREE_VALUE (p1), TREE_VALUE (p2)); |
| parm_done: ; |
| } |
| |
| poplevel (0, 0, 0); |
| |
| t1 = build_function_type (valtype, newargs); |
| /* ... falls through ... */ |
| } |
| |
| default: |
| return build_type_attribute_variant (t1, attributes); |
| } |
| |
| } |
| |
| /* Return 1 if TYPE1 and TYPE2 are compatible types for assignment |
| or various other operations. Return 2 if they are compatible |
| but a warning may be needed if you use them together. */ |
| |
| int |
| comptypes (tree type1, tree type2, int flags) |
| { |
| tree t1 = type1; |
| tree t2 = type2; |
| int attrval, val; |
| |
| /* Suppress errors caused by previously reported errors. */ |
| |
| if (t1 == t2 || !t1 || !t2 |
| || TREE_CODE (t1) == ERROR_MARK || TREE_CODE (t2) == ERROR_MARK) |
| return 1; |
| |
| /* If either type is the internal version of sizetype, return the |
| language version. */ |
| if (TREE_CODE (t1) == INTEGER_TYPE && TYPE_IS_SIZETYPE (t1) |
| && TYPE_DOMAIN (t1) != 0) |
| t1 = TYPE_DOMAIN (t1); |
| |
| if (TREE_CODE (t2) == INTEGER_TYPE && TYPE_IS_SIZETYPE (t2) |
| && TYPE_DOMAIN (t2) != 0) |
| t2 = TYPE_DOMAIN (t2); |
| |
| /* Enumerated types are compatible with integer types, but this is |
| not transitive: two enumerated types in the same translation unit |
| are compatible with each other only if they are the same type. */ |
| |
| if (TREE_CODE (t1) == ENUMERAL_TYPE && TREE_CODE (t2) != ENUMERAL_TYPE) |
| t1 = c_common_type_for_size (TYPE_PRECISION (t1), TREE_UNSIGNED (t1)); |
| else if (TREE_CODE (t2) == ENUMERAL_TYPE && TREE_CODE (t1) != ENUMERAL_TYPE) |
| t2 = c_common_type_for_size (TYPE_PRECISION (t2), TREE_UNSIGNED (t2)); |
| |
| if (t1 == t2) |
| return 1; |
| |
| /* Different classes of types can't be compatible. */ |
| |
| if (TREE_CODE (t1) != TREE_CODE (t2)) |
| return 0; |
| |
| /* Qualifiers must match. */ |
| |
| if (TYPE_QUALS (t1) != TYPE_QUALS (t2)) |
| return 0; |
| |
| /* Allow for two different type nodes which have essentially the same |
| definition. Note that we already checked for equality of the type |
| qualifiers (just above). */ |
| |
| if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2)) |
| return 1; |
| |
| /* 1 if no need for warning yet, 2 if warning cause has been seen. */ |
| if (! (attrval = (*targetm.comp_type_attributes) (t1, t2))) |
| return 0; |
| |
| /* 1 if no need for warning yet, 2 if warning cause has been seen. */ |
| val = 0; |
| |
| switch (TREE_CODE (t1)) |
| { |
| case POINTER_TYPE: |
| /* We must give ObjC the first crack at comparing pointers, since |
| protocol qualifiers may be involved. */ |
| if (c_dialect_objc () && (val = objc_comptypes (t1, t2, 0)) >= 0) |
| break; |
| val = (TREE_TYPE (t1) == TREE_TYPE (t2) |
| ? 1 : comptypes (TREE_TYPE (t1), TREE_TYPE (t2), flags)); |
| break; |
| |
| case FUNCTION_TYPE: |
| val = function_types_compatible_p (t1, t2, flags); |
| break; |
| |
| case ARRAY_TYPE: |
| { |
| tree d1 = TYPE_DOMAIN (t1); |
| tree d2 = TYPE_DOMAIN (t2); |
| bool d1_variable, d2_variable; |
| bool d1_zero, d2_zero; |
| val = 1; |
| |
| /* Target types must match incl. qualifiers. */ |
| if (TREE_TYPE (t1) != TREE_TYPE (t2) |
| && 0 == (val = comptypes (TREE_TYPE (t1), TREE_TYPE (t2), |
| flags))) |
| return 0; |
| |
| /* Sizes must match unless one is missing or variable. */ |
| if (d1 == 0 || d2 == 0 || d1 == d2) |
| break; |
| |
| d1_zero = ! TYPE_MAX_VALUE (d1); |
| d2_zero = ! TYPE_MAX_VALUE (d2); |
| |
| d1_variable = (! d1_zero |
| && (TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST |
| || TREE_CODE (TYPE_MAX_VALUE (d1)) != INTEGER_CST)); |
| d2_variable = (! d2_zero |
| && (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST |
| || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST)); |
| |
| if (d1_variable || d2_variable) |
| break; |
| if (d1_zero && d2_zero) |
| break; |
| if (d1_zero || d2_zero |
| || ! tree_int_cst_equal (TYPE_MIN_VALUE (d1), TYPE_MIN_VALUE (d2)) |
| || ! tree_int_cst_equal (TYPE_MAX_VALUE (d1), TYPE_MAX_VALUE (d2))) |
| val = 0; |
| |
| break; |
| } |
| |
| case RECORD_TYPE: |
| /* We are dealing with two distinct structs. In assorted Objective-C |
| corner cases, however, these can still be deemed equivalent. */ |
| if (c_dialect_objc () && objc_comptypes (t1, t2, 0) == 1) |
| val = 1; |
| |
| case ENUMERAL_TYPE: |
| case UNION_TYPE: |
| if (val != 1 && !same_translation_unit_p (t1, t2)) |
| val = tagged_types_tu_compatible_p (t1, t2, flags); |
| break; |
| |
| case VECTOR_TYPE: |
| /* The target might allow certain vector types to be compatible. */ |
| val = (*targetm.vector_opaque_p) (t1) |
| || (*targetm.vector_opaque_p) (t2); |
| break; |
| |
| default: |
| break; |
| } |
| return attrval == 2 && val == 1 ? 2 : val; |
| } |
| |
| /* Return 1 if TTL and TTR are pointers to types that are equivalent, |
| ignoring their qualifiers. REFLEXIVE is only used by ObjC - set it |
| to 1 or 0 depending if the check of the pointer types is meant to |
| be reflexive or not (typically, assignments are not reflexive, |
| while comparisons are reflexive). |
| */ |
| |
| static int |
| comp_target_types (tree ttl, tree ttr, int reflexive) |
| { |
| int val; |
| |
| /* Give objc_comptypes a crack at letting these types through. */ |
| if ((val = objc_comptypes (ttl, ttr, reflexive)) >= 0) |
| return val; |
| |
| val = comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (ttl)), |
| TYPE_MAIN_VARIANT (TREE_TYPE (ttr)), COMPARE_STRICT); |
| |
| if (val == 2 && pedantic) |
| pedwarn ("types are not quite compatible"); |
| return val; |
| } |
| |
| /* Subroutines of `comptypes'. */ |
| |
| /* Determine whether two types derive from the same translation unit. |
| If the CONTEXT chain ends in a null, that type's context is still |
| being parsed, so if two types have context chains ending in null, |
| they're in the same translation unit. */ |
| static int |
| same_translation_unit_p (tree t1, tree t2) |
| { |
| while (t1 && TREE_CODE (t1) != TRANSLATION_UNIT_DECL) |
| switch (TREE_CODE_CLASS (TREE_CODE (t1))) |
| { |
| case 'd': t1 = DECL_CONTEXT (t1); break; |
| case 't': t1 = TYPE_CONTEXT (t1); break; |
| case 'b': t1 = BLOCK_SUPERCONTEXT (t1); break; |
| default: abort (); |
| } |
| |
| while (t2 && TREE_CODE (t2) != TRANSLATION_UNIT_DECL) |
| switch (TREE_CODE_CLASS (TREE_CODE (t2))) |
| { |
| case 'd': t2 = DECL_CONTEXT (t1); break; |
| case 't': t2 = TYPE_CONTEXT (t2); break; |
| case 'b': t2 = BLOCK_SUPERCONTEXT (t2); break; |
| default: abort (); |
| } |
| |
| return t1 == t2; |
| } |
| |
| /* The C standard says that two structures in different translation |
| units are compatible with each other only if the types of their |
| fields are compatible (among other things). So, consider two copies |
| of this structure: */ |
| |
| struct tagged_tu_seen { |
| const struct tagged_tu_seen * next; |
| tree t1; |
| tree t2; |
| }; |
| |
| /* Can they be compatible with each other? We choose to break the |
| recursion by allowing those types to be compatible. */ |
| |
| static const struct tagged_tu_seen * tagged_tu_seen_base; |
| |
| /* Return 1 if two 'struct', 'union', or 'enum' types T1 and T2 are |
| compatible. If the two types are not the same (which has been |
| checked earlier), this can only happen when multiple translation |
| units are being compiled. See C99 6.2.7 paragraph 1 for the exact |
| rules. */ |
| |
| static int |
| tagged_types_tu_compatible_p (tree t1, tree t2, int flags) |
| { |
| tree s1, s2; |
| bool needs_warning = false; |
| |
| /* We have to verify that the tags of the types are the same. This |
| is harder than it looks because this may be a typedef, so we have |
| to go look at the original type. It may even be a typedef of a |
| typedef... */ |
| while (TYPE_NAME (t1) |
| && TREE_CODE (TYPE_NAME (t1)) == TYPE_DECL |
| && DECL_ORIGINAL_TYPE (TYPE_NAME (t1))) |
| t1 = DECL_ORIGINAL_TYPE (TYPE_NAME (t1)); |
| |
| while (TYPE_NAME (t2) |
| && TREE_CODE (TYPE_NAME (t2)) == TYPE_DECL |
| && DECL_ORIGINAL_TYPE (TYPE_NAME (t2))) |
| t2 = DECL_ORIGINAL_TYPE (TYPE_NAME (t2)); |
| |
| /* C90 didn't have the requirement that the two tags be the same. */ |
| if (flag_isoc99 && TYPE_NAME (t1) != TYPE_NAME (t2)) |
| return 0; |
| |
| /* C90 didn't say what happened if one or both of the types were |
| incomplete; we choose to follow C99 rules here, which is that they |
| are compatible. */ |
| if (TYPE_SIZE (t1) == NULL |
| || TYPE_SIZE (t2) == NULL) |
| return 1; |
| |
| { |
| const struct tagged_tu_seen * tts_i; |
| for (tts_i = tagged_tu_seen_base; tts_i != NULL; tts_i = tts_i->next) |
| if (tts_i->t1 == t1 && tts_i->t2 == t2) |
| return 1; |
| } |
| |
| switch (TREE_CODE (t1)) |
| { |
| case ENUMERAL_TYPE: |
| { |
| if (list_length (TYPE_VALUES (t1)) != list_length (TYPE_VALUES (t2))) |
| return 0; |
| |
| for (s1 = TYPE_VALUES (t1); s1; s1 = TREE_CHAIN (s1)) |
| { |
| s2 = purpose_member (TREE_PURPOSE (s1), TYPE_VALUES (t2)); |
| if (s2 == NULL |
| || simple_cst_equal (TREE_VALUE (s1), TREE_VALUE (s2)) != 1) |
| return 0; |
| } |
| return 1; |
| } |
| |
| case UNION_TYPE: |
| { |
| if (list_length (TYPE_FIELDS (t1)) != list_length (TYPE_FIELDS (t2))) |
| return 0; |
| |
| for (s1 = TYPE_FIELDS (t1); s1; s1 = TREE_CHAIN (s1)) |
| { |
| bool ok = false; |
| struct tagged_tu_seen tts; |
| |
| tts.next = tagged_tu_seen_base; |
| tts.t1 = t1; |
| tts.t2 = t2; |
| tagged_tu_seen_base = &tts; |
| |
| if (DECL_NAME (s1) != NULL) |
| for (s2 = TYPE_VALUES (t2); s2; s2 = TREE_CHAIN (s2)) |
| if (DECL_NAME (s1) == DECL_NAME (s2)) |
| { |
| int result; |
| result = comptypes (TREE_TYPE (s1), TREE_TYPE (s2), flags); |
| if (result == 0) |
| break; |
| if (result == 2) |
| needs_warning = true; |
| |
| if (TREE_CODE (s1) == FIELD_DECL |
| && simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1), |
| DECL_FIELD_BIT_OFFSET (s2)) != 1) |
| break; |
| |
| ok = true; |
| break; |
| } |
| tagged_tu_seen_base = tts.next; |
| if (! ok) |
| return 0; |
| } |
| return needs_warning ? 2 : 1; |
| } |
| |
| case RECORD_TYPE: |
| { |
| struct tagged_tu_seen tts; |
| |
| tts.next = tagged_tu_seen_base; |
| tts.t1 = t1; |
| tts.t2 = t2; |
| tagged_tu_seen_base = &tts; |
| |
| for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2); |
| s1 && s2; |
| s1 = TREE_CHAIN (s1), s2 = TREE_CHAIN (s2)) |
| { |
| int result; |
| if (TREE_CODE (s1) != TREE_CODE (s2) |
| || DECL_NAME (s1) != DECL_NAME (s2)) |
| break; |
| result = comptypes (TREE_TYPE (s1), TREE_TYPE (s2), flags); |
| if (result == 0) |
| break; |
| if (result == 2) |
| needs_warning = true; |
| |
| if (TREE_CODE (s1) == FIELD_DECL |
| && simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1), |
| DECL_FIELD_BIT_OFFSET (s2)) != 1) |
| break; |
| } |
| tagged_tu_seen_base = tts.next; |
| if (s1 && s2) |
| return 0; |
| return needs_warning ? 2 : 1; |
| } |
| |
| default: |
| abort (); |
| } |
| } |
| |
| /* Return 1 if two function types F1 and F2 are compatible. |
| If either type specifies no argument types, |
| the other must specify a fixed number of self-promoting arg types. |
| Otherwise, if one type specifies only the number of arguments, |
| the other must specify that number of self-promoting arg types. |
| Otherwise, the argument types must match. */ |
| |
| static int |
| function_types_compatible_p (tree f1, tree f2, int flags) |
| { |
| tree args1, args2; |
| /* 1 if no need for warning yet, 2 if warning cause has been seen. */ |
| int val = 1; |
| int val1; |
| tree ret1, ret2; |
| |
| ret1 = TREE_TYPE (f1); |
| ret2 = TREE_TYPE (f2); |
| |
| /* 'volatile' qualifiers on a function's return type mean the function |
| is noreturn. */ |
| if (pedantic && TYPE_VOLATILE (ret1) != TYPE_VOLATILE (ret2)) |
| pedwarn ("function return types not compatible due to `volatile'"); |
| if (TYPE_VOLATILE (ret1)) |
| ret1 = build_qualified_type (TYPE_MAIN_VARIANT (ret1), |
| TYPE_QUALS (ret1) & ~TYPE_QUAL_VOLATILE); |
| if (TYPE_VOLATILE (ret2)) |
| ret2 = build_qualified_type (TYPE_MAIN_VARIANT (ret2), |
| TYPE_QUALS (ret2) & ~TYPE_QUAL_VOLATILE); |
| val = comptypes (ret1, ret2, flags); |
| if (val == 0) |
| return 0; |
| |
| args1 = TYPE_ARG_TYPES (f1); |
| args2 = TYPE_ARG_TYPES (f2); |
| |
| /* An unspecified parmlist matches any specified parmlist |
| whose argument types don't need default promotions. */ |
| |
| if (args1 == 0) |
| { |
| if (!self_promoting_args_p (args2)) |
| return 0; |
| /* If one of these types comes from a non-prototype fn definition, |
| compare that with the other type's arglist. |
| If they don't match, ask for a warning (but no error). */ |
| if (TYPE_ACTUAL_ARG_TYPES (f1) |
| && 1 != type_lists_compatible_p (args2, TYPE_ACTUAL_ARG_TYPES (f1), |
| flags)) |
| val = 2; |
| return val; |
| } |
| if (args2 == 0) |
| { |
| if (!self_promoting_args_p (args1)) |
| return 0; |
| if (TYPE_ACTUAL_ARG_TYPES (f2) |
| && 1 != type_lists_compatible_p (args1, TYPE_ACTUAL_ARG_TYPES (f2), |
| flags)) |
| val = 2; |
| return val; |
| } |
| |
| /* Both types have argument lists: compare them and propagate results. */ |
| val1 = type_lists_compatible_p (args1, args2, flags); |
| return val1 != 1 ? val1 : val; |
| } |
| |
| /* Check two lists of types for compatibility, |
| returning 0 for incompatible, 1 for compatible, |
| or 2 for compatible with warning. */ |
| |
| static int |
| type_lists_compatible_p (tree args1, tree args2, int flags) |
| { |
| /* 1 if no need for warning yet, 2 if warning cause has been seen. */ |
| int val = 1; |
| int newval = 0; |
| |
| while (1) |
| { |
| if (args1 == 0 && args2 == 0) |
| return val; |
| /* If one list is shorter than the other, |
| they fail to match. */ |
| if (args1 == 0 || args2 == 0) |
| return 0; |
| /* A null pointer instead of a type |
| means there is supposed to be an argument |
| but nothing is specified about what type it has. |
| So match anything that self-promotes. */ |
| if (TREE_VALUE (args1) == 0) |
| { |
| if (c_type_promotes_to (TREE_VALUE (args2)) != TREE_VALUE (args2)) |
| return 0; |
| } |
| else if (TREE_VALUE (args2) == 0) |
| { |
| if (c_type_promotes_to (TREE_VALUE (args1)) != TREE_VALUE (args1)) |
| return 0; |
| } |
| /* If one of the lists has an error marker, ignore this arg. */ |
| else if (TREE_CODE (TREE_VALUE (args1)) == ERROR_MARK |
| || TREE_CODE (TREE_VALUE (args2)) == ERROR_MARK) |
| ; |
| else if (! (newval = comptypes (TYPE_MAIN_VARIANT (TREE_VALUE (args1)), |
| TYPE_MAIN_VARIANT (TREE_VALUE (args2)), |
| flags))) |
| { |
| /* Allow wait (union {union wait *u; int *i} *) |
| and wait (union wait *) to be compatible. */ |
| if (TREE_CODE (TREE_VALUE (args1)) == UNION_TYPE |
| && (TYPE_NAME (TREE_VALUE (args1)) == 0 |
| || TYPE_TRANSPARENT_UNION (TREE_VALUE (args1))) |
| && TREE_CODE (TYPE_SIZE (TREE_VALUE (args1))) == INTEGER_CST |
| && tree_int_cst_equal (TYPE_SIZE (TREE_VALUE (args1)), |
| TYPE_SIZE (TREE_VALUE (args2)))) |
| { |
| tree memb; |
| for (memb = TYPE_FIELDS (TREE_VALUE (args1)); |
| memb; memb = TREE_CHAIN (memb)) |
| if (comptypes (TREE_TYPE (memb), TREE_VALUE (args2), |
| flags)) |
| break; |
| if (memb == 0) |
| return 0; |
| } |
| else if (TREE_CODE (TREE_VALUE (args2)) == UNION_TYPE |
| && (TYPE_NAME (TREE_VALUE (args2)) == 0 |
| || TYPE_TRANSPARENT_UNION (TREE_VALUE (args2))) |
| && TREE_CODE (TYPE_SIZE (TREE_VALUE (args2))) == INTEGER_CST |
| && tree_int_cst_equal (TYPE_SIZE (TREE_VALUE (args2)), |
| TYPE_SIZE (TREE_VALUE (args1)))) |
| { |
| tree memb; |
| for (memb = TYPE_FIELDS (TREE_VALUE (args2)); |
| memb; memb = TREE_CHAIN (memb)) |
| if (comptypes (TREE_TYPE (memb), TREE_VALUE (args1), |
| flags)) |
| break; |
| if (memb == 0) |
| return 0; |
| } |
| else |
| return 0; |
| } |
| |
| /* comptypes said ok, but record if it said to warn. */ |
| if (newval > val) |
| val = newval; |
| |
| args1 = TREE_CHAIN (args1); |
| args2 = TREE_CHAIN (args2); |
| } |
| } |
| |
| /* Compute the size to increment a pointer by. */ |
| |
| tree |
| c_size_in_bytes (tree type) |
| { |
| enum tree_code code = TREE_CODE (type); |
| |
| if (code == FUNCTION_TYPE || code == VOID_TYPE || code == ERROR_MARK) |
| return size_one_node; |
| |
| if (!COMPLETE_OR_VOID_TYPE_P (type)) |
| { |
| error ("arithmetic on pointer to an incomplete type"); |
| return size_one_node; |
| } |
| |
| /* Convert in case a char is more than one unit. */ |
| return size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type), |
| size_int (TYPE_PRECISION (char_type_node) |
| / BITS_PER_UNIT)); |
| } |
| |
| /* Return either DECL or its known constant value (if it has one). */ |
| |
| tree |
| decl_constant_value (tree decl) |
| { |
| if (/* Don't change a variable array bound or initial value to a constant |
| in a place where a variable is invalid. */ |
| current_function_decl != 0 |
| && ! TREE_THIS_VOLATILE (decl) |
| && TREE_READONLY (decl) |
| && DECL_INITIAL (decl) != 0 |
| && TREE_CODE (DECL_INITIAL (decl)) != ERROR_MARK |
| /* This is invalid if initial value is not constant. |
| If it has either a function call, a memory reference, |
| or a variable, then re-evaluating it could give different results. */ |
| && TREE_CONSTANT (DECL_INITIAL (decl)) |
| /* Check for cases where this is sub-optimal, even though valid. */ |
| && TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR) |
| return DECL_INITIAL (decl); |
| return decl; |
| } |
| |
| /* Return either DECL or its known constant value (if it has one), but |
| return DECL if pedantic or DECL has mode BLKmode. This is for |
| bug-compatibility with the old behavior of decl_constant_value |
| (before GCC 3.0); every use of this function is a bug and it should |
| be removed before GCC 3.1. It is not appropriate to use pedantic |
| in a way that affects optimization, and BLKmode is probably not the |
| right test for avoiding misoptimizations either. */ |
| |
| static tree |
| decl_constant_value_for_broken_optimization (tree decl) |
| { |
| if (pedantic || DECL_MODE (decl) == BLKmode) |
| return decl; |
| else |
| return decl_constant_value (decl); |
| } |
| |
| |
| /* Perform the default conversion of arrays and functions to pointers. |
| Return the result of converting EXP. For any other expression, just |
| return EXP. */ |
| |
| static tree |
| default_function_array_conversion (tree exp) |
| { |
| tree orig_exp; |
| tree type = TREE_TYPE (exp); |
| enum tree_code code = TREE_CODE (type); |
| int not_lvalue = 0; |
| |
| /* Strip NON_LVALUE_EXPRs and no-op conversions, since we aren't using as |
| an lvalue. |
| |
| Do not use STRIP_NOPS here! It will remove conversions from pointer |
| to integer and cause infinite recursion. */ |
| orig_exp = exp; |
| while (TREE_CODE (exp) == NON_LVALUE_EXPR |
| || (TREE_CODE (exp) == NOP_EXPR |
| && TREE_TYPE (TREE_OPERAND (exp, 0)) == TREE_TYPE (exp))) |
| { |
| if (TREE_CODE (exp) == NON_LVALUE_EXPR) |
| not_lvalue = 1; |
| exp = TREE_OPERAND (exp, 0); |
| } |
| |
| /* Preserve the original expression code. */ |
| if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (exp)))) |
| C_SET_EXP_ORIGINAL_CODE (exp, C_EXP_ORIGINAL_CODE (orig_exp)); |
| |
| if (code == FUNCTION_TYPE) |
| { |
| return build_unary_op (ADDR_EXPR, exp, 0); |
| } |
| if (code == ARRAY_TYPE) |
| { |
| tree adr; |
| tree restype = TREE_TYPE (type); |
| tree ptrtype; |
| int constp = 0; |
| int volatilep = 0; |
| int lvalue_array_p; |
| |
| if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'r' || DECL_P (exp)) |
| { |
| constp = TREE_READONLY (exp); |
| volatilep = TREE_THIS_VOLATILE (exp); |
| } |
| |
| if (TYPE_QUALS (type) || constp || volatilep) |
| restype |
| = c_build_qualified_type (restype, |
| TYPE_QUALS (type) |
| | (constp * TYPE_QUAL_CONST) |
| | (volatilep * TYPE_QUAL_VOLATILE)); |
| |
| if (TREE_CODE (exp) == INDIRECT_REF) |
| return convert (TYPE_POINTER_TO (restype), |
| TREE_OPERAND (exp, 0)); |
| |
| if (TREE_CODE (exp) == COMPOUND_EXPR) |
| { |
| tree op1 = default_conversion (TREE_OPERAND (exp, 1)); |
| return build (COMPOUND_EXPR, TREE_TYPE (op1), |
| TREE_OPERAND (exp, 0), op1); |
| } |
| |
| lvalue_array_p = !not_lvalue && lvalue_p (exp); |
| if (!flag_isoc99 && !lvalue_array_p) |
| { |
| /* Before C99, non-lvalue arrays do not decay to pointers. |
| Normally, using such an array would be invalid; but it can |
| be used correctly inside sizeof or as a statement expression. |
| Thus, do not give an error here; an error will result later. */ |
| return exp; |
| } |
| |
| ptrtype = build_pointer_type (restype); |
| |
| if (TREE_CODE (exp) == VAR_DECL) |
| { |
| /* ??? This is not really quite correct |
| in that the type of the operand of ADDR_EXPR |
| is not the target type of the type of the ADDR_EXPR itself. |
| Question is, can this lossage be avoided? */ |
| adr = build1 (ADDR_EXPR, ptrtype, exp); |
| if (!c_mark_addressable (exp)) |
| return error_mark_node; |
| TREE_CONSTANT (adr) = staticp (exp); |
| TREE_SIDE_EFFECTS (adr) = 0; /* Default would be, same as EXP. */ |
| return adr; |
| } |
| /* This way is better for a COMPONENT_REF since it can |
| simplify the offset for a component. */ |
| adr = build_unary_op (ADDR_EXPR, exp, 1); |
| return convert (ptrtype, adr); |
| } |
| return exp; |
| } |
| |
| /* Perform default promotions for C data used in expressions. |
| Arrays and functions are converted to pointers; |
| enumeral types or short or char, to int. |
| In addition, manifest constants symbols are replaced by their values. */ |
| |
| tree |
| default_conversion (tree exp) |
| { |
| tree orig_exp; |
| tree type = TREE_TYPE (exp); |
| enum tree_code code = TREE_CODE (type); |
| |
| if (code == FUNCTION_TYPE || code == ARRAY_TYPE) |
| return default_function_array_conversion (exp); |
| |
| /* Constants can be used directly unless they're not loadable. */ |
| if (TREE_CODE (exp) == CONST_DECL) |
| exp = DECL_INITIAL (exp); |
| |
| /* Replace a nonvolatile const static variable with its value unless |
| it is an array, in which case we must be sure that taking the |
| address of the array produces consistent results. */ |
| else if (optimize && TREE_CODE (exp) == VAR_DECL && code != ARRAY_TYPE) |
| { |
| exp = decl_constant_value_for_broken_optimization (exp); |
| type = TREE_TYPE (exp); |
| } |
| |
| /* Strip NON_LVALUE_EXPRs and no-op conversions, since we aren't using as |
| an lvalue. |
| |
| Do not use STRIP_NOPS here! It will remove conversions from pointer |
| to integer and cause infinite recursion. */ |
| orig_exp = exp; |
| while (TREE_CODE (exp) == NON_LVALUE_EXPR |
| || (TREE_CODE (exp) == NOP_EXPR |
| && TREE_TYPE (TREE_OPERAND (exp, 0)) == TREE_TYPE (exp))) |
| exp = TREE_OPERAND (exp, 0); |
| |
| /* Preserve the original expression code. */ |
| if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (exp)))) |
| C_SET_EXP_ORIGINAL_CODE (exp, C_EXP_ORIGINAL_CODE (orig_exp)); |
| |
| /* Normally convert enums to int, |
| but convert wide enums to something wider. */ |
| if (code == ENUMERAL_TYPE) |
| { |
| type = c_common_type_for_size (MAX (TYPE_PRECISION (type), |
| TYPE_PRECISION (integer_type_node)), |
| ((TYPE_PRECISION (type) |
| >= TYPE_PRECISION (integer_type_node)) |
| && TREE_UNSIGNED (type))); |
| |
| return convert (type, exp); |
| } |
| |
| if (TREE_CODE (exp) == COMPONENT_REF |
| && DECL_C_BIT_FIELD (TREE_OPERAND (exp, 1)) |
| /* If it's thinner than an int, promote it like a |
| c_promoting_integer_type_p, otherwise leave it alone. */ |
| && 0 > compare_tree_int (DECL_SIZE (TREE_OPERAND (exp, 1)), |
| TYPE_PRECISION (integer_type_node))) |
| return convert (integer_type_node, exp); |
| |
| if (c_promoting_integer_type_p (type)) |
| { |
| /* Preserve unsignedness if not really getting any wider. */ |
| if (TREE_UNSIGNED (type) |
| && TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)) |
| return convert (unsigned_type_node, exp); |
| |
| return convert (integer_type_node, exp); |
| } |
| |
| if (code == VOID_TYPE) |
| { |
| error ("void value not ignored as it ought to be"); |
| return error_mark_node; |
| } |
| return exp; |
| } |
| |
| /* Look up COMPONENT in a structure or union DECL. |
| |
| If the component name is not found, returns NULL_TREE. Otherwise, |
| the return value is a TREE_LIST, with each TREE_VALUE a FIELD_DECL |
| stepping down the chain to the component, which is in the last |
| TREE_VALUE of the list. Normally the list is of length one, but if |
| the component is embedded within (nested) anonymous structures or |
| unions, the list steps down the chain to the component. */ |
| |
| static tree |
| lookup_field (tree decl, tree component) |
| { |
| tree type = TREE_TYPE (decl); |
| tree field; |
| |
| /* If TYPE_LANG_SPECIFIC is set, then it is a sorted array of pointers |
| to the field elements. Use a binary search on this array to quickly |
| find the element. Otherwise, do a linear search. TYPE_LANG_SPECIFIC |
| will always be set for structures which have many elements. */ |
| |
| if (TYPE_LANG_SPECIFIC (type)) |
| { |
| int bot, top, half; |
| tree *field_array = &TYPE_LANG_SPECIFIC (type)->s->elts[0]; |
| |
| field = TYPE_FIELDS (type); |
| bot = 0; |
| top = TYPE_LANG_SPECIFIC (type)->s->len; |
| while (top - bot > 1) |
| { |
| half = (top - bot + 1) >> 1; |
| field = field_array[bot+half]; |
| |
| if (DECL_NAME (field) == NULL_TREE) |
| { |
| /* Step through all anon unions in linear fashion. */ |
| while (DECL_NAME (field_array[bot]) == NULL_TREE) |
| { |
| field = field_array[bot++]; |
| if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE |
| || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) |
| { |
| tree anon = lookup_field (field, component); |
| |
| if (anon) |
| return tree_cons (NULL_TREE, field, anon); |
| } |
| } |
| |
| /* Entire record is only anon unions. */ |
| if (bot > top) |
| return NULL_TREE; |
| |
| /* Restart the binary search, with new lower bound. */ |
| continue; |
| } |
| |
| if (DECL_NAME (field) == component) |
| break; |
| if (DECL_NAME (field) < component) |
| bot += half; |
| else |
| top = bot + half; |
| } |
| |
| if (DECL_NAME (field_array[bot]) == component) |
| field = field_array[bot]; |
| else if (DECL_NAME (field) != component) |
| return NULL_TREE; |
| } |
| else |
| { |
| for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) |
| { |
| if (DECL_NAME (field) == NULL_TREE |
| && (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE |
| || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)) |
| { |
| tree anon = lookup_field (field, component); |
| |
| if (anon) |
| return tree_cons (NULL_TREE, field, anon); |
| } |
| |
| if (DECL_NAME (field) == component) |
| break; |
| } |
| |
| if (field == NULL_TREE) |
| return NULL_TREE; |
| } |
| |
| return tree_cons (NULL_TREE, field, NULL_TREE); |
| } |
| |
| /* Make an expression to refer to the COMPONENT field of |
| structure or union value DATUM. COMPONENT is an IDENTIFIER_NODE. */ |
| |
| tree |
| build_component_ref (tree datum, tree component) |
| { |
| tree type = TREE_TYPE (datum); |
| enum tree_code code = TREE_CODE (type); |
| tree field = NULL; |
| tree ref; |
| |
| /* See if there is a field or component with name COMPONENT. */ |
| |
| if (code == RECORD_TYPE || code == UNION_TYPE) |
| { |
| if (!COMPLETE_TYPE_P (type)) |
| { |
| c_incomplete_type_error (NULL_TREE, type); |
| return error_mark_node; |
| } |
| |
| field = lookup_field (datum, component); |
| |
| if (!field) |
| { |
| error ("%s has no member named `%s'", |
| code == RECORD_TYPE ? "structure" : "union", |
| IDENTIFIER_POINTER (component)); |
| return error_mark_node; |
| } |
| |
| /* Chain the COMPONENT_REFs if necessary down to the FIELD. |
| This might be better solved in future the way the C++ front |
| end does it - by giving the anonymous entities each a |
| separate name and type, and then have build_component_ref |
| recursively call itself. We can't do that here. */ |
| do |
| { |
| tree subdatum = TREE_VALUE (field); |
| |
| if (TREE_TYPE (subdatum) == error_mark_node) |
| return error_mark_node; |
| |
| ref = build (COMPONENT_REF, TREE_TYPE (subdatum), datum, subdatum); |
| if (TREE_READONLY (datum) || TREE_READONLY (subdatum)) |
| TREE_READONLY (ref) = 1; |
| if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (subdatum)) |
| TREE_THIS_VOLATILE (ref) = 1; |
| |
| if (TREE_DEPRECATED (subdatum)) |
| warn_deprecated_use (subdatum); |
| |
| datum = ref; |
| |
| field = TREE_CHAIN (field); |
| } |
| while (field); |
| |
| return ref; |
| } |
| else if (code != ERROR_MARK) |
| error ("request for member `%s' in something not a structure or union", |
| IDENTIFIER_POINTER (component)); |
| |
| return error_mark_node; |
| } |
| |
| /* Given an expression PTR for a pointer, return an expression |
| for the value pointed to. |
| ERRORSTRING is the name of the operator to appear in error messages. */ |
| |
| tree |
| build_indirect_ref (tree ptr, const char *errorstring) |
| { |
| tree pointer = default_conversion (ptr); |
| tree type = TREE_TYPE (pointer); |
| |
| if (TREE_CODE (type) == POINTER_TYPE) |
| { |
| if (TREE_CODE (pointer) == ADDR_EXPR |
| && (TREE_TYPE (TREE_OPERAND (pointer, 0)) |
| == TREE_TYPE (type))) |
| return TREE_OPERAND (pointer, 0); |
| else |
| { |
| tree t = TREE_TYPE (type); |
| tree ref = build1 (INDIRECT_REF, TYPE_MAIN_VARIANT (t), pointer); |
| |
| if (!COMPLETE_OR_VOID_TYPE_P (t) && TREE_CODE (t) != ARRAY_TYPE) |
| { |
| error ("dereferencing pointer to incomplete type"); |
| return error_mark_node; |
| } |
| if (VOID_TYPE_P (t) && skip_evaluation == 0) |
| warning ("dereferencing `void *' pointer"); |
| |
| /* We *must* set TREE_READONLY when dereferencing a pointer to const, |
| so that we get the proper error message if the result is used |
| to assign to. Also, &* is supposed to be a no-op. |
| And ANSI C seems to specify that the type of the result |
| should be the const type. */ |
| /* A de-reference of a pointer to const is not a const. It is valid |
| to change it via some other pointer. */ |
| TREE_READONLY (ref) = TYPE_READONLY (t); |
| TREE_SIDE_EFFECTS (ref) |
| = TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer); |
| TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t); |
| return ref; |
| } |
| } |
| else if (TREE_CODE (pointer) != ERROR_MARK) |
| error ("invalid type argument of `%s'", errorstring); |
| return error_mark_node; |
| } |
| |
| /* This handles expressions of the form "a[i]", which denotes |
| an array reference. |
| |
| This is logically equivalent in C to *(a+i), but we may do it differently. |
| If A is a variable or a member, we generate a primitive ARRAY_REF. |
| This avoids forcing the array out of registers, and can work on |
| arrays that are not lvalues (for example, members of structures returned |
| by functions). */ |
| |
| tree |
| build_array_ref (tree array, tree index) |
| { |
| if (index == 0) |
| { |
| error ("subscript missing in array reference"); |
| return error_mark_node; |
| } |
| |
| if (TREE_TYPE (array) == error_mark_node |
| || TREE_TYPE (index) == error_mark_node) |
| return error_mark_node; |
| |
| if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE |
| && TREE_CODE (array) != INDIRECT_REF) |
| { |
| tree rval, type; |
| |
| /* Subscripting with type char is likely to lose |
| on a machine where chars are signed. |
| So warn on any machine, but optionally. |
| Don't warn for unsigned char since that type is safe. |
| Don't warn for signed char because anyone who uses that |
| must have done so deliberately. */ |
| if (warn_char_subscripts |
| && TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node) |
| warning ("array subscript has type `char'"); |
| |
| /* Apply default promotions *after* noticing character types. */ |
| index = default_conversion (index); |
| |
| /* Require integer *after* promotion, for sake of enums. */ |
| if (TREE_CODE (TREE_TYPE (index)) != INTEGER_TYPE) |
| { |
| error ("array subscript is not an integer"); |
| return error_mark_node; |
| } |
| |
| /* An array that is indexed by a non-constant |
| cannot be stored in a register; we must be able to do |
| address arithmetic on its address. |
| Likewise an array of elements of variable size. */ |
| if (TREE_CODE (index) != INTEGER_CST |
| || (COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (array))) |
| && TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (array)))) != INTEGER_CST)) |
| { |
| if (!c_mark_addressable (array)) |
| return error_mark_node; |
| } |
| /* An array that is indexed by a constant value which is not within |
| the array bounds cannot be stored in a register either; because we |
| would get a crash in store_bit_field/extract_bit_field when trying |
| to access a non-existent part of the register. */ |
| if (TREE_CODE (index) == INTEGER_CST |
| && TYPE_VALUES (TREE_TYPE (array)) |
| && ! int_fits_type_p (index, TYPE_VALUES (TREE_TYPE (array)))) |
| { |
| if (!c_mark_addressable (array)) |
| return error_mark_node; |
| } |
| |
| if (pedantic) |
| { |
| tree foo = array; |
| while (TREE_CODE (foo) == COMPONENT_REF) |
| foo = TREE_OPERAND (foo, 0); |
| if (TREE_CODE (foo) == VAR_DECL && DECL_REGISTER (foo)) |
| pedwarn ("ISO C forbids subscripting `register' array"); |
| else if (! flag_isoc99 && ! lvalue_p (foo)) |
| pedwarn ("ISO C90 forbids subscripting non-lvalue array"); |
| } |
| |
| type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (array))); |
| rval = build (ARRAY_REF, type, array, index); |
| /* Array ref is const/volatile if the array elements are |
| or if the array is. */ |
| TREE_READONLY (rval) |
| |= (TYPE_READONLY (TREE_TYPE (TREE_TYPE (array))) |
| | TREE_READONLY (array)); |
| TREE_SIDE_EFFECTS (rval) |
| |= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (array))) |
| | TREE_SIDE_EFFECTS (array)); |
| TREE_THIS_VOLATILE (rval) |
| |= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (array))) |
| /* This was added by rms on 16 Nov 91. |
| It fixes vol struct foo *a; a->elts[1] |
| in an inline function. |
| Hope it doesn't break something else. */ |
| | TREE_THIS_VOLATILE (array)); |
| return require_complete_type (fold (rval)); |
| } |
| |
| { |
| tree ar = default_conversion (array); |
| tree ind = default_conversion (index); |
| |
| /* Do the same warning check as above, but only on the part that's |
| syntactically the index and only if it is also semantically |
| the index. */ |
| if (warn_char_subscripts |
| && TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE |
| && TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node) |
| warning ("subscript has type `char'"); |
| |
| /* Put the integer in IND to simplify error checking. */ |
| if (TREE_CODE (TREE_TYPE (ar)) == INTEGER_TYPE) |
| { |
| tree temp = ar; |
| ar = ind; |
| ind = temp; |
| } |
| |
| if (ar == error_mark_node) |
| return ar; |
| |
| if (TREE_CODE (TREE_TYPE (ar)) != POINTER_TYPE |
| || TREE_CODE (TREE_TYPE (TREE_TYPE (ar))) == FUNCTION_TYPE) |
| { |
| error ("subscripted value is neither array nor pointer"); |
| return error_mark_node; |
| } |
| if (TREE_CODE (TREE_TYPE (ind)) != INTEGER_TYPE) |
| { |
| error ("array subscript is not an integer"); |
| return error_mark_node; |
| } |
| |
| return build_indirect_ref (build_binary_op (PLUS_EXPR, ar, ind, 0), |
| "array indexing"); |
| } |
| } |
| |
| /* Build an external reference to identifier ID. FUN indicates |
| whether this will be used for a function call. */ |
| tree |
| build_external_ref (tree id, int fun) |
| { |
| tree ref; |
| tree decl = lookup_name (id); |
| tree objc_ivar = lookup_objc_ivar (id); |
| |
| if (decl && decl != error_mark_node) |
| { |
| /* Properly declared variable or function reference. */ |
| if (!objc_ivar) |
| ref = decl; |
| else if (decl != objc_ivar && !DECL_FILE_SCOPE_P (decl)) |
| { |
| warning ("local declaration of `%s' hides instance variable", |
| IDENTIFIER_POINTER (id)); |
| ref = decl; |
| } |
| else |
| ref = objc_ivar; |
| } |
| else if (objc_ivar) |
| ref = objc_ivar; |
| else if (fun) |
| /* Implicit function declaration. */ |
| ref = implicitly_declare (id); |
| else if (decl == error_mark_node) |
| /* Don't complain about something that's already been |
| complained about. */ |
| return error_mark_node; |
| else |
| { |
| undeclared_variable (id); |
| return error_mark_node; |
| } |
| |
| if (TREE_TYPE (ref) == error_mark_node) |
| return error_mark_node; |
| |
| if (TREE_DEPRECATED (ref)) |
| warn_deprecated_use (ref); |
| |
| if (!skip_evaluation) |
| assemble_external (ref); |
| TREE_USED (ref) = 1; |
| |
| if (TREE_CODE (ref) == CONST_DECL) |
| { |
| ref = DECL_INITIAL (ref); |
| TREE_CONSTANT (ref) = 1; |
| } |
| else if (current_function_decl != 0 |
| && !DECL_FILE_SCOPE_P (current_function_decl) |
| && (TREE_CODE (ref) == VAR_DECL |
| || TREE_CODE (ref) == PARM_DECL |
| || TREE_CODE (ref) == FUNCTION_DECL)) |
| { |
| tree context = decl_function_context (ref); |
| |
| if (context != 0 && context != current_function_decl) |
| DECL_NONLOCAL (ref) = 1; |
| } |
| |
| return ref; |
| } |
| |
| /* Build a function call to function FUNCTION with parameters PARAMS. |
| PARAMS is a list--a chain of TREE_LIST nodes--in which the |
| TREE_VALUE of each node is a parameter-expression. |
| FUNCTION's data type may be a function type or a pointer-to-function. */ |
| |
| tree |
| build_function_call (tree function, tree params) |
| { |
| tree fntype, fundecl = 0; |
| tree coerced_params; |
| tree name = NULL_TREE, result; |
| tree tem; |
| |
| /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue. */ |
| STRIP_TYPE_NOPS (function); |
| |
| /* Convert anything with function type to a pointer-to-function. */ |
| if (TREE_CODE (function) == FUNCTION_DECL) |
| { |
| name = DECL_NAME (function); |
| |
| /* Differs from default_conversion by not setting TREE_ADDRESSABLE |
| (because calling an inline function does not mean the function |
| needs to be separately compiled). */ |
| fntype = build_type_variant (TREE_TYPE (function), |
| TREE_READONLY (function), |
| TREE_THIS_VOLATILE (function)); |
| fundecl = function; |
| function = build1 (ADDR_EXPR, build_pointer_type (fntype), function); |
| } |
| else |
| function = default_conversion (function); |
| |
| fntype = TREE_TYPE (function); |
| |
| if (TREE_CODE (fntype) == ERROR_MARK) |
| return error_mark_node; |
| |
| if (!(TREE_CODE (fntype) == POINTER_TYPE |
| && TREE_CODE (TREE_TYPE (fntype)) == FUNCTION_TYPE)) |
| { |
| error ("called object is not a function"); |
| return error_mark_node; |
| } |
| |
| if (fundecl && TREE_THIS_VOLATILE (fundecl)) |
| current_function_returns_abnormally = 1; |
| |
| /* fntype now gets the type of function pointed to. */ |
| fntype = TREE_TYPE (fntype); |
| |
| /* Check that the function is called through a compatible prototype. |
| If it is not, replace the call by a trap, wrapped up in a compound |
| expression if necessary. This has the nice side-effect to prevent |
| the tree-inliner from generating invalid assignment trees which may |
| blow up in the RTL expander later. |
| |
| ??? This doesn't work for Objective-C because objc_comptypes |
| refuses to compare function prototypes, yet the compiler appears |
| to build calls that are flagged as invalid by C's comptypes. */ |
| if (! c_dialect_objc () |
| && TREE_CODE (function) == NOP_EXPR |
| && TREE_CODE (tem = TREE_OPERAND (function, 0)) == ADDR_EXPR |
| && TREE_CODE (tem = TREE_OPERAND (tem, 0)) == FUNCTION_DECL |
| && ! comptypes (fntype, TREE_TYPE (tem), COMPARE_STRICT)) |
| { |
| tree return_type = TREE_TYPE (fntype); |
| tree trap = build_function_call (built_in_decls[BUILT_IN_TRAP], |
| NULL_TREE); |
| |
| /* This situation leads to run-time undefined behavior. We can't, |
| therefore, simply error unless we can prove that all possible |
| executions of the program must execute the code. */ |
| warning ("function called through a non-compatible type"); |
| |
| /* We can, however, treat "undefined" any way we please. |
| Call abort to encourage the user to fix the program. */ |
| inform ("if this code is reached, the program will abort"); |
| |
| if (VOID_TYPE_P (return_type)) |
| return trap; |
| else |
| { |
| tree rhs; |
| |
| if (AGGREGATE_TYPE_P (return_type)) |
| rhs = build_compound_literal (return_type, |
| build_constructor (return_type, |
| NULL_TREE)); |
| else |
| rhs = fold (build1 (NOP_EXPR, return_type, integer_zero_node)); |
| |
| return build (COMPOUND_EXPR, return_type, trap, rhs); |
| } |
| } |
| |
| /* Convert the parameters to the types declared in the |
| function prototype, or apply default promotions. */ |
| |
| coerced_params |
| = convert_arguments (TYPE_ARG_TYPES (fntype), params, name, fundecl); |
| |
| /* Check that the arguments to the function are valid. */ |
| |
| check_function_arguments (TYPE_ATTRIBUTES (fntype), coerced_params); |
| |
| /* Recognize certain built-in functions so we can make tree-codes |
| other than CALL_EXPR. We do this when it enables fold-const.c |
| to do something useful. */ |
| |
| if (TREE_CODE (function) == ADDR_EXPR |
| && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL |
| && DECL_BUILT_IN (TREE_OPERAND (function, 0))) |
| { |
| result = expand_tree_builtin (TREE_OPERAND (function, 0), |
| params, coerced_params); |
| if (result) |
| return result; |
| } |
| |
| result = build (CALL_EXPR, TREE_TYPE (fntype), |
| function, coerced_params, NULL_TREE); |
| TREE_SIDE_EFFECTS (result) = 1; |
| |
| if (require_constant_value) |
| { |
| result = fold_initializer (result); |
| |
| if (TREE_CONSTANT (result) |
| && (name == NULL_TREE |
| || strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10) != 0)) |
| pedwarn_init ("initializer element is not constant"); |
| } |
| else |
| result = fold (result); |
| |
| if (VOID_TYPE_P (TREE_TYPE (result))) |
| return result; |
| return require_complete_type (result); |
| } |
| |
| /* Convert the argument expressions in the list VALUES |
| to the types in the list TYPELIST. The result is a list of converted |
| argument expressions. |
| |
| If TYPELIST is exhausted, or when an element has NULL as its type, |
| perform the default conversions. |
| |
| PARMLIST is the chain of parm decls for the function being called. |
| It may be 0, if that info is not available. |
| It is used only for generating error messages. |
| |
| NAME is an IDENTIFIER_NODE or 0. It is used only for error messages. |
| |
| This is also where warnings about wrong number of args are generated. |
| |
| Both VALUES and the returned value are chains of TREE_LIST nodes |
| with the elements of the list in the TREE_VALUE slots of those nodes. */ |
| |
| static tree |
| convert_arguments (tree typelist, tree values, tree name, tree fundecl) |
| { |
| tree typetail, valtail; |
| tree result = NULL; |
| int parmnum; |
| |
| /* Scan the given expressions and types, producing individual |
| converted arguments and pushing them on RESULT in reverse order. */ |
| |
| for (valtail = values, typetail = typelist, parmnum = 0; |
| valtail; |
| valtail = TREE_CHAIN (valtail), parmnum++) |
| { |
| tree type = typetail ? TREE_VALUE (typetail) : 0; |
| tree val = TREE_VALUE (valtail); |
| |
| if (type == void_type_node) |
| { |
| if (name) |
| error ("too many arguments to function `%s'", |
| IDENTIFIER_POINTER (name)); |
| else |
| error ("too many arguments to function"); |
| break; |
| } |
| |
| /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ |
| /* Do not use STRIP_NOPS here! We do not want an enumerator with value 0 |
| to convert automatically to a pointer. */ |
| if (TREE_CODE (val) == NON_LVALUE_EXPR) |
| val = TREE_OPERAND (val, 0); |
| |
| val = default_function_array_conversion (val); |
| |
| val = require_complete_type (val); |
| |
| if (type != 0) |
| { |
| /* Formal parm type is specified by a function prototype. */ |
| tree parmval; |
| |
| if (!COMPLETE_TYPE_P (type)) |
| { |
| error ("type of formal parameter %d is incomplete", parmnum + 1); |
| parmval = val; |
| } |
| else |
| { |
| /* Optionally warn about conversions that |
| differ from the default conversions. */ |
| if (warn_conversion || warn_traditional) |
| { |
| int formal_prec = TYPE_PRECISION (type); |
| |
| if (INTEGRAL_TYPE_P (type) |
| && TREE_CODE (TREE_TYPE (val)) == REAL_TYPE) |
| warn_for_assignment ("%s as integer rather than floating due to prototype", (char *) 0, name, parmnum + 1); |
| if (INTEGRAL_TYPE_P (type) |
| && TREE_CODE (TREE_TYPE (val)) == COMPLEX_TYPE) |
| warn_for_assignment ("%s as integer rather than complex due to prototype", (char *) 0, name, parmnum + 1); |
| else if (TREE_CODE (type) == COMPLEX_TYPE |
| && TREE_CODE (TREE_TYPE (val)) == REAL_TYPE) |
| warn_for_assignment ("%s as complex rather than floating due to prototype", (char *) 0, name, parmnum + 1); |
| else if (TREE_CODE (type) == REAL_TYPE |
| && INTEGRAL_TYPE_P (TREE_TYPE (val))) |
| warn_for_assignment ("%s as floating rather than integer due to prototype", (char *) 0, name, parmnum + 1); |
| else if (TREE_CODE (type) == COMPLEX_TYPE |
| && INTEGRAL_TYPE_P (TREE_TYPE (val))) |
| warn_for_assignment ("%s as complex rather than integer due to prototype", (char *) 0, name, parmnum + 1); |
| else if (TREE_CODE (type) == REAL_TYPE |
| && TREE_CODE (TREE_TYPE (val)) == COMPLEX_TYPE) |
| warn_for_assignment ("%s as floating rather than complex due to prototype", (char *) 0, name, parmnum + 1); |
| /* ??? At some point, messages should be written about |
| conversions between complex types, but that's too messy |
| to do now. */ |
| else if (TREE_CODE (type) == REAL_TYPE |
| && TREE_CODE (TREE_TYPE (val)) == REAL_TYPE) |
| { |
| /* Warn if any argument is passed as `float', |
| since without a prototype it would be `double'. */ |
| if (formal_prec == TYPE_PRECISION (float_type_node)) |
| warn_for_assignment ("%s as `float' rather than `double' due to prototype", (char *) 0, name, parmnum + 1); |
| } |
| /* Detect integer changing in width or signedness. |
| These warnings are only activated with |
| -Wconversion, not with -Wtraditional. */ |
| else if (warn_conversion && INTEGRAL_TYPE_P (type) |
| && INTEGRAL_TYPE_P (TREE_TYPE (val))) |
| { |
| tree would_have_been = default_conversion (val); |
| tree type1 = TREE_TYPE (would_have_been); |
| |
| if (TREE_CODE (type) == ENUMERAL_TYPE |
| && (TYPE_MAIN_VARIANT (type) |
| == TYPE_MAIN_VARIANT (TREE_TYPE (val)))) |
| /* No warning if function asks for enum |
| and the actual arg is that enum type. */ |
| ; |
| else if (formal_prec != TYPE_PRECISION (type1)) |
| warn_for_assignment ("%s with different width due to prototype", (char *) 0, name, parmnum + 1); |
| else if (TREE_UNSIGNED (type) == TREE_UNSIGNED (type1)) |
| ; |
| /* Don't complain if the formal parameter type |
| is an enum, because we can't tell now whether |
| the value was an enum--even the same enum. */ |
| else if (TREE_CODE (type) == ENUMERAL_TYPE) |
| ; |
| else if (TREE_CODE (val) == INTEGER_CST |
| && int_fits_type_p (val, type)) |
| /* Change in signedness doesn't matter |
| if a constant value is unaffected. */ |
| ; |
| /* Likewise for a constant in a NOP_EXPR. */ |
| else if (TREE_CODE (val) == NOP_EXPR |
| && TREE_CODE (TREE_OPERAND (val, 0)) == INTEGER_CST |
| && int_fits_type_p (TREE_OPERAND (val, 0), type)) |
| ; |
| /* If the value is extended from a narrower |
| unsigned type, it doesn't matter whether we |
| pass it as signed or unsigned; the value |
| certainly is the same either way. */ |
| else if (TYPE_PRECISION (TREE_TYPE (val)) < TYPE_PRECISION (type) |
| && TREE_UNSIGNED (TREE_TYPE (val))) |
| ; |
| else if (TREE_UNSIGNED (type)) |
| warn_for_assignment ("%s as unsigned due to prototype", (char *) 0, name, parmnum + 1); |
| else |
| warn_for_assignment ("%s as signed due to prototype", (char *) 0, name, parmnum + 1); |
| } |
| } |
| |
| parmval = convert_for_assignment (type, val, |
| (char *) 0, /* arg passing */ |
| fundecl, name, parmnum + 1); |
| |
| if (targetm.calls.promote_prototypes (fundecl ? TREE_TYPE (fundecl) : 0) |
| && INTEGRAL_TYPE_P (type) |
| && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))) |
| parmval = default_conversion (parmval); |
| } |
| result = tree_cons (NULL_TREE, parmval, result); |
| } |
| else if (TREE_CODE (TREE_TYPE (val)) == REAL_TYPE |
| && (TYPE_PRECISION (TREE_TYPE (val)) |
| < TYPE_PRECISION (double_type_node))) |
| /* Convert `float' to `double'. */ |
| result = tree_cons (NULL_TREE, convert (double_type_node, val), result); |
| else |
| /* Convert `short' and `char' to full-size `int'. */ |
| result = tree_cons (NULL_TREE, default_conversion (val), result); |
| |
| if (typetail) |
| typetail = TREE_CHAIN (typetail); |
| } |
| |
| if (typetail != 0 && TREE_VALUE (typetail) != void_type_node) |
| { |
| if (name) |
| error ("too few arguments to function `%s'", |
| IDENTIFIER_POINTER (name)); |
| else |
| error ("too few arguments to function"); |
| } |
| |
| return nreverse (result); |
| } |
| |
| /* This is the entry point used by the parser |
| for binary operators in the input. |
| In addition to constructing the expression, |
| we check for operands that were written with other binary operators |
| in a way that is likely to confuse the user. */ |
| |
| tree |
| parser_build_binary_op (enum tree_code code, tree arg1, tree arg2) |
| { |
| tree result = build_binary_op (code, arg1, arg2, 1); |
| |
| char class; |
| char class1 = TREE_CODE_CLASS (TREE_CODE (arg1)); |
| char class2 = TREE_CODE_CLASS (TREE_CODE (arg2)); |
| enum tree_code code1 = ERROR_MARK; |
| enum tree_code code2 = ERROR_MARK; |
| |
| if (TREE_CODE (result) == ERROR_MARK) |
| return error_mark_node; |
| |
| if (IS_EXPR_CODE_CLASS (class1)) |
| code1 = C_EXP_ORIGINAL_CODE (arg1); |
| if (IS_EXPR_CODE_CLASS (class2)) |
| code2 = C_EXP_ORIGINAL_CODE (arg2); |
| |
| /* Check for cases such as x+y<<z which users are likely |
| to misinterpret. If parens are used, C_EXP_ORIGINAL_CODE |
| is cleared to prevent these warnings. */ |
| if (warn_parentheses) |
| { |
| if (code == LSHIFT_EXPR || code == RSHIFT_EXPR) |
| { |
| if (code1 == PLUS_EXPR || code1 == MINUS_EXPR |
| || code2 == PLUS_EXPR || code2 == MINUS_EXPR) |
| warning ("suggest parentheses around + or - inside shift"); |
| } |
| |
| if (code == TRUTH_ORIF_EXPR) |
| { |
| if (code1 == TRUTH_ANDIF_EXPR |
| || code2 == TRUTH_ANDIF_EXPR) |
| warning ("suggest parentheses around && within ||"); |
| } |
| |
| if (code == BIT_IOR_EXPR) |
| { |
| if (code1 == BIT_AND_EXPR || code1 == BIT_XOR_EXPR |
| || code1 == PLUS_EXPR || code1 == MINUS_EXPR |
| || code2 == BIT_AND_EXPR || code2 == BIT_XOR_EXPR |
| || code2 == PLUS_EXPR || code2 == MINUS_EXPR) |
| warning ("suggest parentheses around arithmetic in operand of |"); |
| /* Check cases like x|y==z */ |
| if (TREE_CODE_CLASS (code1) == '<' || TREE_CODE_CLASS (code2) == '<') |
| warning ("suggest parentheses around comparison in operand of |"); |
| } |
| |
| if (code == BIT_XOR_EXPR) |
| { |
| if (code1 == BIT_AND_EXPR |
| || code1 == PLUS_EXPR || code1 == MINUS_EXPR |
| || code2 == BIT_AND_EXPR |
| || code2 == PLUS_EXPR || code2 == MINUS_EXPR) |
| warning ("suggest parentheses around arithmetic in operand of ^"); |
| /* Check cases like x^y==z */ |
| if (TREE_CODE_CLASS (code1) == '<' || TREE_CODE_CLASS (code2) == '<') |
| warning ("suggest parentheses around comparison in operand of ^"); |
| } |
| |
| if (code == BIT_AND_EXPR) |
| { |
| if (code1 == PLUS_EXPR || code1 == MINUS_EXPR |
| || code2 == PLUS_EXPR || code2 == MINUS_EXPR) |
| warning ("suggest parentheses around + or - in operand of &"); |
| /* Check cases like x&y==z */ |
| if (TREE_CODE_CLASS (code1) == '<' || TREE_CODE_CLASS (code2) == '<') |
| warning ("suggest parentheses around comparison in operand of &"); |
| } |
| } |
| |
| /* Similarly, check for cases like 1<=i<=10 that are probably errors. */ |
| if (TREE_CODE_CLASS (code) == '<' && extra_warnings |
| && (TREE_CODE_CLASS (code1) == '<' || TREE_CODE_CLASS (code2) == '<')) |
| warning ("comparisons like X<=Y<=Z do not have their mathematical meaning"); |
| |
| unsigned_conversion_warning (result, arg1); |
| unsigned_conversion_warning (result, arg2); |
| overflow_warning (result); |
| |
| class = TREE_CODE_CLASS (TREE_CODE (result)); |
| |
| /* Record the code that was specified in the source, |
| for the sake of warnings about confusing nesting. */ |
| if (IS_EXPR_CODE_CLASS (class)) |
| C_SET_EXP_ORIGINAL_CODE (result, code); |
| else |
| { |
| int flag = TREE_CONSTANT (result); |
| /* We used to use NOP_EXPR rather than NON_LVALUE_EXPR |
| so that convert_for_assignment wouldn't strip it. |
| That way, we got warnings for things like p = (1 - 1). |
| But it turns out we should not get those warnings. */ |
| result = build1 (NON_LVALUE_EXPR, TREE_TYPE (result), result); |
| C_SET_EXP_ORIGINAL_CODE (result, code); |
| TREE_CONSTANT (result) = flag; |
| } |
| |
| return result; |
| } |
| |
| |
| /* Return true if `t' is known to be non-negative. */ |
| |
| int |
| c_tree_expr_nonnegative_p (tree t) |
| { |
| if (TREE_CODE (t) == STMT_EXPR) |
| { |
| t = COMPOUND_BODY (STMT_EXPR_STMT (t)); |
| |
| /* Find the last statement in the chain, ignoring the final |
| * scope statement */ |
| while (TREE_CHAIN (t) != NULL_TREE |
| && TREE_CODE (TREE_CHAIN (t)) != SCOPE_STMT) |
| t = TREE_CHAIN (t); |
| return tree_expr_nonnegative_p (TREE_OPERAND (t, 0)); |
| } |
| return tree_expr_nonnegative_p (t); |
| } |
| |
| /* Return a tree for the difference of pointers OP0 and OP1. |
| The resulting tree has type int. */ |
| |
| static tree |
| pointer_diff (tree op0, tree op1) |
| { |
| tree result, folded; |
| tree restype = ptrdiff_type_node; |
| |
| tree target_type = TREE_TYPE (TREE_TYPE (op0)); |
| tree con0, con1, lit0, lit1; |
| tree orig_op1 = op1; |
| |
| if (pedantic || warn_pointer_arith) |
| { |
| if (TREE_CODE (target_type) == VOID_TYPE) |
| pedwarn ("pointer of type `void *' used in subtraction"); |
| if (TREE_CODE (target_type) == FUNCTION_TYPE) |
| pedwarn ("pointer to a function used in subtraction"); |
| } |
| |
| /* If the conversion to ptrdiff_type does anything like widening or |
| converting a partial to an integral mode, we get a convert_expression |
| that is in the way to do any simplifications. |
| (fold-const.c doesn't know that the extra bits won't be needed. |
| split_tree uses STRIP_SIGN_NOPS, which leaves conversions to a |
| different mode in place.) |
| So first try to find a common term here 'by hand'; we want to cover |
| at least the cases that occur in legal static initializers. */ |
| con0 = TREE_CODE (op0) == NOP_EXPR ? TREE_OPERAND (op0, 0) : op0; |
| con1 = TREE_CODE (op1) == NOP_EXPR ? TREE_OPERAND (op1, 0) : op1; |
| |
| if (TREE_CODE (con0) == PLUS_EXPR) |
| { |
| lit0 = TREE_OPERAND (con0, 1); |
| con0 = TREE_OPERAND (con0, 0); |
| } |
| else |
| lit0 = integer_zero_node; |
| |
| if (TREE_CODE (con1) == PLUS_EXPR) |
| { |
| lit1 = TREE_OPERAND (con1, 1); |
| con1 = TREE_OPERAND (con1, 0); |
| } |
| else |
| lit1 = integer_zero_node; |
| |
| if (operand_equal_p (con0, con1, 0)) |
| { |
| op0 = lit0; |
| op1 = lit1; |
| } |
| |
| |
| /* First do the subtraction as integers; |
| then drop through to build the divide operator. |
| Do not do default conversions on the minus operator |
| in case restype is a short type. */ |
| |
| op0 = build_binary_op (MINUS_EXPR, convert (restype, op0), |
| convert (restype, op1), 0); |
| /* This generates an error if op1 is pointer to incomplete type. */ |
| if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (orig_op1)))) |
| error ("arithmetic on pointer to an incomplete type"); |
| |
| /* This generates an error if op0 is pointer to incomplete type. */ |
| op1 = c_size_in_bytes (target_type); |
| |
| /* Divide by the size, in easiest possible way. */ |
| |
| result = build (EXACT_DIV_EXPR, restype, op0, convert (restype, op1)); |
| |
| folded = fold (result); |
| if (folded == result) |
| TREE_CONSTANT (folded) = TREE_CONSTANT (op0) & TREE_CONSTANT (op1); |
| return folded; |
| } |
| |
| /* Construct and perhaps optimize a tree representation |
| for a unary operation. CODE, a tree_code, specifies the operation |
| and XARG is the operand. |
| For any CODE other than ADDR_EXPR, FLAG nonzero suppresses |
| the default promotions (such as from short to int). |
| For ADDR_EXPR, the default promotions are not applied; FLAG nonzero |
| allows non-lvalues; this is only used to handle conversion of non-lvalue |
| arrays to pointers in C99. */ |
| |
| tree |
| build_unary_op (enum tree_code code, tree xarg, int flag) |
| { |
| /* No default_conversion here. It causes trouble for ADDR_EXPR. */ |
| tree arg = xarg; |
| tree argtype = 0; |
| enum tree_code typecode = TREE_CODE (TREE_TYPE (arg)); |
| tree val; |
| int noconvert = flag; |
| |
| if (typecode == ERROR_MARK) |
| return error_mark_node; |
| if (typecode == ENUMERAL_TYPE || typecode == BOOLEAN_TYPE) |
| typecode = INTEGER_TYPE; |
| |
| switch (code) |
| { |
| case CONVERT_EXPR: |
| /* This is used for unary plus, because a CONVERT_EXPR |
| is enough to prevent anybody from looking inside for |
| associativity, but won't generate any code. */ |
| if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE |
| || typecode == COMPLEX_TYPE)) |
| { |
| error ("wrong type argument to unary plus"); |
| return error_mark_node; |
| } |
| else if (!noconvert) |
| arg = default_conversion (arg); |
| arg = non_lvalue (arg); |
| break; |
| |
| case NEGATE_EXPR: |
| if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE |
| || typecode == COMPLEX_TYPE |
| || typecode == VECTOR_TYPE)) |
| { |
| error ("wrong type argument to unary minus"); |
| return error_mark_node; |
| } |
| else if (!noconvert) |
| arg = default_conversion (arg); |
| break; |
| |
| case BIT_NOT_EXPR: |
| if (typecode == INTEGER_TYPE || typecode == VECTOR_TYPE) |
| { |
| if (!noconvert) |
| arg = default_conversion (arg); |
| } |
| else if (typecode == COMPLEX_TYPE) |
| { |
| code = CONJ_EXPR; |
| if (pedantic) |
| pedwarn ("ISO C does not support `~' for complex conjugation"); |
| if (!noconvert) |
| arg = default_conversion (arg); |
| } |
| else |
| { |
| error ("wrong type argument to bit-complement"); |
| return error_mark_node; |
| } |
| break; |
| |
| case ABS_EXPR: |
| if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE)) |
| { |
| error ("wrong type argument to abs"); |
| return error_mark_node; |
| } |
| else if (!noconvert) |
| arg = default_conversion (arg); |
| break; |
| |
| case CONJ_EXPR: |
| /* Conjugating a real value is a no-op, but allow it anyway. */ |
| if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE |
| || typecode == COMPLEX_TYPE)) |
| { |
| error ("wrong type argument to conjugation"); |
| return error_mark_node; |
| } |
| else if (!noconvert) |
| arg = default_conversion (arg); |
| break; |
| |
| case TRUTH_NOT_EXPR: |
| if (typecode != INTEGER_TYPE |
| && typecode != REAL_TYPE && typecode != POINTER_TYPE |
| && typecode != COMPLEX_TYPE |
| /* These will convert to a pointer. */ |
| && typecode != ARRAY_TYPE && typecode != FUNCTION_TYPE) |
| { |
| error ("wrong type argument to unary exclamation mark"); |
| return error_mark_node; |
| } |
| arg = c_common_truthvalue_conversion (arg); |
| return invert_truthvalue (arg); |
| |
| case NOP_EXPR: |
| break; |
| |
| case REALPART_EXPR: |
| if (TREE_CODE (arg) == COMPLEX_CST) |
| return TREE_REALPART (arg); |
| else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE) |
| return fold (build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg)); |
| else |
| return arg; |
| |
| case IMAGPART_EXPR: |
| if (TREE_CODE (arg) == COMPLEX_CST) |
| return TREE_IMAGPART (arg); |
| else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE) |
| return fold (build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg)); |
| else |
| return convert (TREE_TYPE (arg), integer_zero_node); |
| |
| case PREINCREMENT_EXPR: |
| case POSTINCREMENT_EXPR: |
| case PREDECREMENT_EXPR: |
| case POSTDECREMENT_EXPR: |
| /* Handle complex lvalues (when permitted) |
| by reduction to simpler cases. */ |
| |
| val = unary_complex_lvalue (code, arg, 0); |
| if (val != 0) |
| return val; |
| |
| /* Increment or decrement the real part of the value, |
| and don't change the imaginary part. */ |
| if (typecode == COMPLEX_TYPE) |
| { |
| tree real, imag; |
| |
| if (pedantic) |
| pedwarn ("ISO C does not support `++' and `--' on complex types"); |
| |
| arg = stabilize_reference (arg); |
| real = build_unary_op (REALPART_EXPR, arg, 1); |
| imag = build_unary_op (IMAGPART_EXPR, arg, 1); |
| return build (COMPLEX_EXPR, TREE_TYPE (arg), |
| build_unary_op (code, real, 1), imag); |
| } |
| |
| /* Report invalid types. */ |
| |
| if (typecode != POINTER_TYPE |
| && typecode != INTEGER_TYPE && typecode != REAL_TYPE) |
| { |
| if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) |
| error ("wrong type argument to increment"); |
| else |
| error ("wrong type argument to decrement"); |
| |
| return error_mark_node; |
| } |
| |
| { |
| tree inc; |
| tree result_type = TREE_TYPE (arg); |
| |
| arg = get_unwidened (arg, 0); |
| argtype = TREE_TYPE (arg); |
| |
| /* Compute the increment. */ |
| |
| if (typecode == POINTER_TYPE) |
| { |
| /* If pointer target is an undefined struct, |
| we just cannot know how to do the arithmetic. */ |
| if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (result_type))) |
| { |
| if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) |
| error ("increment of pointer to unknown structure"); |
| else |
| error ("decrement of pointer to unknown structure"); |
| } |
| else if ((pedantic || warn_pointer_arith) |
| && (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE |
| || TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)) |
| { |
| if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) |
| pedwarn ("wrong type argument to increment"); |
| else |
| pedwarn ("wrong type argument to decrement"); |
| } |
| |
| inc = c_size_in_bytes (TREE_TYPE (result_type)); |
| } |
| else |
| inc = integer_one_node; |
| |
| inc = convert (argtype, inc); |
| |
| /* Handle incrementing a cast-expression. */ |
| |
| while (1) |
| switch (TREE_CODE (arg)) |
| { |
| case NOP_EXPR: |
| case CONVERT_EXPR: |
| case FLOAT_EXPR: |
| case FIX_TRUNC_EXPR: |
| case FIX_FLOOR_EXPR: |
| case FIX_ROUND_EXPR: |
| case FIX_CEIL_EXPR: |
| pedantic_lvalue_warning (CONVERT_EXPR); |
| /* If the real type has the same machine representation |
| as the type it is cast to, we can make better output |
| by adding directly to the inside of the cast. */ |
| if ((TREE_CODE (TREE_TYPE (arg)) |
| == TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 0)))) |
| && (TYPE_MODE (TREE_TYPE (arg)) |
| == TYPE_MODE (TREE_TYPE (TREE_OPERAND (arg, 0))))) |
| arg = TREE_OPERAND (arg, 0); |
| else |
| { |
| tree incremented, modify, value; |
| if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE) |
| value = boolean_increment (code, arg); |
| else |
| { |
| arg = stabilize_reference (arg); |
| if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR) |
| value = arg; |
| else |
| value = save_expr (arg); |
| incremented = build (((code == PREINCREMENT_EXPR |
| || code == POSTINCREMENT_EXPR) |
| ? PLUS_EXPR : MINUS_EXPR), |
| argtype, value, inc); |
| TREE_SIDE_EFFECTS (incremented) = 1; |
| modify = build_modify_expr (arg, NOP_EXPR, incremented); |
| value = build (COMPOUND_EXPR, TREE_TYPE (arg), modify, value); |
| } |
| TREE_USED (value) = 1; |
| return value; |
| } |
| break; |
| |
| default: |
| goto give_up; |
| } |
| give_up: |
| |
| /* Complain about anything else that is not a true lvalue. */ |
| if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR |
| || code == POSTINCREMENT_EXPR) |
| ? "invalid lvalue in increment" |
| : "invalid lvalue in decrement"))) |
| return error_mark_node; |
| |
| /* Report a read-only lvalue. */ |
| if (TREE_READONLY (arg)) |
| readonly_error (arg, |
| ((code == PREINCREMENT_EXPR |
| || code == POSTINCREMENT_EXPR) |
| ? "increment" : "decrement")); |
| |
| if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE) |
| val = boolean_increment (code, arg); |
| else |
| val = build (code, TREE_TYPE (arg), arg, inc); |
| TREE_SIDE_EFFECTS (val) = 1; |
| val = convert (result_type, val); |
| if (TREE_CODE (val) != code) |
| TREE_NO_UNUSED_WARNING (val) = 1; |
| return val; |
| } |
| |
| case ADDR_EXPR: |
| /* Note that this operation never does default_conversion. */ |
| |
| /* Let &* cancel out to simplify resulting code. */ |
| if (TREE_CODE (arg) == INDIRECT_REF) |
| { |
| /* Don't let this be an lvalue. */ |
| if (lvalue_p (TREE_OPERAND (arg, 0))) |
| return non_lvalue (TREE_OPERAND (arg, 0)); |
| return TREE_OPERAND (arg, 0); |
| } |
| |
| /* For &x[y], return x+y */ |
| if (TREE_CODE (arg) == ARRAY_REF) |
| { |
| if (!c_mark_addressable (TREE_OPERAND (arg, 0))) |
| return error_mark_node; |
| return build_binary_op (PLUS_EXPR, TREE_OPERAND (arg, 0), |
| TREE_OPERAND (arg, 1), 1); |
| } |
| |
| /* Handle complex lvalues (when permitted) |
| by reduction to simpler cases. */ |
| val = unary_complex_lvalue (code, arg, flag); |
| if (val != 0) |
| return val; |
| |
| /* Anything not already handled and not a true memory reference |
| or a non-lvalue array is an error. */ |
| else if (typecode != FUNCTION_TYPE && !flag |
| && !lvalue_or_else (arg, "invalid lvalue in unary `&'")) |
| return error_mark_node; |
| |
| /* Ordinary case; arg is a COMPONENT_REF or a decl. */ |
| argtype = TREE_TYPE (arg); |
| |
| /* If the lvalue is const or volatile, merge that into the type |
| to which the address will point. Note that you can't get a |
| restricted pointer by taking the address of something, so we |
| only have to deal with `const' and `volatile' here. */ |
| if ((DECL_P (arg) || TREE_CODE_CLASS (TREE_CODE (arg)) == 'r') |
| && (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg))) |
| argtype = c_build_type_variant (argtype, |
| TREE_READONLY (arg), |
| TREE_THIS_VOLATILE (arg)); |
| |
| argtype = build_pointer_type (argtype); |
| |
| if (!c_mark_addressable (arg)) |
| return error_mark_node; |
| |
| { |
| tree addr; |
| |
| if (TREE_CODE (arg) == COMPONENT_REF) |
| { |
| tree field = TREE_OPERAND (arg, 1); |
| |
| addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), flag); |
| |
| if (DECL_C_BIT_FIELD (field)) |
| { |
| error ("attempt to take address of bit-field structure member `%s'", |
| IDENTIFIER_POINTER (DECL_NAME (field))); |
| return error_mark_node; |
| } |
| |
| addr = fold (build (PLUS_EXPR, argtype, |
| convert (argtype, addr), |
| convert (argtype, byte_position (field)))); |
| } |
| else |
| addr = build1 (code, argtype, arg); |
| |
| /* Address of a static or external variable or |
| file-scope function counts as a constant. */ |
| if (staticp (arg) |
| && ! (TREE_CODE (arg) == FUNCTION_DECL |
| && !DECL_FILE_SCOPE_P (arg))) |
| TREE_CONSTANT (addr) = 1; |
| return addr; |
| } |
| |
| default: |
| break; |
| } |
| |
| if (argtype == 0) |
| argtype = TREE_TYPE (arg); |
| val = build1 (code, argtype, arg); |
| return require_constant_value ? fold_initializer (val) : fold (val); |
| } |
| |
| /* Return nonzero if REF is an lvalue valid for this language. |
| Lvalues can be assigned, unless their type has TYPE_READONLY. |
| Lvalues can have their address taken, unless they have DECL_REGISTER. */ |
| |
| int |
| lvalue_p (tree ref) |
| { |
| enum tree_code code = TREE_CODE (ref); |
| |
| switch (code) |
| { |
| case REALPART_EXPR: |
| case IMAGPART_EXPR: |
| case COMPONENT_REF: |
| return lvalue_p (TREE_OPERAND (ref, 0)); |
| |
| case COMPOUND_LITERAL_EXPR: |
| case STRING_CST: |
| return 1; |
| |
| case INDIRECT_REF: |
| case ARRAY_REF: |
| case VAR_DECL: |
| case PARM_DECL: |
| case RESULT_DECL: |
| case ERROR_MARK: |
| return (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE |
| && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE); |
| |
| case BIND_EXPR: |
| case RTL_EXPR: |
| return TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE; |
| |
| default: |
| return 0; |
| } |
| } |
| |
| /* Return nonzero if REF is an lvalue valid for this language; |
| otherwise, print an error message and return zero. */ |
| |
| int |
| lvalue_or_else (tree ref, const char *msgid) |
| { |
| int win = lvalue_p (ref); |
| |
| if (! win) |
| error ("%s", msgid); |
| |
| return win; |
| } |
| |
| /* Apply unary lvalue-demanding operator CODE to the expression ARG |
| for certain kinds of expressions which are not really lvalues |
| but which we can accept as lvalues. If FLAG is nonzero, then |
| non-lvalues are OK since we may be converting a non-lvalue array to |
| a pointer in C99. |
| |
| If ARG is not a kind of expression we can handle, return zero. */ |
| |
| static tree |
| unary_complex_lvalue (enum tree_code code, tree arg, int flag) |
| { |
| /* Handle (a, b) used as an "lvalue". */ |
| if (TREE_CODE (arg) == COMPOUND_EXPR) |
| { |
| tree real_result = build_unary_op (code, TREE_OPERAND (arg, 1), 0); |
| |
| /* If this returns a function type, it isn't really being used as |
| an lvalue, so don't issue a warning about it. */ |
| if (TREE_CODE (TREE_TYPE (arg)) != FUNCTION_TYPE && !flag) |
| pedantic_lvalue_warning (COMPOUND_EXPR); |
| |
| return build (COMPOUND_EXPR, TREE_TYPE (real_result), |
| TREE_OPERAND (arg, 0), real_result); |
| } |
| |
| /* Handle (a ? b : c) used as an "lvalue". */ |
| if (TREE_CODE (arg) == COND_EXPR) |
| { |
| if (!flag) |
| pedantic_lvalue_warning (COND_EXPR); |
| if (TREE_CODE (TREE_TYPE (arg)) != FUNCTION_TYPE && !flag) |
| pedantic_lvalue_warning (COMPOUND_EXPR); |
| |
| return (build_conditional_expr |
| (TREE_OPERAND (arg, 0), |
| build_unary_op (code, TREE_OPERAND (arg, 1), flag), |
| build_unary_op (code, TREE_OPERAND (arg, 2), flag))); |
| } |
| |
| return 0; |
| } |
| |
| /* If pedantic, warn about improper lvalue. CODE is either COND_EXPR |
| COMPOUND_EXPR, or CONVERT_EXPR (for casts). */ |
| |
| static void |
| pedantic_lvalue_warning (enum tree_code code) |
| { |
| switch (code) |
| { |
| case COND_EXPR: |
| pedwarn ("use of conditional expressions as lvalues is deprecated"); |
| break; |
| case COMPOUND_EXPR: |
| pedwarn ("use of compound expressions as lvalues is deprecated"); |
| break; |
| default: |
| pedwarn ("use of cast expressions as lvalues is deprecated"); |
| break; |
| } |
| } |
| |
| /* Warn about storing in something that is `const'. */ |
| |
| void |
| readonly_error (tree arg, const char *msgid) |
| { |
| if (TREE_CODE (arg) == COMPONENT_REF) |
| { |
| if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0)))) |
| readonly_error (TREE_OPERAND (arg, 0), msgid); |
| else |
| error ("%s of read-only member `%s'", _(msgid), |
| IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (arg, 1)))); |
| } |
| else if (TREE_CODE (arg) == VAR_DECL) |
| error ("%s of read-only variable `%s'", _(msgid), |
| IDENTIFIER_POINTER (DECL_NAME (arg))); |
| else |
| error ("%s of read-only location", _(msgid)); |
| } |
| |
| /* Mark EXP saying that we need to be able to take the |
| address of it; it should not be allocated in a register. |
| Returns true if successful. */ |
| |
| bool |
| c_mark_addressable (tree exp) |
| { |
| tree x = exp; |
| |
| while (1) |
| switch (TREE_CODE (x)) |
| { |
| case COMPONENT_REF: |
| if (DECL_C_BIT_FIELD (TREE_OPERAND (x, 1))) |
| { |
| error ("cannot take address of bit-field `%s'", |
| IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (x, 1)))); |
| return false; |
| } |
| |
| /* ... fall through ... */ |
| |
| case ADDR_EXPR: |
| case ARRAY_REF: |
| case REALPART_EXPR: |
| case IMAGPART_EXPR: |
| x = TREE_OPERAND (x, 0); |
| break; |
| |
| case COMPOUND_LITERAL_EXPR: |
| case CONSTRUCTOR: |
| TREE_ADDRESSABLE (x) = 1; |
| return true; |
| |
| case VAR_DECL: |
| case CONST_DECL: |
| case PARM_DECL: |
| case RESULT_DECL: |
| if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x) |
| && DECL_NONLOCAL (x)) |
| { |
| if (TREE_PUBLIC (x) || TREE_STATIC (x) || DECL_EXTERNAL (x)) |
| { |
| error ("global register variable `%s' used in nested function", |
| IDENTIFIER_POINTER (DECL_NAME (x))); |
| return false; |
| } |
| pedwarn ("register variable `%s' used in nested function", |
| IDENTIFIER_POINTER (DECL_NAME (x))); |
| } |
| else if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)) |
| { |
| if (TREE_PUBLIC (x) || TREE_STATIC (x) || DECL_EXTERNAL (x)) |
| { |
| error ("address of global register variable `%s' requested", |
| IDENTIFIER_POINTER (DECL_NAME (x))); |
| return false; |
| } |
| |
| /* If we are making this addressable due to its having |
| volatile components, give a different error message. Also |
| handle the case of an unnamed parameter by not trying |
| to give the name. */ |
| |
| else if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (x))) |
| { |
| error ("cannot put object with volatile field into register"); |
| return false; |
| } |
| |
| pedwarn ("address of register variable `%s' requested", |
| IDENTIFIER_POINTER (DECL_NAME (x))); |
| } |
| put_var_into_stack (x, /*rescan=*/true); |
| |
| /* drops in */ |
| case FUNCTION_DECL: |
| TREE_ADDRESSABLE (x) = 1; |
| /* drops out */ |
| default: |
| return true; |
| } |
| } |
| |
| /* Build and return a conditional expression IFEXP ? OP1 : OP2. */ |
| |
| tree |
| build_conditional_expr (tree ifexp, tree op1, tree op2) |
| { |
| tree type1; |
| tree type2; |
| enum tree_code code1; |
| enum tree_code code2; |
| tree result_type = NULL; |
| tree orig_op1 = op1, orig_op2 = op2; |
| |
| ifexp = c_common_truthvalue_conversion (default_conversion (ifexp)); |
| |
| /* Promote both alternatives. */ |
| |
| if (TREE_CODE (TREE_TYPE (op1)) != VOID_TYPE) |
| op1 = default_conversion (op1); |
| if (TREE_CODE (TREE_TYPE (op2)) != VOID_TYPE) |
| op2 = default_conversion (op2); |
| |
| if (TREE_CODE (ifexp) == ERROR_MARK |
| || TREE_CODE (TREE_TYPE (op1)) == ERROR_MARK |
| || TREE_CODE (TREE_TYPE (op2)) == ERROR_MARK) |
| return error_mark_node; |
| |
| type1 = TREE_TYPE (op1); |
| code1 = TREE_CODE (type1); |
| type2 = TREE_TYPE (op2); |
| code2 = TREE_CODE (type2); |
| |
| /* Quickly detect the usual case where op1 and op2 have the same type |
| after promotion. */ |
| if (TYPE_MAIN_VARIANT (type1) == TYPE_MAIN_VARIANT (type2)) |
| { |
| if (type1 == type2) |
| result_type = type1; |
| else |
| result_type = TYPE_MAIN_VARIANT (type1); |
| } |
| else if ((code1 == INTEGER_TYPE || code1 == REAL_TYPE |
| || code1 == COMPLEX_TYPE) |
| && (code2 == INTEGER_TYPE || code2 == REAL_TYPE |
| || code2 == COMPLEX_TYPE)) |
| { |
| result_type = common_type (type1, type2); |
| |
| /* If -Wsign-compare, warn here if type1 and type2 have |
| different signedness. We'll promote the signed to unsigned |
| and later code won't know it used to be different. |
| Do this check on the original types, so that explicit casts |
| will be considered, but default promotions won't. */ |
| if (warn_sign_compare && !skip_evaluation) |
| { |
| int unsigned_op1 = TREE_UNSIGNED (TREE_TYPE (orig_op1)); |
| int unsigned_op2 = TREE_UNSIGNED (TREE_TYPE (orig_op2)); |
| |
| if (unsigned_op1 ^ unsigned_op2) |
| { |
| /* Do not warn if the result type is signed, since the |
| signed type will only be chosen if it can represent |
| all the values of the unsigned type. */ |
| if (! TREE_UNSIGNED (result_type)) |
| /* OK */; |
| /* Do not warn if the signed quantity is an unsuffixed |
| integer literal (or some static constant expression |
| involving such literals) and it is non-negative. */ |
| else if ((unsigned_op2 && c_tree_expr_nonnegative_p (op1)) |
| || (unsigned_op1 && c_tree_expr_nonnegative_p (op2))) |
| /* OK */; |
| else |
| warning ("signed and unsigned type in conditional expression"); |
| } |
| } |
| } |
| else if (code1 == VOID_TYPE || code2 == VOID_TYPE) |
| { |
| if (pedantic && (code1 != VOID_TYPE || code2 != VOID_TYPE)) |
| pedwarn ("ISO C forbids conditional expr with only one void side"); |
| result_type = void_type_node; |
| } |
| else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE) |
| { |
| if (comp_target_types (type1, type2, 1)) |
| result_type = common_type (type1, type2); |
| else if (integer_zerop (op1) && TREE_TYPE (type1) == void_type_node |
| && TREE_CODE (orig_op1) != NOP_EXPR) |
| result_type = qualify_type (type2, type1); |
| else if (integer_zerop (op2) && TREE_TYPE (type2) == void_type_node |
| && TREE_CODE (orig_op2) != NOP_EXPR) |
| result_type = qualify_type (type1, type2); |
| else if (VOID_TYPE_P (TREE_TYPE (type1))) |
| { |
| if (pedantic && TREE_CODE (TREE_TYPE (type2)) == FUNCTION_TYPE) |
| pedwarn ("ISO C forbids conditional expr between `void *' and function pointer"); |
| result_type = build_pointer_type (qualify_type (TREE_TYPE (type1), |
| TREE_TYPE (type2))); |
| } |
| else if (VOID_TYPE_P (TREE_TYPE (type2))) |
| { |
| if (pedantic && TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE) |
| pedwarn ("ISO C forbids conditional expr between `void *' and function pointer"); |
| result_type = build_pointer_type (qualify_type (TREE_TYPE (type2), |
| TREE_TYPE (type1))); |
| } |
| else |
| { |
| pedwarn ("pointer type mismatch in conditional expression"); |
| result_type = build_pointer_type (void_type_node); |
| } |
| } |
| else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE) |
| { |
| if (! integer_zerop (op2)) |
| pedwarn ("pointer/integer type mismatch in conditional expression"); |
| else |
| { |
| op2 = null_pointer_node; |
| } |
| result_type = type1; |
| } |
| else if (code2 == POINTER_TYPE && code1 == INTEGER_TYPE) |
| { |
| if (!integer_zerop (op1)) |
| pedwarn ("pointer/integer type mismatch in conditional expression"); |
| else |
| { |
| op1 = null_pointer_node; |
| } |
| result_type = type2; |
| } |
| |
| if (!result_type) |
| { |
| if (flag_cond_mismatch) |
| result_type = void_type_node; |
| else |
| { |
| error ("type mismatch in conditional expression"); |
| return error_mark_node; |
| } |
| } |
| |
| /* Merge const and volatile flags of the incoming types. */ |
| result_type |
| = build_type_variant (result_type, |
| TREE_READONLY (op1) || TREE_READONLY (op2), |
| TREE_THIS_VOLATILE (op1) || TREE_THIS_VOLATILE (op2)); |
| |
| if (result_type != TREE_TYPE (op1)) |
| op1 = convert_and_check (result_type, op1); |
| if (result_type != TREE_TYPE (op2)) |
| op2 = convert_and_check (result_type, op2); |
| |
| if (TREE_CODE (ifexp) == INTEGER_CST) |
| return pedantic_non_lvalue (integer_zerop (ifexp) ? op2 : op1); |
| |
| return fold (build (COND_EXPR, result_type, ifexp, op1, op2)); |
| } |
| |
| /* Given a list of expressions, return a compound expression |
| that performs them all and returns the value of the last of them. */ |
| |
| tree |
| build_compound_expr (tree list) |
| { |
| return internal_build_compound_expr (list, TRUE); |
| } |
| |
| static tree |
| internal_build_compound_expr (tree list, int first_p) |
| { |
| tree rest; |
| |
| if (TREE_CHAIN (list) == 0) |
| { |
| /* Convert arrays and functions to pointers when there |
| really is a comma operator. */ |
| if (!first_p) |
| TREE_VALUE (list) |
| = default_function_array_conversion (TREE_VALUE (list)); |
| |
| /* Don't let (0, 0) be null pointer constant. */ |
| if (!first_p && integer_zerop (TREE_VALUE (list))) |
| return non_lvalue (TREE_VALUE (list)); |
| return TREE_VALUE (list); |
| } |
| |
| rest = internal_build_compound_expr (TREE_CHAIN (list), FALSE); |
| |
| if (! TREE_SIDE_EFFECTS (TREE_VALUE (list))) |
| { |
| /* The left-hand operand of a comma expression is like an expression |
| statement: with -Wextra or -Wunused, we should warn if it doesn't have |
| any side-effects, unless it was explicitly cast to (void). */ |
| if (warn_unused_value |
| && ! (TREE_CODE (TREE_VALUE (list)) == CONVERT_EXPR |
| && VOID_TYPE_P (TREE_TYPE (TREE_VALUE (list))))) |
| warning ("left-hand operand of comma expression has no effect"); |
| } |
| |
| /* With -Wunused, we should also warn if the left-hand operand does have |
| side-effects, but computes a value which is not used. For example, in |
| `foo() + bar(), baz()' the result of the `+' operator is not used, |
| so we should issue a warning. */ |
| else if (warn_unused_value) |
| warn_if_unused_value (TREE_VALUE (list)); |
| |
| return build (COMPOUND_EXPR, TREE_TYPE (rest), TREE_VALUE (list), rest); |
| } |
| |
| /* Build an expression representing a cast to type TYPE of expression EXPR. */ |
| |
| tree |
| build_c_cast (tree type, tree expr) |
| { |
| tree value = expr; |
| |
| if (type == error_mark_node || expr == error_mark_node) |
| return error_mark_node; |
| |
| /* The ObjC front-end uses TYPE_MAIN_VARIANT to tie together types differing |
| only in <protocol> qualifications. But when constructing cast expressions, |
| the protocols do matter and must be kept around. */ |
| if (!c_dialect_objc () || !objc_is_object_ptr (type)) |
| type = TYPE_MAIN_VARIANT (type); |
| |
| if (TREE_CODE (type) == ARRAY_TYPE) |
| { |
| error ("cast specifies array type"); |
| return error_mark_node; |
| } |
| |
| if (TREE_CODE (type) == FUNCTION_TYPE) |
| { |
| error ("cast specifies function type"); |
| return error_mark_node; |
| } |
| |
| if (type == TYPE_MAIN_VARIANT (TREE_TYPE (value))) |
| { |
| if (pedantic) |
| { |
| if (TREE_CODE (type) == RECORD_TYPE |
| || TREE_CODE (type) == UNION_TYPE) |
| pedwarn ("ISO C forbids casting nonscalar to the same type"); |
| } |
| } |
| else if (TREE_CODE (type) == UNION_TYPE) |
| { |
| tree field; |
| value = default_function_array_conversion (value); |
| |
| for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) |
| if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)), |
| TYPE_MAIN_VARIANT (TREE_TYPE (value)), COMPARE_STRICT)) |
| break; |
| |
| if (field) |
| { |
| tree t; |
| |
| if (pedantic) |
| pedwarn ("ISO C forbids casts to union type"); |
| t = digest_init (type, |
| build_constructor (type, |
| build_tree_list (field, value)), |
| 0); |
| TREE_CONSTANT (t) = TREE_CONSTANT (value); |
| return t; |
| } |
| error ("cast to union type from type not present in union"); |
| return error_mark_node; |
| } |
| else |
| { |
| tree otype, ovalue; |
| |
| /* If casting to void, avoid the error that would come |
| from default_conversion in the case of a non-lvalue array. */ |
| if (type == void_type_node) |
| return build1 (CONVERT_EXPR, type, value); |
| |
| /* Convert functions and arrays to pointers, |
| but don't convert any other types. */ |
| value = default_function_array_conversion (value); |
| otype = TREE_TYPE (value); |
| |
| /* Optionally warn about potentially worrisome casts. */ |
| |
| if (warn_cast_qual |
| && TREE_CODE (type) == POINTER_TYPE |
| && TREE_CODE (otype) == POINTER_TYPE) |
| { |
| tree in_type = type; |
| tree in_otype = otype; |
| int added = 0; |
| int discarded = 0; |
| |
| /* Check that the qualifiers on IN_TYPE are a superset of |
| the qualifiers of IN_OTYPE. The outermost level of |
| POINTER_TYPE nodes is uninteresting and we stop as soon |
| as we hit a non-POINTER_TYPE node on either type. */ |
| do |
| { |
| in_otype = TREE_TYPE (in_otype); |
| in_type = TREE_TYPE (in_type); |
| |
| /* GNU C allows cv-qualified function types. 'const' |
| means the function is very pure, 'volatile' means it |
| can't return. We need to warn when such qualifiers |
| are added, not when they're taken away. */ |
| if (TREE_CODE (in_otype) == FUNCTION_TYPE |
| && TREE_CODE (in_type) == FUNCTION_TYPE) |
| added |= (TYPE_QUALS (in_type) & ~TYPE_QUALS (in_otype)); |
| else |
| discarded |= (TYPE_QUALS (in_otype) & ~TYPE_QUALS (in_type)); |
| } |
| while (TREE_CODE (in_type) == POINTER_TYPE |
| && TREE_CODE (in_otype) == POINTER_TYPE); |
| |
| if (added) |
| warning ("cast adds new qualifiers to function type"); |
| |
| if (discarded) |
| /* There are qualifiers present in IN_OTYPE that are not |
| present in IN_TYPE. */ |
| warning ("cast discards qualifiers from pointer target type"); |
| } |
| |
| /* Warn about possible alignment problems. */ |
| if (STRICT_ALIGNMENT && warn_cast_align |
| && TREE_CODE (type) == POINTER_TYPE |
| && TREE_CODE (otype) == POINTER_TYPE |
| && TREE_CODE (TREE_TYPE (otype)) != VOID_TYPE |
| && TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE |
| /* Don't warn about opaque types, where the actual alignment |
| restriction is unknown. */ |
| && !((TREE_CODE (TREE_TYPE (otype)) == UNION_TYPE |
| || TREE_CODE (TREE_TYPE (otype)) == RECORD_TYPE) |
| && TYPE_MODE (TREE_TYPE (otype)) == VOIDmode) |
| && TYPE_ALIGN (TREE_TYPE (type)) |