| /* 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, 2005 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. */ |
| |
| #include "config.h" |
| #include "system.h" |
| #include "coretypes.h" |
| #include "tm.h" |
| #include "rtl.h" |
| #include "tree.h" |
| #include "langhooks.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" |
| #include "tree-iterator.h" |
| #include "tree-gimple.h" |
| #include "tree-flow.h" |
| |
| /* Possible cases of implicit bad conversions. Used to select |
| diagnostic messages in convert_for_assignment. */ |
| enum impl_conv { |
| ic_argpass, |
| ic_argpass_nonproto, |
| ic_assign, |
| ic_init, |
| ic_return |
| }; |
| |
| /* The level of nesting inside "__alignof__". */ |
| int in_alignof; |
| |
| /* The level of nesting inside "sizeof". */ |
| int in_sizeof; |
| |
| /* The level of nesting inside "typeof". */ |
| int in_typeof; |
| |
| struct c_label_context_se *label_context_stack_se; |
| struct c_label_context_vm *label_context_stack_vm; |
| |
| /* 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 tagged_types_tu_compatible_p (tree, tree); |
| /* APPLE LOCAL mainline */ |
| static int comp_target_types (tree, tree); |
| static int function_types_compatible_p (tree, tree); |
| static int type_lists_compatible_p (tree, tree); |
| 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 convert_for_assignment (tree, tree, enum impl_conv, tree, 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, bool, int); |
| static void output_init_element (tree, bool, 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); |
| static void readonly_error (tree, enum lvalue_use); |
| static void record_maybe_used_decl (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 ("%qs 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: |
| gcc_unreachable (); |
| } |
| |
| 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 %qs", |
| 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 (TYPE_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)); |
| } |
| |
| /* APPLE LOCAL begin mainline 2006-05-18 4336222 */ |
| /* Return true iff the given tree T is a variable length array. */ |
| |
| bool |
| c_vla_type_p (tree t) |
| { |
| if (TREE_CODE (t) == ARRAY_TYPE |
| && C_TYPE_VARIABLE_SIZE (t)) |
| return true; |
| return false; |
| } |
| /* APPLE LOCAL end mainline 2006-05-18 4336222 */ |
| |
| /* Return the composite type of two compatible types. |
| |
| We assume that comptypes has already been done and returned |
| nonzero; if that isn't so, this may crash. In particular, we |
| assume that qualifiers match. */ |
| |
| tree |
| composite_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; |
| |
| code1 = TREE_CODE (t1); |
| code2 = TREE_CODE (t2); |
| |
| /* Merge the attributes. */ |
| attributes = targetm.merge_type_attributes (t1, t2); |
| |
| /* If one is an enumerated type and the other is the compatible |
| integer type, the composite type might be either of the two |
| (DR#013 question 3). For consistency, use the enumerated type as |
| the composite type. */ |
| |
| if (code1 == ENUMERAL_TYPE && code2 == INTEGER_TYPE) |
| return t1; |
| if (code2 == ENUMERAL_TYPE && code1 == INTEGER_TYPE) |
| return t2; |
| |
| gcc_assert (code1 == code2); |
| |
| switch (code1) |
| { |
| case POINTER_TYPE: |
| /* For two pointers, do this recursively on the target type. */ |
| { |
| tree pointed_to_1 = TREE_TYPE (t1); |
| tree pointed_to_2 = TREE_TYPE (t2); |
| tree target = composite_type (pointed_to_1, pointed_to_2); |
| t1 = build_pointer_type (target); |
| t1 = build_type_attribute_variant (t1, attributes); |
| return qualify_type (t1, t2); |
| } |
| |
| case ARRAY_TYPE: |
| { |
| tree elt = composite_type (TREE_TYPE (t1), TREE_TYPE (t2)); |
| int quals; |
| tree unqual_elt; |
| |
| /* We should not have any type quals on arrays at all. */ |
| gcc_assert (!TYPE_QUALS (t1) && !TYPE_QUALS (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); |
| |
| if (elt == TREE_TYPE (t1) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1)) |
| return build_type_attribute_variant (t1, attributes); |
| if (elt == TREE_TYPE (t2) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1)) |
| return build_type_attribute_variant (t2, attributes); |
| |
| /* Merge the element types, and have a size if either arg has |
| one. We may have qualifiers on the element types. To set |
| up TYPE_MAIN_VARIANT correctly, we need to form the |
| composite of the unqualified types and add the qualifiers |
| back at the end. */ |
| quals = TYPE_QUALS (strip_array_types (elt)); |
| unqual_elt = c_build_qualified_type (elt, TYPE_UNQUALIFIED); |
| t1 = build_array_type (unqual_elt, |
| TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2)); |
| t1 = c_build_qualified_type (t1, quals); |
| 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 = composite_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)); |
| t1 = build_type_attribute_variant (t1, attributes); |
| return qualify_type (t1, t2); |
| } |
| if (TYPE_ARG_TYPES (t2) == 0) |
| { |
| t1 = build_function_type (valtype, TYPE_ARG_TYPES (t1)); |
| t1 = build_type_attribute_variant (t1, attributes); |
| return qualify_type (t1, t2); |
| } |
| |
| /* If both args specify argument types, we must merge the two |
| lists, argument by argument. */ |
| /* Tell global_bindings_p to return false so that variable_size |
| doesn't abort on VLAs in parameter types. */ |
| c_override_global_bindings_to_false = true; |
| |
| 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; |
| tree mv2 = TREE_VALUE (p2); |
| if (mv2 && mv2 != error_mark_node |
| && TREE_CODE (mv2) != ARRAY_TYPE) |
| mv2 = TYPE_MAIN_VARIANT (mv2); |
| for (memb = TYPE_FIELDS (TREE_VALUE (p1)); |
| memb; memb = TREE_CHAIN (memb)) |
| { |
| tree mv3 = TREE_TYPE (memb); |
| if (mv3 && mv3 != error_mark_node |
| && TREE_CODE (mv3) != ARRAY_TYPE) |
| mv3 = TYPE_MAIN_VARIANT (mv3); |
| if (comptypes (mv3, mv2)) |
| { |
| TREE_VALUE (n) = composite_type (TREE_TYPE (memb), |
| 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; |
| tree mv1 = TREE_VALUE (p1); |
| if (mv1 && mv1 != error_mark_node |
| && TREE_CODE (mv1) != ARRAY_TYPE) |
| mv1 = TYPE_MAIN_VARIANT (mv1); |
| for (memb = TYPE_FIELDS (TREE_VALUE (p2)); |
| memb; memb = TREE_CHAIN (memb)) |
| { |
| tree mv3 = TREE_TYPE (memb); |
| if (mv3 && mv3 != error_mark_node |
| && TREE_CODE (mv3) != ARRAY_TYPE) |
| mv3 = TYPE_MAIN_VARIANT (mv3); |
| if (comptypes (mv3, mv1)) |
| { |
| TREE_VALUE (n) = composite_type (TREE_TYPE (memb), |
| TREE_VALUE (p1)); |
| if (pedantic) |
| pedwarn ("function types not truly compatible in ISO C"); |
| goto parm_done; |
| } |
| } |
| } |
| TREE_VALUE (n) = composite_type (TREE_VALUE (p1), TREE_VALUE (p2)); |
| parm_done: ; |
| } |
| |
| c_override_global_bindings_to_false = false; |
| t1 = build_function_type (valtype, newargs); |
| t1 = qualify_type (t1, t2); |
| /* ... falls through ... */ |
| } |
| |
| default: |
| return build_type_attribute_variant (t1, attributes); |
| } |
| |
| } |
| |
| /* Return the type of a conditional expression between pointers to |
| possibly differently qualified versions of compatible types. |
| |
| We assume that comp_target_types has already been done and returned |
| nonzero; if that isn't so, this may crash. */ |
| |
| static tree |
| common_pointer_type (tree t1, tree t2) |
| { |
| tree attributes; |
| tree pointed_to_1, mv1; |
| tree pointed_to_2, mv2; |
| tree target; |
| |
| /* 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; |
| |
| gcc_assert (TREE_CODE (t1) == POINTER_TYPE |
| && TREE_CODE (t2) == POINTER_TYPE); |
| |
| /* Merge the attributes. */ |
| attributes = targetm.merge_type_attributes (t1, t2); |
| |
| /* Find the composite type of the target types, and combine the |
| qualifiers of the two types' targets. Do not lose qualifiers on |
| array element types by taking the TYPE_MAIN_VARIANT. */ |
| mv1 = pointed_to_1 = TREE_TYPE (t1); |
| mv2 = pointed_to_2 = TREE_TYPE (t2); |
| if (TREE_CODE (mv1) != ARRAY_TYPE) |
| mv1 = TYPE_MAIN_VARIANT (pointed_to_1); |
| if (TREE_CODE (mv2) != ARRAY_TYPE) |
| mv2 = TYPE_MAIN_VARIANT (pointed_to_2); |
| target = composite_type (mv1, mv2); |
| 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); |
| } |
| |
| /* Return the common type for two arithmetic types under the usual |
| arithmetic conversions. The default conversions have already been |
| applied, and enumerated types converted to their compatible integer |
| types. The resulting type is unqualified and has no attributes. |
| |
| This is the type for the result of most arithmetic operations |
| if the operands have the given two types. */ |
| |
| static tree |
| c_common_type (tree t1, tree t2) |
| { |
| enum tree_code code1; |
| enum tree_code code2; |
| |
| /* If one type is nonsense, use the other. */ |
| if (t1 == error_mark_node) |
| return t2; |
| if (t2 == error_mark_node) |
| return t1; |
| |
| if (TYPE_QUALS (t1) != TYPE_UNQUALIFIED) |
| t1 = TYPE_MAIN_VARIANT (t1); |
| |
| if (TYPE_QUALS (t2) != TYPE_UNQUALIFIED) |
| t2 = TYPE_MAIN_VARIANT (t2); |
| |
| if (TYPE_ATTRIBUTES (t1) != NULL_TREE) |
| t1 = build_type_attribute_variant (t1, NULL_TREE); |
| |
| if (TYPE_ATTRIBUTES (t2) != NULL_TREE) |
| t2 = build_type_attribute_variant (t2, NULL_TREE); |
| |
| /* Save time if the two types are the same. */ |
| |
| if (t1 == t2) return t1; |
| |
| code1 = TREE_CODE (t1); |
| code2 = TREE_CODE (t2); |
| |
| gcc_assert (code1 == VECTOR_TYPE || code1 == COMPLEX_TYPE |
| || code1 == REAL_TYPE || code1 == INTEGER_TYPE); |
| gcc_assert (code2 == VECTOR_TYPE || code2 == COMPLEX_TYPE |
| || code2 == REAL_TYPE || code2 == INTEGER_TYPE); |
| |
| /* If one type is a vector type, return that type. (How the usual |
| arithmetic conversions apply to the vector types extension is not |
| precisely specified.) */ |
| if (code1 == VECTOR_TYPE) |
| return t1; |
| |
| if (code2 == VECTOR_TYPE) |
| return 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 = c_common_type (subtype1, subtype2); |
| |
| if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype) |
| return t1; |
| else if (code2 == COMPLEX_TYPE && TREE_TYPE (t2) == subtype) |
| return t2; |
| else |
| return build_complex_type (subtype); |
| } |
| |
| /* If only one is real, use it as the result. */ |
| |
| if (code1 == REAL_TYPE && code2 != REAL_TYPE) |
| return t1; |
| |
| if (code2 == REAL_TYPE && code1 != REAL_TYPE) |
| return t2; |
| |
| /* Both real or both integers; use the one with greater precision. */ |
| |
| if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2)) |
| return t1; |
| else if (TYPE_PRECISION (t2) > TYPE_PRECISION (t1)) |
| return t2; |
| |
| /* Same precision. Prefer long longs to longs to ints when the |
| same precision, following the C99 rules on integer type rank |
| (which are equivalent to the C90 rules for C90 types). */ |
| |
| if (TYPE_MAIN_VARIANT (t1) == long_long_unsigned_type_node |
| || TYPE_MAIN_VARIANT (t2) == long_long_unsigned_type_node) |
| return long_long_unsigned_type_node; |
| |
| if (TYPE_MAIN_VARIANT (t1) == long_long_integer_type_node |
| || TYPE_MAIN_VARIANT (t2) == long_long_integer_type_node) |
| { |
| if (TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2)) |
| return long_long_unsigned_type_node; |
| else |
| return long_long_integer_type_node; |
| } |
| |
| if (TYPE_MAIN_VARIANT (t1) == long_unsigned_type_node |
| || TYPE_MAIN_VARIANT (t2) == long_unsigned_type_node) |
| return long_unsigned_type_node; |
| |
| if (TYPE_MAIN_VARIANT (t1) == long_integer_type_node |
| || TYPE_MAIN_VARIANT (t2) == long_integer_type_node) |
| { |
| /* But preserve unsignedness from the other type, |
| since long cannot hold all the values of an unsigned int. */ |
| if (TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2)) |
| return long_unsigned_type_node; |
| else |
| return long_integer_type_node; |
| } |
| |
| /* 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) |
| return long_double_type_node; |
| |
| /* Otherwise prefer the unsigned one. */ |
| |
| if (TYPE_UNSIGNED (t1)) |
| return t1; |
| else |
| return t2; |
| } |
| |
| /* Wrapper around c_common_type that is used by c-common.c. ENUMERAL_TYPEs |
| are allowed here and are converted to their compatible integer types. */ |
| tree |
| common_type (tree t1, tree t2) |
| { |
| 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); |
| return c_common_type (t1, t2); |
| } |
| |
| /* 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) |
| { |
| 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_ORIG_SIZE_TYPE (t1)) |
| t1 = TYPE_ORIG_SIZE_TYPE (t1); |
| |
| if (TREE_CODE (t2) == INTEGER_TYPE && TYPE_IS_SIZETYPE (t2) |
| && TYPE_ORIG_SIZE_TYPE (t2)) |
| t2 = TYPE_ORIG_SIZE_TYPE (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), TYPE_UNSIGNED (t1)); |
| else if (TREE_CODE (t2) == ENUMERAL_TYPE && TREE_CODE (t1) != ENUMERAL_TYPE) |
| t2 = c_common_type_for_size (TYPE_PRECISION (t2), TYPE_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. C99 6.7.3p9 */ |
| |
| 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 (TREE_CODE (t1) != ARRAY_TYPE |
| && 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: |
| /* APPLE LOCAL mainline */ |
| /* Call to 'objc_comptypes' removed. */ |
| /* Do not remove mode or aliasing information. */ |
| if (TYPE_MODE (t1) != TYPE_MODE (t2) |
| || TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2)) |
| break; |
| val = (TREE_TYPE (t1) == TREE_TYPE (t2) |
| ? 1 : comptypes (TREE_TYPE (t1), TREE_TYPE (t2))); |
| break; |
| |
| case FUNCTION_TYPE: |
| val = function_types_compatible_p (t1, t2); |
| 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)))) |
| 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)); |
| /* APPLE LOCAL begin mainline 2006-05-18 4336222 */ |
| d1_variable = d1_variable || (d1_zero && c_vla_type_p (t1)); |
| d2_variable = d2_variable || (d2_zero && c_vla_type_p (t2)); |
| /* APPLE LOCAL end mainline 2006-05-18 4336222 */ |
| |
| 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: |
| /* APPLE LOCAL mainline */ |
| /* Call to 'objc_comptypes' removed. */ |
| |
| case ENUMERAL_TYPE: |
| case UNION_TYPE: |
| if (val != 1 && !same_translation_unit_p (t1, t2)) |
| val = tagged_types_tu_compatible_p (t1, t2); |
| break; |
| |
| case VECTOR_TYPE: |
| val = TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2) |
| && comptypes (TREE_TYPE (t1), TREE_TYPE (t2)); |
| break; |
| |
| default: |
| break; |
| } |
| return attrval == 2 && val == 1 ? 2 : val; |
| } |
| |
| /* APPLE LOCAL begin mainline */ |
| /* Return 1 if TTL and TTR are pointers to types that are equivalent, |
| ignoring their qualifiers. */ |
| /* APPLE LOCAL end mainline */ |
| |
| static int |
| /* APPLE LOCAL mainline */ |
| comp_target_types (tree ttl, tree ttr) |
| { |
| int val; |
| tree mvl, mvr; |
| |
| /* APPLE LOCAL mainline */ |
| /* Call to 'objc_comptypes' removed. */ |
| |
| /* Do not lose qualifiers on element types of array types that are |
| pointer targets by taking their TYPE_MAIN_VARIANT. */ |
| mvl = TREE_TYPE (ttl); |
| mvr = TREE_TYPE (ttr); |
| if (TREE_CODE (mvl) != ARRAY_TYPE) |
| mvl = TYPE_MAIN_VARIANT (mvl); |
| if (TREE_CODE (mvr) != ARRAY_TYPE) |
| mvr = TYPE_MAIN_VARIANT (mvr); |
| val = comptypes (mvl, mvr); |
| |
| if (val == 2 && pedantic) |
| pedwarn ("types are not quite compatible"); |
| return val; |
| } |
| |
| /* Subroutines of `comptypes'. */ |
| |
| /* Determine whether two trees derive from the same translation unit. |
| If the CONTEXT chain ends in a null, that tree's context is still |
| being parsed, so if two trees have context chains ending in null, |
| they're in the same translation unit. */ |
| 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 tcc_declaration: |
| t1 = DECL_CONTEXT (t1); break; |
| case tcc_type: |
| t1 = TYPE_CONTEXT (t1); break; |
| case tcc_exceptional: |
| t1 = BLOCK_SUPERCONTEXT (t1); break; /* assume block */ |
| default: gcc_unreachable (); |
| } |
| |
| while (t2 && TREE_CODE (t2) != TRANSLATION_UNIT_DECL) |
| switch (TREE_CODE_CLASS (TREE_CODE (t2))) |
| { |
| case tcc_declaration: |
| t2 = DECL_CONTEXT (t2); break; |
| case tcc_type: |
| t2 = TYPE_CONTEXT (t2); break; |
| case tcc_exceptional: |
| t2 = BLOCK_SUPERCONTEXT (t2); break; /* assume block */ |
| default: gcc_unreachable (); |
| } |
| |
| 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; |
| /* APPLE LOCAL begin IMA speed up */ |
| int isEnum; |
| int enumMatched; |
| /* APPLE LOCAL end IMA speed up */ |
| }; |
| |
| /* 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) |
| { |
| 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... |
| In the case of compiler-created builtin structs the TYPE_DECL |
| may be a dummy, with no DECL_ORIGINAL_TYPE. Don't fault. */ |
| 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) |
| /* APPLE LOCAL IMA speed up */ |
| return tts_i->isEnum ? tts_i->enumMatched : 1; |
| } |
| |
| switch (TREE_CODE (t1)) |
| { |
| case ENUMERAL_TYPE: |
| { |
| /* APPLE LOCAL begin IMA speed up */ |
| struct tagged_tu_seen *tts; |
| int res; |
| bool done; |
| /* Speed up the case where the type values are in the same order. */ |
| tree tv1 = TYPE_VALUES (t1); |
| tree tv2 = TYPE_VALUES (t2); |
| if (tv1 == tv2) |
| return 1; |
| |
| res = 0; |
| done = false; |
| for (;tv1 && tv2; tv1 = TREE_CHAIN (tv1), tv2 = TREE_CHAIN (tv2)) |
| { |
| if (TREE_PURPOSE (tv1) != TREE_PURPOSE (tv2)) |
| break; |
| if (simple_cst_equal (TREE_VALUE (tv1), TREE_VALUE (tv2)) != 1) |
| { |
| res = 0; |
| done = true; |
| break; |
| } |
| } |
| |
| if (!done) |
| { |
| if (tv1 == NULL_TREE && tv2 == NULL_TREE) |
| res = 1, done = true; |
| else if (tv1 == NULL_TREE || tv2 == NULL_TREE) |
| res = 0, done = true; |
| } |
| |
| if (!done && list_length (TYPE_VALUES (t1)) == list_length (TYPE_VALUES (t2))) |
| { |
| res = 1; |
| 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) |
| { |
| res = 0; |
| break; |
| } |
| } |
| } |
| if (tagged_tu_seen_base) |
| { |
| tts = xmalloc(sizeof (struct tagged_tu_seen)); |
| tts->next = tagged_tu_seen_base; |
| tts->t1 = t1; |
| tts->t2 = t2; |
| tts->isEnum = 1; |
| tts->enumMatched = res; |
| tagged_tu_seen_base = tts; |
| } |
| return res; |
| /* APPLE LOCAL end IMA speed up */ |
| } |
| |
| 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; |
| /* APPLE LOCAL IMA speed up */ |
| const struct tagged_tu_seen * tts_i; |
| |
| tts.next = tagged_tu_seen_base; |
| tts.t1 = t1; |
| tts.t2 = t2; |
| /* APPLE LOCAL IMA speed up */ |
| tts.isEnum = 0; |
| tagged_tu_seen_base = &tts; |
| |
| if (DECL_NAME (s1) != NULL) |
| for (s2 = TYPE_FIELDS (t2); s2; s2 = TREE_CHAIN (s2)) |
| if (DECL_NAME (s1) == DECL_NAME (s2)) |
| { |
| int result; |
| result = comptypes (TREE_TYPE (s1), TREE_TYPE (s2)); |
| 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; |
| } |
| /* APPLE LOCAL begin IMA speed up */ |
| tts_i = tagged_tu_seen_base; |
| while (tts_i->isEnum) |
| { |
| const struct tagged_tu_seen* p = tts_i->next; |
| free((struct tagged_tu_seen*)tts_i); |
| tts_i = p; |
| } |
| /* APPLE LOCAL end IMA speed up */ |
| tagged_tu_seen_base = tts.next; |
| if (!ok) |
| return 0; |
| } |
| return needs_warning ? 2 : 1; |
| } |
| |
| case RECORD_TYPE: |
| { |
| struct tagged_tu_seen tts; |
| /* APPLE LOCAL IMA speed up */ |
| const struct tagged_tu_seen * tts_i; |
| |
| tts.next = tagged_tu_seen_base; |
| tts.t1 = t1; |
| tts.t2 = t2; |
| /* APPLE LOCAL IMA speed up */ |
| tts.isEnum = 0; |
| 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)); |
| 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; |
| } |
| |
| /* APPLE LOCAL begin IMA speed up */ |
| tts_i = tagged_tu_seen_base; |
| while (tts_i->isEnum) |
| { |
| const struct tagged_tu_seen* p = tts_i->next; |
| free((struct tagged_tu_seen*)tts_i); |
| tts_i = p; |
| } |
| /* APPLE LOCAL end IMA speed up */ |
| tagged_tu_seen_base = tts.next; |
| if (s1 && s2) |
| return 0; |
| return needs_warning ? 2 : 1; |
| } |
| |
| default: |
| gcc_unreachable (); |
| } |
| } |
| |
| /* 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) |
| { |
| 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 used to mean |
| the function is noreturn. */ |
| if (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); |
| 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))) |
| 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))) |
| val = 2; |
| return val; |
| } |
| |
| /* Both types have argument lists: compare them and propagate results. */ |
| val1 = type_lists_compatible_p (args1, args2); |
| 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) |
| { |
| /* 1 if no need for warning yet, 2 if warning cause has been seen. */ |
| int val = 1; |
| int newval = 0; |
| |
| while (1) |
| { |
| tree a1, mv1, a2, mv2; |
| 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; |
| mv1 = a1 = TREE_VALUE (args1); |
| mv2 = a2 = TREE_VALUE (args2); |
| if (mv1 && mv1 != error_mark_node && TREE_CODE (mv1) != ARRAY_TYPE) |
| mv1 = TYPE_MAIN_VARIANT (mv1); |
| if (mv2 && mv2 != error_mark_node && TREE_CODE (mv2) != ARRAY_TYPE) |
| mv2 = TYPE_MAIN_VARIANT (mv2); |
| /* 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 (a1 == 0) |
| { |
| if (c_type_promotes_to (a2) != a2) |
| return 0; |
| } |
| else if (a2 == 0) |
| { |
| if (c_type_promotes_to (a1) != a1) |
| return 0; |
| } |
| /* If one of the lists has an error marker, ignore this arg. */ |
| else if (TREE_CODE (a1) == ERROR_MARK |
| || TREE_CODE (a2) == ERROR_MARK) |
| ; |
| else if (!(newval = comptypes (mv1, mv2))) |
| { |
| /* Allow wait (union {union wait *u; int *i} *) |
| and wait (union wait *) to be compatible. */ |
| if (TREE_CODE (a1) == UNION_TYPE |
| && (TYPE_NAME (a1) == 0 |
| || TYPE_TRANSPARENT_UNION (a1)) |
| && TREE_CODE (TYPE_SIZE (a1)) == INTEGER_CST |
| && tree_int_cst_equal (TYPE_SIZE (a1), |
| TYPE_SIZE (a2))) |
| { |
| tree memb; |
| for (memb = TYPE_FIELDS (a1); |
| memb; memb = TREE_CHAIN (memb)) |
| { |
| tree mv3 = TREE_TYPE (memb); |
| if (mv3 && mv3 != error_mark_node |
| && TREE_CODE (mv3) != ARRAY_TYPE) |
| mv3 = TYPE_MAIN_VARIANT (mv3); |
| if (comptypes (mv3, mv2)) |
| break; |
| } |
| if (memb == 0) |
| return 0; |
| } |
| else if (TREE_CODE (a2) == UNION_TYPE |
| && (TYPE_NAME (a2) == 0 |
| || TYPE_TRANSPARENT_UNION (a2)) |
| && TREE_CODE (TYPE_SIZE (a2)) == INTEGER_CST |
| && tree_int_cst_equal (TYPE_SIZE (a2), |
| TYPE_SIZE (a1))) |
| { |
| tree memb; |
| for (memb = TYPE_FIELDS (a2); |
| memb; memb = TREE_CHAIN (memb)) |
| { |
| tree mv3 = TREE_TYPE (memb); |
| if (mv3 && mv3 != error_mark_node |
| && TREE_CODE (mv3) != ARRAY_TYPE) |
| mv3 = TYPE_MAIN_VARIANT (mv3); |
| if (comptypes (mv3, mv1)) |
| 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. */ |
| |
| static 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. Note that DECL_INITIAL |
| isn't valid for a PARM_DECL. */ |
| current_function_decl != 0 |
| && TREE_CODE (decl) != PARM_DECL |
| && !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) |
| { |
| tree ret; |
| |
| if (pedantic || DECL_MODE (decl) == BLKmode) |
| return decl; |
| |
| ret = decl_constant_value (decl); |
| /* Avoid unwanted tree sharing between the initializer and current |
| function's body where the tree can be modified e.g. by the |
| gimplifier. */ |
| if (ret != decl && TREE_STATIC (decl)) |
| ret = unshare_expr (ret); |
| return ret; |
| } |
| |
| |
| /* 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); |
| } |
| |
| if (TREE_NO_WARNING (orig_exp)) |
| TREE_NO_WARNING (exp) = 1; |
| |
| 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 (REFERENCE_CLASS_P (exp) || 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 (build_pointer_type (restype), |
| TREE_OPERAND (exp, 0)); |
| |
| if (TREE_CODE (exp) == COMPOUND_EXPR) |
| { |
| tree op1 = default_conversion (TREE_OPERAND (exp, 1)); |
| return build2 (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) |
| { |
| /* We are making an ADDR_EXPR of ptrtype. This is a valid |
| ADDR_EXPR because it's the best way of representing what |
| happens in C when we take the address of an array and place |
| it in a pointer to the element type. */ |
| adr = build1 (ADDR_EXPR, ptrtype, exp); |
| if (!c_mark_addressable (exp)) |
| return error_mark_node; |
| 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); |
| |
| if (TREE_NO_WARNING (orig_exp)) |
| TREE_NO_WARNING (exp) = 1; |
| |
| /* 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)) |
| && TYPE_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 (TYPE_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) && TYPE_LANG_SPECIFIC (type)->s) |
| { |
| 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; |
| |
| if (!objc_is_public (datum, component)) |
| return error_mark_node; |
| |
| /* APPLE LOCAL begin ObjC new abi */ |
| if ((ref = objc_v2_build_ivar_ref (datum, component))) |
| return ref; |
| /* APPLE LOCAL end ObjC new abi */ |
| |
| /* APPLE LOCAL begin C* property (Radar 4436866) */ |
| if ((ref = objc_build_getter_call (datum, component))) |
| return ref; |
| /* APPLE LOCAL end C* property (Radar 4436866) */ |
| |
| /* 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 ("%qT has no member named %qs", type, |
| 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 = build3 (COMPONENT_REF, TREE_TYPE (subdatum), datum, subdatum, |
| NULL_TREE); |
| /* APPLE LOCAL radar 4697411 */ |
| objc_volatilize_component_ref (ref, TREE_TYPE (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); |
| |
| /* APPLE LOCAL begin "unavailable" attribute (radar 2809697) */ |
| if (TREE_UNAVAILABLE (subdatum)) |
| warn_unavailable_use (subdatum); |
| /* APPLE LOCAL end "unavailable" attribute (radar 2809697) */ |
| |
| datum = ref; |
| |
| field = TREE_CHAIN (field); |
| } |
| while (field); |
| |
| return ref; |
| } |
| else if (code != ERROR_MARK) |
| error ("request for member %qs 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 mvt = t; |
| tree ref; |
| |
| if (TREE_CODE (mvt) != ARRAY_TYPE) |
| mvt = TYPE_MAIN_VARIANT (mvt); |
| ref = build1 (INDIRECT_REF, mvt, 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 %qs", 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) |
| { |
| bool swapped = false; |
| if (TREE_TYPE (array) == error_mark_node |
| || TREE_TYPE (index) == error_mark_node) |
| return error_mark_node; |
| |
| /* APPLE LOCAL begin CW asm blocks */ |
| if (inside_iasm_block) |
| { |
| if (TREE_CODE (array) == BRACKET_EXPR |
| || TREE_CODE (index) == IDENTIFIER_NODE |
| || TREE_TYPE (index) == NULL_TREE) |
| return iasm_build_bracket (array, index); |
| } |
| /* APPLE LOCAL end CW asm blocks */ |
| |
| if (TREE_CODE (TREE_TYPE (array)) != ARRAY_TYPE |
| && TREE_CODE (TREE_TYPE (array)) != POINTER_TYPE) |
| { |
| tree temp; |
| if (TREE_CODE (TREE_TYPE (index)) != ARRAY_TYPE |
| && TREE_CODE (TREE_TYPE (index)) != POINTER_TYPE) |
| { |
| error ("subscripted value is neither array nor pointer"); |
| return error_mark_node; |
| } |
| temp = array; |
| array = index; |
| index = temp; |
| swapped = true; |
| } |
| |
| if (!INTEGRAL_TYPE_P (TREE_TYPE (index))) |
| { |
| error ("array subscript is not an integer"); |
| return error_mark_node; |
| } |
| |
| if (TREE_CODE (TREE_TYPE (TREE_TYPE (array))) == FUNCTION_TYPE) |
| { |
| error ("subscripted value is pointer to function"); |
| return error_mark_node; |
| } |
| |
| /* 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. ??? Existing practice has also been to warn only |
| when the char index is syntactically the index, not for |
| char[array]. */ |
| if (warn_char_subscripts && !swapped |
| && 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); |
| |
| gcc_assert (TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE); |
| |
| if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE) |
| { |
| tree rval, type; |
| |
| /* 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_DOMAIN (TREE_TYPE (array)) |
| && !int_fits_type_p (index, TYPE_DOMAIN (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 && C_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 = TREE_TYPE (TREE_TYPE (array)); |
| if (TREE_CODE (type) != ARRAY_TYPE) |
| type = TYPE_MAIN_VARIANT (type); |
| rval = build4 (ARRAY_REF, type, array, index, NULL_TREE, NULL_TREE); |
| /* 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)); |
| } |
| else |
| { |
| tree ar = default_conversion (array); |
| |
| if (ar == error_mark_node) |
| return ar; |
| |
| gcc_assert (TREE_CODE (TREE_TYPE (ar)) == POINTER_TYPE); |
| gcc_assert (TREE_CODE (TREE_TYPE (TREE_TYPE (ar))) != FUNCTION_TYPE); |
| |
| /* APPLE LOCAL begin LLVM */ |
| #ifdef ENABLE_LLVM |
| /* Do not create explicit pointer arithmetic for pointer subscripts, |
| * instead, generate an array ref, even though the first argument is a |
| * pointer, not an array. The LLVM backend supports this use of ARRAY_REF |
| * and it provides it with more information for optimization. |
| */ |
| { |
| tree ty = TREE_TYPE(TREE_TYPE(ar)); |
| if (TREE_CODE(ty) == RECORD_TYPE || TREE_CODE(ty) == UNION_TYPE |
| || TREE_CODE(ty) == QUAL_UNION_TYPE) |
| ty = TYPE_MAIN_VARIANT (ty); |
| |
| ar = build4 (ARRAY_REF, ty, ar, index, NULL_TREE, NULL_TREE); |
| /* mirror logic from build_indirect_ref to set TREE_THIS_VOLATILE. */ |
| TREE_THIS_VOLATILE(ar) = TYPE_VOLATILE(TREE_TYPE(ar)); |
| return ar; |
| } |
| #endif |
| /* APPLE LOCAL end LLVM */ |
| |
| return build_indirect_ref (build_binary_op (PLUS_EXPR, ar, index, 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); |
| |
| /* APPLE LOCAL begin CW asm blocks */ |
| /* CW assembly has automagical handling of register names. It's |
| also handy to assume undeclared names as labels, although it |
| would be better to have a second pass and complain about names in |
| the block that are not labels. */ |
| if (inside_iasm_block) |
| { |
| if (decl) |
| { |
| if (TREE_CODE (decl) == FUNCTION_DECL) |
| TREE_USED (decl) = 1; |
| /* Locals and parms just need to be left alone for now. */ |
| } |
| else |
| return iasm_do_id (id); |
| } |
| /* APPLE LOCAL end CW asm blocks */ |
| |
| /* In Objective-C, an instance variable (ivar) may be preferred to |
| whatever lookup_name() found. */ |
| decl = objc_lookup_ivar (decl, id); |
| |
| if (decl && decl != error_mark_node) |
| ref = decl; |
| 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); |
| |
| /* APPLE LOCAL begin "unavailable" attribute (radar 2809697) */ |
| if (TREE_UNAVAILABLE (ref)) |
| warn_unavailable_use (ref); |
| /* APPLE LOCAL end "unavailable" attribute (radar 2809697) */ |
| |
| if (!skip_evaluation) |
| assemble_external (ref); |
| TREE_USED (ref) = 1; |
| |
| if (TREE_CODE (ref) == FUNCTION_DECL && !in_alignof) |
| { |
| if (!in_sizeof && !in_typeof) |
| C_DECL_USED (ref) = 1; |
| else if (DECL_INITIAL (ref) == 0 |
| && DECL_EXTERNAL (ref) |
| && !TREE_PUBLIC (ref)) |
| record_maybe_used_decl (ref); |
| } |
| |
| if (TREE_CODE (ref) == CONST_DECL) |
| { |
| ref = DECL_INITIAL (ref); |
| TREE_CONSTANT (ref) = 1; |
| TREE_INVARIANT (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; |
| } |
| /* APPLE LOCAL begin for-4_3 4134307 */ |
| /* C99 6.7.4p3: An inline definition of a function with external |
| linkage ... shall not contain a reference to an identifier with |
| internal linkage. */ |
| else if (current_function_decl != 0 |
| && DECL_DECLARED_INLINE_P (current_function_decl) |
| && DECL_EXTERNAL (current_function_decl) |
| && VAR_OR_FUNCTION_DECL_P (ref) |
| && (TREE_CODE (ref) != VAR_DECL || TREE_STATIC (ref)) |
| && ! TREE_PUBLIC (ref)) |
| pedwarn ("%qD is static but used in inline function %qD " |
| "which is not static", ref, current_function_decl); |
| |
| /* APPLE LOCAL end for-4_3 4134307 */ |
| return ref; |
| } |
| |
| /* Record details of decls possibly used inside sizeof or typeof. */ |
| struct maybe_used_decl |
| { |
| /* The decl. */ |
| tree decl; |
| /* The level seen at (in_sizeof + in_typeof). */ |
| int level; |
| /* The next one at this level or above, or NULL. */ |
| struct maybe_used_decl *next; |
| }; |
| |
| static struct maybe_used_decl *maybe_used_decls; |
| |
| /* Record that DECL, an undefined static function reference seen |
| inside sizeof or typeof, might be used if the operand of sizeof is |
| a VLA type or the operand of typeof is a variably modified |
| type. */ |
| |
| static void |
| record_maybe_used_decl (tree decl) |
| { |
| struct maybe_used_decl *t = XOBNEW (&parser_obstack, struct maybe_used_decl); |
| t->decl = decl; |
| t->level = in_sizeof + in_typeof; |
| t->next = maybe_used_decls; |
| maybe_used_decls = t; |
| } |
| |
| /* Pop the stack of decls possibly used inside sizeof or typeof. If |
| USED is false, just discard them. If it is true, mark them used |
| (if no longer inside sizeof or typeof) or move them to the next |
| level up (if still inside sizeof or typeof). */ |
| |
| void |
| pop_maybe_used (bool used) |
| { |
| struct maybe_used_decl *p = maybe_used_decls; |
| int cur_level = in_sizeof + in_typeof; |
| while (p && p->level > cur_level) |
| { |
| if (used) |
| { |
| if (cur_level == 0) |
| C_DECL_USED (p->decl) = 1; |
| else |
| p->level = cur_level; |
| } |
| p = p->next; |
| } |
| if (!used || cur_level == 0) |
| maybe_used_decls = p; |
| } |
| |
| /* Return the result of sizeof applied to EXPR. */ |
| |
| struct c_expr |
| c_expr_sizeof_expr (struct c_expr expr) |
| { |
| struct c_expr ret; |
| if (expr.value == error_mark_node) |
| { |
| ret.value = error_mark_node; |
| ret.original_code = ERROR_MARK; |
| pop_maybe_used (false); |
| } |
| else |
| { |
| ret.value = c_sizeof (TREE_TYPE (expr.value)); |
| ret.original_code = ERROR_MARK; |
| /* APPLE LOCAL begin mainline 2006-05-18 4336222 */ |
| if (c_vla_type_p (TREE_TYPE (expr.value))) |
| { |
| /* sizeof is evaluated when given a vla (C99 6.5.3.4p2). */ |
| ret.value = build2 (COMPOUND_EXPR, TREE_TYPE (ret.value), expr.value, ret.value); |
| } |
| /* APPLE LOCAL end mainline 2006-05-18 4336222 */ |
| pop_maybe_used (C_TYPE_VARIABLE_SIZE (TREE_TYPE (expr.value))); |
| } |
| return ret; |
| } |
| |
| /* Return the result of sizeof applied to T, a structure for the type |
| name passed to sizeof (rather than the type itself). */ |
| |
| struct c_expr |
| c_expr_sizeof_type (struct c_type_name *t) |
| { |
| tree type; |
| struct c_expr ret; |
| type = groktypename (t); |
| ret.value = c_sizeof (type); |
| ret.original_code = ERROR_MARK; |
| pop_maybe_used (C_TYPE_VARIABLE_SIZE (type)); |
| return ret; |
| } |
| |
| /* 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); |
| |
| /* APPLE LOCAL begin mainline */ |
| /* For Objective-C, convert any calls via a cast to OBJC_TYPE_REF |
| expressions, like those used for ObjC messenger dispatches. */ |
| function = objc_rewrite_function_call (function, params); |
| |
| /* APPLE LOCAL end mainline */ |
| 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 %qE is not a function", 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); |
| |
| /* APPLE LOCAL begin mainline */ |
| /* 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. */ |
| /* APPLE LOCAL end mainline */ |
| |
| /* APPLE LOCAL mainline */ |
| if (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))) |
| { |
| 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 build2 (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, function, fundecl); |
| |
| if (coerced_params == error_mark_node) |
| return error_mark_node; |
| |
| /* Check that the arguments to the function are valid. */ |
| |
| check_function_arguments (TYPE_ATTRIBUTES (fntype), coerced_params); |
| |
| result = build3 (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, unless there are too few arguments in which |
| case it is error_mark_node. |
| |
| 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. |
| |
| FUNCTION is a tree for the called function. It is used only for |
| error messages, where it is formatted with %qE. |
| |
| 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 function, tree fundecl) |
| { |
| tree typetail, valtail; |
| tree result = NULL; |
| int parmnum; |
| tree selector; |
| /* APPLE LOCAL mainline 2005-04-14 */ |
| const char *invalid_func_diag; |
| |
| /* Change pointer to function to the function itself for |
| diagnostics. */ |
| if (TREE_CODE (function) == ADDR_EXPR |
| && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL) |
| function = TREE_OPERAND (function, 0); |
| |
| /* Handle an ObjC selector specially for diagnostics. */ |
| selector = objc_message_selector (); |
| |
| /* 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); |
| tree rname = function; |
| int argnum = parmnum + 1; |
| |
| if (type == void_type_node) |
| { |
| /* APPLE LOCAL begin radar 4491608 */ |
| error ("too many arguments to function %qE", selector ? selector |
| : function); |
| /* APPLE LOCAL end radar 4491608 */ |
| break; |
| } |
| |
| if (selector && argnum > 2) |
| { |
| rname = selector; |
| argnum -= 2; |
| } |
| |
| /* 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 (type == error_mark_node || !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) |
| { |
| unsigned int formal_prec = TYPE_PRECISION (type); |
| |
| if (INTEGRAL_TYPE_P (type) |
| && TREE_CODE (TREE_TYPE (val)) == REAL_TYPE) |
| warning ("passing argument %d of %qE as integer " |
| "rather than floating due to prototype", |
| argnum, rname); |
| if (INTEGRAL_TYPE_P (type) |
| && TREE_CODE (TREE_TYPE (val)) == COMPLEX_TYPE) |
| warning ("passing argument %d of %qE as integer " |
| "rather than complex due to prototype", |
| argnum, rname); |
| else if (TREE_CODE (type) == COMPLEX_TYPE |
| && TREE_CODE (TREE_TYPE (val)) == REAL_TYPE) |
| warning ("passing argument %d of %qE as complex " |
| "rather than floating due to prototype", |
| argnum, rname); |
| else if (TREE_CODE (type) == REAL_TYPE |
| && INTEGRAL_TYPE_P (TREE_TYPE (val))) |
| warning ("passing argument %d of %qE as floating " |
| "rather than integer due to prototype", |
| argnum, rname); |
| else if (TREE_CODE (type) == COMPLEX_TYPE |
| && INTEGRAL_TYPE_P (TREE_TYPE (val))) |
| warning ("passing argument %d of %qE as complex " |
| "rather than integer due to prototype", |
| argnum, rname); |
| else if (TREE_CODE (type) == REAL_TYPE |
| && TREE_CODE (TREE_TYPE (val)) == COMPLEX_TYPE) |
| warning ("passing argument %d of %qE as floating " |
| "rather than complex due to prototype", |
| argnum, rname); |
| /* ??? 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)) |
| warning ("passing argument %d of %qE as %<float%> " |
| "rather than %<double%> due to prototype", |
| argnum, rname); |
| } |
| /* 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)) |
| warning ("passing argument %d of %qE with different " |
| "width due to prototype", argnum, rname); |
| else if (TYPE_UNSIGNED (type) == TYPE_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) |
| && TYPE_UNSIGNED (TREE_TYPE (val))) |
| ; |
| else if (TYPE_UNSIGNED (type)) |
| warning ("passing argument %d of %qE as unsigned " |
| "due to prototype", argnum, rname); |
| else |
| warning ("passing argument %d of %qE as signed " |
| "due to prototype", argnum, rname); |
| } |
| } |
| |
| parmval = convert_for_assignment (type, val, ic_argpass, |
| fundecl, function, |
| 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); |
| /* APPLE LOCAL begin mainline 2005-04-14 */ |
| else if ((invalid_func_diag = |
| targetm.calls.invalid_arg_for_unprototyped_fn (typelist, fundecl, val))) |
| { |
| error (invalid_func_diag); |
| return error_mark_node; |
| } |
| /* APPLE LOCAL end mainline 2005-04-14 */ |
| 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) |
| { |
| error ("too few arguments to function %qE", function); |
| return error_mark_node; |
| } |
| |
| 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. */ |
| |
| struct c_expr |
| parser_build_binary_op (enum tree_code code, struct c_expr arg1, |
| struct c_expr arg2) |
| { |
| struct c_expr result; |
| |
| enum tree_code code1 = arg1.original_code; |
| enum tree_code code2 = arg2.original_code; |
| |
| /* APPLE LOCAL begin CW asm blocks */ |
| if (inside_iasm_block) |
| { |
| if (TREE_CODE (arg1.value) == IDENTIFIER_NODE |
| || TREE_CODE (arg2.value) == IDENTIFIER_NODE |
| || TREE_TYPE (arg1.value) == NULL_TREE |
| || TREE_TYPE (arg2.value) == NULL_TREE) |
| { |
| result.value = build2 (code, NULL_TREE, arg1.value, arg2.value); |
| result.original_code = code; |
| return result; |
| } |
| else if ((code == MINUS_EXPR && TREE_CODE (arg1.value) == VAR_DECL |
| && TREE_CODE (arg2.value) == LABEL_DECL)) |
| { |
| result.value = build2 (code, TREE_TYPE (arg1.value), arg1.value, arg2.value); |
| result.original_code = code; |
| return result; |
| } |
| else |
| if (TREE_CODE (arg1.value) == LABEL_DECL |
| || TREE_CODE (arg2.value) == LABEL_DECL |
| || TREE_CODE (arg1.value) == IDENTIFIER_NODE |
| || TREE_CODE (arg2.value) == IDENTIFIER_NODE) |
| { |
| result.value = error_mark_node; |
| result.original_code = code; |
| return result; |
| } |
| } |
| /* APPLE LOCAL end CW asm blocks */ |
| |
| result.value = build_binary_op (code, arg1.value, arg2.value, 1); |
| result.original_code = code; |
| |
| if (TREE_CODE (result.value) == ERROR_MARK) |
| return result; |
| |
| /* Check for cases such as x+y<<z which users are likely |
| to misinterpret. */ |
| 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) == tcc_comparison |
| || TREE_CODE_CLASS (code2) == tcc_comparison) |
| 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) == tcc_comparison |
| || TREE_CODE_CLASS (code2) == tcc_comparison) |
| 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) == tcc_comparison |
| || TREE_CODE_CLASS (code2) == tcc_comparison) |
| 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) == tcc_comparison |
| && (TREE_CODE_CLASS (code1) == tcc_comparison |
| || TREE_CODE_CLASS (code2) == tcc_comparison)) |
| warning ("comparisons like X<=Y<=Z do not have their mathematical meaning"); |
| |
| } |
| |
| unsigned_conversion_warning (result.value, arg1.value); |
| unsigned_conversion_warning (result.value, arg2.value); |
| overflow_warning (result.value); |
| |
| return result; |
| } |
| |
| /* 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 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. */ |
| return fold (build2 (EXACT_DIV_EXPR, restype, op0, convert (restype, op1))); |
| } |
| |
| /* 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 |
| || typecode == VECTOR_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 = lang_hooks.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: |
| |
| /* 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 build2 (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); |
| |
| /* APPLE LOCAL begin radar 4712269 */ |
| if ((val = objc_build_incr_decr_setter_call (code, arg, inc))) |
| return val; |
| /* APPLE LOCAL end radar 4712269 */ |
| |
| /* Complain about anything else that is not a true lvalue. */ |
| /* APPLE LOCAL begin non lvalue assign */ |
| if (!lvalue_or_else (&arg, ((code == PREINCREMENT_EXPR |
| || code == POSTINCREMENT_EXPR) |
| ? lv_increment |
| : lv_decrement))) |
| /* APPLE LOCAL end non lvalue assign */ |
| return error_mark_node; |
| |
| /* Report a read-only lvalue. */ |
| if (TREE_READONLY (arg)) |
| readonly_error (arg, |
| ((code == PREINCREMENT_EXPR |
| || code == POSTINCREMENT_EXPR) |
| ? lv_increment : lv_decrement)); |
| |
| if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE) |
| val = boolean_increment (code, arg); |
| else |
| val = build2 (code, TREE_TYPE (arg), arg, inc); |
| TREE_SIDE_EFFECTS (val) = 1; |
| val = convert (result_type, val); |
| if (TREE_CODE (val) != code) |
| TREE_NO_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); |
| } |
| |
| /* APPLE LOCAL begin LLVM */ |
| /* LLVM wants &x[y] to be kept as an &x[y] for better optimization. */ |
| #ifndef ENABLE_LLVM |
| /* 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); |
| } |
| #endif |
| /* APPLE LOCAL end LLVM */ |
| |
| /* Anything not already handled and not a true memory reference |
| or a non-lvalue array is an error. */ |
| else if (typecode != FUNCTION_TYPE && !flag |
| /* APPLE LOCAL non lvalue assign */ |
| && !lvalue_or_else (&arg, lv_addressof)) |
| 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) || REFERENCE_CLASS_P (arg)) |
| && (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg))) |
| argtype = c_build_type_variant (argtype, |
| TREE_READONLY (arg), |
| TREE_THIS_VOLATILE (arg)); |
| |
| if (!c_mark_addressable (arg)) |
| return error_mark_node; |
| |
| gcc_assert (TREE_CODE (arg) != COMPONENT_REF |
| || !DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1))); |
| |
| argtype = build_pointer_type (argtype); |
| |
| /* ??? Cope with user tricks that amount to offsetof. Delete this |
| when we have proper support for integer constant expressions. */ |
| val = get_base_address (arg); |
| if (val && TREE_CODE (val) == INDIRECT_REF |
| && integer_zerop (TREE_OPERAND (val, 0))) |
| return fold_convert (argtype, fold_offsetof (arg)); |
| |
| val = build1 (ADDR_EXPR, argtype, arg); |
| |
| if (TREE_CODE (arg) == COMPOUND_LITERAL_EXPR) |
| TREE_INVARIANT (val) = TREE_CONSTANT (val) = 1; |
| |
| return val; |
| |
| 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 C_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: |
| return TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE; |
| |
| default: |
| return 0; |
| } |
| } |
| |
| /* Give an error for storing in something that is 'const'. */ |
| |
| static void |
| readonly_error (tree arg, enum lvalue_use use) |
| { |
| gcc_assert (use == lv_assign || use == lv_increment || use == lv_decrement); |
| /* Using this macro rather than (for example) arrays of messages |
| ensures that all the format strings are checked at compile |
| time. */ |
| #define READONLY_MSG(A, I, D) (use == lv_assign \ |
| ? (A) \ |
| : (use == lv_increment ? (I) : (D))) |
| if (TREE_CODE (arg) == COMPONENT_REF) |
| { |
| if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0)))) |
| readonly_error (TREE_OPERAND (arg, 0), use); |
| else |
| error (READONLY_MSG (G_("assignment of read-only member %qs"), |
| G_("increment of read-only member %qs"), |
| G_("decrement of read-only member %qs")), |
| IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (arg, 1)))); |
| } |
| else if (TREE_CODE (arg) == VAR_DECL) |
| error (READONLY_MSG (G_("assignment of read-only variable %qs"), |
| G_("increment of read-only variable %qs"), |
| G_("decrement of read-only variable %qs")), |
| IDENTIFIER_POINTER (DECL_NAME (arg))); |
| else |
| error (READONLY_MSG (G_("assignment of read-only location"), |
| G_("increment of read-only location"), |
| G_("decrement of read-only location"))); |
| } |
| |
| /* 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 %qD", TREE_OPERAND (x, 1)); |
| return false; |
| } |
| |
| /* ... fall through ... */ |
| |
| case ADDR_EXPR: |
| case ARRAY_REF: |
| case REALPART_EXPR: |
| case IMAGPART_EXPR: |
| /* APPLE LOCAL begin LLVM */ |
| #ifdef ENABLE_LLVM |
| if (TREE_CODE (x) == ARRAY_REF && |
| TREE_CODE (TREE_TYPE (TREE_OPERAND (x, 0))) != ARRAY_TYPE) |
| return true; /* Ignore pointer base of array ref extension. */ |
| #endif |
| /* APPLE LOCAL end LLVM */ |
| 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 (C_DECL_REGISTER (x) |
| && DECL_NONLOCAL (x)) |
| { |
| if (TREE_PUBLIC (x) || TREE_STATIC (x) || DECL_EXTERNAL (x)) |
| { |
| error |
| ("global register variable %qD used in nested function", x); |
| return false; |
| } |
| pedwarn ("register variable %qD used in nested function", x); |
| } |
| else if (C_DECL_REGISTER (x)) |
| { |
| if (TREE_PUBLIC (x) || TREE_STATIC (x) || DECL_EXTERNAL (x)) |
| error ("address of global register variable %qD requested", x); |
| else |
| error ("address of register variable %qD requested", x); |
| return false; |
| } |
| |
| /* 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<
|