X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ftree.c;h=8eeecff7122a0c3bdb6757f140389b9807ec77a9;hb=f7d2ed1eb1ae30a88dfcc1bb92ebdfaa95ed8173;hp=ad81827052aaf764b01e9f10fccdb214ce09103e;hpb=4189e6771feda58eeb5859eb78adaeb1ce9729e1;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/tree.c b/gcc/tree.c index ad81827052a..8eeecff7122 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -1,6 +1,6 @@ /* 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 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GCC. @@ -52,6 +52,14 @@ along with GCC; see the file COPYING3. If not see #include "params.h" #include "pointer-set.h" #include "fixed-value.h" +#include "tree-pass.h" +#include "langhooks-def.h" +#include "diagnostic.h" +#include "cgraph.h" +#include "timevar.h" +#include "except.h" +#include "debug.h" +#include "intl.h" /* Tree code classes. */ @@ -145,6 +153,9 @@ static const char * const tree_node_kind_names[] = { static GTY(()) int next_decl_uid; /* Unique id for next type created. */ static GTY(()) int next_type_uid = 1; +/* Unique id for next debug decl created. Use negative numbers, + to catch erroneous uses. */ +static GTY(()) int next_debug_decl_uid; /* Since we cannot rehash a type after it is in the table, we have to keep the hash code. */ @@ -185,13 +196,13 @@ static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node))) /* General tree->tree mapping structure for use in hash tables. */ -static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map))) +static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map))) htab_t debug_expr_for_decl; -static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map))) +static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map))) htab_t value_expr_for_decl; -static GTY ((if_marked ("tree_priority_map_marked_p"), +static GTY ((if_marked ("tree_priority_map_marked_p"), param_is (struct tree_priority_map))) htab_t init_priority_for_decl; @@ -254,7 +265,265 @@ const char * const omp_clause_code_name[] = "collapse", "untied" }; - + + +/* Return the tree node structure used by tree code CODE. */ + +static inline enum tree_node_structure_enum +tree_node_structure_for_code (enum tree_code code) +{ + switch (TREE_CODE_CLASS (code)) + { + case tcc_declaration: + { + switch (code) + { + case FIELD_DECL: + return TS_FIELD_DECL; + case PARM_DECL: + return TS_PARM_DECL; + case VAR_DECL: + return TS_VAR_DECL; + case LABEL_DECL: + return TS_LABEL_DECL; + case RESULT_DECL: + return TS_RESULT_DECL; + case DEBUG_EXPR_DECL: + return TS_DECL_WRTL; + case CONST_DECL: + return TS_CONST_DECL; + case TYPE_DECL: + return TS_TYPE_DECL; + case FUNCTION_DECL: + return TS_FUNCTION_DECL; + default: + return TS_DECL_NON_COMMON; + } + } + case tcc_type: + return TS_TYPE; + case tcc_reference: + case tcc_comparison: + case tcc_unary: + case tcc_binary: + case tcc_expression: + case tcc_statement: + case tcc_vl_exp: + return TS_EXP; + default: /* tcc_constant and tcc_exceptional */ + break; + } + switch (code) + { + /* tcc_constant cases. */ + case INTEGER_CST: return TS_INT_CST; + case REAL_CST: return TS_REAL_CST; + case FIXED_CST: return TS_FIXED_CST; + case COMPLEX_CST: return TS_COMPLEX; + case VECTOR_CST: return TS_VECTOR; + case STRING_CST: return TS_STRING; + /* tcc_exceptional cases. */ + case ERROR_MARK: return TS_COMMON; + case IDENTIFIER_NODE: return TS_IDENTIFIER; + case TREE_LIST: return TS_LIST; + case TREE_VEC: return TS_VEC; + case SSA_NAME: return TS_SSA_NAME; + case PLACEHOLDER_EXPR: return TS_COMMON; + case STATEMENT_LIST: return TS_STATEMENT_LIST; + case BLOCK: return TS_BLOCK; + case CONSTRUCTOR: return TS_CONSTRUCTOR; + case TREE_BINFO: return TS_BINFO; + case OMP_CLAUSE: return TS_OMP_CLAUSE; + case OPTIMIZATION_NODE: return TS_OPTIMIZATION; + case TARGET_OPTION_NODE: return TS_TARGET_OPTION; + + default: + gcc_unreachable (); + } +} + + +/* Initialize tree_contains_struct to describe the hierarchy of tree + nodes. */ + +static void +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; + enum tree_node_structure_enum ts_code; + + code = (enum tree_code) i; + ts_code = tree_node_structure_for_code (code); + + /* Mark the TS structure itself. */ + tree_contains_struct[code][ts_code] = 1; + + /* Mark all the structures that TS is derived from. */ + switch (ts_code) + { + case TS_COMMON: + MARK_TS_BASE (code); + break; + + case TS_INT_CST: + case TS_REAL_CST: + case TS_FIXED_CST: + case TS_VECTOR: + case TS_STRING: + case TS_COMPLEX: + 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: + MARK_TS_COMMON (code); + break; + + case TS_DECL_COMMON: + MARK_TS_DECL_MINIMAL (code); + break; + + case TS_DECL_WRTL: + MARK_TS_DECL_COMMON (code); + break; + + case TS_DECL_NON_COMMON: + MARK_TS_DECL_WITH_VIS (code); + break; + + case TS_DECL_WITH_VIS: + case TS_PARM_DECL: + case TS_LABEL_DECL: + case TS_RESULT_DECL: + case TS_CONST_DECL: + MARK_TS_DECL_WRTL (code); + break; + + case TS_FIELD_DECL: + MARK_TS_DECL_COMMON (code); + break; + + case TS_VAR_DECL: + MARK_TS_DECL_WITH_VIS (code); + break; + + case TS_TYPE_DECL: + case TS_FUNCTION_DECL: + MARK_TS_DECL_NON_COMMON (code); + break; + + default: + gcc_unreachable (); + } + } + + /* 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]); + gcc_assert (tree_contains_struct[PARM_DECL][TS_DECL_COMMON]); + gcc_assert (tree_contains_struct[RESULT_DECL][TS_DECL_COMMON]); + gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_DECL_COMMON]); + gcc_assert (tree_contains_struct[TYPE_DECL][TS_DECL_COMMON]); + 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]); + gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_DECL_WRTL]); + gcc_assert (tree_contains_struct[LABEL_DECL][TS_DECL_WRTL]); + gcc_assert (tree_contains_struct[CONST_DECL][TS_DECL_MINIMAL]); + gcc_assert (tree_contains_struct[VAR_DECL][TS_DECL_MINIMAL]); + gcc_assert (tree_contains_struct[PARM_DECL][TS_DECL_MINIMAL]); + gcc_assert (tree_contains_struct[RESULT_DECL][TS_DECL_MINIMAL]); + gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_DECL_MINIMAL]); + gcc_assert (tree_contains_struct[TYPE_DECL][TS_DECL_MINIMAL]); + gcc_assert (tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_MINIMAL]); + gcc_assert (tree_contains_struct[LABEL_DECL][TS_DECL_MINIMAL]); + gcc_assert (tree_contains_struct[FIELD_DECL][TS_DECL_MINIMAL]); + 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]); + gcc_assert (tree_contains_struct[LABEL_DECL][TS_LABEL_DECL]); + gcc_assert (tree_contains_struct[RESULT_DECL][TS_RESULT_DECL]); + gcc_assert (tree_contains_struct[CONST_DECL][TS_CONST_DECL]); + gcc_assert (tree_contains_struct[TYPE_DECL][TS_TYPE_DECL]); + 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 +} + + /* Init tree.c. */ void @@ -274,7 +543,7 @@ init_ttree (void) int_cst_hash_table = htab_create_ggc (1024, int_cst_hash_hash, int_cst_hash_eq, NULL); - + int_cst_node = make_node (INTEGER_CST); cl_option_hash_table = htab_create_ggc (64, cl_option_hash_hash, @@ -283,55 +552,8 @@ init_ttree (void) cl_optimization_node = make_node (OPTIMIZATION_NODE); cl_target_option_node = make_node (TARGET_OPTION_NODE); - tree_contains_struct[FUNCTION_DECL][TS_DECL_NON_COMMON] = 1; - tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_NON_COMMON] = 1; - tree_contains_struct[TYPE_DECL][TS_DECL_NON_COMMON] = 1; - - - tree_contains_struct[CONST_DECL][TS_DECL_COMMON] = 1; - tree_contains_struct[VAR_DECL][TS_DECL_COMMON] = 1; - tree_contains_struct[PARM_DECL][TS_DECL_COMMON] = 1; - tree_contains_struct[RESULT_DECL][TS_DECL_COMMON] = 1; - tree_contains_struct[FUNCTION_DECL][TS_DECL_COMMON] = 1; - tree_contains_struct[TYPE_DECL][TS_DECL_COMMON] = 1; - tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_COMMON] = 1; - tree_contains_struct[LABEL_DECL][TS_DECL_COMMON] = 1; - tree_contains_struct[FIELD_DECL][TS_DECL_COMMON] = 1; - - - tree_contains_struct[CONST_DECL][TS_DECL_WRTL] = 1; - tree_contains_struct[VAR_DECL][TS_DECL_WRTL] = 1; - tree_contains_struct[PARM_DECL][TS_DECL_WRTL] = 1; - tree_contains_struct[RESULT_DECL][TS_DECL_WRTL] = 1; - tree_contains_struct[FUNCTION_DECL][TS_DECL_WRTL] = 1; - tree_contains_struct[LABEL_DECL][TS_DECL_WRTL] = 1; - - tree_contains_struct[CONST_DECL][TS_DECL_MINIMAL] = 1; - tree_contains_struct[VAR_DECL][TS_DECL_MINIMAL] = 1; - tree_contains_struct[PARM_DECL][TS_DECL_MINIMAL] = 1; - tree_contains_struct[RESULT_DECL][TS_DECL_MINIMAL] = 1; - tree_contains_struct[FUNCTION_DECL][TS_DECL_MINIMAL] = 1; - tree_contains_struct[TYPE_DECL][TS_DECL_MINIMAL] = 1; - tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_MINIMAL] = 1; - tree_contains_struct[LABEL_DECL][TS_DECL_MINIMAL] = 1; - tree_contains_struct[FIELD_DECL][TS_DECL_MINIMAL] = 1; - - tree_contains_struct[VAR_DECL][TS_DECL_WITH_VIS] = 1; - tree_contains_struct[FUNCTION_DECL][TS_DECL_WITH_VIS] = 1; - tree_contains_struct[TYPE_DECL][TS_DECL_WITH_VIS] = 1; - tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_WITH_VIS] = 1; - - tree_contains_struct[VAR_DECL][TS_VAR_DECL] = 1; - tree_contains_struct[FIELD_DECL][TS_FIELD_DECL] = 1; - tree_contains_struct[PARM_DECL][TS_PARM_DECL] = 1; - tree_contains_struct[LABEL_DECL][TS_LABEL_DECL] = 1; - tree_contains_struct[RESULT_DECL][TS_RESULT_DECL] = 1; - tree_contains_struct[CONST_DECL][TS_CONST_DECL] = 1; - tree_contains_struct[TYPE_DECL][TS_TYPE_DECL] = 1; - tree_contains_struct[FUNCTION_DECL][TS_FUNCTION_DECL] = 1; - tree_contains_struct[IMPORTED_DECL][TS_DECL_MINIMAL] = 1; - tree_contains_struct[IMPORTED_DECL][TS_DECL_COMMON] = 1; - + /* Initialize the tree_contains_struct array. */ + initialize_tree_contains_struct (); lang_hooks.init_ts (); } @@ -362,7 +584,7 @@ decl_assembler_name_equal (tree decl, const_tree asmname) decl_str = IDENTIFIER_POINTER (decl_asmname); asmname_str = IDENTIFIER_POINTER (asmname); - + /* If the target assembler name was set by the user, things are trickier. We have a leading '*' to begin with. After that, it's arguable what @@ -451,6 +673,8 @@ tree_code_size (enum tree_code code) return sizeof (struct tree_type_decl); case FUNCTION_DECL: return sizeof (struct tree_function_decl); + case DEBUG_EXPR_DECL: + return sizeof (struct tree_decl_with_rtl); default: return sizeof (struct tree_decl_non_common); } @@ -620,7 +844,7 @@ make_node_stat (enum tree_code code MEM_STAT_DECL) break; } break; - + default: gcc_unreachable (); } @@ -656,7 +880,13 @@ make_node_stat (enum tree_code code MEM_STAT_DECL) DECL_ALIGN (t) = 1; } DECL_SOURCE_LOCATION (t) = input_location; - DECL_UID (t) = next_decl_uid++; + if (TREE_CODE (t) == DEBUG_EXPR_DECL) + DECL_UID (t) = --next_debug_decl_uid; + else + { + DECL_UID (t) = next_decl_uid++; + SET_DECL_PT_UID (t, -1); + } if (TREE_CODE (t) == LABEL_DECL) LABEL_DECL_UID (t) = -1; @@ -728,11 +958,19 @@ copy_node_stat (tree node MEM_STAT_DECL) TREE_CHAIN (t) = 0; TREE_ASM_WRITTEN (t) = 0; TREE_VISITED (t) = 0; - t->base.ann = 0; + if (code == VAR_DECL || code == PARM_DECL || code == RESULT_DECL) + *DECL_VAR_ANN_PTR (t) = 0; if (TREE_CODE_CLASS (code) == tcc_declaration) { - DECL_UID (t) = next_decl_uid++; + if (code == DEBUG_EXPR_DECL) + DECL_UID (t) = --next_debug_decl_uid; + else + { + DECL_UID (t) = next_decl_uid++; + if (DECL_PT_UID_SET_P (node)) + SET_DECL_PT_UID (t, DECL_PT_UID (node)); + } if ((TREE_CODE (node) == PARM_DECL || TREE_CODE (node) == VAR_DECL) && DECL_HAS_VALUE_EXPR_P (node)) { @@ -755,7 +993,7 @@ copy_node_stat (tree node MEM_STAT_DECL) but the optimizer should catch that. */ TYPE_SYMTAB_POINTER (t) = 0; TYPE_SYMTAB_ADDRESS (t) = 0; - + /* Do not copy the values cache. */ if (TYPE_CACHED_VALUES_P(t)) { @@ -956,7 +1194,7 @@ build_int_cst_wide (tree type, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi) TREE_INT_CST_LOW (t) = low; TREE_INT_CST_HIGH (t) = hi; TREE_TYPE (t) = type; - + TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) = t; } } @@ -990,32 +1228,18 @@ build_int_cst_wide (tree type, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi) tree build_low_bits_mask (tree type, unsigned bits) { - unsigned HOST_WIDE_INT low; - HOST_WIDE_INT high; - unsigned HOST_WIDE_INT all_ones = ~(unsigned HOST_WIDE_INT) 0; + double_int mask; gcc_assert (bits <= TYPE_PRECISION (type)); if (bits == TYPE_PRECISION (type) && !TYPE_UNSIGNED (type)) - { - /* Sign extended all-ones mask. */ - low = all_ones; - high = -1; - } - else if (bits <= HOST_BITS_PER_WIDE_INT) - { - low = all_ones >> (HOST_BITS_PER_WIDE_INT - bits); - high = 0; - } + /* Sign extended all-ones mask. */ + mask = double_int_minus_one; else - { - bits -= HOST_BITS_PER_WIDE_INT; - low = all_ones; - high = all_ones >> (HOST_BITS_PER_WIDE_INT - bits); - } + mask = double_int_mask (bits); - return build_int_cst_wide (type, low, high); + return build_int_cst_wide (type, mask.low, mask.high); } /* Checks that X is integer constant that can be expressed in (unsigned) @@ -1225,7 +1449,7 @@ build_string (int len, const char *str) #ifdef GATHER_STATISTICS tree_node_counts[(int) c_kind]++; tree_node_sizes[(int) c_kind] += length; -#endif +#endif s = ggc_alloc_tree (length); @@ -1454,8 +1678,7 @@ integer_pow2p (const_tree expr) if (TREE_CODE (expr) != INTEGER_CST) return 0; - prec = (POINTER_TYPE_P (TREE_TYPE (expr)) - ? POINTER_SIZE : TYPE_PRECISION (TREE_TYPE (expr))); + prec = TYPE_PRECISION (TREE_TYPE (expr)); high = TREE_INT_CST_HIGH (expr); low = TREE_INT_CST_LOW (expr); @@ -1519,9 +1742,7 @@ tree_log2 (const_tree expr) if (TREE_CODE (expr) == COMPLEX_CST) return tree_log2 (TREE_REALPART (expr)); - prec = (POINTER_TYPE_P (TREE_TYPE (expr)) - ? POINTER_SIZE : TYPE_PRECISION (TREE_TYPE (expr))); - + prec = TYPE_PRECISION (TREE_TYPE (expr)); high = TREE_INT_CST_HIGH (expr); low = TREE_INT_CST_LOW (expr); @@ -1557,9 +1778,7 @@ tree_floor_log2 (const_tree expr) if (TREE_CODE (expr) == COMPLEX_CST) return tree_log2 (TREE_REALPART (expr)); - prec = (POINTER_TYPE_P (TREE_TYPE (expr)) - ? POINTER_SIZE : TYPE_PRECISION (TREE_TYPE (expr))); - + prec = TYPE_PRECISION (TREE_TYPE (expr)); high = TREE_INT_CST_HIGH (expr); low = TREE_INT_CST_LOW (expr); @@ -1689,6 +1908,17 @@ purpose_member (const_tree elem, tree list) return NULL_TREE; } +/* Returns element number IDX (zero-origin) of chain CHAIN, or + NULL_TREE. */ + +tree +chain_index (int idx, tree chain) +{ + for (; chain && idx > 0; --idx) + chain = TREE_CHAIN (chain); + return chain; +} + /* Return nonzero if ELEM is part of the chain CHAIN. */ int @@ -1746,6 +1976,18 @@ fields_length (const_tree type) return count; } +/* Returns the first FIELD_DECL in the TYPE_FIELDS of the RECORD_TYPE or + UNION_TYPE TYPE, or NULL_TREE if none. */ + +tree +first_field (const_tree type) +{ + tree t = TYPE_FIELDS (type); + while (t && TREE_CODE (t) != FIELD_DECL) + t = TREE_CHAIN (t); + return t; +} + /* Concatenate two chains of nodes (chained through TREE_CHAIN) by modifying the last node in chain 1 to point to chain 2. This is the Lisp primitive `nconc'. */ @@ -1787,18 +2029,6 @@ tree_last (tree chain) return chain; } -/* Return the node in a chain of nodes whose value is x, NULL if not found. */ - -tree -tree_find_value (tree chain, tree x) -{ - tree list; - for (list = chain; list; list = TREE_CHAIN (list)) - if (TREE_VALUE (list) == x) - return list; - return NULL; -} - /* Reverse the order of elements in the chain T, and return the new head of the chain (old last element). */ @@ -1985,6 +2215,18 @@ max_int_size_in_bytes (const_tree type) return size; } + +/* Returns a tree for the size of EXP in bytes. */ + +tree +tree_expr_size (const_tree exp) +{ + if (DECL_P (exp) + && DECL_SIZE_UNIT (exp) != 0) + return DECL_SIZE_UNIT (exp); + else + return size_in_bytes (TREE_TYPE (exp)); +} /* Return the bit position of FIELD, in bits from the start of the record. This is a tree of type bitsizetype. */ @@ -2399,79 +2641,14 @@ skip_simple_arithmetic (tree expr) return inner; } + /* Return which tree structure is used by T. */ enum tree_node_structure_enum tree_node_structure (const_tree t) { const enum tree_code code = TREE_CODE (t); - - switch (TREE_CODE_CLASS (code)) - { - case tcc_declaration: - { - switch (code) - { - case FIELD_DECL: - return TS_FIELD_DECL; - case PARM_DECL: - return TS_PARM_DECL; - case VAR_DECL: - return TS_VAR_DECL; - case LABEL_DECL: - return TS_LABEL_DECL; - case RESULT_DECL: - return TS_RESULT_DECL; - case CONST_DECL: - return TS_CONST_DECL; - case TYPE_DECL: - return TS_TYPE_DECL; - case FUNCTION_DECL: - return TS_FUNCTION_DECL; - default: - return TS_DECL_NON_COMMON; - } - } - case tcc_type: - return TS_TYPE; - case tcc_reference: - case tcc_comparison: - case tcc_unary: - case tcc_binary: - case tcc_expression: - case tcc_statement: - case tcc_vl_exp: - return TS_EXP; - default: /* tcc_constant and tcc_exceptional */ - break; - } - switch (code) - { - /* tcc_constant cases. */ - case INTEGER_CST: return TS_INT_CST; - case REAL_CST: return TS_REAL_CST; - case FIXED_CST: return TS_FIXED_CST; - case COMPLEX_CST: return TS_COMPLEX; - case VECTOR_CST: return TS_VECTOR; - case STRING_CST: return TS_STRING; - /* tcc_exceptional cases. */ - case ERROR_MARK: return TS_COMMON; - case IDENTIFIER_NODE: return TS_IDENTIFIER; - case TREE_LIST: return TS_LIST; - case TREE_VEC: return TS_VEC; - case SSA_NAME: return TS_SSA_NAME; - case PLACEHOLDER_EXPR: return TS_COMMON; - case STATEMENT_LIST: return TS_STATEMENT_LIST; - case BLOCK: return TS_BLOCK; - case CONSTRUCTOR: return TS_CONSTRUCTOR; - case TREE_BINFO: return TS_BINFO; - case OMP_CLAUSE: return TS_OMP_CLAUSE; - case OPTIMIZATION_NODE: return TS_OPTIMIZATION; - case TARGET_OPTION_NODE: return TS_TARGET_OPTION; - - default: - gcc_unreachable (); - } + return tree_node_structure_for_code (code); } /* Set various status flags when building a CALL_EXPR object T. */ @@ -3468,9 +3645,9 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL) side_effects = 1; \ if (!TREE_READONLY (arg##N) \ && !CONSTANT_CLASS_P (arg##N)) \ - read_only = 0; \ + (void) (read_only = 0); \ if (!TREE_CONSTANT (arg##N)) \ - constant = 0; \ + (void) (constant = 0); \ } \ } while (0) @@ -3640,10 +3817,14 @@ build6_stat (enum tree_code code, tree tt, tree arg0, tree arg1, PROCESS_ARG(2); PROCESS_ARG(3); PROCESS_ARG(4); + if (code == TARGET_MEM_REF) + side_effects = 0; PROCESS_ARG(5); TREE_SIDE_EFFECTS (t) = side_effects; - TREE_THIS_VOLATILE (t) = 0; + TREE_THIS_VOLATILE (t) + = (code == TARGET_MEM_REF + && arg5 && TREE_THIS_VOLATILE (arg5)); return t; } @@ -3777,9 +3958,9 @@ expanded_location expand_location (source_location loc) { expanded_location xloc; - if (loc == 0) + if (loc <= BUILTINS_LOCATION) { - xloc.file = NULL; + xloc.file = loc == UNKNOWN_LOCATION ? NULL : _(""); xloc.line = 0; xloc.column = 0; xloc.sysp = 0; @@ -3795,191 +3976,1038 @@ expand_location (source_location loc) return xloc; } - -/* Source location accessor functions. */ + +/* Like SET_EXPR_LOCATION, but make sure the tree can have a location. + + LOC is the location to use in tree T. */ + +void +protected_set_expr_location (tree t, location_t loc) +{ + if (t && CAN_HAVE_LOCATION_P (t)) + SET_EXPR_LOCATION (t, loc); +} + +/* Return a declaration like DDECL except that its DECL_ATTRIBUTES + is ATTRIBUTE. */ + +tree +build_decl_attribute_variant (tree ddecl, tree attribute) +{ + DECL_ATTRIBUTES (ddecl) = attribute; + return ddecl; +} + +/* Borrowed from hashtab.c iterative_hash implementation. */ +#define mix(a,b,c) \ +{ \ + a -= b; a -= c; a ^= (c>>13); \ + b -= c; b -= a; b ^= (a<< 8); \ + c -= a; c -= b; c ^= ((b&0xffffffff)>>13); \ + a -= b; a -= c; a ^= ((c&0xffffffff)>>12); \ + b -= c; b -= a; b = (b ^ (a<<16)) & 0xffffffff; \ + c -= a; c -= b; c = (c ^ (b>> 5)) & 0xffffffff; \ + a -= b; a -= c; a = (a ^ (c>> 3)) & 0xffffffff; \ + b -= c; b -= a; b = (b ^ (a<<10)) & 0xffffffff; \ + c -= a; c -= b; c = (c ^ (b>>15)) & 0xffffffff; \ +} + + +/* Produce good hash value combining VAL and VAL2. */ +hashval_t +iterative_hash_hashval_t (hashval_t val, hashval_t val2) +{ + /* the golden ratio; an arbitrary value. */ + hashval_t a = 0x9e3779b9; + + mix (a, val, val2); + return val2; +} + +/* Produce good hash value combining VAL and VAL2. */ +hashval_t +iterative_hash_host_wide_int (HOST_WIDE_INT val, hashval_t val2) +{ + if (sizeof (HOST_WIDE_INT) == sizeof (hashval_t)) + return iterative_hash_hashval_t (val, val2); + else + { + hashval_t a = (hashval_t) val; + /* Avoid warnings about shifting of more than the width of the type on + hosts that won't execute this path. */ + int zero = 0; + hashval_t b = (hashval_t) (val >> (sizeof (hashval_t) * 8 + zero)); + mix (a, b, val2); + if (sizeof (HOST_WIDE_INT) > 2 * sizeof (hashval_t)) + { + hashval_t a = (hashval_t) (val >> (sizeof (hashval_t) * 16 + zero)); + hashval_t b = (hashval_t) (val >> (sizeof (hashval_t) * 24 + zero)); + mix (a, b, val2); + } + return val2; + } +} + +/* Return a type like TTYPE except that its TYPE_ATTRIBUTE + is ATTRIBUTE and its qualifiers are QUALS. + + Record such modified types already made so we don't make duplicates. */ + +tree +build_type_attribute_qual_variant (tree ttype, tree attribute, int quals) +{ + if (! attribute_list_equal (TYPE_ATTRIBUTES (ttype), attribute)) + { + hashval_t hashcode = 0; + tree ntype; + enum tree_code code = TREE_CODE (ttype); + + /* Building a distinct copy of a tagged type is inappropriate; it + causes breakage in code that expects there to be a one-to-one + relationship between a struct and its fields. + build_duplicate_type is another solution (as used in + handle_transparent_union_attribute), but that doesn't play well + with the stronger C++ type identity model. */ + if (TREE_CODE (ttype) == RECORD_TYPE + || TREE_CODE (ttype) == UNION_TYPE + || TREE_CODE (ttype) == QUAL_UNION_TYPE + || TREE_CODE (ttype) == ENUMERAL_TYPE) + { + warning (OPT_Wattributes, + "ignoring attributes applied to %qT after definition", + TYPE_MAIN_VARIANT (ttype)); + return build_qualified_type (ttype, quals); + } + + ttype = build_qualified_type (ttype, TYPE_UNQUALIFIED); + ntype = build_distinct_type_copy (ttype); + + TYPE_ATTRIBUTES (ntype) = attribute; + + hashcode = iterative_hash_object (code, hashcode); + if (TREE_TYPE (ntype)) + hashcode = iterative_hash_object (TYPE_HASH (TREE_TYPE (ntype)), + hashcode); + hashcode = attribute_hash_list (attribute, hashcode); + + switch (TREE_CODE (ntype)) + { + case FUNCTION_TYPE: + hashcode = type_hash_list (TYPE_ARG_TYPES (ntype), hashcode); + break; + case ARRAY_TYPE: + if (TYPE_DOMAIN (ntype)) + hashcode = iterative_hash_object (TYPE_HASH (TYPE_DOMAIN (ntype)), + hashcode); + break; + case INTEGER_TYPE: + hashcode = iterative_hash_object + (TREE_INT_CST_LOW (TYPE_MAX_VALUE (ntype)), hashcode); + hashcode = iterative_hash_object + (TREE_INT_CST_HIGH (TYPE_MAX_VALUE (ntype)), hashcode); + break; + case REAL_TYPE: + case FIXED_POINT_TYPE: + { + unsigned int precision = TYPE_PRECISION (ntype); + hashcode = iterative_hash_object (precision, hashcode); + } + break; + default: + break; + } + + ntype = type_hash_canon (hashcode, ntype); + + /* If the target-dependent attributes make NTYPE different from + 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)) + SET_TYPE_STRUCTURAL_EQUALITY (ntype); + else if (TYPE_CANONICAL (ntype) == ntype) + TYPE_CANONICAL (ntype) = TYPE_CANONICAL (ttype); + + ttype = build_qualified_type (ntype, quals); + } + else if (TYPE_QUALS (ttype) != quals) + ttype = build_qualified_type (ttype, quals); + + return ttype; +} + + +/* Return a type like TTYPE except that its TYPE_ATTRIBUTE + is ATTRIBUTE. + + Record such modified types already made so we don't make duplicates. */ + +tree +build_type_attribute_variant (tree ttype, tree attribute) +{ + return build_type_attribute_qual_variant (ttype, attribute, + TYPE_QUALS (ttype)); +} + + +/* Reset all the fields in a binfo node BINFO. We only keep + BINFO_VIRTUALS, which is used by gimple_fold_obj_type_ref. */ + +static void +free_lang_data_in_binfo (tree binfo) +{ + unsigned i; + tree t; + + gcc_assert (TREE_CODE (binfo) == TREE_BINFO); + + BINFO_VTABLE (binfo) = NULL_TREE; + BINFO_BASE_ACCESSES (binfo) = NULL; + 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++) + free_lang_data_in_binfo (t); +} + + +/* Reset all language specific information still present in TYPE. */ + +static void +free_lang_data_in_type (tree type) +{ + gcc_assert (TYPE_P (type)); + + /* Give the FE a chance to remove its own data first. */ + lang_hooks.free_lang_data (type); + + TREE_LANG_FLAG_0 (type) = 0; + TREE_LANG_FLAG_1 (type) = 0; + TREE_LANG_FLAG_2 (type) = 0; + TREE_LANG_FLAG_3 (type) = 0; + TREE_LANG_FLAG_4 (type) = 0; + TREE_LANG_FLAG_5 (type) = 0; + TREE_LANG_FLAG_6 (type) = 0; + + if (TREE_CODE (type) == FUNCTION_TYPE) + { + /* Remove the const and volatile qualifiers from arguments. The + C++ front end removes them, but the C front end does not, + leading to false ODR violation errors when merging two + instances of the same function signature compiled by + different front ends. */ + tree p; + + for (p = TYPE_ARG_TYPES (type); p; p = TREE_CHAIN (p)) + { + tree arg_type = TREE_VALUE (p); + + if (TYPE_READONLY (arg_type) || TYPE_VOLATILE (arg_type)) + { + int quals = TYPE_QUALS (arg_type) + & ~TYPE_QUAL_CONST + & ~TYPE_QUAL_VOLATILE; + TREE_VALUE (p) = build_qualified_type (arg_type, quals); + free_lang_data_in_type (TREE_VALUE (p)); + } + } + } + + /* Remove members that are not actually FIELD_DECLs from the field + list of an aggregate. These occur in C++. */ + if (RECORD_OR_UNION_TYPE_P (type)) + { + tree prev, member; + + /* Note that TYPE_FIELDS can be shared across distinct + TREE_TYPEs. Therefore, if the first field of TYPE_FIELDS is + to be removed, we cannot set its TREE_CHAIN to NULL. + Otherwise, we would not be able to find all the other fields + in the other instances of this TREE_TYPE. + + This was causing an ICE in testsuite/g++.dg/lto/20080915.C. */ + prev = NULL_TREE; + member = TYPE_FIELDS (type); + while (member) + { + if (TREE_CODE (member) == FIELD_DECL) + { + if (prev) + TREE_CHAIN (prev) = member; + else + TYPE_FIELDS (type) = member; + prev = member; + } + + member = TREE_CHAIN (member); + } + + if (prev) + TREE_CHAIN (prev) = NULL_TREE; + else + TYPE_FIELDS (type) = NULL_TREE; + + TYPE_METHODS (type) = NULL_TREE; + if (TYPE_BINFO (type)) + free_lang_data_in_binfo (TYPE_BINFO (type)); + } + else + { + /* For non-aggregate types, clear out the language slot (which + overloads TYPE_BINFO). */ + TYPE_LANG_SLOT_1 (type) = NULL_TREE; + } + + if (debug_info_level < DINFO_LEVEL_TERSE + || (TYPE_CONTEXT (type) + && TREE_CODE (TYPE_CONTEXT (type)) != FUNCTION_DECL + && TREE_CODE (TYPE_CONTEXT (type)) != NAMESPACE_DECL)) + TYPE_CONTEXT (type) = NULL_TREE; + + if (debug_info_level < DINFO_LEVEL_TERSE) + TYPE_STUB_DECL (type) = NULL_TREE; +} + + +/* Return true if DECL may need an assembler name to be set. */ + +static inline bool +need_assembler_name_p (tree decl) +{ + /* Only FUNCTION_DECLs and VAR_DECLs are considered. */ + if (TREE_CODE (decl) != FUNCTION_DECL + && TREE_CODE (decl) != VAR_DECL) + return false; + + /* If DECL already has its assembler name set, it does not need a + new one. */ + if (!HAS_DECL_ASSEMBLER_NAME_P (decl) + || DECL_ASSEMBLER_NAME_SET_P (decl)) + return false; + + /* Abstract decls do not need an assembler name. */ + if (DECL_ABSTRACT (decl)) + return false; + + /* For VAR_DECLs, only static, public and external symbols need an + assembler name. */ + if (TREE_CODE (decl) == VAR_DECL + && !TREE_STATIC (decl) + && !TREE_PUBLIC (decl) + && !DECL_EXTERNAL (decl)) + return false; + + if (TREE_CODE (decl) == FUNCTION_DECL) + { + /* Do not set assembler name on builtins. Allow RTL expansion to + decide whether to expand inline or via a regular call. */ + if (DECL_BUILT_IN (decl) + && DECL_BUILT_IN_CLASS (decl) != BUILT_IN_FRONTEND) + return false; + + /* Functions represented in the callgraph need an assembler name. */ + if (cgraph_get_node (decl) != NULL) + return true; + + /* Unused and not public functions don't need an assembler name. */ + if (!TREE_USED (decl) && !TREE_PUBLIC (decl)) + return false; + } + + return true; +} + + +/* 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. */ + +static void +free_lang_data_in_decl (tree decl) +{ + gcc_assert (DECL_P (decl)); + + /* Give the FE a chance to remove its own data first. */ + lang_hooks.free_lang_data (decl); + + TREE_LANG_FLAG_0 (decl) = 0; + TREE_LANG_FLAG_1 (decl) = 0; + TREE_LANG_FLAG_2 (decl) = 0; + TREE_LANG_FLAG_3 (decl) = 0; + TREE_LANG_FLAG_4 (decl) = 0; + TREE_LANG_FLAG_5 (decl) = 0; + TREE_LANG_FLAG_6 (decl) = 0; + + /* Identifiers need not have a type. */ + 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; + } + } + + /* ??? We could free non-constant DECL_SIZE, DECL_SIZE_UNIT + and DECL_FIELD_OFFSET. But it's cheap enough to not do + that and refrain from adding workarounds to dwarf2out.c */ + + /* DECL_FCONTEXT is only used for debug info generation. */ + if (TREE_CODE (decl) == FIELD_DECL + && debug_info_level < DINFO_LEVEL_TERSE) + DECL_FCONTEXT (decl) = NULL_TREE; + + if (TREE_CODE (decl) == FUNCTION_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 + matter, as we will not be emitting any code for DECL. In + general, there may be other instances of DECL created by + the front end and since PARM_DECLs are generally shared, + their DECL_CONTEXT changes as the replicas of DECL are + created. The only time where DECL_CONTEXT is important + is for the FUNCTION_DECLs that have a gimple body (since + 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; + } + 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))) + 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; + } +} + + +/* Data used when collecting DECLs and TYPEs for language data removal. */ + +struct free_lang_data_d +{ + /* Worklist to avoid excessive recursion. */ + VEC(tree,heap) *worklist; + + /* Set of traversed objects. Used to avoid duplicate visits. */ + struct pointer_set_t *pset; + + /* Array of symbols to process with free_lang_data_in_decl. */ + VEC(tree,heap) *decls; + + /* Array of types to process with free_lang_data_in_type. */ + VEC(tree,heap) *types; +}; + + +/* Save all language fields needed to generate proper debug information + for DECL. This saves most fields cleared out by free_lang_data_in_decl. */ + +static void +save_debug_info_for_decl (tree t) +{ + /*struct saved_debug_info_d *sdi;*/ + + gcc_assert (debug_info_level > DINFO_LEVEL_TERSE && t && DECL_P (t)); + + /* FIXME. Partial implementation for saving debug info removed. */ +} + + +/* Save all language fields needed to generate proper debug information + for TYPE. This saves most fields cleared out by free_lang_data_in_type. */ + +static void +save_debug_info_for_type (tree t) +{ + /*struct saved_debug_info_d *sdi;*/ + + gcc_assert (debug_info_level > DINFO_LEVEL_TERSE && t && TYPE_P (t)); + + /* FIXME. Partial implementation for saving debug info removed. */ +} + + +/* Add type or decl T to one of the list of tree nodes that need their + language data removed. The lists are held inside FLD. */ + +static void +add_tree_to_fld_list (tree t, struct free_lang_data_d *fld) +{ + if (DECL_P (t)) + { + VEC_safe_push (tree, heap, fld->decls, t); + if (debug_info_level > DINFO_LEVEL_TERSE) + save_debug_info_for_decl (t); + } + else if (TYPE_P (t)) + { + VEC_safe_push (tree, heap, fld->types, t); + if (debug_info_level > DINFO_LEVEL_TERSE) + save_debug_info_for_type (t); + } + else + gcc_unreachable (); +} + +/* Push tree node T into FLD->WORKLIST. */ + +static inline void +fld_worklist_push (tree t, struct free_lang_data_d *fld) +{ + if (t && !is_lang_specific (t) && !pointer_set_contains (fld->pset, t)) + VEC_safe_push (tree, heap, fld->worklist, (t)); +} + + +/* Operand callback helper for free_lang_data_in_node. *TP is the + subtree operand being considered. */ + +static tree +find_decls_types_r (tree *tp, int *ws, void *data) +{ + tree t = *tp; + struct free_lang_data_d *fld = (struct free_lang_data_d *) data; + + if (TREE_CODE (t) == TREE_LIST) + return NULL_TREE; + + /* Language specific nodes will be removed, so there is no need + to gather anything under them. */ + if (is_lang_specific (t)) + { + *ws = 0; + return NULL_TREE; + } + + if (DECL_P (t)) + { + /* Note that walk_tree does not traverse every possible field in + decls, so we have to do our own traversals here. */ + add_tree_to_fld_list (t, fld); + + fld_worklist_push (DECL_NAME (t), fld); + fld_worklist_push (DECL_CONTEXT (t), fld); + fld_worklist_push (DECL_SIZE (t), fld); + fld_worklist_push (DECL_SIZE_UNIT (t), fld); + + /* We are going to remove everything under DECL_INITIAL for + TYPE_DECLs. No point walking them. */ + if (TREE_CODE (t) != TYPE_DECL) + fld_worklist_push (DECL_INITIAL (t), fld); + + fld_worklist_push (DECL_ATTRIBUTES (t), fld); + fld_worklist_push (DECL_ABSTRACT_ORIGIN (t), fld); + + if (TREE_CODE (t) == FUNCTION_DECL) + { + fld_worklist_push (DECL_ARGUMENTS (t), fld); + fld_worklist_push (DECL_RESULT (t), fld); + } + else if (TREE_CODE (t) == TYPE_DECL) + { + fld_worklist_push (DECL_ARGUMENT_FLD (t), fld); + fld_worklist_push (DECL_VINDEX (t), fld); + } + else if (TREE_CODE (t) == FIELD_DECL) + { + fld_worklist_push (DECL_FIELD_OFFSET (t), fld); + fld_worklist_push (DECL_BIT_FIELD_TYPE (t), fld); + fld_worklist_push (DECL_QUALIFIER (t), fld); + fld_worklist_push (DECL_FIELD_BIT_OFFSET (t), fld); + fld_worklist_push (DECL_FCONTEXT (t), fld); + } + else if (TREE_CODE (t) == VAR_DECL) + { + fld_worklist_push (DECL_SECTION_NAME (t), fld); + fld_worklist_push (DECL_COMDAT_GROUP (t), fld); + } + + if (TREE_CODE (t) != FIELD_DECL) + fld_worklist_push (TREE_CHAIN (t), fld); + *ws = 0; + } + else if (TYPE_P (t)) + { + /* Note that walk_tree does not traverse every possible field in + types, so we have to do our own traversals here. */ + add_tree_to_fld_list (t, fld); + + if (!RECORD_OR_UNION_TYPE_P (t)) + fld_worklist_push (TYPE_CACHED_VALUES (t), fld); + fld_worklist_push (TYPE_SIZE (t), fld); + fld_worklist_push (TYPE_SIZE_UNIT (t), fld); + fld_worklist_push (TYPE_ATTRIBUTES (t), fld); + 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); + 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); + fld_worklist_push (TYPE_CONTEXT (t), fld); + fld_worklist_push (TYPE_CANONICAL (t), fld); + + if (RECORD_OR_UNION_TYPE_P (t) && TYPE_BINFO (t)) + { + unsigned i; + tree tem; + for (i = 0; VEC_iterate (tree, BINFO_BASE_BINFOS (TYPE_BINFO (t)), + i, tem); ++i) + fld_worklist_push (TREE_TYPE (tem), fld); + tem = BINFO_VIRTUALS (TYPE_BINFO (t)); + if (tem + /* The Java FE overloads BINFO_VIRTUALS for its own purpose. */ + && TREE_CODE (tem) == TREE_LIST) + do + { + fld_worklist_push (TREE_VALUE (tem), fld); + tem = TREE_CHAIN (tem); + } + while (tem); + } + if (RECORD_OR_UNION_TYPE_P (t)) + { + tree tem; + /* Push all TYPE_FIELDS - there can be interleaving interesting + and non-interesting things. */ + tem = TYPE_FIELDS (t); + while (tem) + { + if (TREE_CODE (tem) == FIELD_DECL) + fld_worklist_push (tem, fld); + tem = TREE_CHAIN (tem); + } + } + + fld_worklist_push (TREE_CHAIN (t), fld); + *ws = 0; + } + + fld_worklist_push (TREE_TYPE (t), fld); + + return NULL_TREE; +} + + +/* Find decls and types in T. */ + +static void +find_decls_types (tree t, struct free_lang_data_d *fld) +{ + while (1) + { + if (!pointer_set_contains (fld->pset, t)) + walk_tree (&t, find_decls_types_r, fld, fld->pset); + if (VEC_empty (tree, fld->worklist)) + break; + t = VEC_pop (tree, fld->worklist); + } +} + +/* Translate all the types in LIST with the corresponding runtime + types. */ + +static tree +get_eh_types_for_runtime (tree list) +{ + tree head, prev; + + if (list == NULL_TREE) + return NULL_TREE; + + head = build_tree_list (0, lookup_type_for_runtime (TREE_VALUE (list))); + prev = head; + list = TREE_CHAIN (list); + while (list) + { + tree n = build_tree_list (0, lookup_type_for_runtime (TREE_VALUE (list))); + TREE_CHAIN (prev) = n; + prev = TREE_CHAIN (prev); + list = TREE_CHAIN (list); + } + + return head; +} + + +/* Find decls and types referenced in EH region R and store them in + FLD->DECLS and FLD->TYPES. */ + +static void +find_decls_types_in_eh_region (eh_region r, struct free_lang_data_d *fld) +{ + switch (r->type) + { + case ERT_CLEANUP: + break; + + case ERT_TRY: + { + eh_catch c; + + /* The types referenced in each catch must first be changed to the + EH types used at runtime. This removes references to FE types + in the region. */ + for (c = r->u.eh_try.first_catch; c ; c = c->next_catch) + { + c->type_list = get_eh_types_for_runtime (c->type_list); + walk_tree (&c->type_list, find_decls_types_r, fld, fld->pset); + } + } + break; + + case ERT_ALLOWED_EXCEPTIONS: + r->u.allowed.type_list + = get_eh_types_for_runtime (r->u.allowed.type_list); + walk_tree (&r->u.allowed.type_list, find_decls_types_r, fld, fld->pset); + break; + + case ERT_MUST_NOT_THROW: + walk_tree (&r->u.must_not_throw.failure_decl, + find_decls_types_r, fld, fld->pset); + break; + } +} + + +/* Find decls and types referenced in cgraph node N and store them in + FLD->DECLS and FLD->TYPES. Unlike pass_referenced_vars, this will + look for *every* kind of DECL and TYPE node reachable from N, + including those embedded inside types and decls (i.e,, TYPE_DECLs, + NAMESPACE_DECLs, etc). */ + +static void +find_decls_types_in_node (struct cgraph_node *n, struct free_lang_data_d *fld) +{ + basic_block bb; + struct function *fn; + tree t; + + find_decls_types (n->decl, fld); + + if (!gimple_has_body_p (n->decl)) + return; + + gcc_assert (current_function_decl == NULL_TREE && cfun == NULL); + + 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); + + /* Traverse EH regions in FN. */ + { + eh_region r; + FOR_ALL_EH_REGION_FN (r, fn) + find_decls_types_in_eh_region (r, fld); + } + + /* Traverse every statement in FN. */ + FOR_EACH_BB_FN (bb, fn) + { + gimple_stmt_iterator si; + unsigned i; + + for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si)) + { + gimple phi = gsi_stmt (si); + + for (i = 0; i < gimple_phi_num_args (phi); i++) + { + tree *arg_p = gimple_phi_arg_def_ptr (phi, i); + find_decls_types (*arg_p, fld); + } + } + + for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si)) + { + gimple stmt = gsi_stmt (si); + + for (i = 0; i < gimple_num_ops (stmt); i++) + { + tree arg = gimple_op (stmt, i); + find_decls_types (arg, fld); + } + } + } +} + +/* Find decls and types referenced in varpool node N and store them in + FLD->DECLS and FLD->TYPES. Unlike pass_referenced_vars, this will + look for *every* kind of DECL and TYPE node reachable from N, + including those embedded inside types and decls (i.e,, TYPE_DECLs, + NAMESPACE_DECLs, etc). */ -void -set_expr_locus (tree node, source_location *loc) +static void +find_decls_types_in_var (struct varpool_node *v, struct free_lang_data_d *fld) { - if (loc == NULL) - EXPR_CHECK (node)->exp.locus = UNKNOWN_LOCATION; - else - EXPR_CHECK (node)->exp.locus = *loc; + find_decls_types (v->decl, fld); } -/* Like SET_EXPR_LOCATION, but make sure the tree can have a location. - - LOC is the location to use in tree T. */ +/* If T needs an assembler name, have one created for it. */ void -protected_set_expr_location (tree t, location_t loc) +assign_assembler_name_if_neeeded (tree t) { - if (t && CAN_HAVE_LOCATION_P (t)) - SET_EXPR_LOCATION (t, loc); -} - -/* Return a declaration like DDECL except that its DECL_ATTRIBUTES - is ATTRIBUTE. */ + if (need_assembler_name_p (t)) + { + /* When setting DECL_ASSEMBLER_NAME, the C++ mangler may emit + diagnostics that use input_location to show locus + information. The problem here is that, at this point, + input_location is generally anchored to the end of the file + (since the parser is long gone), so we don't have a good + position to pin it to. -tree -build_decl_attribute_variant (tree ddecl, tree attribute) -{ - DECL_ATTRIBUTES (ddecl) = attribute; - return ddecl; -} + To alleviate this problem, this uses the location of T's + declaration. Examples of this are + testsuite/g++.dg/template/cond2.C and + testsuite/g++.dg/template/pr35240.C. */ + location_t saved_location = input_location; + input_location = DECL_SOURCE_LOCATION (t); -/* Borrowed from hashtab.c iterative_hash implementation. */ -#define mix(a,b,c) \ -{ \ - a -= b; a -= c; a ^= (c>>13); \ - b -= c; b -= a; b ^= (a<< 8); \ - c -= a; c -= b; c ^= ((b&0xffffffff)>>13); \ - a -= b; a -= c; a ^= ((c&0xffffffff)>>12); \ - b -= c; b -= a; b = (b ^ (a<<16)) & 0xffffffff; \ - c -= a; c -= b; c = (c ^ (b>> 5)) & 0xffffffff; \ - a -= b; a -= c; a = (a ^ (c>> 3)) & 0xffffffff; \ - b -= c; b -= a; b = (b ^ (a<<10)) & 0xffffffff; \ - c -= a; c -= b; c = (c ^ (b>>15)) & 0xffffffff; \ + decl_assembler_name (t); + + input_location = saved_location; + } } -/* Produce good hash value combining VAL and VAL2. */ -hashval_t -iterative_hash_hashval_t (hashval_t val, hashval_t val2) -{ - /* the golden ratio; an arbitrary value. */ - hashval_t a = 0x9e3779b9; +/* Free language specific information for every operand and expression + in every node of the call graph. This process operates in three stages: - mix (a, val, val2); - return val2; -} + 1- Every callgraph node and varpool node is traversed looking for + decls and types embedded in them. This is a more exhaustive + search than that done by find_referenced_vars, because it will + also collect individual fields, decls embedded in types, etc. -/* Produce good hash value combining VAL and VAL2. */ -static inline hashval_t -iterative_hash_host_wide_int (HOST_WIDE_INT val, hashval_t val2) -{ - if (sizeof (HOST_WIDE_INT) == sizeof (hashval_t)) - return iterative_hash_hashval_t (val, val2); - else - { - hashval_t a = (hashval_t) val; - /* Avoid warnings about shifting of more than the width of the type on - hosts that won't execute this path. */ - int zero = 0; - hashval_t b = (hashval_t) (val >> (sizeof (hashval_t) * 8 + zero)); - mix (a, b, val2); - if (sizeof (HOST_WIDE_INT) > 2 * sizeof (hashval_t)) - { - hashval_t a = (hashval_t) (val >> (sizeof (hashval_t) * 16 + zero)); - hashval_t b = (hashval_t) (val >> (sizeof (hashval_t) * 24 + zero)); - mix (a, b, val2); - } - return val2; - } -} + 2- All the decls found are sent to free_lang_data_in_decl. -/* Return a type like TTYPE except that its TYPE_ATTRIBUTE - is ATTRIBUTE and its qualifiers are QUALS. + 3- All the types found are sent to free_lang_data_in_type. - Record such modified types already made so we don't make duplicates. */ + The ordering between decls and types is important because + free_lang_data_in_decl sets assembler names, which includes + mangling. So types cannot be freed up until assembler names have + been set up. */ -static tree -build_type_attribute_qual_variant (tree ttype, tree attribute, int quals) +static void +free_lang_data_in_cgraph (void) { - if (! attribute_list_equal (TYPE_ATTRIBUTES (ttype), attribute)) - { - hashval_t hashcode = 0; - tree ntype; - enum tree_code code = TREE_CODE (ttype); - - /* Building a distinct copy of a tagged type is inappropriate; it - causes breakage in code that expects there to be a one-to-one - relationship between a struct and its fields. - build_duplicate_type is another solution (as used in - handle_transparent_union_attribute), but that doesn't play well - with the stronger C++ type identity model. */ - if (TREE_CODE (ttype) == RECORD_TYPE - || TREE_CODE (ttype) == UNION_TYPE - || TREE_CODE (ttype) == QUAL_UNION_TYPE - || TREE_CODE (ttype) == ENUMERAL_TYPE) - { - warning (OPT_Wattributes, - "ignoring attributes applied to %qT after definition", - TYPE_MAIN_VARIANT (ttype)); - return build_qualified_type (ttype, quals); - } + struct cgraph_node *n; + struct varpool_node *v; + struct free_lang_data_d fld; + tree t; + unsigned i; + alias_pair *p; - ttype = build_qualified_type (ttype, TYPE_UNQUALIFIED); - ntype = build_distinct_type_copy (ttype); + /* Initialize sets and arrays to store referenced decls and types. */ + fld.pset = pointer_set_create (); + fld.worklist = NULL; + fld.decls = VEC_alloc (tree, heap, 100); + fld.types = VEC_alloc (tree, heap, 100); - TYPE_ATTRIBUTES (ntype) = attribute; + /* Find decls and types in the body of every function in the callgraph. */ + for (n = cgraph_nodes; n; n = n->next) + find_decls_types_in_node (n, &fld); - hashcode = iterative_hash_object (code, hashcode); - if (TREE_TYPE (ntype)) - hashcode = iterative_hash_object (TYPE_HASH (TREE_TYPE (ntype)), - hashcode); - hashcode = attribute_hash_list (attribute, hashcode); + for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p); i++) + find_decls_types (p->decl, &fld); - switch (TREE_CODE (ntype)) - { - case FUNCTION_TYPE: - hashcode = type_hash_list (TYPE_ARG_TYPES (ntype), hashcode); - break; - case ARRAY_TYPE: - if (TYPE_DOMAIN (ntype)) - hashcode = iterative_hash_object (TYPE_HASH (TYPE_DOMAIN (ntype)), - hashcode); - break; - case INTEGER_TYPE: - hashcode = iterative_hash_object - (TREE_INT_CST_LOW (TYPE_MAX_VALUE (ntype)), hashcode); - hashcode = iterative_hash_object - (TREE_INT_CST_HIGH (TYPE_MAX_VALUE (ntype)), hashcode); - break; - case REAL_TYPE: - case FIXED_POINT_TYPE: - { - unsigned int precision = TYPE_PRECISION (ntype); - hashcode = iterative_hash_object (precision, hashcode); - } - break; - default: - break; - } + /* Find decls and types in every varpool symbol. */ + for (v = varpool_nodes_queue; v; v = v->next_needed) + find_decls_types_in_var (v, &fld); - ntype = type_hash_canon (hashcode, ntype); + /* 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++) + assign_assembler_name_if_neeeded (t); - /* If the target-dependent attributes make NTYPE different from - 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)) - SET_TYPE_STRUCTURAL_EQUALITY (ntype); - else if (TYPE_CANONICAL (ntype) == ntype) - TYPE_CANONICAL (ntype) = TYPE_CANONICAL (ttype); + /* Traverse every decl found freeing its language data. */ + for (i = 0; VEC_iterate (tree, fld.decls, i, t); i++) + free_lang_data_in_decl (t); - ttype = build_qualified_type (ntype, quals); - } - else if (TYPE_QUALS (ttype) != quals) - ttype = build_qualified_type (ttype, quals); + /* Traverse every type found freeing its language data. */ + for (i = 0; VEC_iterate (tree, fld.types, i, t); i++) + free_lang_data_in_type (t); - return ttype; + pointer_set_destroy (fld.pset); + VEC_free (tree, heap, fld.worklist); + VEC_free (tree, heap, fld.decls); + VEC_free (tree, heap, fld.types); } -/* Return a type like TTYPE except that its TYPE_ATTRIBUTE - is ATTRIBUTE. - - Record such modified types already made so we don't make duplicates. */ +/* Free resources that are used by FE but are not needed once they are done. */ -tree -build_type_attribute_variant (tree ttype, tree attribute) +static unsigned +free_lang_data (void) { - return build_type_attribute_qual_variant (ttype, attribute, - TYPE_QUALS (ttype)); + unsigned i; + + /* If we are the LTO frontend we have freed lang-specific data already. */ + if (in_lto_p + || !flag_generate_lto) + return 0; + + /* Allocate and assign alias sets to the standard integer types + while the slots are still in the way the frontends generated them. */ + for (i = 0; i < itk_none; ++i) + if (integer_types[i]) + TYPE_ALIAS_SET (integer_types[i]) = get_alias_set (integer_types[i]); + + /* Traverse the IL resetting language specific information for + operands, expressions, etc. */ + free_lang_data_in_cgraph (); + + /* Create gimple variants for common types. */ + ptrdiff_type_node = integer_type_node; + fileptr_type_node = ptr_type_node; + if (TREE_CODE (boolean_type_node) != BOOLEAN_TYPE + || (TYPE_MODE (boolean_type_node) + != mode_for_size (BOOL_TYPE_SIZE, MODE_INT, 0)) + || TYPE_PRECISION (boolean_type_node) != 1 + || !TYPE_UNSIGNED (boolean_type_node)) + { + boolean_type_node = make_unsigned_type (BOOL_TYPE_SIZE); + TREE_SET_CODE (boolean_type_node, BOOLEAN_TYPE); + TYPE_MAX_VALUE (boolean_type_node) = build_int_cst (boolean_type_node, 1); + TYPE_PRECISION (boolean_type_node) = 1; + boolean_false_node = TYPE_MIN_VALUE (boolean_type_node); + boolean_true_node = TYPE_MAX_VALUE (boolean_type_node); + } + + /* Unify char_type_node with its properly signed variant. */ + if (TYPE_UNSIGNED (char_type_node)) + unsigned_char_type_node = char_type_node; + else + signed_char_type_node = char_type_node; + + /* Reset some langhooks. Do not reset types_compatible_p, it may + still be used indirectly via the get_alias_set langhook. */ + 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; + lang_hooks.fold_obj_type_ref = gimple_fold_obj_type_ref; + + /* Reset diagnostic machinery. */ + diagnostic_starter (global_dc) = default_diagnostic_starter; + diagnostic_finalizer (global_dc) = default_diagnostic_finalizer; + diagnostic_format_decoder (global_dc) = default_tree_printer; + + return 0; } + +struct simple_ipa_opt_pass pass_ipa_free_lang_data = +{ + { + SIMPLE_IPA_PASS, + "*free_lang_data", /* name */ + NULL, /* gate */ + free_lang_data, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_IPA_FREE_LANG_DATA, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_ggc_collect /* todo_flags_finish */ + } +}; + /* Return nonzero if IDENT is a valid name for attribute ATTR, or zero if not. @@ -3996,10 +5024,10 @@ is_attribute_with_length_p (const char *attr, int attr_len, const_tree ident) if (TREE_CODE (ident) != IDENTIFIER_NODE) return 0; - + p = IDENTIFIER_POINTER (ident); ident_len = IDENTIFIER_LENGTH (ident); - + if (ident_len == attr_len && strcmp (attr, p) == 0) return 1; @@ -4181,12 +5209,12 @@ merge_dllimport_decl_attributes (tree old, tree new_tree) marked dllimport and a definition appears later, then the object is not dllimport'd. We also remove a `new' dllimport if the old list contains dllexport: dllexport always overrides dllimport, regardless - of the order of declaration. */ + of the order of declaration. */ if (!VAR_OR_FUNCTION_DECL_P (new_tree)) delete_dllimport_p = 0; else if (DECL_DLLIMPORT_P (new_tree) && lookup_attribute ("dllexport", DECL_ATTRIBUTES (old))) - { + { DECL_DLLIMPORT_P (new_tree) = 0; warning (OPT_Wattributes, "%q+D already declared with dllexport attribute: " "dllimport ignored", new_tree); @@ -4212,7 +5240,7 @@ merge_dllimport_decl_attributes (tree old, tree new_tree) } /* Let an inline definition silently override the external reference, - but otherwise warn about attribute inconsistency. */ + but otherwise warn about attribute inconsistency. */ else if (TREE_CODE (new_tree) == VAR_DECL || !DECL_DECLARED_INLINE_P (new_tree)) warning (OPT_Wattributes, "%q+D redeclared without dllimport attribute: " @@ -4223,11 +5251,11 @@ merge_dllimport_decl_attributes (tree old, tree new_tree) a = merge_attributes (DECL_ATTRIBUTES (old), DECL_ATTRIBUTES (new_tree)); - if (delete_dllimport_p) + if (delete_dllimport_p) { tree prev, t; - const size_t attr_len = strlen ("dllimport"); - + const size_t attr_len = strlen ("dllimport"); + /* Scan the list for dllimport and delete it. */ for (prev = NULL_TREE, t = a; t; prev = t, t = TREE_CHAIN (t)) { @@ -4308,7 +5336,7 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags, any damage. */ if (is_dllimport) { - /* Honor any target-specific overrides. */ + /* Honor any target-specific overrides. */ if (!targetm.valid_dllimport_attribute_p (node)) *no_add_attrs = true; @@ -4316,7 +5344,7 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags, && DECL_DECLARED_INLINE_P (node)) { warning (OPT_Wattributes, "inline function %q+D declared as " - " dllimport: attribute ignored", node); + " dllimport: attribute ignored", node); *no_add_attrs = true; } /* Like MS, treat definition of dllimported variables and @@ -4373,7 +5401,7 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags, if (DECL_VISIBILITY_SPECIFIED (node) && DECL_VISIBILITY (node) != VISIBILITY_DEFAULT) error ("%qE implies default visibility, but %qD has already " - "been declared with a different visibility", + "been declared with a different visibility", name, node); DECL_VISIBILITY (node) = VISIBILITY_DEFAULT; DECL_VISIBILITY_SPECIFIED (node) = 1; @@ -4393,6 +5421,7 @@ set_type_quals (tree type, int type_quals) TYPE_READONLY (type) = (type_quals & TYPE_QUAL_CONST) != 0; TYPE_VOLATILE (type) = (type_quals & TYPE_QUAL_VOLATILE) != 0; TYPE_RESTRICT (type) = (type_quals & TYPE_QUAL_RESTRICT) != 0; + TYPE_ADDR_SPACE (type) = DECODE_QUAL_ADDR_SPACE (type_quals); } /* Returns true iff CAND is equivalent to BASE with TYPE_QUALS. */ @@ -4458,7 +5487,7 @@ build_qualified_type (tree type, int type_quals) else /* T is its own canonical type. */ TYPE_CANONICAL (t) = t; - + } return t; @@ -4473,7 +5502,7 @@ tree build_distinct_type_copy (tree type) { tree t = copy_node (type); - + TYPE_POINTER_TO (t) = 0; TYPE_REFERENCE_TO (t) = 0; @@ -4511,7 +5540,7 @@ build_variant_type_copy (tree type) /* Since we're building a variant, assume that it is a non-semantic variant. This also propagates TYPE_STRUCTURAL_EQUALITY_P. */ TYPE_CANONICAL (t) = TYPE_CANONICAL (type); - + /* Add the new type to the chain of variants of TYPE. */ TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m); TYPE_NEXT_VARIANT (m) = t; @@ -4618,7 +5647,7 @@ decl_init_priority_insert (tree decl, priority_type priority) gcc_assert (VAR_OR_FUNCTION_DECL_P (decl)); h = decl_priority_info (decl); h->init = priority; -} +} /* Set the finalization priority for DECL to PRIORITY. */ @@ -4630,7 +5659,7 @@ decl_fini_priority_insert (tree decl, priority_type priority) gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); h = decl_priority_info (decl); h->fini = priority; -} +} /* Print out the statistics for the DECL_DEBUG_EXPR hash table. */ @@ -4656,7 +5685,7 @@ print_value_expr_statistics (void) /* Lookup a debug expression for FROM, and return it if we find one. */ -tree +tree decl_debug_expr_lookup (tree from) { struct tree_map *h, in; @@ -4683,11 +5712,11 @@ decl_debug_expr_insert (tree from, tree to) h->to = to; loc = htab_find_slot_with_hash (debug_expr_for_decl, h, h->hash, INSERT); *(struct tree_map **) loc = h; -} +} /* Lookup a value expression for FROM, and return it if we find one. */ -tree +tree decl_value_expr_lookup (tree from) { struct tree_map *h, in; @@ -4754,7 +5783,7 @@ type_hash_eq (const void *va, const void *vb) 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 + || (TREE_CODE (a->type) != COMPLEX_TYPE && TYPE_NAME (a->type) != TYPE_NAME (b->type))) return 0; @@ -5148,6 +6177,9 @@ tree_int_cst_compare (const_tree t1, const_tree t2) int host_integerp (const_tree t, int pos) { + if (t == NULL_TREE) + return 0; + return (TREE_CODE (t) == INTEGER_CST && ((TREE_INT_CST_HIGH (t) == 0 && (HOST_WIDE_INT) TREE_INT_CST_LOW (t) >= 0) @@ -5581,7 +6613,7 @@ iterative_hash_expr (const_tree t, hashval_t val) else { gcc_assert (IS_EXPR_CODE_CLASS (tclass)); - + val = iterative_hash_object (code, val); /* Don't hash the type, that can lead to having nodes which @@ -5711,7 +6743,10 @@ build_pointer_type_for_mode (tree to_type, enum machine_mode mode, tree build_pointer_type (tree to_type) { - return build_pointer_type_for_mode (to_type, ptr_mode, false); + addr_space_t as = to_type == error_mark_node? ADDR_SPACE_GENERIC + : TYPE_ADDR_SPACE (to_type); + enum machine_mode pointer_mode = targetm.addr_space.pointer_mode (as); + return build_pointer_type_for_mode (to_type, pointer_mode, false); } /* Same as build_pointer_type_for_mode, but for REFERENCE_TYPE. */ @@ -5759,7 +6794,7 @@ build_reference_type_for_mode (tree to_type, enum machine_mode mode, if (TYPE_STRUCTURAL_EQUALITY_P (to_type)) SET_TYPE_STRUCTURAL_EQUALITY (t); else if (TYPE_CANONICAL (to_type) != to_type) - TYPE_CANONICAL (t) + TYPE_CANONICAL (t) = build_reference_type_for_mode (TYPE_CANONICAL (to_type), mode, can_alias_all); @@ -5775,7 +6810,10 @@ build_reference_type_for_mode (tree to_type, enum machine_mode mode, tree build_reference_type (tree to_type) { - return build_reference_type_for_mode (to_type, ptr_mode, false); + addr_space_t as = to_type == error_mark_node? ADDR_SPACE_GENERIC + : TYPE_ADDR_SPACE (to_type); + enum machine_mode pointer_mode = targetm.addr_space.pointer_mode (as); + return build_reference_type_for_mode (to_type, pointer_mode, false); } /* Build a type that is compatible with t but has no cv quals anywhere @@ -5837,6 +6875,10 @@ build_index_type (tree maxval) } } +#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]; + /* Builds a signed or unsigned integer type of precision PRECISION. Used for C bitfields whose precision does not match that of built-in target types. */ @@ -5844,8 +6886,19 @@ tree build_nonstandard_integer_type (unsigned HOST_WIDE_INT precision, int unsignedp) { - tree itype = make_node (INTEGER_TYPE); + tree itype, ret; + + if (unsignedp) + unsignedp = MAX_INT_CACHED_PREC + 1; + + if (precision <= MAX_INT_CACHED_PREC) + { + itype = nonstandard_integer_type_cache[precision + unsignedp]; + if (itype) + return itype; + } + itype = make_node (INTEGER_TYPE); TYPE_PRECISION (itype) = precision; if (unsignedp) @@ -5853,10 +6906,13 @@ build_nonstandard_integer_type (unsigned HOST_WIDE_INT precision, else fixup_signed_type (itype); + ret = itype; if (host_integerp (TYPE_MAX_VALUE (itype), 1)) - return type_hash_canon (tree_low_cst (TYPE_MAX_VALUE (itype), 1), itype); + ret = type_hash_canon (tree_low_cst (TYPE_MAX_VALUE (itype), 1), itype); + if (precision <= MAX_INT_CACHED_PREC && lang_hooks.types.hash_types) + nonstandard_integer_type_cache[precision + unsignedp] = ret; - return itype; + return ret; } /* Create a range of some discrete type TYPE (an INTEGER_TYPE, @@ -5969,44 +7025,30 @@ build_array_type (tree elt_type, tree index_type) t = make_node (ARRAY_TYPE); TREE_TYPE (t) = elt_type; TYPE_DOMAIN (t) = index_type; - - if (index_type == 0) - { - tree save = t; - hashcode = iterative_hash_object (TYPE_HASH (elt_type), hashcode); - t = type_hash_canon (hashcode, t); - if (save == t) - layout_type (t); - - if (TYPE_CANONICAL (t) == t) - { - if (TYPE_STRUCTURAL_EQUALITY_P (elt_type)) - SET_TYPE_STRUCTURAL_EQUALITY (t); - else if (TYPE_CANONICAL (elt_type) != elt_type) - TYPE_CANONICAL (t) - = build_array_type (TYPE_CANONICAL (elt_type), index_type); - } + TYPE_ADDR_SPACE (t) = TYPE_ADDR_SPACE (elt_type); + layout_type (t); - return t; - } + /* If the element type is incomplete at this point we get marked for + structural equality. Do not record these types in the canonical + type hashtable. */ + if (TYPE_STRUCTURAL_EQUALITY_P (t)) + return t; hashcode = iterative_hash_object (TYPE_HASH (elt_type), hashcode); - hashcode = iterative_hash_object (TYPE_HASH (index_type), hashcode); + if (index_type) + hashcode = iterative_hash_object (TYPE_HASH (index_type), hashcode); t = type_hash_canon (hashcode, t); - if (!COMPLETE_TYPE_P (t)) - layout_type (t); - if (TYPE_CANONICAL (t) == t) { if (TYPE_STRUCTURAL_EQUALITY_P (elt_type) - || TYPE_STRUCTURAL_EQUALITY_P (index_type)) + || (index_type && TYPE_STRUCTURAL_EQUALITY_P (index_type))) SET_TYPE_STRUCTURAL_EQUALITY (t); else if (TYPE_CANONICAL (elt_type) != elt_type - || TYPE_CANONICAL (index_type) != index_type) - TYPE_CANONICAL (t) + || (index_type && TYPE_CANONICAL (index_type) != index_type)) + TYPE_CANONICAL (t) = build_array_type (TYPE_CANONICAL (elt_type), - TYPE_CANONICAL (index_type)); + index_type ? TYPE_CANONICAL (index_type) : NULL); } return t; @@ -6025,7 +7067,7 @@ strip_array_types (tree type) } /* Computes the canonical argument types from the argument type list - ARGTYPES. + ARGTYPES. Upon return, *ANY_STRUCTURAL_P will be true iff either it was true on entry to this function, or if any of the ARGTYPES are @@ -6039,14 +7081,14 @@ strip_array_types (tree type) canonical argument list is unneeded (i.e., *ANY_STRUCTURAL_P is true) or would not differ from ARGTYPES. */ -static tree -maybe_canonicalize_argtypes(tree argtypes, +static tree +maybe_canonicalize_argtypes(tree argtypes, bool *any_structural_p, bool *any_noncanonical_p) { tree arg; bool any_noncanonical_argtypes_p = false; - + for (arg = argtypes; arg && !(*any_structural_p); arg = TREE_CHAIN (arg)) { if (!TREE_VALUE (arg) || TREE_VALUE (arg) == error_mark_node) @@ -6130,7 +7172,7 @@ build_function_type (tree value_type, tree arg_types) /* Set up the canonical type. */ any_structural_p = TYPE_STRUCTURAL_EQUALITY_P (value_type); any_noncanonical_p = TYPE_CANONICAL (value_type) != value_type; - canon_argtypes = maybe_canonicalize_argtypes (arg_types, + canon_argtypes = maybe_canonicalize_argtypes (arg_types, &any_structural_p, &any_noncanonical_p); if (any_structural_p) @@ -6138,7 +7180,7 @@ build_function_type (tree value_type, tree arg_types) else if (any_noncanonical_p) TYPE_CANONICAL (t) = build_function_type (TYPE_CANONICAL (value_type), canon_argtypes); - + if (!COMPLETE_TYPE_P (t)) layout_type (t); return t; @@ -6167,7 +7209,6 @@ build_function_type_skip_args (tree orig_type, bitmap args_to_skip) else new_reversed = void_list_node; } - gcc_assert (new_reversed); /* Use copy_node to preserve as much as possible from original type (debug info, attribute lists etc.) @@ -6205,8 +7246,8 @@ build_function_type_skip_args (tree orig_type, bitmap args_to_skip) return new_type; } -/* Build variant of function type ORIG_TYPE skipping ARGS_TO_SKIP. - +/* Build variant of function type ORIG_TYPE skipping ARGS_TO_SKIP. + Arguments from DECL_ARGUMENTS list can't be removed now, since they are linked by TREE_CHAIN directly. It is caller responsibility to eliminate them when they are being duplicated (i.e. copy_arguments_for_versioning). */ @@ -6344,7 +7385,7 @@ build_method_type_directly (tree basetype, if (any_structural_p) SET_TYPE_STRUCTURAL_EQUALITY (t); else if (any_noncanonical_p) - TYPE_CANONICAL (t) + TYPE_CANONICAL (t) = build_method_type_directly (TYPE_CANONICAL (basetype), TYPE_CANONICAL (rettype), canon_argtypes); @@ -6400,7 +7441,7 @@ build_offset_type (tree basetype, tree type) SET_TYPE_STRUCTURAL_EQUALITY (t); else if (TYPE_CANONICAL (TYPE_MAIN_VARIANT (basetype)) != basetype || TYPE_CANONICAL (type) != type) - TYPE_CANONICAL (t) + TYPE_CANONICAL (t) = build_offset_type (TYPE_CANONICAL (TYPE_MAIN_VARIANT (basetype)), TYPE_CANONICAL (type)); } @@ -6437,7 +7478,7 @@ build_complex_type (tree component_type) if (TYPE_STRUCTURAL_EQUALITY_P (component_type)) SET_TYPE_STRUCTURAL_EQUALITY (t); else if (TYPE_CANONICAL (component_type) != component_type) - TYPE_CANONICAL (t) + TYPE_CANONICAL (t) = build_complex_type (TYPE_CANONICAL (component_type)); } @@ -6611,6 +7652,14 @@ get_unwidened (tree op, tree for_type) } } + /* If we finally reach a constant see if it fits in for_type and + in that case convert it. */ + if (for_type + && TREE_CODE (win) == INTEGER_CST + && TREE_TYPE (win) != for_type + && int_fits_type_p (win, for_type)) + win = fold_convert (for_type, win); + return win; } @@ -6866,7 +7915,7 @@ get_type_static_bounds (const_tree type, mpz_t min, mpz_t max) } } - if (!POINTER_TYPE_P (type) && TYPE_MAX_VALUE (type) + if (!POINTER_TYPE_P (type) && TYPE_MAX_VALUE (type) && TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST) mpz_set_double_int (max, tree_to_double_int (TYPE_MAX_VALUE (type)), TYPE_UNSIGNED (type)); @@ -7315,7 +8364,7 @@ tree_check_failed (const_tree node, const char *file, while ((code = va_arg (args, int))) { const char *prefix = length ? " or " : "expected "; - + strcpy (tmp + length, prefix); length += strlen (prefix); strcpy (tmp + length, tree_code_name[code]); @@ -7492,9 +8541,9 @@ static const char *ts_enum_names[] = { whether CODE contains the tree structure identified by EN. */ void -tree_contains_struct_check_failed (const_tree node, +tree_contains_struct_check_failed (const_tree node, const enum tree_node_structure_enum en, - const char *file, int line, + const char *file, int line, const char *function) { internal_error @@ -7555,27 +8604,16 @@ make_vector_type (tree innertype, int nunits, enum machine_mode mode) tree t; hashval_t hashcode = 0; - /* Build a main variant, based on the main variant of the inner type, then - use it to build the variant we return. */ - if ((TYPE_ATTRIBUTES (innertype) || TYPE_QUALS (innertype)) - && TYPE_MAIN_VARIANT (innertype) != innertype) - return build_type_attribute_qual_variant ( - make_vector_type (TYPE_MAIN_VARIANT (innertype), nunits, mode), - TYPE_ATTRIBUTES (innertype), - TYPE_QUALS (innertype)); - t = make_node (VECTOR_TYPE); TREE_TYPE (t) = TYPE_MAIN_VARIANT (innertype); SET_TYPE_VECTOR_SUBPARTS (t, nunits); SET_TYPE_MODE (t, mode); - TYPE_READONLY (t) = TYPE_READONLY (innertype); - TYPE_VOLATILE (t) = TYPE_VOLATILE (innertype); if (TYPE_STRUCTURAL_EQUALITY_P (innertype)) SET_TYPE_STRUCTURAL_EQUALITY (t); else if (TYPE_CANONICAL (innertype) != innertype || mode != VOIDmode) - TYPE_CANONICAL (t) + TYPE_CANONICAL (t) = make_vector_type (TYPE_CANONICAL (innertype), nunits, VOIDmode); layout_type (t); @@ -7599,9 +8637,20 @@ make_vector_type (tree innertype, int nunits, enum machine_mode mode) } 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); - hashcode = iterative_hash_object (TYPE_HASH (innertype), hashcode); - return type_hash_canon (hashcode, t); + hashcode = iterative_hash_object (TYPE_HASH (TREE_TYPE (t)), hashcode); + t = type_hash_canon (hashcode, t); + + /* We have built a main variant, based on the main variant of the + inner type. Use it to build the variant we return. */ + if ((TYPE_ATTRIBUTES (innertype) || TYPE_QUALS (innertype)) + && TREE_TYPE (t) != innertype) + return build_type_attribute_qual_variant (t, + TYPE_ATTRIBUTES (innertype), + TYPE_QUALS (innertype)); + + return t; } static tree @@ -7704,12 +8753,12 @@ make_or_reuse_accum_type (unsigned size, int unsignedp, int satp) this function to select one of the types as sizetype. */ void -build_common_tree_nodes (bool signed_char, bool signed_sizetype) +build_common_tree_nodes (bool signed_char) { error_mark_node = make_node (ERROR_MARK); TREE_TYPE (error_mark_node) = error_mark_node; - initialize_sizetypes (signed_sizetype); + initialize_sizetypes (); /* Define both `signed char' and `unsigned char'. */ signed_char_type_node = make_signed_type (CHAR_TYPE_SIZE); @@ -7824,7 +8873,7 @@ build_common_tree_nodes_2 (int short_double) /* Decimal float types. */ dfloat32_type_node = make_node (REAL_TYPE); - TYPE_PRECISION (dfloat32_type_node) = DECIMAL32_TYPE_SIZE; + TYPE_PRECISION (dfloat32_type_node) = DECIMAL32_TYPE_SIZE; layout_type (dfloat32_type_node); SET_TYPE_MODE (dfloat32_type_node, SDmode); dfloat32_ptr_type_node = build_pointer_type (dfloat32_type_node); @@ -7836,7 +8885,7 @@ build_common_tree_nodes_2 (int short_double) dfloat64_ptr_type_node = build_pointer_type (dfloat64_type_node); dfloat128_type_node = make_node (REAL_TYPE); - TYPE_PRECISION (dfloat128_type_node) = DECIMAL128_TYPE_SIZE; + TYPE_PRECISION (dfloat128_type_node) = DECIMAL128_TYPE_SIZE; layout_type (dfloat128_type_node); SET_TYPE_MODE (dfloat128_type_node, TDmode); dfloat128_ptr_type_node = build_pointer_type (dfloat128_type_node); @@ -7909,7 +8958,7 @@ build_common_tree_nodes_2 (int short_double) declare the type to be __builtin_va_list. */ if (TREE_CODE (t) != RECORD_TYPE) t = build_variant_type_copy (t); - + va_list_type_node = t; } } @@ -7948,7 +8997,7 @@ local_define_builtin (const char *name, tree type, enum built_in_function code, void build_common_builtin_nodes (void) { - tree tmp, ftype; + tree tmp, tmp2, ftype; if (built_in_decls[BUILT_IN_MEMCPY] == NULL || built_in_decls[BUILT_IN_MEMMOVE] == NULL) @@ -7991,7 +9040,8 @@ build_common_builtin_nodes (void) tmp = tree_cons (NULL_TREE, size_type_node, void_list_node); ftype = build_function_type (ptr_type_node, tmp); local_define_builtin ("__builtin_alloca", ftype, BUILT_IN_ALLOCA, - "alloca", ECF_NOTHROW | ECF_MALLOC); + "alloca", + ECF_MALLOC | (flag_stack_check ? 0 : ECF_NOTHROW)); } tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node); @@ -8053,9 +9103,50 @@ build_common_builtin_nodes (void) 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) + { + ftype = build_function_type (void_type_node, void_list_node); + local_define_builtin ("__builtin_cxa_end_cleanup", ftype, + BUILT_IN_CXA_END_CLEANUP, + "__cxa_end_cleanup", ECF_NORETURN); + } + + tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node); + ftype = build_function_type (void_type_node, tmp); + local_define_builtin ("__builtin_unwind_resume", ftype, + BUILT_IN_UNWIND_RESUME, + (USING_SJLJ_EXCEPTIONS + ? "_Unwind_SjLj_Resume" : "_Unwind_Resume"), + ECF_NORETURN); + + /* The exception object and filter values from the runtime. The argument + must be zero before exception lowering, i.e. from the front end. After + exception lowering, it will be the region number for the exception + 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); + local_define_builtin ("__builtin_eh_pointer", ftype, BUILT_IN_EH_POINTER, + "__builtin_eh_pointer", ECF_PURE | ECF_NOTHROW); + + tmp2 = lang_hooks.types.type_for_mode (targetm.eh_return_filter_mode (), 0); + ftype = build_function_type (tmp2, tmp); + local_define_builtin ("__builtin_eh_filter", ftype, BUILT_IN_EH_FILTER, + "__builtin_eh_filter", ECF_PURE | ECF_NOTHROW); + + 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); + local_define_builtin ("__builtin_eh_copy_values", ftype, + BUILT_IN_EH_COPY_VALUES, + "__builtin_eh_copy_values", ECF_NOTHROW); + /* Complex multiplication and division. These are handled as builtins rather than optabs because emit_library_call_value doesn't support - complex. Further, we can do slightly better with folding these + complex. Further, we can do slightly better with folding these beasties if the real and complex parts of the arguments are separate. */ { int mode; @@ -8112,7 +9203,7 @@ tree reconstruct_complex_type (tree type, tree bottom) { tree inner, outer; - + if (TREE_CODE (type) == POINTER_TYPE) { inner = reconstruct_complex_type (TREE_TYPE (type), bottom); @@ -8140,8 +9231,8 @@ reconstruct_complex_type (tree type, tree bottom) inner = reconstruct_complex_type (TREE_TYPE (type), bottom); /* The build_method_type_directly() routine prepends 'this' to argument list, so we must compensate by getting rid of it. */ - outer - = build_method_type_directly + outer + = build_method_type_directly (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (type))), inner, TREE_CHAIN (TYPE_ARG_TYPES (type))); @@ -8154,7 +9245,8 @@ reconstruct_complex_type (tree type, tree bottom) else return bottom; - return build_qualified_type (outer, TYPE_QUALS (type)); + return build_type_attribute_qual_variant (outer, TYPE_ATTRIBUTES (type), + TYPE_QUALS (type)); } /* Returns a vector tree node given a mode (integer, vector, or BLKmode) and @@ -8214,16 +9306,6 @@ build_opaque_vector_type (tree innertype, int nunits) } -/* Build RESX_EXPR with given REGION_NUMBER. */ -tree -build_resx (int region_number) -{ - tree t; - t = build1 (RESX_EXPR, void_type_node, - build_int_cst (NULL_TREE, region_number)); - return t; -} - /* Given an initializer INIT, return TRUE if INIT is zero or some aggregate of zeros. Otherwise return FALSE. */ bool @@ -8308,7 +9390,7 @@ build_omp_clause (location_t loc, enum omp_clause_code code) tree_node_counts[(int) omp_clause_kind]++; tree_node_sizes[(int) omp_clause_kind] += size; #endif - + return t; } @@ -8405,7 +9487,8 @@ build_call_valist (tree return_type, tree fn, int nargs, va_list args) which are specified as a tree array ARGS. */ tree -build_call_array (tree return_type, tree fn, int nargs, const tree *args) +build_call_array_loc (location_t loc, tree return_type, tree fn, + int nargs, const tree *args) { tree t; int i; @@ -8417,6 +9500,7 @@ build_call_array (tree return_type, tree fn, int nargs, const tree *args) for (i = 0; i < nargs; i++) CALL_EXPR_ARG (t, i) = args[i]; process_call_operands (t); + SET_EXPR_LOCATION (t, loc); return t; } @@ -8622,11 +9706,19 @@ signed_or_unsigned_type_for (int unsignedp, tree type) { tree t = type; if (POINTER_TYPE_P (type)) - t = size_type_node; + { + /* If the pointer points to the normal address space, use the + size_type_node. Otherwise use an appropriate size for the pointer + based on the named address space it points to. */ + if (!TYPE_ADDR_SPACE (TREE_TYPE (t))) + t = size_type_node; + else + return lang_hooks.types.type_for_size (TYPE_PRECISION (t), unsignedp); + } if (!INTEGRAL_TYPE_P (t) || TYPE_UNSIGNED (t) == unsignedp) return t; - + return lang_hooks.types.type_for_size (TYPE_PRECISION (t), unsignedp); } @@ -8772,7 +9864,7 @@ operand_equal_for_phi_arg_p (const_tree arg0, const_tree arg1) } /* Returns number of zeros at the end of binary representation of X. - + ??? Use ffs if available? */ tree @@ -9110,7 +10202,7 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, that are directly gimplified in gimplify_type_sizes in order for the mark/copy-if-shared/unmark machinery of the gimplifier to work with variable-sized types. - + Note that DECLs get walked as part of processing the BIND_EXPR. */ if (TREE_CODE (DECL_EXPR_DECL (*tp)) == TYPE_DECL) { @@ -9130,9 +10222,7 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, return result; /* If this is a record type, also walk the fields. */ - if (TREE_CODE (*type_p) == RECORD_TYPE - || TREE_CODE (*type_p) == UNION_TYPE - || TREE_CODE (*type_p) == QUAL_UNION_TYPE) + if (RECORD_OR_UNION_TYPE_P (*type_p)) { tree field; @@ -9572,6 +10662,9 @@ tree_nop_conversion (const_tree exp) outer_type = TREE_TYPE (exp); inner_type = TREE_TYPE (TREE_OPERAND (exp, 0)); + if (!inner_type) + return false; + /* Use precision rather then machine mode when we can, which gives the correct answer even for submode (bit-field) types. */ if ((INTEGRAL_TYPE_P (outer_type) @@ -9627,5 +10720,20 @@ tree_strip_sign_nop_conversions (tree exp) return exp; } +static GTY(()) tree gcc_eh_personality_decl; + +/* Return the GCC personality function decl. */ + +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"); + + return gcc_eh_personality_decl; +} #include "gt-tree.h"