X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gcc%2Ftree.c;h=eec4a8b290580adfccc264a7b548e11aa1c56a5f;hb=91f2fae8cc58e1b1dae3b62e2407903190ed1af4;hp=88666d3e0e8f16d2a210542466121d9d714f5e6b;hpb=a803773f0ef89ce35786465e125772a57e6936c1;p=gcc.git diff --git a/gcc/tree.c b/gcc/tree.c index 88666d3e0e8..eec4a8b2905 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -1,7 +1,7 @@ /* Language-independent node constructors for parse phase of GNU compiler. Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 - Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, + 2011 Free Software Foundation, Inc. This file is part of GCC. @@ -41,6 +41,7 @@ along with GCC; see the file COPYING3. If not see #include "toplev.h" #include "ggc.h" #include "hashtab.h" +#include "filenames.h" #include "output.h" #include "target.h" #include "langhooks.h" @@ -769,20 +770,15 @@ tree_size (const_tree node) } } -/* Return a newly allocated node of code CODE. For decl and type - nodes, some other fields are initialized. The rest of the node is - initialized to zero. This function cannot be used for TREE_VEC or - OMP_CLAUSE nodes, which is enforced by asserts in tree_code_size. - - Achoo! I got a code in the node. */ +/* Record interesting allocation statistics for a tree node with CODE + and LENGTH. */ -tree -make_node_stat (enum tree_code code MEM_STAT_DECL) +static void +record_node_allocation_statistics (enum tree_code code ATTRIBUTE_UNUSED, + size_t length ATTRIBUTE_UNUSED) { - tree t; - enum tree_code_class type = TREE_CODE_CLASS (code); - size_t length = tree_code_size (code); #ifdef GATHER_STATISTICS + enum tree_code_class type = TREE_CODE_CLASS (code); tree_node_kind kind; switch (type) @@ -841,12 +837,20 @@ make_node_stat (enum tree_code code MEM_STAT_DECL) kind = constr_kind; break; + case OMP_CLAUSE: + kind = omp_clause_kind; + break; + default: kind = x_kind; break; } break; + case tcc_vl_exp: + kind = e_kind; + break; + default: gcc_unreachable (); } @@ -854,6 +858,23 @@ make_node_stat (enum tree_code code MEM_STAT_DECL) tree_node_counts[(int) kind]++; tree_node_sizes[(int) kind] += length; #endif +} + +/* Return a newly allocated node of code CODE. For decl and type + nodes, some other fields are initialized. The rest of the node is + initialized to zero. This function cannot be used for TREE_VEC or + OMP_CLAUSE nodes, which is enforced by asserts in tree_code_size. + + Achoo! I got a code in the node. */ + +tree +make_node_stat (enum tree_code code MEM_STAT_DECL) +{ + tree t; + enum tree_code_class type = TREE_CODE_CLASS (code); + size_t length = tree_code_size (code); + + record_node_allocation_statistics (code, length); t = ggc_alloc_zone_cleared_tree_node_stat ( (code == IDENTIFIER_NODE) ? &tree_id_zone : &tree_zone, @@ -950,6 +971,7 @@ copy_node_stat (tree node MEM_STAT_DECL) gcc_assert (code != STATEMENT_LIST); length = tree_size (node); + record_node_allocation_statistics (code, length); t = ggc_alloc_zone_tree_node_stat (&tree_zone, length PASS_MEM_STAT); memcpy (t, node, length); @@ -1376,8 +1398,14 @@ build_vector_from_val (tree vectype, tree sc) if (sc == error_mark_node) return sc; - gcc_assert (useless_type_conversion_p (TREE_TYPE (sc), - TREE_TYPE (vectype))); + /* Verify that the vector type is suitable for SC. Note that there + is some inconsistency in the type-system with respect to restrict + qualifications of pointers. Vector types always have a main-variant + element type and the qualification is applied to the vector-type. + So TREE_TYPE (vector-type) does not return a properly qualified + vector element-type. */ + gcc_checking_assert (types_compatible_p (TYPE_MAIN_VARIANT (TREE_TYPE (sc)), + TREE_TYPE (vectype))); v = VEC_alloc (constructor_elt, gc, nunits); for (i = 0; i < nunits; ++i) @@ -1534,10 +1562,7 @@ build_string (int len, const char *str) /* Do not waste bytes provided by padding of struct tree_string. */ length = len + offsetof (struct tree_string, str) + 1; -#ifdef GATHER_STATISTICS - tree_node_counts[(int) c_kind]++; - tree_node_sizes[(int) c_kind] += length; -#endif + record_node_allocation_statistics (STRING_CST, length); s = ggc_alloc_tree_node (length); @@ -1657,10 +1682,7 @@ make_tree_binfo_stat (unsigned base_binfos MEM_STAT_DECL) size_t length = (offsetof (struct tree_binfo, base_binfos) + VEC_embedded_size (tree, base_binfos)); -#ifdef GATHER_STATISTICS - tree_node_counts[(int) binfo_kind]++; - tree_node_sizes[(int) binfo_kind] += length; -#endif + record_node_allocation_statistics (TREE_BINFO, length); t = ggc_alloc_zone_tree_node_stat (&tree_zone, length PASS_MEM_STAT); @@ -1682,10 +1704,7 @@ make_tree_vec_stat (int len MEM_STAT_DECL) tree t; int length = (len - 1) * sizeof (tree) + sizeof (struct tree_vec); -#ifdef GATHER_STATISTICS - tree_node_counts[(int) vec_kind]++; - tree_node_sizes[(int) vec_kind] += length; -#endif + record_node_allocation_statistics (TREE_VEC, length); t = ggc_alloc_zone_cleared_tree_node_stat (&tree_zone, length PASS_MEM_STAT); @@ -2223,10 +2242,7 @@ tree_cons_stat (tree purpose, tree value, tree chain MEM_STAT_DECL) PASS_MEM_STAT); memset (node, 0, sizeof (struct tree_common)); -#ifdef GATHER_STATISTICS - tree_node_counts[(int) x_kind]++; - tree_node_sizes[(int) x_kind] += sizeof (struct tree_list); -#endif + record_node_allocation_statistics (TREE_LIST, sizeof (struct tree_list)); TREE_SET_CODE (node, TREE_LIST); TREE_CHAIN (node) = chain; @@ -3683,28 +3699,9 @@ tree build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL) { int length = sizeof (struct tree_exp); -#ifdef GATHER_STATISTICS - tree_node_kind kind; -#endif tree t; -#ifdef GATHER_STATISTICS - switch (TREE_CODE_CLASS (code)) - { - case tcc_statement: /* an expression with side effects */ - kind = s_kind; - break; - case tcc_reference: /* a reference */ - kind = r_kind; - break; - default: - kind = e_kind; - break; - } - - tree_node_counts[(int) kind]++; - tree_node_sizes[(int) kind] += length; -#endif + record_node_allocation_statistics (code, length); gcc_assert (TREE_CODE_LENGTH (code) == 1); @@ -4007,6 +4004,20 @@ reference_alias_ptr_type (const_tree t) return build_pointer_type (TYPE_MAIN_VARIANT (TREE_TYPE (base))); } +/* Return an invariant ADDR_EXPR of type TYPE taking the address of BASE + offsetted by OFFSET units. */ + +tree +build_invariant_address (tree type, tree base, HOST_WIDE_INT offset) +{ + tree ref = fold_build2 (MEM_REF, TREE_TYPE (type), + build_fold_addr_expr (base), + build_int_cst (ptr_type_node, offset)); + tree addr = build1 (ADDR_EXPR, type, ref); + recompute_tree_invariant_for_addr_expr (addr); + return addr; +} + /* Similar except don't specify the TREE_TYPE and leave the TREE_SIDE_EFFECTS as 0. It is permissible for arguments to be null, @@ -4277,7 +4288,7 @@ build_type_attribute_qual_variant (tree ttype, tree attribute, int quals) its canonical type, we will need to use structural equality checks for this type. */ if (TYPE_STRUCTURAL_EQUALITY_P (ttype) - || !targetm.comp_type_attributes (ntype, ttype)) + || !comp_type_attributes (ntype, ttype)) SET_TYPE_STRUCTURAL_EQUALITY (ntype); else if (TYPE_CANONICAL (ntype) == ntype) TYPE_CANONICAL (ntype) = TYPE_CANONICAL (ttype); @@ -4290,6 +4301,75 @@ build_type_attribute_qual_variant (tree ttype, tree attribute, int quals) return ttype; } +/* Compare two attributes for their value identity. Return true if the + attribute values are known to be equal; otherwise return false. +*/ + +static bool +attribute_value_equal (const_tree attr1, const_tree attr2) +{ + if (TREE_VALUE (attr1) == TREE_VALUE (attr2)) + return true; + + if (TREE_VALUE (attr1) != NULL_TREE + && TREE_CODE (TREE_VALUE (attr1)) == TREE_LIST + && TREE_VALUE (attr2) != NULL + && TREE_CODE (TREE_VALUE (attr2)) == TREE_LIST) + return (simple_cst_list_equal (TREE_VALUE (attr1), + TREE_VALUE (attr2)) == 1); + + return (simple_cst_equal (TREE_VALUE (attr1), TREE_VALUE (attr2)) == 1); +} + +/* Return 0 if the attributes for two types are incompatible, 1 if they + are compatible, and 2 if they are nearly compatible (which causes a + warning to be generated). */ +int +comp_type_attributes (const_tree type1, const_tree type2) +{ + const_tree a1 = TYPE_ATTRIBUTES (type1); + const_tree a2 = TYPE_ATTRIBUTES (type2); + const_tree a; + + if (a1 == a2) + return 1; + for (a = a1; a != NULL_TREE; a = TREE_CHAIN (a)) + { + const struct attribute_spec *as; + const_tree attr; + + as = lookup_attribute_spec (TREE_PURPOSE (a)); + if (!as || as->affects_type_identity == false) + continue; + + attr = lookup_attribute (as->name, CONST_CAST_TREE (a2)); + if (!attr || !attribute_value_equal (a, attr)) + break; + } + if (!a) + { + for (a = a2; a != NULL_TREE; a = TREE_CHAIN (a)) + { + const struct attribute_spec *as; + + as = lookup_attribute_spec (TREE_PURPOSE (a)); + if (!as || as->affects_type_identity == false) + continue; + + if (!lookup_attribute (as->name, CONST_CAST_TREE (a1))) + break; + /* We don't need to compare trees again, as we did this + already in first loop. */ + } + /* All types - affecting identity - are equal, so + there is no need to call target hook for comparison. */ + if (!a) + return 1; + } + /* As some type combinations - like default calling-convention - might + be compatible, we have to call the target hook to get the final result. */ + return targetm.comp_type_attributes (type1, type2); +} /* Return a type like TTYPE except that its TYPE_ATTRIBUTE is ATTRIBUTE. @@ -4577,6 +4657,25 @@ free_lang_data_in_decl (tree decl) } else if (TREE_CODE (decl) == TYPE_DECL) DECL_INITIAL (decl) = NULL_TREE; + else if (TREE_CODE (decl) == TRANSLATION_UNIT_DECL + && DECL_INITIAL (decl) + && TREE_CODE (DECL_INITIAL (decl)) == BLOCK) + { + /* Strip builtins from the translation-unit BLOCK. We still have + targets without builtin_decl support and also builtins are + shared nodes and thus we can't use TREE_CHAIN in multiple + lists. */ + tree *nextp = &BLOCK_VARS (DECL_INITIAL (decl)); + while (*nextp) + { + tree var = *nextp; + if (TREE_CODE (var) == FUNCTION_DECL + && DECL_BUILT_IN (var)) + *nextp = TREE_CHAIN (var); + else + nextp = &TREE_CHAIN (var); + } + } } @@ -4803,7 +4902,8 @@ find_decls_types_r (tree *tp, int *ws, void *data) fld_worklist_push (BLOCK_ABSTRACT_ORIGIN (t), fld); } - fld_worklist_push (TREE_TYPE (t), fld); + if (TREE_CODE (t) != IDENTIFIER_NODE) + fld_worklist_push (TREE_TYPE (t), fld); return NULL_TREE; } @@ -5270,23 +5370,10 @@ merge_attributes (tree a1, tree a2) tree a; for (a = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)), attributes); - a != NULL_TREE; + a != NULL_TREE && !attribute_value_equal (a, a2); a = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)), TREE_CHAIN (a))) - { - if (TREE_VALUE (a) != NULL - && TREE_CODE (TREE_VALUE (a)) == TREE_LIST - && TREE_VALUE (a2) != NULL - && TREE_CODE (TREE_VALUE (a2)) == TREE_LIST) - { - if (simple_cst_list_equal (TREE_VALUE (a), - TREE_VALUE (a2)) == 1) - break; - } - else if (simple_cst_equal (TREE_VALUE (a), - TREE_VALUE (a2)) == 1) - break; - } + ; if (a == NULL_TREE) { a1 = copy_node (a2); @@ -5509,7 +5596,8 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags, DECL_DLLIMPORT_P (node) = 1; } else if (TREE_CODE (node) == FUNCTION_DECL - && DECL_DECLARED_INLINE_P (node)) + && DECL_DECLARED_INLINE_P (node) + && flag_keep_inline_dllexport) /* An exported function, even if inline, must be emitted. */ DECL_EXTERNAL (node) = 0; @@ -5825,6 +5913,8 @@ decl_init_priority_insert (tree decl, priority_type priority) struct tree_priority_map *h; gcc_assert (VAR_OR_FUNCTION_DECL_P (decl)); + if (priority == DEFAULT_INIT_PRIORITY) + return; h = decl_priority_info (decl); h->init = priority; } @@ -5837,6 +5927,8 @@ decl_fini_priority_insert (tree decl, priority_type priority) struct tree_priority_map *h; gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); + if (priority == DEFAULT_INIT_PRIORITY) + return; h = decl_priority_info (decl); h->fini = priority; } @@ -5961,12 +6053,18 @@ type_hash_eq (const void *va, const void *vb) || TREE_TYPE (a->type) != TREE_TYPE (b->type) || !attribute_list_equal (TYPE_ATTRIBUTES (a->type), TYPE_ATTRIBUTES (b->type)) - || TYPE_ALIGN (a->type) != TYPE_ALIGN (b->type) - || TYPE_MODE (a->type) != TYPE_MODE (b->type) || (TREE_CODE (a->type) != COMPLEX_TYPE && TYPE_NAME (a->type) != TYPE_NAME (b->type))) return 0; + /* Be careful about comparing arrays before and after the element type + has been completed; don't compare TYPE_ALIGN unless both types are + complete. */ + if (COMPLETE_TYPE_P (a->type) && COMPLETE_TYPE_P (b->type) + && (TYPE_ALIGN (a->type) != TYPE_ALIGN (b->type) + || TYPE_MODE (a->type) != TYPE_MODE (b->type))) + return 0; + switch (TREE_CODE (a->type)) { case VOID_TYPE: @@ -6007,15 +6105,16 @@ type_hash_eq (const void *va, const void *vb) return TYPE_OFFSET_BASETYPE (a->type) == TYPE_OFFSET_BASETYPE (b->type); case METHOD_TYPE: - return (TYPE_METHOD_BASETYPE (a->type) == TYPE_METHOD_BASETYPE (b->type) - && (TYPE_ARG_TYPES (a->type) == TYPE_ARG_TYPES (b->type) - || (TYPE_ARG_TYPES (a->type) - && TREE_CODE (TYPE_ARG_TYPES (a->type)) == TREE_LIST - && TYPE_ARG_TYPES (b->type) - && TREE_CODE (TYPE_ARG_TYPES (b->type)) == TREE_LIST - && type_list_equal (TYPE_ARG_TYPES (a->type), - TYPE_ARG_TYPES (b->type))))); - + if (TYPE_METHOD_BASETYPE (a->type) == TYPE_METHOD_BASETYPE (b->type) + && (TYPE_ARG_TYPES (a->type) == TYPE_ARG_TYPES (b->type) + || (TYPE_ARG_TYPES (a->type) + && TREE_CODE (TYPE_ARG_TYPES (a->type)) == TREE_LIST + && TYPE_ARG_TYPES (b->type) + && TREE_CODE (TYPE_ARG_TYPES (b->type)) == TREE_LIST + && type_list_equal (TYPE_ARG_TYPES (a->type), + TYPE_ARG_TYPES (b->type))))) + break; + return 0; case ARRAY_TYPE: return TYPE_DOMAIN (a->type) == TYPE_DOMAIN (b->type); @@ -6216,24 +6315,12 @@ attribute_list_contained (const_tree l1, const_tree l2) const_tree. */ for (attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)), CONST_CAST_TREE(l1)); - attr != NULL_TREE; + attr != NULL_TREE && !attribute_value_equal (t2, attr); attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)), TREE_CHAIN (attr))) - { - if (TREE_VALUE (t2) != NULL - && TREE_CODE (TREE_VALUE (t2)) == TREE_LIST - && TREE_VALUE (attr) != NULL - && TREE_CODE (TREE_VALUE (attr)) == TREE_LIST) - { - if (simple_cst_list_equal (TREE_VALUE (t2), - TREE_VALUE (attr)) == 1) - break; - } - else if (simple_cst_equal (TREE_VALUE (t2), TREE_VALUE (attr)) == 1) - break; - } + ; - if (attr == 0) + if (attr == NULL_TREE) return 0; } @@ -7096,6 +7183,7 @@ static tree build_range_type_1 (tree type, tree lowval, tree highval, bool shared) { tree itype = make_node (INTEGER_TYPE); + hashval_t hashcode = 0; TREE_TYPE (itype) = type; @@ -7109,6 +7197,9 @@ build_range_type_1 (tree type, tree lowval, tree highval, bool shared) TYPE_ALIGN (itype) = TYPE_ALIGN (type); TYPE_USER_ALIGN (itype) = TYPE_USER_ALIGN (type); + if (!shared) + return itype; + if ((TYPE_MIN_VALUE (itype) && TREE_CODE (TYPE_MIN_VALUE (itype)) != INTEGER_CST) || (TYPE_MAX_VALUE (itype) @@ -7120,13 +7211,10 @@ build_range_type_1 (tree type, tree lowval, tree highval, bool shared) return itype; } - if (shared) - { - hashval_t hash = iterative_hash_expr (TYPE_MIN_VALUE (itype), 0); - hash = iterative_hash_expr (TYPE_MAX_VALUE (itype), hash); - hash = iterative_hash_hashval_t (TYPE_HASH (type), hash); - itype = type_hash_canon (hash, itype); - } + hashcode = iterative_hash_expr (TYPE_MIN_VALUE (itype), hashcode); + hashcode = iterative_hash_expr (TYPE_MAX_VALUE (itype), hashcode); + hashcode = iterative_hash_hashval_t (TYPE_HASH (type), hashcode); + itype = type_hash_canon (hashcode, itype); return itype; } @@ -8517,20 +8605,19 @@ get_file_function_name (const char *type) p = q = ASTRDUP (first_global_object_name); /* If the target is handling the constructors/destructors, they will be local to this file and the name is only necessary for - debugging purposes. */ - else if ((type[0] == 'I' || type[0] == 'D') && targetm.have_ctors_dtors) + debugging purposes. + We also assign sub_I and sub_D sufixes to constructors called from + the global static constructors. These are always local. */ + else if (((type[0] == 'I' || type[0] == 'D') && targetm.have_ctors_dtors) + || (strncmp (type, "sub_", 4) == 0 + && (type[4] == 'I' || type[4] == 'D'))) { const char *file = main_input_filename; if (! file) file = input_filename; /* Just use the file's basename, because the full pathname might be quite long. */ - p = strrchr (file, '/'); - if (p) - p++; - else - p = file; - p = q = ASTRDUP (p); + p = q = ASTRDUP (lbasename (file)); } else { @@ -9324,12 +9411,6 @@ build_common_builtin_nodes (void) BUILT_IN_STACK_RESTORE, "__builtin_stack_restore", ECF_NOTHROW | ECF_LEAF); - ftype = build_function_type_list (void_type_node, NULL_TREE); - local_define_builtin ("__builtin_profile_func_enter", ftype, - BUILT_IN_PROFILE_FUNC_ENTER, "profile_func_enter", 0); - local_define_builtin ("__builtin_profile_func_exit", ftype, - BUILT_IN_PROFILE_FUNC_EXIT, "profile_func_exit", 0); - /* If there's a possibility that we might use the ARM EABI, build the alternate __cxa_end_cleanup node used to resume from C++ and Java. */ if (targetm.arm_eabi_unwinder) @@ -9617,17 +9698,14 @@ build_omp_clause (location_t loc, enum omp_clause_code code) length = omp_clause_num_ops[code]; size = (sizeof (struct tree_omp_clause) + (length - 1) * sizeof (tree)); + record_node_allocation_statistics (OMP_CLAUSE, size); + t = ggc_alloc_tree_node (size); memset (t, 0, size); TREE_SET_CODE (t, OMP_CLAUSE); OMP_CLAUSE_SET_CODE (t, code); OMP_CLAUSE_LOCATION (t) = loc; -#ifdef GATHER_STATISTICS - tree_node_counts[(int) omp_clause_kind]++; - tree_node_sizes[(int) omp_clause_kind] += size; -#endif - return t; } @@ -9645,10 +9723,7 @@ build_vl_exp_stat (enum tree_code code, int len MEM_STAT_DECL) gcc_assert (TREE_CODE_CLASS (code) == tcc_vl_exp); gcc_assert (len >= 1); -#ifdef GATHER_STATISTICS - tree_node_counts[(int) e_kind]++; - tree_node_sizes[(int) e_kind] += length; -#endif + record_node_allocation_statistics (code, length); t = ggc_alloc_zone_cleared_tree_node_stat (&tree_zone, length PASS_MEM_STAT); @@ -9661,6 +9736,23 @@ build_vl_exp_stat (enum tree_code code, int len MEM_STAT_DECL) return t; } +/* Helper function for build_call_* functions; build a CALL_EXPR with + indicated RETURN_TYPE, FN, and NARGS, but do not initialize any of + the argument slots. */ + +static tree +build_call_1 (tree return_type, tree fn, int nargs) +{ + tree t; + + t = build_vl_exp (CALL_EXPR, nargs + 3); + TREE_TYPE (t) = return_type; + CALL_EXPR_FN (t) = fn; + CALL_EXPR_STATIC_CHAIN (t) = NULL; + + return t; +} + /* Build a CALL_EXPR of class tcc_vl_exp with the indicated RETURN_TYPE and FN and a null static chain slot. NARGS is the number of call arguments which are specified as "..." arguments. */ @@ -9686,10 +9778,7 @@ build_call_valist (tree return_type, tree fn, int nargs, va_list args) tree t; int i; - t = build_vl_exp (CALL_EXPR, nargs + 3); - TREE_TYPE (t) = return_type; - CALL_EXPR_FN (t) = fn; - CALL_EXPR_STATIC_CHAIN (t) = NULL_TREE; + t = build_call_1 (return_type, fn, nargs); for (i = 0; i < nargs; i++) CALL_EXPR_ARG (t, i) = va_arg (args, tree); process_call_operands (t); @@ -9707,10 +9796,7 @@ build_call_array_loc (location_t loc, tree return_type, tree fn, tree t; int i; - t = build_vl_exp (CALL_EXPR, nargs + 3); - TREE_TYPE (t) = return_type; - CALL_EXPR_FN (t) = fn; - CALL_EXPR_STATIC_CHAIN (t) = NULL_TREE; + t = build_call_1 (return_type, fn, nargs); for (i = 0; i < nargs; i++) CALL_EXPR_ARG (t, i) = args[i]; process_call_operands (t); @@ -9726,10 +9812,7 @@ build_call_vec (tree return_type, tree fn, VEC(tree,gc) *args) tree ret, t; unsigned int ix; - ret = build_vl_exp (CALL_EXPR, VEC_length (tree, args) + 3); - TREE_TYPE (ret) = return_type; - CALL_EXPR_FN (ret) = fn; - CALL_EXPR_STATIC_CHAIN (ret) = NULL_TREE; + ret = build_call_1 (return_type, fn, VEC_length (tree, args)); FOR_EACH_VEC_ELT (tree, args, ix, t) CALL_EXPR_ARG (ret, ix) = t; process_call_operands (ret); @@ -9814,50 +9897,6 @@ needs_to_live_in_memory (const_tree t) && aggregate_value_p (t, current_function_decl))); } -/* There are situations in which a language considers record types - compatible which have different field lists. Decide if two fields - are compatible. It is assumed that the parent records are compatible. */ - -bool -fields_compatible_p (const_tree f1, const_tree f2) -{ - if (!operand_equal_p (DECL_FIELD_BIT_OFFSET (f1), - DECL_FIELD_BIT_OFFSET (f2), OEP_ONLY_CONST)) - return false; - - if (!operand_equal_p (DECL_FIELD_OFFSET (f1), - DECL_FIELD_OFFSET (f2), OEP_ONLY_CONST)) - return false; - - if (!types_compatible_p (TREE_TYPE (f1), TREE_TYPE (f2))) - return false; - - return true; -} - -/* Locate within RECORD a field that is compatible with ORIG_FIELD. */ - -tree -find_compatible_field (tree record, tree orig_field) -{ - tree f; - - for (f = TYPE_FIELDS (record); f ; f = TREE_CHAIN (f)) - if (TREE_CODE (f) == FIELD_DECL - && fields_compatible_p (f, orig_field)) - return f; - - /* ??? Why isn't this on the main fields list? */ - f = TYPE_VFIELD (record); - if (f && TREE_CODE (f) == FIELD_DECL - && fields_compatible_p (f, orig_field)) - return f; - - /* ??? We should abort here, but Java appears to do Bad Things - with inherited fields. */ - return orig_field; -} - /* Return value of a constant X and sign-extend it. */ HOST_WIDE_INT @@ -10940,7 +10979,7 @@ lhd_gcc_personality (void) tree get_binfo_at_offset (tree binfo, HOST_WIDE_INT offset, tree expected_type) { - tree type = TREE_TYPE (binfo); + tree type = BINFO_TYPE (binfo); while (true) { @@ -10948,10 +10987,9 @@ get_binfo_at_offset (tree binfo, HOST_WIDE_INT offset, tree expected_type) tree fld; int i; - if (type == expected_type) + if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (expected_type)) return binfo; - if (TREE_CODE (type) != RECORD_TYPE - || offset < 0) + if (offset < 0) return NULL_TREE; for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld)) @@ -10964,12 +11002,18 @@ get_binfo_at_offset (tree binfo, HOST_WIDE_INT offset, tree expected_type) if (pos <= offset && (pos + size) > offset) break; } - if (!fld || !DECL_ARTIFICIAL (fld)) + if (!fld || TREE_CODE (TREE_TYPE (fld)) != RECORD_TYPE) return NULL_TREE; + if (!DECL_ARTIFICIAL (fld)) + { + binfo = TYPE_BINFO (TREE_TYPE (fld)); + if (!binfo) + return NULL_TREE; + } /* Offset 0 indicates the primary base, whose vtable contents are represented in the binfo for the derived class. */ - if (offset != 0) + else if (offset != 0) { tree base_binfo, found_binfo = NULL_TREE; for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)