X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ftree.c;h=d0c18b17ae2ff9671158865a5ceda18697967f45;hb=046f323efd9149bb5d2d5638466e98ed238b7635;hp=67e2f417cb9cfd8447a7f34889c72f4cede7e8dd;hpb=cc194b6e3a0bb9be324e211b2f5011ba34653d1e;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/tree.c b/gcc/tree.c index 67e2f417cb9..d0c18b17ae2 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" @@ -136,8 +137,6 @@ static const char * const tree_node_kind_names[] = { "exprs", "constants", "identifiers", - "perm_tree_lists", - "temp_tree_lists", "vecs", "binfos", "ssa names", @@ -296,6 +295,8 @@ tree_node_structure_for_code (enum tree_code code) return TS_TYPE_DECL; case FUNCTION_DECL: return TS_FUNCTION_DECL; + case TRANSLATION_UNIT_DECL: + return TS_TRANSLATION_UNIT_DECL; default: return TS_DECL_NON_COMMON; } @@ -351,47 +352,6 @@ initialize_tree_contains_struct (void) { unsigned i; -#define MARK_TS_BASE(C) \ - do { \ - tree_contains_struct[C][TS_BASE] = 1; \ - } while (0) - -#define MARK_TS_COMMON(C) \ - do { \ - MARK_TS_BASE (C); \ - tree_contains_struct[C][TS_COMMON] = 1; \ - } while (0) - -#define MARK_TS_DECL_MINIMAL(C) \ - do { \ - MARK_TS_COMMON (C); \ - tree_contains_struct[C][TS_DECL_MINIMAL] = 1; \ - } while (0) - -#define MARK_TS_DECL_COMMON(C) \ - do { \ - MARK_TS_DECL_MINIMAL (C); \ - tree_contains_struct[C][TS_DECL_COMMON] = 1; \ - } while (0) - -#define MARK_TS_DECL_WRTL(C) \ - do { \ - MARK_TS_DECL_COMMON (C); \ - tree_contains_struct[C][TS_DECL_WRTL] = 1; \ - } while (0) - -#define MARK_TS_DECL_WITH_VIS(C) \ - do { \ - MARK_TS_DECL_WRTL (C); \ - tree_contains_struct[C][TS_DECL_WITH_VIS] = 1; \ - } while (0) - -#define MARK_TS_DECL_NON_COMMON(C) \ - do { \ - MARK_TS_DECL_WITH_VIS (C); \ - tree_contains_struct[C][TS_DECL_NON_COMMON] = 1; \ - } while (0) - for (i = ERROR_MARK; i < LAST_AND_UNUSED_TREE_CODE; i++) { enum tree_code code; @@ -406,27 +366,31 @@ initialize_tree_contains_struct (void) /* Mark all the structures that TS is derived from. */ switch (ts_code) { - case TS_COMMON: + case TS_TYPED: MARK_TS_BASE (code); break; + case TS_COMMON: case TS_INT_CST: case TS_REAL_CST: case TS_FIXED_CST: case TS_VECTOR: case TS_STRING: case TS_COMPLEX: + case TS_SSA_NAME: + case TS_CONSTRUCTOR: + MARK_TS_TYPED (code); + break; + case TS_IDENTIFIER: case TS_DECL_MINIMAL: case TS_TYPE: case TS_LIST: case TS_VEC: case TS_EXP: - case TS_SSA_NAME: case TS_BLOCK: case TS_BINFO: case TS_STATEMENT_LIST: - case TS_CONSTRUCTOR: case TS_OMP_CLAUSE: case TS_OPTIMIZATION: case TS_TARGET_OPTION: @@ -438,6 +402,7 @@ initialize_tree_contains_struct (void) break; case TS_DECL_WRTL: + case TS_CONST_DECL: MARK_TS_DECL_COMMON (code); break; @@ -449,7 +414,6 @@ initialize_tree_contains_struct (void) case TS_PARM_DECL: case TS_LABEL_DECL: case TS_RESULT_DECL: - case TS_CONST_DECL: MARK_TS_DECL_WRTL (code); break; @@ -466,6 +430,10 @@ initialize_tree_contains_struct (void) MARK_TS_DECL_NON_COMMON (code); break; + case TS_TRANSLATION_UNIT_DECL: + MARK_TS_DECL_COMMON (code); + break; + default: gcc_unreachable (); } @@ -473,7 +441,6 @@ initialize_tree_contains_struct (void) /* Basic consistency checks for attributes used in fold. */ gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_DECL_NON_COMMON]); - gcc_assert (tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_NON_COMMON]); gcc_assert (tree_contains_struct[TYPE_DECL][TS_DECL_NON_COMMON]); gcc_assert (tree_contains_struct[CONST_DECL][TS_DECL_COMMON]); gcc_assert (tree_contains_struct[VAR_DECL][TS_DECL_COMMON]); @@ -484,7 +451,6 @@ initialize_tree_contains_struct (void) gcc_assert (tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_COMMON]); gcc_assert (tree_contains_struct[LABEL_DECL][TS_DECL_COMMON]); gcc_assert (tree_contains_struct[FIELD_DECL][TS_DECL_COMMON]); - gcc_assert (tree_contains_struct[CONST_DECL][TS_DECL_WRTL]); gcc_assert (tree_contains_struct[VAR_DECL][TS_DECL_WRTL]); gcc_assert (tree_contains_struct[PARM_DECL][TS_DECL_WRTL]); gcc_assert (tree_contains_struct[RESULT_DECL][TS_DECL_WRTL]); @@ -502,7 +468,6 @@ initialize_tree_contains_struct (void) gcc_assert (tree_contains_struct[VAR_DECL][TS_DECL_WITH_VIS]); gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_DECL_WITH_VIS]); gcc_assert (tree_contains_struct[TYPE_DECL][TS_DECL_WITH_VIS]); - gcc_assert (tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_WITH_VIS]); gcc_assert (tree_contains_struct[VAR_DECL][TS_VAR_DECL]); gcc_assert (tree_contains_struct[FIELD_DECL][TS_FIELD_DECL]); gcc_assert (tree_contains_struct[PARM_DECL][TS_PARM_DECL]); @@ -513,14 +478,6 @@ initialize_tree_contains_struct (void) gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_FUNCTION_DECL]); gcc_assert (tree_contains_struct[IMPORTED_DECL][TS_DECL_MINIMAL]); gcc_assert (tree_contains_struct[IMPORTED_DECL][TS_DECL_COMMON]); - -#undef MARK_TS_BASE -#undef MARK_TS_COMMON -#undef MARK_TS_DECL_MINIMAL -#undef MARK_TS_DECL_COMMON -#undef MARK_TS_DECL_WRTL -#undef MARK_TS_DECL_WITH_VIS -#undef MARK_TS_DECL_NON_COMMON } @@ -767,20 +724,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) @@ -839,12 +791,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 (); } @@ -852,14 +812,27 @@ make_node_stat (enum tree_code code MEM_STAT_DECL) tree_node_counts[(int) kind]++; tree_node_sizes[(int) kind] += length; #endif +} - if (code == IDENTIFIER_NODE) - t = (tree) ggc_alloc_zone_pass_stat (length, &tree_id_zone); - else - t = (tree) ggc_alloc_zone_pass_stat (length, &tree_zone); +/* 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); - memset (t, 0, length); + record_node_allocation_statistics (code, length); + t = ggc_alloc_zone_cleared_tree_node_stat ( + (code == IDENTIFIER_NODE) ? &tree_id_zone : &tree_zone, + length PASS_MEM_STAT); TREE_SET_CODE (t, code); switch (type) @@ -940,7 +913,7 @@ make_node_stat (enum tree_code code MEM_STAT_DECL) } /* Return a new node with the same contents as NODE except that its - TREE_CHAIN is zero and it has a fresh uid. */ + TREE_CHAIN, if it has one, is zero and it has a fresh uid. */ tree copy_node_stat (tree node MEM_STAT_DECL) @@ -952,10 +925,12 @@ copy_node_stat (tree node MEM_STAT_DECL) gcc_assert (code != STATEMENT_LIST); length = tree_size (node); - t = (tree) ggc_alloc_zone_pass_stat (length, &tree_zone); + record_node_allocation_statistics (code, length); + t = ggc_alloc_zone_tree_node_stat (&tree_zone, length PASS_MEM_STAT); memcpy (t, node, length); - TREE_CHAIN (t) = 0; + if (CODE_CONTAINS_STRUCT (code, TS_COMMON)) + TREE_CHAIN (t) = 0; TREE_ASM_WRITTEN (t) = 0; TREE_VISITED (t) = 0; if (code == VAR_DECL || code == PARM_DECL || code == RESULT_DECL) @@ -1053,14 +1028,9 @@ build_int_cst (tree type, HOST_WIDE_INT low) tree build_int_cst_type (tree type, HOST_WIDE_INT low) { - unsigned HOST_WIDE_INT low1; - HOST_WIDE_INT hi; - gcc_assert (type); - fit_double_type (low, low < 0 ? -1 : 0, &low1, &hi, type); - - return build_int_cst_wide (type, low1, hi); + return double_int_to_tree (type, shwi_to_double_int (low)); } /* Constructs tree in type TYPE from with value given by CST. Signedness @@ -1096,6 +1066,52 @@ double_int_fits_to_tree_p (const_tree type, double_int cst) return double_int_equal_p (cst, ext); } +/* We force the double_int CST to the range of the type TYPE by sign or + zero extending it. OVERFLOWABLE indicates if we are interested in + overflow of the value, when >0 we are only interested in signed + overflow, for <0 we are interested in any overflow. OVERFLOWED + indicates whether overflow has already occurred. CONST_OVERFLOWED + indicates whether constant overflow has already occurred. We force + T's value to be within range of T's type (by setting to 0 or 1 all + the bits outside the type's range). We set TREE_OVERFLOWED if, + OVERFLOWED is nonzero, + or OVERFLOWABLE is >0 and signed overflow occurs + or OVERFLOWABLE is <0 and any overflow occurs + We return a new tree node for the extended double_int. The node + is shared if no overflow flags are set. */ + + +tree +force_fit_type_double (tree type, double_int cst, int overflowable, + bool overflowed) +{ + bool sign_extended_type; + + /* Size types *are* sign extended. */ + sign_extended_type = (!TYPE_UNSIGNED (type) + || (TREE_CODE (type) == INTEGER_TYPE + && TYPE_IS_SIZETYPE (type))); + + /* If we need to set overflow flags, return a new unshared node. */ + if (overflowed || !double_int_fits_to_tree_p(type, cst)) + { + if (overflowed + || overflowable < 0 + || (overflowable > 0 && sign_extended_type)) + { + tree t = make_node (INTEGER_CST); + TREE_INT_CST (t) = double_int_ext (cst, TYPE_PRECISION (type), + !sign_extended_type); + TREE_TYPE (t) = type; + TREE_OVERFLOW (t) = 1; + return t; + } + } + + /* Else build a shared node. */ + return double_int_to_tree (type, cst); +} + /* These are the hash table functions for the hash table of INTEGER_CST nodes of a sizetype. */ @@ -1139,6 +1155,10 @@ build_int_cst_wide (tree type, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi) switch (TREE_CODE (type)) { + case NULLPTR_TYPE: + gcc_assert (hi == 0 && low == 0); + /* Fallthru. */ + case POINTER_TYPE: case REFERENCE_TYPE: /* Cache NULL pointer. */ @@ -1281,6 +1301,7 @@ build_vector (tree type, tree vals) tree v = make_node (VECTOR_CST); int over = 0; tree link; + unsigned cnt = 0; TREE_VECTOR_CST_ELTS (v) = vals; TREE_TYPE (v) = type; @@ -1289,6 +1310,7 @@ build_vector (tree type, tree vals) for (link = vals; link; link = TREE_CHAIN (link)) { tree value = TREE_VALUE (link); + cnt++; /* Don't crash if we get an address constant. */ if (!CONSTANT_CLASS_P (value)) @@ -1297,6 +1319,8 @@ build_vector (tree type, tree vals) over |= TREE_OVERFLOW (value); } + gcc_assert (cnt == TYPE_VECTOR_SUBPARTS (type)); + TREE_OVERFLOW (v) = over; return v; } @@ -1313,9 +1337,41 @@ build_vector_from_ctor (tree type, VEC(constructor_elt,gc) *v) FOR_EACH_CONSTRUCTOR_VALUE (v, idx, value) list = tree_cons (NULL_TREE, value, list); + for (; idx < TYPE_VECTOR_SUBPARTS (type); ++idx) + list = tree_cons (NULL_TREE, + build_zero_cst (TREE_TYPE (type)), list); return build_vector (type, nreverse (list)); } +/* Build a vector of type VECTYPE where all the elements are SCs. */ +tree +build_vector_from_val (tree vectype, tree sc) +{ + int i, nunits = TYPE_VECTOR_SUBPARTS (vectype); + VEC(constructor_elt, gc) *v = NULL; + + if (sc == error_mark_node) + return sc; + + /* 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) + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, sc); + + if (CONSTANT_CLASS_P (sc)) + return build_vector_from_ctor (vectype, v); + else + return build_constructor (vectype, v); +} + /* Return a new CONSTRUCTOR node whose type is TYPE and whose values are in the VEC pointed to by VALS. */ tree @@ -1329,7 +1385,7 @@ build_constructor (tree type, VEC(constructor_elt,gc) *vals) TREE_TYPE (c) = type; CONSTRUCTOR_ELTS (c) = vals; - for (i = 0; VEC_iterate (constructor_elt, vals, i, elt); i++) + FOR_EACH_VEC_ELT (constructor_elt, vals, i, elt) if (!TREE_CONSTANT (elt->value)) { constant_p = false; @@ -1385,7 +1441,7 @@ build_fixed (tree type, FIXED_VALUE_TYPE f) FIXED_VALUE_TYPE *fp; v = make_node (FIXED_CST); - fp = GGC_NEW (FIXED_VALUE_TYPE); + fp = ggc_alloc_fixed_value (); memcpy (fp, &f, sizeof (FIXED_VALUE_TYPE)); TREE_TYPE (v) = type; @@ -1406,7 +1462,7 @@ build_real (tree type, REAL_VALUE_TYPE d) Consider doing it via real_convert now. */ v = make_node (REAL_CST); - dp = GGC_NEW (REAL_VALUE_TYPE); + dp = ggc_alloc_real_value (); memcpy (dp, &d, sizeof (REAL_VALUE_TYPE)); TREE_TYPE (v) = type; @@ -1461,14 +1517,11 @@ 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 (length); + s = ggc_alloc_tree_node (length); - memset (s, 0, sizeof (struct tree_common)); + memset (s, 0, sizeof (struct tree_typed)); TREE_SET_CODE (s, STRING_CST); TREE_CONSTANT (s) = 1; TREE_STRING_LENGTH (s) = len; @@ -1518,29 +1571,63 @@ build_one_cst (tree type) case VECTOR_TYPE: { - tree scalar, cst; - int i; + tree scalar = build_one_cst (TREE_TYPE (type)); - scalar = build_one_cst (TREE_TYPE (type)); - - /* Create 'vect_cst_ = {cst,cst,...,cst}' */ - cst = NULL_TREE; - for (i = TYPE_VECTOR_SUBPARTS (type); --i >= 0; ) - cst = tree_cons (NULL_TREE, scalar, cst); - - return build_vector (type, cst); + return build_vector_from_val (type, scalar); } case COMPLEX_TYPE: return build_complex (type, build_one_cst (TREE_TYPE (type)), - fold_convert (TREE_TYPE (type), integer_zero_node)); + build_zero_cst (TREE_TYPE (type))); default: gcc_unreachable (); } } +/* Build 0 constant of type TYPE. This is used by constructor folding + and thus the constant should be represented in memory by + zero(es). */ + +tree +build_zero_cst (tree type) +{ + switch (TREE_CODE (type)) + { + case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE: + case POINTER_TYPE: case REFERENCE_TYPE: + case OFFSET_TYPE: + return build_int_cst (type, 0); + + case REAL_TYPE: + return build_real (type, dconst0); + + case FIXED_POINT_TYPE: + return build_fixed (type, FCONST0 (TYPE_MODE (type))); + + case VECTOR_TYPE: + { + tree scalar = build_zero_cst (TREE_TYPE (type)); + + return build_vector_from_val (type, scalar); + } + + case COMPLEX_TYPE: + { + tree zero = build_zero_cst (TREE_TYPE (type)); + + return build_complex (type, zero, zero); + } + + default: + if (!AGGREGATE_TYPE_P (type)) + return fold_convert (type, integer_zero_node); + return build_constructor (type, NULL); + } +} + + /* Build a BINFO with LEN language slots. */ tree @@ -1550,12 +1637,9 @@ 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 = (tree) ggc_alloc_zone_pass_stat (length, &tree_zone); + t = ggc_alloc_zone_tree_node_stat (&tree_zone, length PASS_MEM_STAT); memset (t, 0, offsetof (struct tree_binfo, base_binfos)); @@ -1575,14 +1659,9 @@ 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 = (tree) ggc_alloc_zone_pass_stat (length, &tree_zone); - - memset (t, 0, length); + t = ggc_alloc_zone_cleared_tree_node_stat (&tree_zone, length PASS_MEM_STAT); TREE_SET_CODE (t, TREE_VEC); TREE_VEC_LENGTH (t) = len; @@ -1923,6 +2002,19 @@ purpose_member (const_tree elem, tree list) return NULL_TREE; } +/* Return true if ELEM is in V. */ + +bool +vec_member (const_tree elem, VEC(tree,gc) *v) +{ + unsigned ix; + tree t; + FOR_EACH_VEC_ELT (tree, v, ix, t) + if (elem == t) + return true; + return false; +} + /* Returns element number IDX (zero-origin) of chain CHAIN, or NULL_TREE. */ @@ -1943,7 +2035,7 @@ chain_member (const_tree elem, const_tree chain) { if (elem == chain) return 1; - chain = TREE_CHAIN (chain); + chain = DECL_CHAIN (chain); } return 0; @@ -1984,7 +2076,7 @@ fields_length (const_tree type) tree t = TYPE_FIELDS (type); int count = 0; - for (; t; t = TREE_CHAIN (t)) + for (; t; t = DECL_CHAIN (t)) if (TREE_CODE (t) == FIELD_DECL) ++count; @@ -2053,6 +2145,9 @@ nreverse (tree t) tree prev = 0, decl, next; for (decl = t; decl; decl = next) { + /* We shouldn't be using this function to reverse BLOCK chains; we + have blocks_nreverse for that. */ + gcc_checking_assert (TREE_CODE (decl) != BLOCK); next = TREE_CHAIN (decl); TREE_CHAIN (decl) = prev; prev = decl; @@ -2081,7 +2176,7 @@ build_tree_list_vec_stat (const VEC(tree,gc) *vec MEM_STAT_DECL) tree *pp = &ret; unsigned int i; tree t; - for (i = 0; VEC_iterate (tree, vec, i, t); ++i) + FOR_EACH_VEC_ELT (tree, vec, i, t) { *pp = build_tree_list_stat (NULL, t PASS_MEM_STAT); pp = &TREE_CHAIN (*pp); @@ -2093,19 +2188,16 @@ build_tree_list_vec_stat (const VEC(tree,gc) *vec MEM_STAT_DECL) purpose and value fields are PURPOSE and VALUE and whose TREE_CHAIN is CHAIN. */ -tree +tree tree_cons_stat (tree purpose, tree value, tree chain MEM_STAT_DECL) { tree node; - node = (tree) ggc_alloc_zone_pass_stat (sizeof (struct tree_list), &tree_zone); - + node = ggc_alloc_zone_tree_node_stat (&tree_zone, sizeof (struct tree_list) + 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; @@ -2326,6 +2418,10 @@ array_type_nelts (const_tree type) min = TYPE_MIN_VALUE (index_type); max = TYPE_MAX_VALUE (index_type); + /* TYPE_MAX_VALUE may not be set if the array has unknown length. */ + if (!max) + return error_mark_node; + return (integer_zerop (min) ? max : fold_build2 (MINUS_EXPR, TREE_TYPE (max), max, min)); @@ -2378,8 +2474,6 @@ staticp (tree arg) case BIT_FIELD_REF: return NULL; - case MISALIGNED_INDIRECT_REF: - case ALIGN_INDIRECT_REF: case INDIRECT_REF: return TREE_CONSTANT (TREE_OPERAND (arg, 0)) ? arg : NULL; @@ -2419,8 +2513,7 @@ decl_address_invariant_p (const_tree op) return true; case VAR_DECL: - if (((TREE_STATIC (op) || DECL_EXTERNAL (op)) - && !DECL_DLLIMPORT_P (op)) + if ((TREE_STATIC (op) || DECL_EXTERNAL (op)) || DECL_THREAD_LOCAL_P (op) || DECL_CONTEXT (op) == current_function_decl || decl_function_context (op) == current_function_decl) @@ -2677,8 +2770,8 @@ process_call_operands (tree t) TREE_READONLY (t) = read_only; } -/* Return 1 if EXP contains a PLACEHOLDER_EXPR; i.e., if it represents a size - or offset that depends on a field within a record. */ +/* Return true if EXP contains a PLACEHOLDER_EXPR, i.e. if it represents a + size or offset that depends on a field within a record. */ bool contains_placeholder_p (const_tree exp) @@ -2764,9 +2857,9 @@ contains_placeholder_p (const_tree exp) return 0; } -/* Return true if any part of the computation of TYPE involves a - PLACEHOLDER_EXPR. This includes size, bounds, qualifiers - (for QUAL_UNION_TYPE) and field positions. */ +/* Return true if any part of the structure of TYPE involves a PLACEHOLDER_EXPR + directly. This includes size, bounds, qualifiers (for QUAL_UNION_TYPE) and + field positions. */ static bool type_contains_placeholder_1 (const_tree type) @@ -2775,7 +2868,8 @@ type_contains_placeholder_1 (const_tree type) the case of arrays) type involves a placeholder, this type does. */ if (CONTAINS_PLACEHOLDER_P (TYPE_SIZE (type)) || CONTAINS_PLACEHOLDER_P (TYPE_SIZE_UNIT (type)) - || (TREE_TYPE (type) != 0 + || (!POINTER_TYPE_P (type) + && TREE_TYPE (type) && type_contains_placeholder_p (TREE_TYPE (type)))) return true; @@ -2803,8 +2897,8 @@ type_contains_placeholder_1 (const_tree type) || CONTAINS_PLACEHOLDER_P (TYPE_MAX_VALUE (type))); case ARRAY_TYPE: - /* We're already checked the component type (TREE_TYPE), so just check - the index type. */ + /* We have already checked the component type above, so just check the + domain type. */ return type_contains_placeholder_p (TYPE_DOMAIN (type)); case RECORD_TYPE: @@ -2813,7 +2907,7 @@ type_contains_placeholder_1 (const_tree type) { tree field; - for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) if (TREE_CODE (field) == FIELD_DECL && (CONTAINS_PLACEHOLDER_P (DECL_FIELD_OFFSET (field)) || (TREE_CODE (type) == QUAL_UNION_TYPE @@ -2829,6 +2923,8 @@ type_contains_placeholder_1 (const_tree type) } } +/* Wrapper around above function used to cache its result. */ + bool type_contains_placeholder_p (tree type) { @@ -2860,7 +2956,7 @@ push_without_duplicates (tree exp, VEC (tree, heap) **queue) unsigned int i; tree iter; - for (i = 0; VEC_iterate (tree, *queue, i, iter); i++) + FOR_EACH_VEC_ELT (tree, *queue, i, iter) if (simple_cst_equal (iter, exp) == 1) break; @@ -3117,6 +3213,10 @@ substitute_in_expr (tree exp, tree f, tree r) } TREE_READONLY (new_tree) |= TREE_READONLY (exp); + + if (code == INDIRECT_REF || code == ARRAY_REF || code == ARRAY_RANGE_REF) + TREE_THIS_NOTRAP (new_tree) |= TREE_THIS_NOTRAP (exp); + return new_tree; } @@ -3284,6 +3384,10 @@ substitute_placeholder_in_expr (tree exp, tree obj) } TREE_READONLY (new_tree) |= TREE_READONLY (exp); + + if (code == INDIRECT_REF || code == ARRAY_REF || code == ARRAY_RANGE_REF) + TREE_THIS_NOTRAP (new_tree) |= TREE_THIS_NOTRAP (exp); + return new_tree; } @@ -3511,7 +3615,8 @@ do { tree _node = (NODE); \ address is constant too. If it's a decl, its address is constant if the decl is static. Everything else is not constant and, furthermore, taking the address of a volatile variable is not volatile. */ - if (TREE_CODE (node) == INDIRECT_REF) + if (TREE_CODE (node) == INDIRECT_REF + || TREE_CODE (node) == MEM_REF) UPDATE_FLAGS (TREE_OPERAND (node, 0)); else if (CONSTANT_CLASS_P (node)) ; @@ -3553,32 +3658,13 @@ 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); - t = (tree) ggc_alloc_zone_pass_stat (length, &tree_zone); + t = ggc_alloc_zone_tree_node_stat (&tree_zone, length PASS_MEM_STAT); memset (t, 0, sizeof (struct tree_common)); @@ -3605,8 +3691,6 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL) TREE_READONLY (t) = 0; break; - case MISALIGNED_INDIRECT_REF: - case ALIGN_INDIRECT_REF: case INDIRECT_REF: /* Whether a dereference is readonly has nothing to do with whether its operand is readonly. */ @@ -3825,6 +3909,74 @@ build6_stat (enum tree_code code, tree tt, tree arg0, tree arg1, return t; } +/* Build a simple MEM_REF tree with the sematics of a plain INDIRECT_REF + on the pointer PTR. */ + +tree +build_simple_mem_ref_loc (location_t loc, tree ptr) +{ + HOST_WIDE_INT offset = 0; + tree ptype = TREE_TYPE (ptr); + tree tem; + /* For convenience allow addresses that collapse to a simple base + and offset. */ + if (TREE_CODE (ptr) == ADDR_EXPR + && (handled_component_p (TREE_OPERAND (ptr, 0)) + || TREE_CODE (TREE_OPERAND (ptr, 0)) == MEM_REF)) + { + ptr = get_addr_base_and_unit_offset (TREE_OPERAND (ptr, 0), &offset); + gcc_assert (ptr); + ptr = build_fold_addr_expr (ptr); + gcc_assert (is_gimple_reg (ptr) || is_gimple_min_invariant (ptr)); + } + tem = build2 (MEM_REF, TREE_TYPE (ptype), + ptr, build_int_cst (ptype, offset)); + SET_EXPR_LOCATION (tem, loc); + return tem; +} + +/* Return the constant offset of a MEM_REF or TARGET_MEM_REF tree T. */ + +double_int +mem_ref_offset (const_tree t) +{ + tree toff = TREE_OPERAND (t, 1); + return double_int_sext (tree_to_double_int (toff), + TYPE_PRECISION (TREE_TYPE (toff))); +} + +/* Return the pointer-type relevant for TBAA purposes from the + gimple memory reference tree T. This is the type to be used for + the offset operand of MEM_REF or TARGET_MEM_REF replacements of T. */ + +tree +reference_alias_ptr_type (const_tree t) +{ + const_tree base = t; + while (handled_component_p (base)) + base = TREE_OPERAND (base, 0); + if (TREE_CODE (base) == MEM_REF) + return TREE_TYPE (TREE_OPERAND (base, 1)); + else if (TREE_CODE (base) == TARGET_MEM_REF) + return TREE_TYPE (TMR_OFFSET (base)); + else + 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, @@ -3864,7 +4016,7 @@ build_nt_call_vec (tree fn, VEC(tree,gc) *args) ret = build_vl_exp (CALL_EXPR, VEC_length (tree, args) + 3); CALL_EXPR_FN (ret) = fn; CALL_EXPR_STATIC_CHAIN (ret) = NULL_TREE; - for (ix = 0; VEC_iterate (tree, args, ix, t); ++ix) + FOR_EACH_VEC_ELT (tree, args, ix, t) CALL_EXPR_ARG (ret, ix) = t; return ret; } @@ -3916,6 +4068,21 @@ build_fn_decl (const char *name, tree type) return decl; } +VEC(tree,gc) *all_translation_units; + +/* Builds a new translation-unit decl with name NAME, queues it in the + global list of translation-unit decls and returns it. */ + +tree +build_translation_unit_decl (tree name) +{ + tree tu = build_decl (UNKNOWN_LOCATION, TRANSLATION_UNIT_DECL, + name, NULL_TREE); + TRANSLATION_UNIT_LANGUAGE (tu) = lang_hooks.name; + VEC_safe_push (tree, gc, all_translation_units, tu); + return tu; +} + /* BLOCK nodes are used to represent the structure of binding contours and declarations, once those contours have been exited and their contents @@ -4080,7 +4247,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); @@ -4093,6 +4260,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. @@ -4143,7 +4379,7 @@ free_lang_data_in_binfo (tree binfo) BINFO_INHERITANCE_CHAIN (binfo) = NULL_TREE; BINFO_SUBVTT_INDEX (binfo) = NULL_TREE; - for (i = 0; VEC_iterate (tree, BINFO_BASE_BINFOS (binfo), i, t); i++) + FOR_EACH_VEC_ELT (tree, BINFO_BASE_BINFOS (binfo), i, t) free_lang_data_in_binfo (t); } @@ -4306,29 +4542,6 @@ need_assembler_name_p (tree decl) } -/* Remove all the non-variable decls from BLOCK. LOCALS is the set of - variables in DECL_STRUCT_FUNCTION (FN)->local_decls. Every decl - in BLOCK that is not in LOCALS is removed. */ - -static void -free_lang_data_in_block (tree fn, tree block, struct pointer_set_t *locals) -{ - tree *tp, t; - - tp = &BLOCK_VARS (block); - while (*tp) - { - if (!pointer_set_contains (locals, *tp)) - *tp = TREE_CHAIN (*tp); - else - tp = &TREE_CHAIN (*tp); - } - - for (t = BLOCK_SUBBLOCKS (block); t; t = BLOCK_CHAIN (t)) - free_lang_data_in_block (fn, t, locals); -} - - /* Reset all language specific information still present in symbol DECL. */ @@ -4352,35 +4565,6 @@ free_lang_data_in_decl (tree decl) if (DECL_NAME (decl)) TREE_TYPE (DECL_NAME (decl)) = NULL_TREE; - /* Ignore any intervening types, because we are going to clear their - TYPE_CONTEXT fields. */ - if (TREE_CODE (decl) != FIELD_DECL - && TREE_CODE (decl) != FUNCTION_DECL) - DECL_CONTEXT (decl) = decl_function_context (decl); - - if (DECL_CONTEXT (decl) - && TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL) - DECL_CONTEXT (decl) = NULL_TREE; - - if (TREE_CODE (decl) == VAR_DECL) - { - tree context = DECL_CONTEXT (decl); - - if (context) - { - enum tree_code code = TREE_CODE (context); - if (code == FUNCTION_DECL && DECL_ABSTRACT (context)) - { - /* Do not clear the decl context here, that will promote - all vars to global ones. */ - DECL_INITIAL (decl) = NULL_TREE; - } - - if (TREE_STATIC (decl)) - DECL_CONTEXT (decl) = NULL_TREE; - } - } - free_lang_data_in_one_sizepos (&DECL_SIZE (decl)); free_lang_data_in_one_sizepos (&DECL_SIZE_UNIT (decl)); if (TREE_CODE (decl) == FIELD_DECL) @@ -4396,7 +4580,6 @@ free_lang_data_in_decl (tree decl) if (gimple_has_body_p (decl)) { tree t; - struct pointer_set_t *locals; /* If DECL has a gimple body, then the context for its arguments must be DECL. Otherwise, it doesn't really @@ -4409,50 +4592,55 @@ free_lang_data_in_decl (tree decl) the PARM_DECL will be used in the function's body). */ for (t = DECL_ARGUMENTS (decl); t; t = TREE_CHAIN (t)) DECL_CONTEXT (t) = decl; - - /* Collect all the symbols declared in DECL. */ - locals = pointer_set_create (); - t = DECL_STRUCT_FUNCTION (decl)->local_decls; - for (; t; t = TREE_CHAIN (t)) - { - pointer_set_insert (locals, TREE_VALUE (t)); - - /* All the local symbols should have DECL as their - context. */ - DECL_CONTEXT (TREE_VALUE (t)) = decl; - } - - /* Get rid of any decl not in local_decls. */ - free_lang_data_in_block (decl, DECL_INITIAL (decl), locals); - - pointer_set_destroy (locals); } /* DECL_SAVED_TREE holds the GENERIC representation for DECL. At this point, it is not needed anymore. */ DECL_SAVED_TREE (decl) = NULL_TREE; + + /* Clear the abstract origin if it refers to a method. Otherwise + dwarf2out.c will ICE as we clear TYPE_METHODS and thus the + origin will not be output correctly. */ + if (DECL_ABSTRACT_ORIGIN (decl) + && DECL_CONTEXT (DECL_ABSTRACT_ORIGIN (decl)) + && RECORD_OR_UNION_TYPE_P + (DECL_CONTEXT (DECL_ABSTRACT_ORIGIN (decl)))) + DECL_ABSTRACT_ORIGIN (decl) = NULL_TREE; + + /* Sometimes the C++ frontend doesn't manage to transform a temporary + DECL_VINDEX referring to itself into a vtable slot number as it + should. Happens with functions that are copied and then forgotten + about. Just clear it, it won't matter anymore. */ + if (DECL_VINDEX (decl) && !host_integerp (DECL_VINDEX (decl), 0)) + DECL_VINDEX (decl) = NULL_TREE; } else if (TREE_CODE (decl) == VAR_DECL) { - tree expr = DECL_DEBUG_EXPR (decl); - if (expr - && TREE_CODE (expr) == VAR_DECL - && !TREE_STATIC (expr) && !DECL_EXTERNAL (expr)) - SET_DECL_DEBUG_EXPR (decl, NULL_TREE); - - if (DECL_EXTERNAL (decl) - && (!TREE_STATIC (decl) || !TREE_READONLY (decl))) + if ((DECL_EXTERNAL (decl) + && (!TREE_STATIC (decl) || !TREE_READONLY (decl))) + || (decl_function_context (decl) && !TREE_STATIC (decl))) DECL_INITIAL (decl) = NULL_TREE; } else if (TREE_CODE (decl) == TYPE_DECL) - { - DECL_INITIAL (decl) = NULL_TREE; - - /* DECL_CONTEXT is overloaded as DECL_FIELD_CONTEXT for - FIELD_DECLs, which should be preserved. Otherwise, - we shouldn't be concerned with source-level lexical - nesting beyond this point. */ - DECL_CONTEXT (decl) = NULL_TREE; + 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); + } } } @@ -4602,7 +4790,8 @@ find_decls_types_r (tree *tp, int *ws, void *data) && DECL_HAS_VALUE_EXPR_P (t)) fld_worklist_push (DECL_VALUE_EXPR (t), fld); - if (TREE_CODE (t) != FIELD_DECL) + if (TREE_CODE (t) != FIELD_DECL + && TREE_CODE (t) != TYPE_DECL) fld_worklist_push (TREE_CHAIN (t), fld); *ws = 0; } @@ -4620,13 +4809,19 @@ find_decls_types_r (tree *tp, int *ws, void *data) fld_worklist_push (TYPE_POINTER_TO (t), fld); fld_worklist_push (TYPE_REFERENCE_TO (t), fld); fld_worklist_push (TYPE_NAME (t), fld); - fld_worklist_push (TYPE_MINVAL (t), fld); + /* Do not walk TYPE_NEXT_PTR_TO or TYPE_NEXT_REF_TO. We do not stream + them and thus do not and want not to reach unused pointer types + this way. */ + if (!POINTER_TYPE_P (t)) + fld_worklist_push (TYPE_MINVAL (t), fld); if (!RECORD_OR_UNION_TYPE_P (t)) fld_worklist_push (TYPE_MAXVAL (t), fld); fld_worklist_push (TYPE_MAIN_VARIANT (t), fld); - fld_worklist_push (TYPE_NEXT_VARIANT (t), fld); + /* Do not walk TYPE_NEXT_VARIANT. We do not stream it and thus + do not and want not to reach unused variants this way. */ fld_worklist_push (TYPE_CONTEXT (t), fld); - fld_worklist_push (TYPE_CANONICAL (t), fld); + /* Do not walk TYPE_CANONICAL. We do not stream it and thus do not + and want not to reach unused types this way. */ if (RECORD_OR_UNION_TYPE_P (t) && TYPE_BINFO (t)) { @@ -4673,7 +4868,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; } @@ -4771,6 +4967,7 @@ find_decls_types_in_node (struct cgraph_node *n, struct free_lang_data_d *fld) { basic_block bb; struct function *fn; + unsigned ix; tree t; find_decls_types (n->decl, fld); @@ -4783,8 +4980,8 @@ find_decls_types_in_node (struct cgraph_node *n, struct free_lang_data_d *fld) fn = DECL_STRUCT_FUNCTION (n->decl); /* Traverse locals. */ - for (t = fn->local_decls; t; t = TREE_CHAIN (t)) - find_decls_types (TREE_VALUE (t), fld); + FOR_EACH_LOCAL_DECL (fn, ix, t) + find_decls_types (t, fld); /* Traverse EH regions in FN. */ { @@ -4901,25 +5098,25 @@ free_lang_data_in_cgraph (void) for (n = cgraph_nodes; n; n = n->next) find_decls_types_in_node (n, &fld); - for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p); i++) + FOR_EACH_VEC_ELT (alias_pair, alias_pairs, i, p) find_decls_types (p->decl, &fld); /* Find decls and types in every varpool symbol. */ - for (v = varpool_nodes_queue; v; v = v->next_needed) + for (v = varpool_nodes; v; v = v->next) find_decls_types_in_var (v, &fld); /* Set the assembler name on every decl found. We need to do this now because free_lang_data_in_decl will invalidate data needed for mangling. This breaks mangling on interdependent decls. */ - for (i = 0; VEC_iterate (tree, fld.decls, i, t); i++) + FOR_EACH_VEC_ELT (tree, fld.decls, i, t) assign_assembler_name_if_neeeded (t); /* Traverse every decl found freeing its language data. */ - for (i = 0; VEC_iterate (tree, fld.decls, i, t); i++) + FOR_EACH_VEC_ELT (tree, fld.decls, i, t) free_lang_data_in_decl (t); /* Traverse every type found freeing its language data. */ - for (i = 0; VEC_iterate (tree, fld.types, i, t); i++) + FOR_EACH_VEC_ELT (tree, fld.types, i, t) free_lang_data_in_type (t); pointer_set_destroy (fld.pset); @@ -4979,7 +5176,12 @@ free_lang_data (void) lang_hooks.callgraph.analyze_expr = NULL; lang_hooks.dwarf_name = lhd_dwarf_name; lang_hooks.decl_printable_name = gimple_decl_printable_name; - lang_hooks.set_decl_assembler_name = lhd_set_decl_assembler_name; + /* We do not want the default decl_assembler_name implementation, + rather if we have fixed everything we want a wrapper around it + asserting that all non-local symbols already got their assembler + name and only produce assembler names for local symbols. Or rather + make sure we never call decl_assembler_name on local symbols and + devise a separate, middle-end private scheme for it. */ /* Reset diagnostic machinery. */ diagnostic_starter (global_dc) = default_tree_diagnostic_starter; @@ -5139,23 +5341,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); @@ -5378,7 +5567,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; @@ -5434,16 +5624,33 @@ check_qualified_type (const_tree cand, const_tree base, int type_quals) && TYPE_NAME (cand) == TYPE_NAME (base) /* Apparently this is needed for Objective-C. */ && TYPE_CONTEXT (cand) == TYPE_CONTEXT (base) + /* Check alignment. */ + && TYPE_ALIGN (cand) == TYPE_ALIGN (base) && attribute_list_equal (TYPE_ATTRIBUTES (cand), TYPE_ATTRIBUTES (base))); } -/* Return a version of the TYPE, qualified as indicated by the - TYPE_QUALS, if one exists. If no qualified version exists yet, - return NULL_TREE. */ +/* Returns true iff CAND is equivalent to BASE with ALIGN. */ -tree -get_qualified_type (tree type, int type_quals) +static bool +check_aligned_type (const_tree cand, const_tree base, unsigned int align) +{ + return (TYPE_QUALS (cand) == TYPE_QUALS (base) + && TYPE_NAME (cand) == TYPE_NAME (base) + /* Apparently this is needed for Objective-C. */ + && TYPE_CONTEXT (cand) == TYPE_CONTEXT (base) + /* Check alignment. */ + && TYPE_ALIGN (cand) == align + && attribute_list_equal (TYPE_ATTRIBUTES (cand), + TYPE_ATTRIBUTES (base))); +} + +/* Return a version of the TYPE, qualified as indicated by the + TYPE_QUALS, if one exists. If no qualified version exists yet, + return NULL_TREE. */ + +tree +get_qualified_type (tree type, int type_quals) { tree t; @@ -5494,6 +5701,27 @@ build_qualified_type (tree type, int type_quals) return t; } +/* Create a variant of type T with alignment ALIGN. */ + +tree +build_aligned_type (tree type, unsigned int align) +{ + tree t; + + if (TYPE_PACKED (type) + || TYPE_ALIGN (type) == align) + return type; + + for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t)) + if (check_aligned_type (t, type, align)) + return t; + + t = build_variant_type_copy (type); + TYPE_ALIGN (t) = align; + + return t; +} + /* Create a new distinct copy of TYPE. The new type is made its own MAIN_VARIANT. If TYPE requires structural equality checks, the resulting type requires structural equality checks; otherwise, its @@ -5638,7 +5866,7 @@ decl_priority_info (tree decl) h = (struct tree_priority_map *) *loc; if (!h) { - h = GGC_CNEW (struct tree_priority_map); + h = ggc_alloc_cleared_tree_priority_map (); *loc = h; h->base.from = decl; h->init = DEFAULT_INIT_PRIORITY; @@ -5656,6 +5884,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; } @@ -5668,6 +5898,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; } @@ -5717,7 +5949,7 @@ decl_debug_expr_insert (tree from, tree to) struct tree_decl_map *h; void **loc; - h = GGC_NEW (struct tree_decl_map); + h = ggc_alloc_tree_decl_map (); h->base.from = from; h->to = to; loc = htab_find_slot_with_hash (debug_expr_for_decl, h, DECL_UID (from), @@ -5748,7 +5980,7 @@ decl_value_expr_insert (tree from, tree to) struct tree_decl_map *h; void **loc; - h = GGC_NEW (struct tree_decl_map); + h = ggc_alloc_tree_decl_map (); h->base.from = from; h->to = to; loc = htab_find_slot_with_hash (value_expr_for_decl, h, DECL_UID (from), @@ -5792,12 +6024,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: @@ -5838,15 +6076,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); @@ -5921,7 +6160,7 @@ type_hash_add (hashval_t hashcode, tree type) struct type_hash *h; void **loc; - h = GGC_NEW (struct type_hash); + h = ggc_alloc_type_hash (); h->hash = hashcode; h->type = type; loc = htab_find_slot_with_hash (type_hash_table, h, hashcode, INSERT); @@ -5946,9 +6185,6 @@ type_hash_canon (unsigned int hashcode, tree type) being passed. */ gcc_assert (TYPE_MAIN_VARIANT (type) == type); - if (!lang_hooks.types.hash_types) - return type; - /* See if the type is in the hash table already. If so, return it. Otherwise, add the type. */ t1 = type_hash_lookup (hashcode, type); @@ -5969,16 +6205,14 @@ type_hash_canon (unsigned int hashcode, tree type) /* See if the data pointed to by the type hash table is marked. We consider it marked if the type is marked or if a debug type number or symbol - table entry has been made for the type. This reduces the amount of - debugging output and eliminates that dependency of the debug output on - the number of garbage collections. */ + table entry has been made for the type. */ static int type_hash_marked_p (const void *p) { const_tree const type = ((const struct type_hash *) p)->type; - return ggc_marked_p (type) || TYPE_SYMTAB_POINTER (type); + return ggc_marked_p (type); } static void @@ -6052,24 +6286,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; } @@ -6533,6 +6755,23 @@ commutative_tree_code (enum tree_code code) return false; } +/* Return true if CODE represents a ternary tree code for which the + first two operands are commutative. Otherwise return false. */ +bool +commutative_ternary_tree_code (enum tree_code code) +{ + switch (code) + { + case WIDEN_MULT_PLUS_EXPR: + case WIDEN_MULT_MINUS_EXPR: + return true; + + default: + break; + } + return false; +} + /* Generate a hash value for an expression. This can be used iteratively by passing a previous result as the VAL argument. @@ -6601,6 +6840,21 @@ iterative_hash_expr (const_tree t, hashval_t val) } return val; } + case MEM_REF: + { + /* The type of the second operand is relevant, except for + its top-level qualifiers. */ + tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (t, 1))); + + val = iterative_hash_object (TYPE_HASH (type), val); + + /* We could use the standard hash computation from this point + on. */ + val = iterative_hash_object (code, val); + val = iterative_hash_expr (TREE_OPERAND (t, 1), val); + val = iterative_hash_expr (TREE_OPERAND (t, 0), val); + return val; + } case FUNCTION_DECL: /* When referring to a built-in FUNCTION_DECL, use the __builtin__ form. Otherwise nodes that compare equal according to operand_equal_p might @@ -6852,41 +7106,6 @@ build_type_no_quals (tree t) } } -/* Create a type of integers to be the TYPE_DOMAIN of an ARRAY_TYPE. - MAXVAL should be the maximum value in the domain - (one less than the length of the array). - - The maximum value that MAXVAL can have is INT_MAX for a HOST_WIDE_INT. - We don't enforce this limit, that is up to caller (e.g. language front end). - The limit exists because the result is a signed type and we don't handle - sizes that use more than one HOST_WIDE_INT. */ - -tree -build_index_type (tree maxval) -{ - tree itype = make_node (INTEGER_TYPE); - - TREE_TYPE (itype) = sizetype; - TYPE_PRECISION (itype) = TYPE_PRECISION (sizetype); - TYPE_MIN_VALUE (itype) = size_zero_node; - TYPE_MAX_VALUE (itype) = fold_convert (sizetype, maxval); - SET_TYPE_MODE (itype, TYPE_MODE (sizetype)); - TYPE_SIZE (itype) = TYPE_SIZE (sizetype); - TYPE_SIZE_UNIT (itype) = TYPE_SIZE_UNIT (sizetype); - TYPE_ALIGN (itype) = TYPE_ALIGN (sizetype); - TYPE_USER_ALIGN (itype) = TYPE_USER_ALIGN (sizetype); - - if (host_integerp (maxval, 1)) - return type_hash_canon (tree_low_cst (maxval, 1), itype); - else - { - /* Since we cannot hash this type, we need to compare it using - structural equality checks. */ - SET_TYPE_STRUCTURAL_EQUALITY (itype); - return itype; - } -} - #define MAX_INT_CACHED_PREC \ (HOST_BITS_PER_WIDE_INT > 64 ? HOST_BITS_PER_WIDE_INT : 64) static GTY(()) tree nonstandard_integer_type_cache[2 * MAX_INT_CACHED_PREC + 2]; @@ -6921,24 +7140,23 @@ build_nonstandard_integer_type (unsigned HOST_WIDE_INT precision, ret = itype; if (host_integerp (TYPE_MAX_VALUE (itype), 1)) ret = type_hash_canon (tree_low_cst (TYPE_MAX_VALUE (itype), 1), itype); - if (precision <= MAX_INT_CACHED_PREC && lang_hooks.types.hash_types) + if (precision <= MAX_INT_CACHED_PREC) nonstandard_integer_type_cache[precision + unsignedp] = ret; return ret; } -/* Create a range of some discrete type TYPE (an INTEGER_TYPE, - ENUMERAL_TYPE or BOOLEAN_TYPE), with low bound LOWVAL and - high bound HIGHVAL. If TYPE is NULL, sizetype is used. */ +/* Create a range of some discrete type TYPE (an INTEGER_TYPE, ENUMERAL_TYPE + or BOOLEAN_TYPE) with low bound LOWVAL and high bound HIGHVAL. If SHARED + is true, reuse such a type that has already been constructed. */ -tree -build_range_type (tree type, tree lowval, tree highval) +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; - if (type == NULL_TREE) - type = sizetype; TYPE_MIN_VALUE (itype) = fold_convert (type, lowval); TYPE_MAX_VALUE (itype) = highval ? fold_convert (type, highval) : NULL; @@ -6950,12 +7168,57 @@ build_range_type (tree type, tree lowval, tree highval) TYPE_ALIGN (itype) = TYPE_ALIGN (type); TYPE_USER_ALIGN (itype) = TYPE_USER_ALIGN (type); - if (host_integerp (lowval, 0) && highval != 0 && host_integerp (highval, 0)) - return type_hash_canon (tree_low_cst (highval, 0) - - tree_low_cst (lowval, 0), - itype); - else + if (!shared) return itype; + + if ((TYPE_MIN_VALUE (itype) + && TREE_CODE (TYPE_MIN_VALUE (itype)) != INTEGER_CST) + || (TYPE_MAX_VALUE (itype) + && TREE_CODE (TYPE_MAX_VALUE (itype)) != INTEGER_CST)) + { + /* Since we cannot reliably merge this type, we need to compare it using + structural equality checks. */ + SET_TYPE_STRUCTURAL_EQUALITY (itype); + return 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; +} + +/* Wrapper around build_range_type_1 with SHARED set to true. */ + +tree +build_range_type (tree type, tree lowval, tree highval) +{ + return build_range_type_1 (type, lowval, highval, true); +} + +/* Wrapper around build_range_type_1 with SHARED set to false. */ + +tree +build_nonshared_range_type (tree type, tree lowval, tree highval) +{ + return build_range_type_1 (type, lowval, highval, false); +} + +/* Create a type of integers to be the TYPE_DOMAIN of an ARRAY_TYPE. + MAXVAL should be the maximum value in the domain + (one less than the length of the array). + + The maximum value that MAXVAL can have is INT_MAX for a HOST_WIDE_INT. + We don't enforce this limit, that is up to caller (e.g. language front end). + The limit exists because the result is a signed type and we don't handle + sizes that use more than one HOST_WIDE_INT. */ + +tree +build_index_type (tree maxval) +{ + return build_range_type (sizetype, size_zero_node, maxval); } /* Return true if the debug information for TYPE, a subtype, should be emitted @@ -7009,24 +7272,14 @@ subrange_type_for_debug_p (const_tree type, tree *lowval, tree *highval) return true; } -/* Just like build_index_type, but takes lowval and highval instead - of just highval (maxval). */ - -tree -build_index_2_type (tree lowval, tree highval) -{ - return build_range_type (sizetype, lowval, highval); -} - /* Construct, lay out and return the type of arrays of elements with ELT_TYPE and number of elements specified by the range of values of INDEX_TYPE. - If such a type has already been constructed, reuse it. */ + If SHARED is true, reuse such a type that has already been constructed. */ -tree -build_array_type (tree elt_type, tree index_type) +static tree +build_array_type_1 (tree elt_type, tree index_type, bool shared) { tree t; - hashval_t hashcode = 0; if (TREE_CODE (elt_type) == FUNCTION_TYPE) { @@ -7046,10 +7299,13 @@ build_array_type (tree elt_type, tree index_type) if (TYPE_STRUCTURAL_EQUALITY_P (t)) return t; - hashcode = iterative_hash_object (TYPE_HASH (elt_type), hashcode); - if (index_type) - hashcode = iterative_hash_object (TYPE_HASH (index_type), hashcode); - t = type_hash_canon (hashcode, t); + if (shared) + { + hashval_t hashcode = iterative_hash_object (TYPE_HASH (elt_type), 0); + if (index_type) + hashcode = iterative_hash_object (TYPE_HASH (index_type), hashcode); + t = type_hash_canon (hashcode, t); + } if (TYPE_CANONICAL (t) == t) { @@ -7059,13 +7315,31 @@ build_array_type (tree elt_type, tree index_type) else if (TYPE_CANONICAL (elt_type) != elt_type || (index_type && TYPE_CANONICAL (index_type) != index_type)) TYPE_CANONICAL (t) - = build_array_type (TYPE_CANONICAL (elt_type), - index_type ? TYPE_CANONICAL (index_type) : NULL); + = build_array_type_1 (TYPE_CANONICAL (elt_type), + index_type + ? TYPE_CANONICAL (index_type) : NULL_TREE, + shared); } return t; } +/* Wrapper around build_array_type_1 with SHARED set to true. */ + +tree +build_array_type (tree elt_type, tree index_type) +{ + return build_array_type_1 (elt_type, index_type, true); +} + +/* Wrapper around build_array_type_1 with SHARED set to false. */ + +tree +build_nonshared_array_type (tree elt_type, tree index_type) +{ + return build_array_type_1 (elt_type, index_type, false); +} + /* Recursively examines the array elements of TYPE, until a non-array element type is found. */ @@ -7230,7 +7504,7 @@ build_function_type_skip_args (tree orig_type, bitmap args_to_skip) if (TREE_CODE (orig_type) != METHOD_TYPE || !bitmap_bit_p (args_to_skip, 0)) { - new_type = copy_node (orig_type); + new_type = build_distinct_type_copy (orig_type); TYPE_ARG_TYPES (new_type) = new_reversed; } else @@ -7279,6 +7553,13 @@ build_function_decl_skip_args (tree orig_decl, bitmap args_to_skip) we expect first argument to be THIS pointer. */ if (bitmap_bit_p (args_to_skip, 0)) DECL_VINDEX (new_decl) = NULL_TREE; + + /* When signature changes, we need to clear builtin info. */ + if (DECL_BUILT_IN (new_decl) && !bitmap_empty_p (args_to_skip)) + { + DECL_BUILT_IN_CLASS (new_decl) = NOT_BUILT_IN; + DECL_FUNCTION_CODE (new_decl) = (enum built_in_function) 0; + } return new_decl; } @@ -7769,10 +8050,10 @@ get_narrower (tree op, int *unsignedp_ptr) return win; } -/* Nonzero if integer constant C has a value that is permissible +/* Returns true if integer constant C has a value that is permissible for type TYPE (an INTEGER_TYPE). */ -int +bool int_fits_type_p (const_tree c, const_tree type) { tree type_low_bound, type_high_bound; @@ -7801,7 +8082,7 @@ retry: /* If at least one bound of the type is a constant integer, we can check ourselves and maybe make a decision. If no such decision is possible, but this type is a subtype, try checking against that. Otherwise, use - fit_double_type, which checks against the precision. + double_int_fits_to_tree_p, which checks against the precision. Compute the status for each possibly constant bound, and return if we see one does not match. Use ok_for_xxx_bound for this purpose, assigning -1 @@ -7822,12 +8103,12 @@ retry: int t_neg = (unsc && double_int_negative_p (dd)); if (c_neg && !t_neg) - return 0; + return false; if ((c_neg || !t_neg) && double_int_ucmp (dc, dd) < 0) - return 0; + return false; } else if (double_int_cmp (dc, dd, unsc) < 0) - return 0; + return false; ok_for_low_bound = true; } else @@ -7847,12 +8128,12 @@ retry: int t_neg = (unsc && double_int_negative_p (dd)); if (t_neg && !c_neg) - return 0; + return false; if ((t_neg || !c_neg) && double_int_ucmp (dc, dd) > 0) - return 0; + return false; } else if (double_int_cmp (dc, dd, unsc) > 0) - return 0; + return false; ok_for_high_bound = true; } else @@ -7860,17 +8141,17 @@ retry: /* If the constant fits both bounds, the result is known. */ if (ok_for_low_bound && ok_for_high_bound) - return 1; + return true; /* Perform some generic filtering which may allow making a decision even if the bounds are not constant. First, negative integers never fit in unsigned types, */ if (TYPE_UNSIGNED (type) && !unsc && double_int_negative_p (dc)) - return 0; + return false; /* Second, narrower types always fit in wider ones. */ if (TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (c))) - return 1; + return true; /* Third, unsigned integers with top bit set never fit signed types. */ if (! TYPE_UNSIGNED (type) && unsc) @@ -7879,11 +8160,11 @@ retry: if (prec < HOST_BITS_PER_WIDE_INT) { if (((((unsigned HOST_WIDE_INT) 1) << prec) & dc.low) != 0) - return 0; + return false; } else if (((((unsigned HOST_WIDE_INT) 1) << (prec - HOST_BITS_PER_WIDE_INT)) & dc.high) != 0) - return 0; + return false; } /* If we haven't been able to decide at this point, there nothing more we @@ -7897,8 +8178,8 @@ retry: goto retry; } - /* Or to fit_double_type, if nothing else. */ - return !fit_double_type (dc.low, dc.high, &dc.low, &dc.high, type); + /* Or to double_int_fits_to_tree_p, if nothing else. */ + return double_int_fits_to_tree_p (type, dc); } /* Stores bounds of an integer TYPE in MIN and MAX. If TYPE has non-constant @@ -8044,7 +8325,7 @@ variably_modified_type_p (tree type, tree fn) definition we normally use, since that would produce infinite recursion via pointers. */ /* This is variably modified if some field's type is. */ - for (t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t)) + for (t = TYPE_FIELDS (type); t; t = DECL_CHAIN (t)) if (TREE_CODE (t) == FIELD_DECL) { RETURN_TRUE_IF_VAR (DECL_FIELD_OFFSET (t)); @@ -8295,20 +8576,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 { @@ -8631,24 +8911,6 @@ make_vector_type (tree innertype, int nunits, enum machine_mode mode) layout_type (t); - { - tree index = build_int_cst (NULL_TREE, nunits - 1); - tree array = build_array_type (TYPE_MAIN_VARIANT (innertype), - build_index_type (index)); - tree rt = make_node (RECORD_TYPE); - - TYPE_FIELDS (rt) = build_decl (UNKNOWN_LOCATION, FIELD_DECL, - get_identifier ("f"), array); - DECL_CONTEXT (TYPE_FIELDS (rt)) = rt; - layout_type (rt); - TYPE_DEBUG_REPRESENTATION_TYPE (t) = rt; - /* In dwarfout.c, type lookup uses TYPE_UID numbers. We want to output - the representation type, and we want to find that die when looking up - the vector type. This is most easily achieved by making the TYPE_UID - numbers equal. */ - TYPE_UID (rt) = TYPE_UID (t); - } - hashcode = iterative_hash_host_wide_int (VECTOR_TYPE, hashcode); hashcode = iterative_hash_host_wide_int (nunits, hashcode); hashcode = iterative_hash_host_wide_int (mode, hashcode); @@ -8844,9 +9106,10 @@ void build_common_tree_nodes_2 (int short_double) { /* Define these next since types below may used them. */ - integer_zero_node = build_int_cst (NULL_TREE, 0); - integer_one_node = build_int_cst (NULL_TREE, 1); - integer_minus_one_node = build_int_cst (NULL_TREE, -1); + integer_zero_node = build_int_cst (integer_type_node, 0); + integer_one_node = build_int_cst (integer_type_node, 1); + integer_three_node = build_int_cst (integer_type_node, 3); + integer_minus_one_node = build_int_cst (integer_type_node, -1); size_zero_node = size_int (0); size_one_node = size_int (1); @@ -9011,6 +9274,9 @@ local_define_builtin (const char *name, tree type, enum built_in_function code, TREE_NOTHROW (decl) = 1; if (ecf_flags & ECF_MALLOC) DECL_IS_MALLOC (decl) = 1; + if (ecf_flags & ECF_LEAF) + DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("leaf"), + NULL, DECL_ATTRIBUTES (decl)); built_in_decls[code] = decl; implicit_built_in_decls[code] = decl; @@ -9023,130 +9289,114 @@ local_define_builtin (const char *name, tree type, enum built_in_function code, void build_common_builtin_nodes (void) { - tree tmp, tmp2, ftype; + tree tmp, ftype; if (built_in_decls[BUILT_IN_MEMCPY] == NULL || built_in_decls[BUILT_IN_MEMMOVE] == NULL) { - tmp = tree_cons (NULL_TREE, size_type_node, void_list_node); - tmp = tree_cons (NULL_TREE, const_ptr_type_node, tmp); - tmp = tree_cons (NULL_TREE, ptr_type_node, tmp); - ftype = build_function_type (ptr_type_node, tmp); + ftype = build_function_type_list (ptr_type_node, + ptr_type_node, const_ptr_type_node, + size_type_node, NULL_TREE); if (built_in_decls[BUILT_IN_MEMCPY] == NULL) local_define_builtin ("__builtin_memcpy", ftype, BUILT_IN_MEMCPY, - "memcpy", ECF_NOTHROW); + "memcpy", ECF_NOTHROW | ECF_LEAF); if (built_in_decls[BUILT_IN_MEMMOVE] == NULL) local_define_builtin ("__builtin_memmove", ftype, BUILT_IN_MEMMOVE, - "memmove", ECF_NOTHROW); + "memmove", ECF_NOTHROW | ECF_LEAF); } if (built_in_decls[BUILT_IN_MEMCMP] == NULL) { - tmp = tree_cons (NULL_TREE, size_type_node, void_list_node); - tmp = tree_cons (NULL_TREE, const_ptr_type_node, tmp); - tmp = tree_cons (NULL_TREE, const_ptr_type_node, tmp); - ftype = build_function_type (integer_type_node, tmp); + ftype = build_function_type_list (integer_type_node, const_ptr_type_node, + const_ptr_type_node, size_type_node, + NULL_TREE); local_define_builtin ("__builtin_memcmp", ftype, BUILT_IN_MEMCMP, - "memcmp", ECF_PURE | ECF_NOTHROW); + "memcmp", ECF_PURE | ECF_NOTHROW | ECF_LEAF); } if (built_in_decls[BUILT_IN_MEMSET] == NULL) { - tmp = tree_cons (NULL_TREE, size_type_node, void_list_node); - tmp = tree_cons (NULL_TREE, integer_type_node, tmp); - tmp = tree_cons (NULL_TREE, ptr_type_node, tmp); - ftype = build_function_type (ptr_type_node, tmp); + ftype = build_function_type_list (ptr_type_node, + ptr_type_node, integer_type_node, + size_type_node, NULL_TREE); local_define_builtin ("__builtin_memset", ftype, BUILT_IN_MEMSET, - "memset", ECF_NOTHROW); + "memset", ECF_NOTHROW | ECF_LEAF); } if (built_in_decls[BUILT_IN_ALLOCA] == NULL) { - tmp = tree_cons (NULL_TREE, size_type_node, void_list_node); - ftype = build_function_type (ptr_type_node, tmp); + ftype = build_function_type_list (ptr_type_node, + size_type_node, NULL_TREE); local_define_builtin ("__builtin_alloca", ftype, BUILT_IN_ALLOCA, - "alloca", ECF_MALLOC | ECF_NOTHROW); + "alloca", ECF_MALLOC | ECF_NOTHROW | ECF_LEAF); } /* If we're checking the stack, `alloca' can throw. */ if (flag_stack_check) TREE_NOTHROW (built_in_decls[BUILT_IN_ALLOCA]) = 0; - tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node); - tmp = tree_cons (NULL_TREE, ptr_type_node, tmp); - tmp = tree_cons (NULL_TREE, ptr_type_node, tmp); - ftype = build_function_type (void_type_node, tmp); + ftype = build_function_type_list (void_type_node, + ptr_type_node, ptr_type_node, + ptr_type_node, NULL_TREE); local_define_builtin ("__builtin_init_trampoline", ftype, BUILT_IN_INIT_TRAMPOLINE, - "__builtin_init_trampoline", ECF_NOTHROW); + "__builtin_init_trampoline", ECF_NOTHROW | ECF_LEAF); - tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node); - ftype = build_function_type (ptr_type_node, tmp); + ftype = build_function_type_list (ptr_type_node, ptr_type_node, NULL_TREE); local_define_builtin ("__builtin_adjust_trampoline", ftype, BUILT_IN_ADJUST_TRAMPOLINE, "__builtin_adjust_trampoline", ECF_CONST | ECF_NOTHROW); - tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node); - tmp = tree_cons (NULL_TREE, ptr_type_node, tmp); - ftype = build_function_type (void_type_node, tmp); + ftype = build_function_type_list (void_type_node, + ptr_type_node, ptr_type_node, NULL_TREE); local_define_builtin ("__builtin_nonlocal_goto", ftype, BUILT_IN_NONLOCAL_GOTO, "__builtin_nonlocal_goto", ECF_NORETURN | ECF_NOTHROW); - tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node); - tmp = tree_cons (NULL_TREE, ptr_type_node, tmp); - ftype = build_function_type (void_type_node, tmp); + ftype = build_function_type_list (void_type_node, + ptr_type_node, ptr_type_node, NULL_TREE); local_define_builtin ("__builtin_setjmp_setup", ftype, BUILT_IN_SETJMP_SETUP, "__builtin_setjmp_setup", ECF_NOTHROW); - tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node); - ftype = build_function_type (ptr_type_node, tmp); + ftype = build_function_type_list (ptr_type_node, ptr_type_node, NULL_TREE); local_define_builtin ("__builtin_setjmp_dispatcher", ftype, BUILT_IN_SETJMP_DISPATCHER, "__builtin_setjmp_dispatcher", ECF_PURE | ECF_NOTHROW); - tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node); - ftype = build_function_type (void_type_node, tmp); + ftype = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE); local_define_builtin ("__builtin_setjmp_receiver", ftype, BUILT_IN_SETJMP_RECEIVER, "__builtin_setjmp_receiver", ECF_NOTHROW); - ftype = build_function_type (ptr_type_node, void_list_node); + ftype = build_function_type_list (ptr_type_node, NULL_TREE); local_define_builtin ("__builtin_stack_save", ftype, BUILT_IN_STACK_SAVE, - "__builtin_stack_save", ECF_NOTHROW); + "__builtin_stack_save", ECF_NOTHROW | ECF_LEAF); - tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node); - ftype = build_function_type (void_type_node, tmp); + ftype = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE); local_define_builtin ("__builtin_stack_restore", ftype, BUILT_IN_STACK_RESTORE, - "__builtin_stack_restore", ECF_NOTHROW); - - ftype = build_function_type (void_type_node, void_list_node); - 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); + "__builtin_stack_restore", ECF_NOTHROW | ECF_LEAF); /* 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) { - ftype = build_function_type (void_type_node, void_list_node); + ftype = build_function_type_list (void_type_node, NULL_TREE); local_define_builtin ("__builtin_cxa_end_cleanup", ftype, BUILT_IN_CXA_END_CLEANUP, - "__cxa_end_cleanup", ECF_NORETURN); + "__cxa_end_cleanup", ECF_NORETURN | ECF_LEAF); } - tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node); - ftype = build_function_type (void_type_node, tmp); + ftype = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE); local_define_builtin ("__builtin_unwind_resume", ftype, BUILT_IN_UNWIND_RESUME, - (USING_SJLJ_EXCEPTIONS + ((targetm.except_unwind_info (&global_options) + == UI_SJLJ) ? "_Unwind_SjLj_Resume" : "_Unwind_Resume"), ECF_NORETURN); @@ -9156,19 +9406,19 @@ build_common_builtin_nodes (void) landing pad. These functions are PURE instead of CONST to prevent them from being hoisted past the exception edge that will initialize its value in the landing pad. */ - tmp = tree_cons (NULL_TREE, integer_type_node, void_list_node); - ftype = build_function_type (ptr_type_node, tmp); + ftype = build_function_type_list (ptr_type_node, + integer_type_node, NULL_TREE); local_define_builtin ("__builtin_eh_pointer", ftype, BUILT_IN_EH_POINTER, - "__builtin_eh_pointer", ECF_PURE | ECF_NOTHROW); + "__builtin_eh_pointer", ECF_PURE | ECF_NOTHROW | ECF_LEAF); - tmp2 = lang_hooks.types.type_for_mode (targetm.eh_return_filter_mode (), 0); - ftype = build_function_type (tmp2, tmp); + tmp = lang_hooks.types.type_for_mode (targetm.eh_return_filter_mode (), 0); + ftype = build_function_type_list (tmp, integer_type_node, NULL_TREE); local_define_builtin ("__builtin_eh_filter", ftype, BUILT_IN_EH_FILTER, - "__builtin_eh_filter", ECF_PURE | ECF_NOTHROW); + "__builtin_eh_filter", ECF_PURE | ECF_NOTHROW | ECF_LEAF); - tmp = tree_cons (NULL_TREE, integer_type_node, void_list_node); - tmp = tree_cons (NULL_TREE, integer_type_node, tmp); - ftype = build_function_type (void_type_node, tmp); + ftype = build_function_type_list (void_type_node, + integer_type_node, integer_type_node, + NULL_TREE); local_define_builtin ("__builtin_eh_copy_values", ftype, BUILT_IN_EH_COPY_VALUES, "__builtin_eh_copy_values", ECF_NOTHROW); @@ -9192,11 +9442,8 @@ build_common_builtin_nodes (void) continue; inner_type = TREE_TYPE (type); - tmp = tree_cons (NULL_TREE, inner_type, void_list_node); - tmp = tree_cons (NULL_TREE, inner_type, tmp); - tmp = tree_cons (NULL_TREE, inner_type, tmp); - tmp = tree_cons (NULL_TREE, inner_type, tmp); - ftype = build_function_type (type, tmp); + ftype = build_function_type_list (type, inner_type, inner_type, + inner_type, inner_type, NULL_TREE); mcode = ((enum built_in_function) (BUILT_IN_COMPLEX_MUL_MIN + mode - MIN_MODE_COMPLEX_FLOAT)); @@ -9209,11 +9456,11 @@ build_common_builtin_nodes (void) built_in_names[mcode] = concat ("__mul", mode_name_buf, "3", NULL); local_define_builtin (built_in_names[mcode], ftype, mcode, - built_in_names[mcode], ECF_CONST | ECF_NOTHROW); + built_in_names[mcode], ECF_CONST | ECF_NOTHROW | ECF_LEAF); built_in_names[dcode] = concat ("__div", mode_name_buf, "3", NULL); local_define_builtin (built_in_names[dcode], ftype, dcode, - built_in_names[dcode], ECF_CONST | ECF_NOTHROW); + built_in_names[dcode], ECF_CONST | ECF_NOTHROW | ECF_LEAF); } } } @@ -9422,17 +9669,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)); - t = GGC_NEWVAR (union tree_node, size); + 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; } @@ -9450,14 +9694,9 @@ 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 = (tree) ggc_alloc_zone_pass_stat (length, &tree_zone); - - memset (t, 0, length); + t = ggc_alloc_zone_cleared_tree_node_stat (&tree_zone, length PASS_MEM_STAT); TREE_SET_CODE (t, code); @@ -9468,24 +9707,20 @@ 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. */ -/* Build a CALL_EXPR of class tcc_vl_exp with the indicated RETURN_TYPE - and FN and a null static chain slot. ARGLIST is a TREE_LIST of the - arguments. */ - -tree -build_call_list (tree return_type, tree fn, tree arglist) +static tree +build_call_1 (tree return_type, tree fn, int nargs) { tree t; - int i; - t = build_vl_exp (CALL_EXPR, list_length (arglist) + 3); + 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; - for (i = 0; arglist; arglist = TREE_CHAIN (arglist), i++) - CALL_EXPR_ARG (t, i) = TREE_VALUE (arglist); - process_call_operands (t); + CALL_EXPR_STATIC_CHAIN (t) = NULL; + return t; } @@ -9514,10 +9749,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); @@ -9535,10 +9767,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); @@ -9554,11 +9783,8 @@ 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; - for (ix = 0; VEC_iterate (tree, args, ix, t); ++ix) + 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); return ret; @@ -9638,53 +9864,10 @@ needs_to_live_in_memory (const_tree t) return (TREE_ADDRESSABLE (t) || is_global_var (t) || (TREE_CODE (t) == RESULT_DECL + && !DECL_BY_REFERENCE (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 @@ -9786,7 +9969,7 @@ signed_type_for (tree type) tree upper_bound_in_type (tree outer, tree inner) { - unsigned HOST_WIDE_INT lo, hi; + double_int high; unsigned int det = 0; unsigned oprec = TYPE_PRECISION (outer); unsigned iprec = TYPE_PRECISION (inner); @@ -9833,18 +10016,18 @@ upper_bound_in_type (tree outer, tree inner) /* Compute 2^^prec - 1. */ if (prec <= HOST_BITS_PER_WIDE_INT) { - hi = 0; - lo = ((~(unsigned HOST_WIDE_INT) 0) + high.high = 0; + high.low = ((~(unsigned HOST_WIDE_INT) 0) >> (HOST_BITS_PER_WIDE_INT - prec)); } else { - hi = ((~(unsigned HOST_WIDE_INT) 0) + high.high = ((~(unsigned HOST_WIDE_INT) 0) >> (2 * HOST_BITS_PER_WIDE_INT - prec)); - lo = ~(unsigned HOST_WIDE_INT) 0; + high.low = ~(unsigned HOST_WIDE_INT) 0; } - return build_int_cst_wide (outer, lo, hi); + return double_int_to_tree (outer, high); } /* Returns the smallest value obtainable by casting something in INNER type to @@ -9853,7 +10036,7 @@ upper_bound_in_type (tree outer, tree inner) tree lower_bound_in_type (tree outer, tree inner) { - unsigned HOST_WIDE_INT lo, hi; + double_int low; unsigned oprec = TYPE_PRECISION (outer); unsigned iprec = TYPE_PRECISION (inner); @@ -9864,7 +10047,7 @@ lower_bound_in_type (tree outer, tree inner) contains all values of INNER type. In particular, both INNER and OUTER types have zero in common. */ || (oprec > iprec && TYPE_UNSIGNED (inner))) - lo = hi = 0; + low.low = low.high = 0; else { /* If we are widening a signed type to another signed type, we @@ -9875,18 +10058,18 @@ lower_bound_in_type (tree outer, tree inner) if (prec <= HOST_BITS_PER_WIDE_INT) { - hi = ~(unsigned HOST_WIDE_INT) 0; - lo = (~(unsigned HOST_WIDE_INT) 0) << (prec - 1); + low.high = ~(unsigned HOST_WIDE_INT) 0; + low.low = (~(unsigned HOST_WIDE_INT) 0) << (prec - 1); } else { - hi = ((~(unsigned HOST_WIDE_INT) 0) + low.high = ((~(unsigned HOST_WIDE_INT) 0) << (prec - HOST_BITS_PER_WIDE_INT - 1)); - lo = 0; + low.low = 0; } } - return build_int_cst_wide (outer, lo, hi); + return double_int_to_tree (outer, low); } /* Return nonzero if two operands that are suitable for PHI nodes are @@ -10154,7 +10337,7 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, case BIND_EXPR: { tree decl; - for (decl = BIND_EXPR_VARS (*tp); decl; decl = TREE_CHAIN (decl)) + for (decl = BIND_EXPR_VARS (*tp); decl; decl = DECL_CHAIN (decl)) { /* Walk the DECL_INITIAL and DECL_SIZE. We don't want to walk into declarations that are just mentioned, rather than @@ -10269,7 +10452,7 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, tree field; for (field = TYPE_FIELDS (*type_p); field; - field = TREE_CHAIN (field)) + field = DECL_CHAIN (field)) { /* We'd like to look at the type of the field, but we can easily get infinite recursion. So assume it's pointed @@ -10403,7 +10586,7 @@ get_name (tree t) /* Return true if TYPE has a variable argument list. */ bool -stdarg_p (tree fntype) +stdarg_p (const_tree fntype) { function_args_iterator args_iter; tree n = NULL_TREE, t; @@ -10570,7 +10753,8 @@ build_optimization_node (void) /* Use the cache of optimization nodes. */ - cl_optimization_save (TREE_OPTIMIZATION (cl_optimization_node)); + cl_optimization_save (TREE_OPTIMIZATION (cl_optimization_node), + &global_options); slot = htab_find_slot (cl_option_hash_table, cl_optimization_node, INSERT); t = (tree) *slot; @@ -10597,7 +10781,8 @@ build_target_option_node (void) /* Use the cache of optimization nodes. */ - cl_target_option_save (TREE_TARGET_OPTION (cl_target_option_node)); + cl_target_option_save (TREE_TARGET_OPTION (cl_target_option_node), + &global_options); slot = htab_find_slot (cl_option_hash_table, cl_target_option_node, INSERT); t = (tree) *slot; @@ -10754,11 +10939,7 @@ tree lhd_gcc_personality (void) { if (!gcc_eh_personality_decl) - gcc_eh_personality_decl - = build_personality_function (USING_SJLJ_EXCEPTIONS - ? "__gcc_personality_sj0" - : "__gcc_personality_v0"); - + gcc_eh_personality_decl = build_personality_function ("gcc"); return gcc_eh_personality_decl; } @@ -10769,23 +10950,20 @@ lhd_gcc_personality (void) tree get_binfo_at_offset (tree binfo, HOST_WIDE_INT offset, tree expected_type) { - tree type; + tree type = BINFO_TYPE (binfo); - if (offset == 0) - return binfo; - - type = TREE_TYPE (binfo); - while (offset > 0) + while (true) { - tree base_binfo, found_binfo; HOST_WIDE_INT pos, size; tree fld; int i; - if (TREE_CODE (type) != RECORD_TYPE) + if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (expected_type)) + return binfo; + if (offset < 0) return NULL_TREE; - for (fld = TYPE_FIELDS (type); fld; fld = TREE_CHAIN (fld)) + for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld)) { if (TREE_CODE (fld) != FIELD_DECL) continue; @@ -10795,27 +10973,156 @@ get_binfo_at_offset (tree binfo, HOST_WIDE_INT offset, tree expected_type) if (pos <= offset && (pos + size) > offset) break; } - if (!fld) + if (!fld || TREE_CODE (TREE_TYPE (fld)) != RECORD_TYPE) return NULL_TREE; - found_binfo = NULL_TREE; - for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) - if (TREE_TYPE (base_binfo) == TREE_TYPE (fld)) - { - found_binfo = base_binfo; - break; - } - - if (!found_binfo) - 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. */ + else if (offset != 0) + { + tree base_binfo, found_binfo = NULL_TREE; + for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) + if (TREE_TYPE (base_binfo) == TREE_TYPE (fld)) + { + found_binfo = base_binfo; + break; + } + if (!found_binfo) + return NULL_TREE; + binfo = found_binfo; + } type = TREE_TYPE (fld); - binfo = found_binfo; offset -= pos; } - if (type != expected_type) - return NULL_TREE; - return binfo; +} + +/* Returns true if X is a typedef decl. */ + +bool +is_typedef_decl (tree x) +{ + return (x && TREE_CODE (x) == TYPE_DECL + && DECL_ORIGINAL_TYPE (x) != NULL_TREE); +} + +/* Returns true iff TYPE is a type variant created for a typedef. */ + +bool +typedef_variant_p (tree type) +{ + return is_typedef_decl (TYPE_NAME (type)); +} + +/* Warn about a use of an identifier which was marked deprecated. */ +void +warn_deprecated_use (tree node, tree attr) +{ + const char *msg; + + if (node == 0 || !warn_deprecated_decl) + return; + + if (!attr) + { + if (DECL_P (node)) + attr = DECL_ATTRIBUTES (node); + else if (TYPE_P (node)) + { + tree decl = TYPE_STUB_DECL (node); + if (decl) + attr = lookup_attribute ("deprecated", + TYPE_ATTRIBUTES (TREE_TYPE (decl))); + } + } + + if (attr) + attr = lookup_attribute ("deprecated", attr); + + if (attr) + msg = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))); + else + msg = NULL; + + if (DECL_P (node)) + { + expanded_location xloc = expand_location (DECL_SOURCE_LOCATION (node)); + if (msg) + warning (OPT_Wdeprecated_declarations, + "%qD is deprecated (declared at %s:%d): %s", + node, xloc.file, xloc.line, msg); + else + warning (OPT_Wdeprecated_declarations, + "%qD is deprecated (declared at %s:%d)", + node, xloc.file, xloc.line); + } + else if (TYPE_P (node)) + { + tree what = NULL_TREE; + tree decl = TYPE_STUB_DECL (node); + + if (TYPE_NAME (node)) + { + if (TREE_CODE (TYPE_NAME (node)) == IDENTIFIER_NODE) + what = TYPE_NAME (node); + else if (TREE_CODE (TYPE_NAME (node)) == TYPE_DECL + && DECL_NAME (TYPE_NAME (node))) + what = DECL_NAME (TYPE_NAME (node)); + } + + if (decl) + { + expanded_location xloc + = expand_location (DECL_SOURCE_LOCATION (decl)); + if (what) + { + if (msg) + warning (OPT_Wdeprecated_declarations, + "%qE is deprecated (declared at %s:%d): %s", + what, xloc.file, xloc.line, msg); + else + warning (OPT_Wdeprecated_declarations, + "%qE is deprecated (declared at %s:%d)", what, + xloc.file, xloc.line); + } + else + { + if (msg) + warning (OPT_Wdeprecated_declarations, + "type is deprecated (declared at %s:%d): %s", + xloc.file, xloc.line, msg); + else + warning (OPT_Wdeprecated_declarations, + "type is deprecated (declared at %s:%d)", + xloc.file, xloc.line); + } + } + else + { + if (what) + { + if (msg) + warning (OPT_Wdeprecated_declarations, "%qE is deprecated: %s", + what, msg); + else + warning (OPT_Wdeprecated_declarations, "%qE is deprecated", what); + } + else + { + if (msg) + warning (OPT_Wdeprecated_declarations, "type is deprecated: %s", + msg); + else + warning (OPT_Wdeprecated_declarations, "type is deprecated"); + } + } + } } #include "gt-tree.h"