X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ftree.c;h=48b4c655faa4fef79d8fe386c84784aa31d7d2eb;hb=2934c6b590ded021f96a83dbb8b1100acedde68c;hp=c19e3cc43f5a96318c8e0489c9b95a88c1f999bb;hpb=67ce556b47830dd825524e8370969b814c355216;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/tree.c b/gcc/tree.c index c19e3cc43f5..48b4c655faa 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -1,6 +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 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. This file is part of GCC. @@ -93,9 +94,11 @@ static const char * const tree_node_kind_names[] = { "binfos", "phi_nodes", "ssa names", + "constructors", "random kinds", "lang_decl kinds", - "lang_type kinds" + "lang_type kinds", + "omp clauses" }; #endif /* GATHER_STATISTICS */ @@ -133,12 +136,6 @@ static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node))) /* General tree->tree mapping structure for use in hash tables. */ -struct tree_map GTY(()) -{ - hashval_t hash; - tree from; - tree to; -}; static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map))) htab_t debug_expr_for_decl; @@ -146,11 +143,23 @@ 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_int_map_marked_p"), param_is (struct tree_int_map))) + htab_t init_priority_for_decl; + +static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map))) + htab_t restrict_base_for_decl; + +struct tree_int_map GTY(()) +{ + tree from; + unsigned short to; +}; +static unsigned int tree_int_map_hash (const void *); +static int tree_int_map_eq (const void *, const void *); +static int tree_int_map_marked_p (const void *); static void set_type_quals (tree, int); static int type_hash_eq (const void *, const void *); static hashval_t type_hash_hash (const void *); -static int tree_map_eq (const void *, const void *); -static hashval_t tree_map_hash (const void *); static hashval_t int_cst_hash_hash (const void *); static int int_cst_hash_eq (const void *, const void *); static void print_type_hash_statistics (void); @@ -158,13 +167,50 @@ static void print_debug_expr_statistics (void); static void print_value_expr_statistics (void); static tree make_vector_type (tree, int, enum machine_mode); static int type_hash_marked_p (const void *); -static int tree_map_marked_p (const void *); static unsigned int type_hash_list (tree, hashval_t); static unsigned int attribute_hash_list (tree, hashval_t); tree global_trees[TI_MAX]; tree integer_types[itk_none]; +unsigned char tree_contains_struct[256][64]; + +/* Number of operands for each OpenMP clause. */ +unsigned const char omp_clause_num_ops[] = +{ + 0, /* OMP_CLAUSE_ERROR */ + 1, /* OMP_CLAUSE_PRIVATE */ + 1, /* OMP_CLAUSE_SHARED */ + 1, /* OMP_CLAUSE_FIRSTPRIVATE */ + 1, /* OMP_CLAUSE_LASTPRIVATE */ + 4, /* OMP_CLAUSE_REDUCTION */ + 1, /* OMP_CLAUSE_COPYIN */ + 1, /* OMP_CLAUSE_COPYPRIVATE */ + 1, /* OMP_CLAUSE_IF */ + 1, /* OMP_CLAUSE_NUM_THREADS */ + 1, /* OMP_CLAUSE_SCHEDULE */ + 0, /* OMP_CLAUSE_NOWAIT */ + 0, /* OMP_CLAUSE_ORDERED */ + 0 /* OMP_CLAUSE_DEFAULT */ +}; + +const char * const omp_clause_code_name[] = +{ + "error_clause", + "private", + "shared", + "firstprivate", + "lastprivate", + "reduction", + "copyin", + "copyprivate", + "if", + "num_threads", + "schedule", + "nowait", + "ordered", + "default" +}; /* Init tree.c. */ @@ -180,12 +226,73 @@ init_ttree (void) value_expr_for_decl = htab_create_ggc (512, tree_map_hash, tree_map_eq, 0); + init_priority_for_decl = htab_create_ggc (512, tree_int_map_hash, + tree_int_map_eq, 0); + restrict_base_for_decl = htab_create_ggc (256, tree_map_hash, + tree_map_eq, 0); int_cst_hash_table = htab_create_ggc (1024, int_cst_hash_hash, int_cst_hash_eq, NULL); int_cst_node = make_node (INTEGER_CST); + 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[STRUCT_FIELD_TAG][TS_DECL_MINIMAL] = 1; + tree_contains_struct[NAME_MEMORY_TAG][TS_DECL_MINIMAL] = 1; + tree_contains_struct[SYMBOL_MEMORY_TAG][TS_DECL_MINIMAL] = 1; + + tree_contains_struct[STRUCT_FIELD_TAG][TS_MEMORY_TAG] = 1; + tree_contains_struct[NAME_MEMORY_TAG][TS_MEMORY_TAG] = 1; + tree_contains_struct[SYMBOL_MEMORY_TAG][TS_MEMORY_TAG] = 1; + + tree_contains_struct[STRUCT_FIELD_TAG][TS_STRUCT_FIELD_TAG] = 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; + + lang_hooks.init_ts (); } @@ -197,7 +304,7 @@ decl_assembler_name (tree decl) { if (!DECL_ASSEMBLER_NAME_SET_P (decl)) lang_hooks.set_decl_assembler_name (decl); - return DECL_CHECK (decl)->decl.assembler_name; + return DECL_WITH_VIS_CHECK (decl)->decl_with_vis.assembler_name; } /* Compute the number of bytes occupied by a tree with code CODE. @@ -209,7 +316,34 @@ tree_code_size (enum tree_code code) switch (TREE_CODE_CLASS (code)) { case tcc_declaration: /* A decl node */ - return sizeof (struct tree_decl); + { + switch (code) + { + case FIELD_DECL: + return sizeof (struct tree_field_decl); + case PARM_DECL: + return sizeof (struct tree_parm_decl); + case VAR_DECL: + return sizeof (struct tree_var_decl); + case LABEL_DECL: + return sizeof (struct tree_label_decl); + case RESULT_DECL: + return sizeof (struct tree_result_decl); + case CONST_DECL: + return sizeof (struct tree_const_decl); + case TYPE_DECL: + return sizeof (struct tree_type_decl); + case FUNCTION_DECL: + return sizeof (struct tree_function_decl); + case NAME_MEMORY_TAG: + case SYMBOL_MEMORY_TAG: + return sizeof (struct tree_memory_tag); + case STRUCT_FIELD_TAG: + return sizeof (struct tree_struct_field_tag); + default: + return sizeof (struct tree_decl_non_common); + } + } case tcc_type: /* a type node */ return sizeof (struct tree_type); @@ -245,6 +379,7 @@ tree_code_size (enum tree_code code) case PLACEHOLDER_EXPR: return sizeof (struct tree_common); case TREE_VEC: + case OMP_CLAUSE: case PHI_NODE: gcc_unreachable (); case SSA_NAME: return sizeof (struct tree_ssa_name); @@ -252,6 +387,7 @@ tree_code_size (enum tree_code code) case STATEMENT_LIST: return sizeof (struct tree_statement_list); case BLOCK: return sizeof (struct tree_block); case VALUE_HANDLE: return sizeof (struct tree_value_handle); + case CONSTRUCTOR: return sizeof (struct tree_constructor); default: return lang_hooks.tree_size (code); @@ -285,6 +421,11 @@ tree_size (tree node) case STRING_CST: return sizeof (struct tree_string) + TREE_STRING_LENGTH (node) - 1; + case OMP_CLAUSE: + return (sizeof (struct tree_omp_clause) + + (omp_clause_num_ops[OMP_CLAUSE_CODE (node)] - 1) + * sizeof (tree)); + default: return tree_code_size (code); } @@ -292,8 +433,9 @@ tree_size (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 PHI_NODE or - TREE_VEC nodes, which is enforced by asserts in tree_code_size. + initialized to zero. This function cannot be used for PHI_NODE, + TREE_VEC or OMP_CLAUSE nodes, which is enforced by asserts in + tree_code_size. Achoo! I got a code in the node. */ @@ -342,7 +484,7 @@ make_node_stat (enum tree_code code MEM_STAT_DECL) kind = id_kind; break; - case TREE_VEC:; + case TREE_VEC: kind = vec_kind; break; @@ -362,6 +504,10 @@ make_node_stat (enum tree_code code MEM_STAT_DECL) kind = b_kind; break; + case CONSTRUCTOR: + kind = constr_kind; + break; + default: kind = x_kind; break; @@ -392,20 +538,24 @@ make_node_stat (enum tree_code code MEM_STAT_DECL) break; case tcc_declaration: - if (code != FUNCTION_DECL) - DECL_ALIGN (t) = 1; - DECL_USER_ALIGN (t) = 0; - DECL_IN_SYSTEM_HEADER (t) = in_system_header; + if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS)) + DECL_IN_SYSTEM_HEADER (t) = in_system_header; + if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON)) + { + if (code != FUNCTION_DECL) + DECL_ALIGN (t) = 1; + DECL_USER_ALIGN (t) = 0; + /* We have not yet computed the alias set for this declaration. */ + DECL_POINTER_ALIAS_SET (t) = -1; + } DECL_SOURCE_LOCATION (t) = input_location; DECL_UID (t) = next_decl_uid++; - /* We have not yet computed the alias set for this declaration. */ - DECL_POINTER_ALIAS_SET (t) = -1; break; case tcc_type: TYPE_UID (t) = next_type_uid++; - TYPE_ALIGN (t) = char_type_node ? TYPE_ALIGN (char_type_node) : 0; + TYPE_ALIGN (t) = BITS_PER_UNIT; TYPE_USER_ALIGN (t) = 0; TYPE_MAIN_VARIANT (t) = t; @@ -480,7 +630,16 @@ copy_node_stat (tree node MEM_STAT_DECL) SET_DECL_VALUE_EXPR (t, DECL_VALUE_EXPR (node)); DECL_HAS_VALUE_EXPR_P (t) = 1; } - + if (TREE_CODE (node) == VAR_DECL && DECL_HAS_INIT_PRIORITY_P (node)) + { + SET_DECL_INIT_PRIORITY (t, DECL_INIT_PRIORITY (node)); + DECL_HAS_INIT_PRIORITY_P (t) = 1; + } + if (TREE_CODE (node) == VAR_DECL && DECL_BASED_ON_RESTRICT_P (node)) + { + SET_DECL_RESTRICT_BASE (t, DECL_GET_RESTRICT_BASE (node)); + DECL_BASED_ON_RESTRICT_P (t) = 1; + } } else if (TREE_CODE_CLASS (code) == tcc_type) { @@ -668,7 +827,6 @@ build_int_cst_wide (tree type, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi) break; case INTEGER_TYPE: - case CHAR_TYPE: case OFFSET_TYPE: if (TYPE_UNSIGNED (type)) { @@ -795,7 +953,7 @@ cst_and_fits_in_hwi (tree x) } /* Return a new VECTOR_CST node whose type is TYPE and whose values - are in a list pointed by VALS. */ + are in a list pointed to by VALS. */ tree build_vector (tree type, tree vals) @@ -822,27 +980,72 @@ build_vector (tree type, tree vals) return v; } +/* Return a new VECTOR_CST node whose type is TYPE and whose values + are extracted from V, a vector of CONSTRUCTOR_ELT. */ + +tree +build_vector_from_ctor (tree type, VEC(constructor_elt,gc) *v) +{ + tree list = NULL_TREE; + unsigned HOST_WIDE_INT idx; + tree value; + + FOR_EACH_CONSTRUCTOR_VALUE (v, idx, value) + list = tree_cons (NULL_TREE, value, list); + return build_vector (type, nreverse (list)); +} + /* Return a new CONSTRUCTOR node whose type is TYPE and whose values - are in a list pointed to by VALS. */ + are in the VEC pointed to by VALS. */ tree -build_constructor (tree type, tree vals) +build_constructor (tree type, VEC(constructor_elt,gc) *vals) { tree c = make_node (CONSTRUCTOR); TREE_TYPE (c) = type; CONSTRUCTOR_ELTS (c) = vals; + return c; +} + +/* Build a CONSTRUCTOR node made of a single initializer, with the specified + INDEX and VALUE. */ +tree +build_constructor_single (tree type, tree index, tree value) +{ + VEC(constructor_elt,gc) *v; + constructor_elt *elt; + + v = VEC_alloc (constructor_elt, gc, 1); + elt = VEC_quick_push (constructor_elt, v, NULL); + elt->index = index; + elt->value = value; + + return build_constructor (type, v); +} + + +/* Return a new CONSTRUCTOR node whose type is TYPE and whose values + are in a list pointed to by VALS. */ +tree +build_constructor_from_list (tree type, tree vals) +{ + tree t; + VEC(constructor_elt,gc) *v = NULL; - /* ??? May not be necessary. Mirrors what build does. */ if (vals) { - TREE_SIDE_EFFECTS (c) = TREE_SIDE_EFFECTS (vals); - TREE_READONLY (c) = TREE_READONLY (vals); - TREE_CONSTANT (c) = TREE_CONSTANT (vals); - TREE_INVARIANT (c) = TREE_INVARIANT (vals); + v = VEC_alloc (constructor_elt, gc, list_length (vals)); + for (t = vals; t; t = TREE_CHAIN (t)) + { + constructor_elt *elt = VEC_quick_push (constructor_elt, v, NULL); + elt->index = TREE_PURPOSE (t); + elt->value = TREE_VALUE (t); + } } - return c; + return build_constructor (type, v); } + /* Return a new REAL_CST node whose type is TYPE and value is D. */ tree @@ -920,6 +1123,8 @@ build_string (int len, const char *str) memset (s, 0, sizeof (struct tree_common)); TREE_SET_CODE (s, STRING_CST); + TREE_CONSTANT (s) = 1; + TREE_INVARIANT (s) = 1; TREE_STRING_LENGTH (s) = len; memcpy ((char *) TREE_STRING_POINTER (s), str, len); ((char *) TREE_STRING_POINTER (s))[len] = '\0'; @@ -1004,7 +1209,6 @@ integer_zerop (tree expr) STRIP_NOPS (expr); return ((TREE_CODE (expr) == INTEGER_CST - && ! TREE_CONSTANT_OVERFLOW (expr) && TREE_INT_CST_LOW (expr) == 0 && TREE_INT_CST_HIGH (expr) == 0) || (TREE_CODE (expr) == COMPLEX_CST @@ -1021,7 +1225,6 @@ integer_onep (tree expr) STRIP_NOPS (expr); return ((TREE_CODE (expr) == INTEGER_CST - && ! TREE_CONSTANT_OVERFLOW (expr) && TREE_INT_CST_LOW (expr) == 1 && TREE_INT_CST_HIGH (expr) == 0) || (TREE_CODE (expr) == COMPLEX_CST @@ -1045,14 +1248,15 @@ integer_all_onesp (tree expr) && integer_zerop (TREE_IMAGPART (expr))) return 1; - else if (TREE_CODE (expr) != INTEGER_CST - || TREE_CONSTANT_OVERFLOW (expr)) + else if (TREE_CODE (expr) != INTEGER_CST) return 0; uns = TYPE_UNSIGNED (TREE_TYPE (expr)); + if (TREE_INT_CST_LOW (expr) == ~(unsigned HOST_WIDE_INT) 0 + && TREE_INT_CST_HIGH (expr) == -1) + return 1; if (!uns) - return (TREE_INT_CST_LOW (expr) == ~(unsigned HOST_WIDE_INT) 0 - && TREE_INT_CST_HIGH (expr) == -1); + return 0; /* Note that using TYPE_PRECISION here is wrong. We care about the actual bits, not the (arbitrary) range of the type. */ @@ -1096,7 +1300,7 @@ integer_pow2p (tree expr) && integer_zerop (TREE_IMAGPART (expr))) return 1; - if (TREE_CODE (expr) != INTEGER_CST || TREE_CONSTANT_OVERFLOW (expr)) + if (TREE_CODE (expr) != INTEGER_CST) return 0; prec = (POINTER_TYPE_P (TREE_TYPE (expr)) @@ -1134,7 +1338,6 @@ integer_nonzerop (tree expr) STRIP_NOPS (expr); return ((TREE_CODE (expr) == INTEGER_CST - && ! TREE_CONSTANT_OVERFLOW (expr) && (TREE_INT_CST_LOW (expr) != 0 || TREE_INT_CST_HIGH (expr) != 0)) || (TREE_CODE (expr) == COMPLEX_CST @@ -1227,7 +1430,6 @@ real_zerop (tree expr) STRIP_NOPS (expr); return ((TREE_CODE (expr) == REAL_CST - && ! TREE_CONSTANT_OVERFLOW (expr) && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst0)) || (TREE_CODE (expr) == COMPLEX_CST && real_zerop (TREE_REALPART (expr)) @@ -1242,7 +1444,6 @@ real_onep (tree expr) STRIP_NOPS (expr); return ((TREE_CODE (expr) == REAL_CST - && ! TREE_CONSTANT_OVERFLOW (expr) && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst1)) || (TREE_CODE (expr) == COMPLEX_CST && real_onep (TREE_REALPART (expr)) @@ -1257,7 +1458,6 @@ real_twop (tree expr) STRIP_NOPS (expr); return ((TREE_CODE (expr) == REAL_CST - && ! TREE_CONSTANT_OVERFLOW (expr) && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst2)) || (TREE_CODE (expr) == COMPLEX_CST && real_twop (TREE_REALPART (expr)) @@ -1272,7 +1472,6 @@ real_minus_onep (tree expr) STRIP_NOPS (expr); return ((TREE_CODE (expr) == REAL_CST - && ! TREE_CONSTANT_OVERFLOW (expr) && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconstm1)) || (TREE_CODE (expr) == COMPLEX_CST && real_minus_onep (TREE_REALPART (expr)) @@ -1518,7 +1717,6 @@ int_size_in_bytes (tree type) t = TYPE_SIZE_UNIT (type); if (t == 0 || TREE_CODE (t) != INTEGER_CST - || TREE_OVERFLOW (t) || TREE_INT_CST_HIGH (t) != 0 /* If the result would appear negative, it's too big to represent. */ || (HOST_WIDE_INT) TREE_INT_CST_LOW (t) < 0) @@ -1632,7 +1830,7 @@ array_type_nelts (tree type) return (integer_zerop (min) ? max - : fold (build2 (MINUS_EXPR, TREE_TYPE (max), max, min))); + : fold_build2 (MINUS_EXPR, TREE_TYPE (max), max, min)); } /* If arg is static -- a reference to an object in static storage -- then @@ -1652,8 +1850,8 @@ staticp (tree arg) case VAR_DECL: return ((TREE_STATIC (arg) || DECL_EXTERNAL (arg)) - && ! DECL_THREAD_LOCAL (arg) - && ! DECL_NON_ADDR_CONST_P (arg) + && ! DECL_THREAD_LOCAL_P (arg) + && ! DECL_DLLIMPORT_P (arg) ? arg : NULL); case CONST_DECL: @@ -1814,9 +2012,35 @@ tree_node_structure (tree t) enum tree_code code = TREE_CODE (t); switch (TREE_CODE_CLASS (code)) - { + { case tcc_declaration: - return TS_DECL; + { + 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; + case SYMBOL_MEMORY_TAG: + case NAME_MEMORY_TAG: + case STRUCT_FIELD_TAG: + return TS_MEMORY_TAG; + default: + return TS_DECL_NON_COMMON; + } + } case tcc_type: return TS_TYPE; case tcc_reference: @@ -1847,8 +2071,10 @@ tree_node_structure (tree t) 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 VALUE_HANDLE: return TS_VALUE_HANDLE; + case OMP_CLAUSE: return TS_OMP_CLAUSE; default: gcc_unreachable (); @@ -1900,6 +2126,9 @@ contains_placeholder_p (tree exp) || CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1)) || CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 2))); + case CALL_EXPR: + return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1)); + default: break; } @@ -1944,7 +2173,6 @@ type_contains_placeholder_1 (tree type) case COMPLEX_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE: - case CHAR_TYPE: case POINTER_TYPE: case OFFSET_TYPE: case REFERENCE_TYPE: @@ -2019,7 +2247,7 @@ tree substitute_in_expr (tree exp, tree f, tree r) { enum tree_code code = TREE_CODE (exp); - tree op0, op1, op2; + tree op0, op1, op2, op3; tree new; tree inner; @@ -2053,8 +2281,8 @@ substitute_in_expr (tree exp, tree f, tree r) if (op0 == TREE_OPERAND (exp, 0)) return exp; - new = fold (build3 (COMPONENT_REF, TREE_TYPE (exp), - op0, TREE_OPERAND (exp, 1), NULL_TREE)); + new = fold_build3 (COMPONENT_REF, TREE_TYPE (exp), + op0, TREE_OPERAND (exp, 1), NULL_TREE); } else switch (TREE_CODE_CLASS (code)) @@ -2079,7 +2307,7 @@ substitute_in_expr (tree exp, tree f, tree r) if (op0 == TREE_OPERAND (exp, 0)) return exp; - new = fold (build1 (code, TREE_TYPE (exp), op0)); + new = fold_build1 (code, TREE_TYPE (exp), op0); break; case 2: @@ -2089,7 +2317,7 @@ substitute_in_expr (tree exp, tree f, tree r) if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1)) return exp; - new = fold (build2 (code, TREE_TYPE (exp), op0, op1)); + new = fold_build2 (code, TREE_TYPE (exp), op0, op1); break; case 3: @@ -2101,7 +2329,21 @@ substitute_in_expr (tree exp, tree f, tree r) && op2 == TREE_OPERAND (exp, 2)) return exp; - new = fold (build3 (code, TREE_TYPE (exp), op0, op1, op2)); + new = fold_build3 (code, TREE_TYPE (exp), op0, op1, op2); + break; + + case 4: + op0 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 0), f, r); + op1 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 1), f, r); + op2 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 2), f, r); + op3 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 3), f, r); + + if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1) + && op2 == TREE_OPERAND (exp, 2) + && op3 == TREE_OPERAND (exp, 3)) + return exp; + + new = fold (build4 (code, TREE_TYPE (exp), op0, op1, op2, op3)); break; default: @@ -2157,7 +2399,7 @@ substitute_placeholder_in_expr (tree exp, tree obj) if (POINTER_TYPE_P (TREE_TYPE (elt)) && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (elt))) == need_type)) - return fold (build1 (INDIRECT_REF, need_type, elt)); + return fold_build1 (INDIRECT_REF, need_type, elt); /* If we didn't find it, return the original PLACEHOLDER_EXPR. If it survives until RTL generation, there will be an error. */ @@ -2199,7 +2441,7 @@ substitute_placeholder_in_expr (tree exp, tree obj) if (op0 == TREE_OPERAND (exp, 0)) return exp; else - return fold (build1 (code, TREE_TYPE (exp), op0)); + return fold_build1 (code, TREE_TYPE (exp), op0); case 2: op0 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 0), obj); @@ -2208,7 +2450,7 @@ substitute_placeholder_in_expr (tree exp, tree obj) if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1)) return exp; else - return fold (build2 (code, TREE_TYPE (exp), op0, op1)); + return fold_build2 (code, TREE_TYPE (exp), op0, op1); case 3: op0 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 0), obj); @@ -2219,7 +2461,7 @@ substitute_placeholder_in_expr (tree exp, tree obj) && op2 == TREE_OPERAND (exp, 2)) return exp; else - return fold (build3 (code, TREE_TYPE (exp), op0, op1, op2)); + return fold_build3 (code, TREE_TYPE (exp), op0, op1, op2); case 4: op0 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 0), obj); @@ -2418,7 +2660,7 @@ stabilize_reference_1 (tree e) TREE_INVARIANT, and TREE_SIDE_EFFECTS for an ADDR_EXPR. */ void -recompute_tree_invarant_for_addr_expr (tree t) +recompute_tree_invariant_for_addr_expr (tree t) { tree node; bool tc = true, ti = true, se = false; @@ -2466,6 +2708,8 @@ do { tree _node = (NODE); \ UPDATE_TITCSE (TREE_OPERAND (node, 2)); } + node = lang_hooks.expr_to_decl (node, &tc, &ti, &se); + /* Now see what's inside. If it's an INDIRECT_REF, copy our properties from the address, since &(*a)->b is a form of addition. If it's a decl, it's invariant and constant if the decl is static. It's also invariant if it's @@ -2480,7 +2724,8 @@ do { tree _node = (NODE); \ ; else if (decl_function_context (node) == current_function_decl /* Addresses of thread-local variables are invariant. */ - || (TREE_CODE (node) == VAR_DECL && DECL_THREAD_LOCAL (node))) + || (TREE_CODE (node) == VAR_DECL + && DECL_THREAD_LOCAL_P (node))) tc = false; else ti = tc = false; @@ -2504,9 +2749,7 @@ do { tree _node = (NODE); \ Constants, decls, types and misc nodes cannot be. We define 5 non-variadic functions, from 0 to 4 arguments. This is - enough for all extant tree codes. These functions can be called - directly (preferably!), but can also be obtained via GCC preprocessor - magic within the build macro. */ + enough for all extant tree codes. */ tree build0_stat (enum tree_code code, tree tt MEM_STAT_DECL) @@ -2592,7 +2835,7 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL) case ADDR_EXPR: if (node) - recompute_tree_invarant_for_addr_expr (t); + recompute_tree_invariant_for_addr_expr (t); break; default: @@ -2740,14 +2983,13 @@ build4_stat (enum tree_code code, tree tt, tree arg0, tree arg1, } tree -build7_stat (enum tree_code code, tree tt, tree arg0, tree arg1, - tree arg2, tree arg3, tree arg4, tree arg5, - tree arg6 MEM_STAT_DECL) +build5_stat (enum tree_code code, tree tt, tree arg0, tree arg1, + tree arg2, tree arg3, tree arg4 MEM_STAT_DECL) { bool constant, read_only, side_effects, invariant; tree t; - gcc_assert (code == TARGET_MEM_REF); + gcc_assert (TREE_CODE_LENGTH (code) == 5); t = make_node_stat (code PASS_MEM_STAT); TREE_TYPE (t) = tt; @@ -2759,66 +3001,40 @@ build7_stat (enum tree_code code, tree tt, tree arg0, tree arg1, PROCESS_ARG(2); PROCESS_ARG(3); PROCESS_ARG(4); - PROCESS_ARG(5); - PROCESS_ARG(6); TREE_SIDE_EFFECTS (t) = side_effects; - TREE_THIS_VOLATILE (t) = 0; + TREE_THIS_VOLATILE (t) + = (TREE_CODE_CLASS (code) == tcc_reference + && arg0 && TREE_THIS_VOLATILE (arg0)); return t; } -/* Backup definition for non-gcc build compilers. */ - tree -(build) (enum tree_code code, tree tt, ...) +build7_stat (enum tree_code code, tree tt, tree arg0, tree arg1, + tree arg2, tree arg3, tree arg4, tree arg5, + tree arg6 MEM_STAT_DECL) { - tree t, arg0, arg1, arg2, arg3, arg4, arg5, arg6; - int length = TREE_CODE_LENGTH (code); - va_list p; + bool constant, read_only, side_effects, invariant; + tree t; - va_start (p, tt); - switch (length) - { - case 0: - t = build0 (code, tt); - break; - case 1: - arg0 = va_arg (p, tree); - t = build1 (code, tt, arg0); - break; - case 2: - arg0 = va_arg (p, tree); - arg1 = va_arg (p, tree); - t = build2 (code, tt, arg0, arg1); - break; - case 3: - arg0 = va_arg (p, tree); - arg1 = va_arg (p, tree); - arg2 = va_arg (p, tree); - t = build3 (code, tt, arg0, arg1, arg2); - break; - case 4: - arg0 = va_arg (p, tree); - arg1 = va_arg (p, tree); - arg2 = va_arg (p, tree); - arg3 = va_arg (p, tree); - t = build4 (code, tt, arg0, arg1, arg2, arg3); - break; - case 7: - arg0 = va_arg (p, tree); - arg1 = va_arg (p, tree); - arg2 = va_arg (p, tree); - arg3 = va_arg (p, tree); - arg4 = va_arg (p, tree); - arg5 = va_arg (p, tree); - arg6 = va_arg (p, tree); - t = build7 (code, tt, arg0, arg1, arg2, arg3, arg4, arg5, arg6); - break; - default: - gcc_unreachable (); - } - va_end (p); + gcc_assert (code == TARGET_MEM_REF); + + t = make_node_stat (code PASS_MEM_STAT); + TREE_TYPE (t) = tt; + + side_effects = TREE_SIDE_EFFECTS (t); + + PROCESS_ARG(0); + PROCESS_ARG(1); + PROCESS_ARG(2); + PROCESS_ARG(3); + PROCESS_ARG(4); + PROCESS_ARG(5); + PROCESS_ARG(6); + + TREE_SIDE_EFFECTS (t) = side_effects; + TREE_THIS_VOLATILE (t) = 0; return t; } @@ -2874,10 +3090,13 @@ build_decl_stat (enum tree_code code, tree name, tree type MEM_STAT_DECL) else if (code == FUNCTION_DECL) DECL_MODE (t) = FUNCTION_MODE; - /* Set default visibility to whatever the user supplied with - visibility_specified depending on #pragma GCC visibility. */ - DECL_VISIBILITY (t) = default_visibility; - DECL_VISIBILITY_SPECIFIED (t) = visibility_options.inpragma; + if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS)) + { + /* Set default visibility to whatever the user supplied with + visibility_specified depending on #pragma GCC visibility. */ + DECL_VISIBILITY (t) = default_visibility; + DECL_VISIBILITY_SPECIFIED (t) = visibility_options.inpragma; + } return t; } @@ -2917,7 +3136,7 @@ build_block (tree vars, tree subblocks, tree supercontext, tree chain) #if 1 /* ! defined(USE_MAPPED_LOCATION) */ /* ??? gengtype doesn't handle conditionals */ -static GTY(()) tree last_annotated_node; +static GTY(()) location_t *last_annotated_node; #endif #ifdef USE_MAPPED_LOCATION @@ -2949,11 +3168,11 @@ annotate_with_file_line (tree node, const char *file, int line) a node with the same information already attached to that node! Just return instead of wasting memory. */ if (EXPR_LOCUS (node) + && EXPR_LINENO (node) == line && (EXPR_FILENAME (node) == file - || ! strcmp (EXPR_FILENAME (node), file)) - && EXPR_LINENO (node) == line) + || !strcmp (EXPR_FILENAME (node), file))) { - last_annotated_node = node; + last_annotated_node = EXPR_LOCUS (node); return; } @@ -2961,19 +3180,18 @@ annotate_with_file_line (tree node, const char *file, int line) entry cache can reduce the number of allocations by more than half. */ if (last_annotated_node - && EXPR_LOCUS (last_annotated_node) - && (EXPR_FILENAME (last_annotated_node) == file - || ! strcmp (EXPR_FILENAME (last_annotated_node), file)) - && EXPR_LINENO (last_annotated_node) == line) + && last_annotated_node->line == line + && (last_annotated_node->file == file + || !strcmp (last_annotated_node->file, file))) { - SET_EXPR_LOCUS (node, EXPR_LOCUS (last_annotated_node)); + SET_EXPR_LOCUS (node, last_annotated_node); return; } SET_EXPR_LOCUS (node, ggc_alloc (sizeof (location_t))); EXPR_LINENO (node) = line; EXPR_FILENAME (node) = file; - last_annotated_node = node; + last_annotated_node = EXPR_LOCUS (node); } void @@ -3289,31 +3507,66 @@ tree merge_dllimport_decl_attributes (tree old, tree new) { tree a; - int delete_dllimport_p; - - old = DECL_ATTRIBUTES (old); - new = DECL_ATTRIBUTES (new); + int delete_dllimport_p = 1; /* What we need to do here is remove from `old' dllimport if it doesn't appear in `new'. dllimport behaves like extern: if a declaration is marked dllimport and a definition appears later, then the object - is not dllimport'd. */ - if (lookup_attribute ("dllimport", old) != NULL_TREE - && lookup_attribute ("dllimport", new) == NULL_TREE) - delete_dllimport_p = 1; + 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. */ + if (!VAR_OR_FUNCTION_DECL_P (new)) + delete_dllimport_p = 0; + else if (DECL_DLLIMPORT_P (new) + && lookup_attribute ("dllexport", DECL_ATTRIBUTES (old))) + { + DECL_DLLIMPORT_P (new) = 0; + warning (OPT_Wattributes, "%q+D already declared with dllexport attribute: " + "dllimport ignored", new); + } + else if (DECL_DLLIMPORT_P (old) && !DECL_DLLIMPORT_P (new)) + { + /* Warn about overriding a symbol that has already been used. eg: + extern int __attribute__ ((dllimport)) foo; + int* bar () {return &foo;} + int foo; + */ + if (TREE_USED (old)) + { + warning (0, "%q+D redeclared without dllimport attribute " + "after being referenced with dll linkage", new); + /* If we have used a variable's address with dllimport linkage, + keep the old DECL_DLLIMPORT_P flag: the ADDR_EXPR using the + decl may already have had TREE_INVARIANT and TREE_CONSTANT + computed. + We still remove the attribute so that assembler code refers + to '&foo rather than '_imp__foo'. */ + if (TREE_CODE (old) == VAR_DECL && TREE_ADDRESSABLE (old)) + DECL_DLLIMPORT_P (new) = 1; + } + + /* Let an inline definition silently override the external reference, + but otherwise warn about attribute inconsistency. */ + else if (TREE_CODE (new) == VAR_DECL + || !DECL_DECLARED_INLINE_P (new)) + warning (OPT_Wattributes, "%q+D redeclared without dllimport attribute: " + "previous dllimport ignored", new); + } else delete_dllimport_p = 0; - a = merge_attributes (old, new); + a = merge_attributes (DECL_ATTRIBUTES (old), DECL_ATTRIBUTES (new)); - if (delete_dllimport_p) + if (delete_dllimport_p) { tree prev, t; - + 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)) { - if (is_attribute_p ("dllimport", TREE_PURPOSE (t))) + if (is_attribute_with_length_p ("dllimport", attr_len, + TREE_PURPOSE (t))) { if (prev == NULL_TREE) a = TREE_CHAIN (a); @@ -3360,23 +3613,31 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags, any damage. */ if (is_attribute_p ("dllimport", name)) { + /* Honor any target-specific overrides. */ + if (!targetm.valid_dllimport_attribute_p (node)) + *no_add_attrs = true; + + else if (TREE_CODE (node) == FUNCTION_DECL + && DECL_DECLARED_INLINE_P (node)) + { + warning (OPT_Wattributes, "inline function %q+D declared as " + " dllimport: attribute ignored", node); + *no_add_attrs = true; + } /* Like MS, treat definition of dllimported variables and - non-inlined functions on declaration as syntax errors. We - allow the attribute for function definitions if declared - inline. */ - if (TREE_CODE (node) == FUNCTION_DECL && DECL_INITIAL (node) - && !DECL_DECLARED_INLINE_P (node)) + non-inlined functions on declaration as syntax errors. */ + else if (TREE_CODE (node) == FUNCTION_DECL && DECL_INITIAL (node)) { - error ("%Jfunction %qD definition is marked dllimport.", node, node); + error ("function %q+D definition is marked dllimport", node); *no_add_attrs = true; } - else if (TREE_CODE (node) == VAR_DECL) + else if (TREE_CODE (node) == VAR_DECL) { if (DECL_INITIAL (node)) { - error ("%Jvariable %qD definition is marked dllimport.", - node, node); + error ("variable %q+D definition is marked dllimport", + node); *no_add_attrs = true; } @@ -3388,6 +3649,9 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags, if (current_function_decl != NULL_TREE && !TREE_STATIC (node)) TREE_PUBLIC (node) = 1; } + + if (*no_add_attrs == false) + DECL_DLLIMPORT_P (node) = 1; } /* Report error if symbol is not accessible at global scope. */ @@ -3395,8 +3659,8 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags, && (TREE_CODE (node) == VAR_DECL || TREE_CODE (node) == FUNCTION_DECL)) { - error ("%Jexternal linkage required for symbol %qD because of " - "%qs attribute.", node, node, IDENTIFIER_POINTER (name)); + error ("external linkage required for symbol %q+D because of " + "%qs attribute", node, IDENTIFIER_POINTER (name)); *no_add_attrs = true; } @@ -3510,7 +3774,7 @@ build_variant_type_copy (tree type) /* Return true if the from tree in both tree maps are equal. */ -static int +int tree_map_eq (const void *va, const void *vb) { const struct tree_map *a = va, *b = vb; @@ -3519,7 +3783,7 @@ tree_map_eq (const void *va, const void *vb) /* Hash a from tree in a tree_map. */ -static hashval_t +unsigned int tree_map_hash (const void *item) { return (((const struct tree_map *) item)->hash); @@ -3529,7 +3793,7 @@ tree_map_hash (const void *item) purposes. We simply return true if the from tree is marked, so that this structure goes away when the from tree goes away. */ -static int +int tree_map_marked_p (const void *p) { tree from = ((struct tree_map *) p)->from; @@ -3537,6 +3801,95 @@ tree_map_marked_p (const void *p) return ggc_marked_p (from); } +/* Return true if the trees in the tree_int_map *'s VA and VB are equal. */ + +static int +tree_int_map_eq (const void *va, const void *vb) +{ + const struct tree_int_map *a = va, *b = vb; + return (a->from == b->from); +} + +/* Hash a from tree in the tree_int_map * ITEM. */ + +static unsigned int +tree_int_map_hash (const void *item) +{ + return htab_hash_pointer (((const struct tree_int_map *)item)->from); +} + +/* Return true if this tree int map structure is marked for garbage collection + purposes. We simply return true if the from tree_int_map *P's from tree is marked, so that this + structure goes away when the from tree goes away. */ + +static int +tree_int_map_marked_p (const void *p) +{ + tree from = ((struct tree_int_map *) p)->from; + + return ggc_marked_p (from); +} +/* Lookup an init priority for FROM, and return it if we find one. */ + +unsigned short +decl_init_priority_lookup (tree from) +{ + struct tree_int_map *h, in; + in.from = from; + + h = htab_find_with_hash (init_priority_for_decl, + &in, htab_hash_pointer (from)); + if (h) + return h->to; + return 0; +} + +/* Insert a mapping FROM->TO in the init priority hashtable. */ + +void +decl_init_priority_insert (tree from, unsigned short to) +{ + struct tree_int_map *h; + void **loc; + + h = ggc_alloc (sizeof (struct tree_int_map)); + h->from = from; + h->to = to; + loc = htab_find_slot_with_hash (init_priority_for_decl, h, + htab_hash_pointer (from), INSERT); + *(struct tree_int_map **) loc = h; +} + +/* Look up a restrict qualified base decl for FROM. */ + +tree +decl_restrict_base_lookup (tree from) +{ + struct tree_map *h; + struct tree_map in; + + in.from = from; + h = htab_find_with_hash (restrict_base_for_decl, &in, + htab_hash_pointer (from)); + return h ? h->to : NULL_TREE; +} + +/* Record the restrict qualified base TO for FROM. */ + +void +decl_restrict_base_insert (tree from, tree to) +{ + struct tree_map *h; + void **loc; + + h = ggc_alloc (sizeof (struct tree_map)); + h->hash = htab_hash_pointer (from); + h->from = from; + h->to = to; + loc = htab_find_slot_with_hash (restrict_base_for_decl, h, h->hash, INSERT); + *(struct tree_map **) loc = h; +} + /* Print out the statistics for the DECL_DEBUG_EXPR hash table. */ static void @@ -3558,6 +3911,21 @@ print_value_expr_statistics (void) (long) htab_elements (value_expr_for_decl), htab_collisions (value_expr_for_decl)); } + +/* Print out statistics for the RESTRICT_BASE_FOR_DECL hash table, but + don't print anything if the table is empty. */ + +static void +print_restrict_base_statistics (void) +{ + if (htab_elements (restrict_base_for_decl) != 0) + fprintf (stderr, + "RESTRICT_BASE hash: size %ld, %ld elements, %f collisions\n", + (long) htab_size (restrict_base_for_decl), + (long) htab_elements (restrict_base_for_decl), + htab_collisions (restrict_base_for_decl)); +} + /* Lookup a debug expression for FROM, and return it if we find one. */ tree @@ -3683,7 +4051,6 @@ type_hash_eq (const void *va, const void *vb) case INTEGER_TYPE: case REAL_TYPE: case BOOLEAN_TYPE: - case CHAR_TYPE: return ((TYPE_MAX_VALUE (a->type) == TYPE_MAX_VALUE (b->type) || tree_int_cst_equal (TYPE_MAX_VALUE (a->type), TYPE_MAX_VALUE (b->type))) @@ -4021,14 +4388,13 @@ tree_int_cst_compare (tree t1, tree t2) /* Return 1 if T is an INTEGER_CST that can be manipulated efficiently on the host. If POS is zero, the value can be represented in a single - HOST_WIDE_INT. If POS is nonzero, the value must be positive and can + HOST_WIDE_INT. If POS is nonzero, the value must be non-negative and can be represented in a single unsigned HOST_WIDE_INT. */ int host_integerp (tree t, int pos) { return (TREE_CODE (t) == INTEGER_CST - && ! TREE_OVERFLOW (t) && ((TREE_INT_CST_HIGH (t) == 0 && (HOST_WIDE_INT) TREE_INT_CST_LOW (t) >= 0) || (! pos && TREE_INT_CST_HIGH (t) == -1 @@ -4039,7 +4405,7 @@ host_integerp (tree t, int pos) /* Return the HOST_WIDE_INT least significant bits of T if it is an INTEGER_CST and there is no overflow. POS is nonzero if the result must - be positive. We must be able to satisfy the above conditions. */ + be non-negative. We must be able to satisfy the above conditions. */ HOST_WIDE_INT tree_low_cst (tree t, int pos) @@ -4067,7 +4433,7 @@ tree_int_cst_msb (tree t) /* Return an indication of the sign of the integer constant T. The return value is -1 if T < 0, 0 if T == 0, and 1 if T > 0. - Note that -1 will never be returned it T's type is unsigned. */ + Note that -1 will never be returned if T's type is unsigned. */ int tree_int_cst_sgn (tree t) @@ -4152,8 +4518,21 @@ simple_cst_equal (tree t1, tree t2) TREE_STRING_LENGTH (t1))); case CONSTRUCTOR: - return simple_cst_list_equal (CONSTRUCTOR_ELTS (t1), - CONSTRUCTOR_ELTS (t2)); + { + unsigned HOST_WIDE_INT idx; + VEC(constructor_elt, gc) *v1 = CONSTRUCTOR_ELTS (t1); + VEC(constructor_elt, gc) *v2 = CONSTRUCTOR_ELTS (t2); + + if (VEC_length (constructor_elt, v1) != VEC_length (constructor_elt, v2)) + return false; + + for (idx = 0; idx < VEC_length (constructor_elt, v1); ++idx) + /* ??? Should we handle also fields here? */ + if (!simple_cst_equal (VEC_index (constructor_elt, v1, idx)->value, + VEC_index (constructor_elt, v2, idx)->value)) + return false; + return true; + } case SAVE_EXPR: return simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)); @@ -4361,6 +4740,17 @@ iterative_hash_expr (tree t, hashval_t val) for (; t; t = TREE_CHAIN (t)) val = iterative_hash_expr (TREE_VALUE (t), val); return val; + case CONSTRUCTOR: + { + unsigned HOST_WIDE_INT idx; + tree field, value; + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), idx, field, value) + { + val = iterative_hash_expr (field, val); + val = iterative_hash_expr (value, val); + } + return val; + } case FUNCTION_DECL: /* When referring to a built-in FUNCTION_DECL, use the __builtin__ form. Otherwise nodes that compare equal @@ -4378,8 +4768,8 @@ iterative_hash_expr (tree t, hashval_t val) if (class == tcc_declaration) { - /* Otherwise, we can just compare decls by pointer. */ - val = iterative_hash_pointer (t, val); + /* DECL's have a unique ID */ + val = iterative_hash_host_wide_int (DECL_UID (t), val); } else { @@ -4439,6 +4829,9 @@ build_pointer_type_for_mode (tree to_type, enum machine_mode mode, { tree t; + if (to_type == error_mark_node) + return error_mark_node; + /* In some cases, languages will have things that aren't a POINTER_TYPE (such as a RECORD_TYPE for fat pointers in Ada) as TYPE_POINTER_TO. In that case, return that type without regard to the rest of our @@ -4606,9 +4999,8 @@ build_nonstandard_integer_type (unsigned HOST_WIDE_INT precision, } /* Create a range of some discrete type TYPE (an INTEGER_TYPE, - ENUMERAL_TYPE, BOOLEAN_TYPE, or CHAR_TYPE), with - low bound LOWVAL and high bound HIGHVAL. - if TYPE==NULL_TREE, sizetype is used. */ + ENUMERAL_TYPE or BOOLEAN_TYPE), with low bound LOWVAL and + high bound HIGHVAL. If TYPE is NULL, sizetype is used. */ tree build_range_type (tree type, tree lowval, tree highval) @@ -4619,8 +5011,8 @@ build_range_type (tree type, tree lowval, tree highval) if (type == NULL_TREE) type = sizetype; - TYPE_MIN_VALUE (itype) = convert (type, lowval); - TYPE_MAX_VALUE (itype) = highval ? convert (type, highval) : NULL; + TYPE_MIN_VALUE (itype) = fold_convert (type, lowval); + TYPE_MAX_VALUE (itype) = highval ? fold_convert (type, highval) : NULL; TYPE_PRECISION (itype) = TYPE_PRECISION (type); TYPE_MODE (itype) = TYPE_MODE (type); @@ -5174,8 +5566,11 @@ int_fits_type_p (tree c, tree type) return 0; /* If we haven't been able to decide at this point, there nothing more we - can check ourselves here. Look at the base type if we have one. */ - if (TREE_CODE (type) == INTEGER_TYPE && TREE_TYPE (type) != 0) + can check ourselves here. Look at the base type if we have one and it + has the same precision. */ + if (TREE_CODE (type) == INTEGER_TYPE + && TREE_TYPE (type) != 0 + && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (type))) return int_fits_type_p (c, TREE_TYPE (type)); /* Or to force_fit_type, if nothing else. */ @@ -5270,7 +5665,6 @@ variably_modified_type_p (tree type, tree fn) case REAL_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE: - case CHAR_TYPE: /* Scalar types are variably modified if their end points aren't constant. */ RETURN_TRUE_IF_VAR (TYPE_MIN_VALUE (type)); @@ -5397,6 +5791,9 @@ get_callee_fndecl (tree call) { tree addr; + if (call == error_mark_node) + return call; + /* It's invalid to call this function with anything but a CALL_EXPR. */ gcc_assert (TREE_CODE (call) == CALL_EXPR); @@ -5458,6 +5855,7 @@ dump_tree_statistics (void) print_type_hash_statistics (); print_debug_expr_statistics (); print_value_expr_statistics (); + print_restrict_base_statistics (); lang_hooks.print_statistics (); } @@ -5516,7 +5914,26 @@ get_file_function_name_long (const char *type) char *q; if (first_global_object_name) - p = first_global_object_name; + { + p = first_global_object_name; + + /* For type 'F', the generated name must be unique not only to this + translation unit but also to any given link. Since global names + can be overloaded, we concatenate the first global object name + with a string derived from the file name of this object. */ + if (!strcmp (type, "F")) + { + const char *file = main_input_filename; + + if (! file) + file = input_filename; + + q = alloca (strlen (p) + 10); + sprintf (q, "%s_%08X", p, crc32_string (0, file)); + + p = q; + } + } else { /* We don't have anything that we know to be unique to this translation @@ -5662,6 +6079,128 @@ tree_class_check_failed (const tree node, const enum tree_code_class cl, tree_code_name[TREE_CODE (node)], function, trim_filename (file), line); } +/* Similar to tree_check_failed, except that instead of specifying a + dozen codes, use the knowledge that they're all sequential. */ + +void +tree_range_check_failed (const tree node, const char *file, int line, + const char *function, enum tree_code c1, + enum tree_code c2) +{ + char *buffer; + unsigned length = 0; + enum tree_code c; + + for (c = c1; c <= c2; ++c) + length += 4 + strlen (tree_code_name[c]); + + length += strlen ("expected "); + buffer = alloca (length); + length = 0; + + for (c = c1; c <= c2; ++c) + { + const char *prefix = length ? " or " : "expected "; + + strcpy (buffer + length, prefix); + length += strlen (prefix); + strcpy (buffer + length, tree_code_name[c]); + length += strlen (tree_code_name[c]); + } + + internal_error ("tree check: %s, have %s in %s, at %s:%d", + buffer, tree_code_name[TREE_CODE (node)], + function, trim_filename (file), line); +} + + +/* Similar to tree_check_failed, except that we check that a tree does + not have the specified code, given in CL. */ + +void +tree_not_class_check_failed (const tree node, const enum tree_code_class cl, + const char *file, int line, const char *function) +{ + internal_error + ("tree check: did not expect class %qs, have %qs (%s) in %s, at %s:%d", + TREE_CODE_CLASS_STRING (cl), + TREE_CODE_CLASS_STRING (TREE_CODE_CLASS (TREE_CODE (node))), + tree_code_name[TREE_CODE (node)], function, trim_filename (file), line); +} + + +/* Similar to tree_check_failed but applied to OMP_CLAUSE codes. */ + +void +omp_clause_check_failed (const tree node, const char *file, int line, + const char *function, enum omp_clause_code code) +{ + internal_error ("tree check: expected omp_clause %s, have %s in %s, at %s:%d", + omp_clause_code_name[code], tree_code_name[TREE_CODE (node)], + function, trim_filename (file), line); +} + + +/* Similar to tree_range_check_failed but applied to OMP_CLAUSE codes. */ + +void +omp_clause_range_check_failed (const tree node, const char *file, int line, + const char *function, enum omp_clause_code c1, + enum omp_clause_code c2) +{ + char *buffer; + unsigned length = 0; + enum omp_clause_code c; + + for (c = c1; c <= c2; ++c) + length += 4 + strlen (omp_clause_code_name[c]); + + length += strlen ("expected "); + buffer = alloca (length); + length = 0; + + for (c = c1; c <= c2; ++c) + { + const char *prefix = length ? " or " : "expected "; + + strcpy (buffer + length, prefix); + length += strlen (prefix); + strcpy (buffer + length, omp_clause_code_name[c]); + length += strlen (omp_clause_code_name[c]); + } + + internal_error ("tree check: %s, have %s in %s, at %s:%d", + buffer, omp_clause_code_name[TREE_CODE (node)], + function, trim_filename (file), line); +} + + +#undef DEFTREESTRUCT +#define DEFTREESTRUCT(VAL, NAME) NAME, + +static const char *ts_enum_names[] = { +#include "treestruct.def" +}; +#undef DEFTREESTRUCT + +#define TS_ENUM_NAME(EN) (ts_enum_names[(EN)]) + +/* Similar to tree_class_check_failed, except that we check for + whether CODE contains the tree structure identified by EN. */ + +void +tree_contains_struct_check_failed (const tree node, + const enum tree_node_structure_enum en, + const char *file, int line, + const char *function) +{ + internal_error + ("tree check: expected tree that contains %qs structure, have %qs in %s, at %s:%d", + TS_ENUM_NAME(en), + tree_code_name[TREE_CODE (node)], function, trim_filename (file), line); +} + + /* Similar to above, except that the check is for the bounds of a TREE_VEC's (dynamically sized) vector. */ @@ -5698,6 +6237,20 @@ tree_operand_check_failed (int idx, enum tree_code code, const char *file, idx + 1, tree_code_name[code], TREE_CODE_LENGTH (code), function, trim_filename (file), line); } + +/* Similar to above, except that the check is for the number of + operands of an OMP_CLAUSE node. */ + +void +omp_clause_operand_check_failed (int idx, tree t, const char *file, + int line, const char *function) +{ + internal_error + ("tree check: accessed operand %d of omp_clause %s with %d operands " + "in %s, at %s:%d", idx + 1, omp_clause_code_name[OMP_CLAUSE_CODE (t)], + omp_clause_num_ops [OMP_CLAUSE_CODE (t)], function, + trim_filename (file), line); +} #endif /* ENABLE_TREE_CHECKING */ /* Create a new vector type node holding SUBPARTS units of type INNERTYPE, @@ -5710,7 +6263,7 @@ make_vector_type (tree innertype, int nunits, enum machine_mode mode) tree t = make_node (VECTOR_TYPE); TREE_TYPE (t) = TYPE_MAIN_VARIANT (innertype); - TYPE_VECTOR_SUBPARTS (t) = nunits; + SET_TYPE_VECTOR_SUBPARTS (t, nunits); TYPE_MODE (t) = mode; TYPE_READONLY (t) = TYPE_READONLY (innertype); TYPE_VOLATILE (t) = TYPE_VOLATILE (innertype); @@ -5781,7 +6334,9 @@ build_common_tree_nodes (bool signed_char, bool signed_sizetype) /* Define both `signed char' and `unsigned char'. */ signed_char_type_node = make_signed_type (CHAR_TYPE_SIZE); + TYPE_STRING_FLAG (signed_char_type_node) = 1; unsigned_char_type_node = make_unsigned_type (CHAR_TYPE_SIZE); + TYPE_STRING_FLAG (unsigned_char_type_node) = 1; /* Define `char', which is like either `signed char' or `unsigned char' but not the same as either. */ @@ -5789,6 +6344,7 @@ build_common_tree_nodes (bool signed_char, bool signed_sizetype) = (signed_char ? make_signed_type (CHAR_TYPE_SIZE) : make_unsigned_type (CHAR_TYPE_SIZE)); + TYPE_STRING_FLAG (char_type_node) = 1; short_integer_type_node = make_signed_type (SHORT_TYPE_SIZE); short_unsigned_type_node = make_unsigned_type (SHORT_TYPE_SIZE); @@ -5883,6 +6439,25 @@ build_common_tree_nodes_2 (int short_double) long_double_ptr_type_node = build_pointer_type (long_double_type_node); integer_ptr_type_node = build_pointer_type (integer_type_node); + /* Decimal float types. */ + dfloat32_type_node = make_node (REAL_TYPE); + TYPE_PRECISION (dfloat32_type_node) = DECIMAL32_TYPE_SIZE; + layout_type (dfloat32_type_node); + TYPE_MODE (dfloat32_type_node) = SDmode; + dfloat32_ptr_type_node = build_pointer_type (dfloat32_type_node); + + dfloat64_type_node = make_node (REAL_TYPE); + TYPE_PRECISION (dfloat64_type_node) = DECIMAL64_TYPE_SIZE; + layout_type (dfloat64_type_node); + TYPE_MODE (dfloat64_type_node) = DDmode; + 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; + layout_type (dfloat128_type_node); + TYPE_MODE (dfloat128_type_node) = TDmode; + dfloat128_ptr_type_node = build_pointer_type (dfloat128_type_node); + complex_integer_type_node = make_node (COMPLEX_TYPE); TREE_TYPE (complex_integer_type_node) = integer_type_node; layout_type (complex_integer_type_node); @@ -6208,30 +6783,20 @@ initializer_zerop (tree init) return true; case CONSTRUCTOR: - elt = CONSTRUCTOR_ELTS (init); - if (elt == NULL_TREE) - return true; + { + unsigned HOST_WIDE_INT idx; - for (; elt ; elt = TREE_CHAIN (elt)) - if (! initializer_zerop (TREE_VALUE (elt))) - return false; - return true; + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), idx, elt) + if (!initializer_zerop (elt)) + return false; + return true; + } default: return false; } } -void -add_var_to_bind_expr (tree bind_expr, tree var) -{ - BIND_EXPR_VARS (bind_expr) - = chainon (BIND_EXPR_VARS (bind_expr), var); - if (BIND_EXPR_BLOCK (bind_expr)) - BLOCK_VARS (BIND_EXPR_BLOCK (bind_expr)) - = BIND_EXPR_VARS (bind_expr); -} - /* Build an empty statement. */ tree @@ -6241,6 +6806,31 @@ build_empty_stmt (void) } +/* Build an OpenMP clause with code CODE. */ + +tree +build_omp_clause (enum omp_clause_code code) +{ + tree t; + int size, length; + + length = omp_clause_num_ops[code]; + size = (sizeof (struct tree_omp_clause) + (length - 1) * sizeof (tree)); + + t = ggc_alloc (size); + memset (t, 0, size); + TREE_SET_CODE (t, OMP_CLAUSE); + OMP_CLAUSE_SET_CODE (t, code); + +#ifdef GATHER_STATISTICS + tree_node_counts[(int) omp_clause_kind]++; + tree_node_sizes[(int) omp_clause_kind] += size; +#endif + + return t; +} + + /* Returns true if it is possible to prove that the index of an array access REF (an ARRAY_REF expression) falls into the array bounds. */ @@ -6274,7 +6864,10 @@ in_array_bounds_p (tree ref) bool is_global_var (tree t) { - return (TREE_STATIC (t) || DECL_EXTERNAL (t)); + if (MTAG_P (t)) + return (TREE_STATIC (t) || MTAG_GLOBAL (t)); + else + return (TREE_STATIC (t) || DECL_EXTERNAL (t)); } /* Return true if T (assumed to be a DECL) must be assigned a memory @@ -6371,16 +6964,16 @@ tree_fold_gcd (tree a, tree b) return a; if (tree_int_cst_sgn (a) == -1) - a = fold (build2 (MULT_EXPR, type, a, - convert (type, integer_minus_one_node))); + a = fold_build2 (MULT_EXPR, type, a, + build_int_cst (type, -1)); if (tree_int_cst_sgn (b) == -1) - b = fold (build2 (MULT_EXPR, type, b, - convert (type, integer_minus_one_node))); + b = fold_build2 (MULT_EXPR, type, b, + build_int_cst (type, -1)); while (1) { - a_mod_b = fold (build2 (FLOOR_MOD_EXPR, type, a, b)); + a_mod_b = fold_build2 (FLOOR_MOD_EXPR, type, a, b); if (!TREE_INT_CST_LOW (a_mod_b) && !TREE_INT_CST_HIGH (a_mod_b)) @@ -6396,6 +6989,8 @@ tree_fold_gcd (tree a, tree b) tree unsigned_type_for (tree type) { + if (POINTER_TYPE_P (type)) + return size_type_node; return lang_hooks.types.unsigned_type (type); } @@ -6414,43 +7009,64 @@ tree upper_bound_in_type (tree outer, tree inner) { unsigned HOST_WIDE_INT lo, hi; - unsigned bits = TYPE_PRECISION (inner); + unsigned int det = 0; + unsigned oprec = TYPE_PRECISION (outer); + unsigned iprec = TYPE_PRECISION (inner); + unsigned prec; + + /* Compute a unique number for every combination. */ + det |= (oprec > iprec) ? 4 : 0; + det |= TYPE_UNSIGNED (outer) ? 2 : 0; + det |= TYPE_UNSIGNED (inner) ? 1 : 0; + + /* Determine the exponent to use. */ + switch (det) + { + case 0: + case 1: + /* oprec <= iprec, outer: signed, inner: don't care. */ + prec = oprec - 1; + break; + case 2: + case 3: + /* oprec <= iprec, outer: unsigned, inner: don't care. */ + prec = oprec; + break; + case 4: + /* oprec > iprec, outer: signed, inner: signed. */ + prec = iprec - 1; + break; + case 5: + /* oprec > iprec, outer: signed, inner: unsigned. */ + prec = iprec; + break; + case 6: + /* oprec > iprec, outer: unsigned, inner: signed. */ + prec = oprec; + break; + case 7: + /* oprec > iprec, outer: unsigned, inner: unsigned. */ + prec = iprec; + break; + default: + gcc_unreachable (); + } - if (TYPE_UNSIGNED (outer) || TYPE_UNSIGNED (inner)) + /* Compute 2^^prec - 1. */ + if (prec <= HOST_BITS_PER_WIDE_INT) { - /* Zero extending in these cases. */ - if (bits <= HOST_BITS_PER_WIDE_INT) - { - hi = 0; - lo = (~(unsigned HOST_WIDE_INT) 0) - >> (HOST_BITS_PER_WIDE_INT - bits); - } - else - { - hi = (~(unsigned HOST_WIDE_INT) 0) - >> (2 * HOST_BITS_PER_WIDE_INT - bits); - lo = ~(unsigned HOST_WIDE_INT) 0; - } + hi = 0; + lo = ((~(unsigned HOST_WIDE_INT) 0) + >> (HOST_BITS_PER_WIDE_INT - prec)); } else { - /* Sign extending in these cases. */ - if (bits <= HOST_BITS_PER_WIDE_INT) - { - hi = 0; - lo = (~(unsigned HOST_WIDE_INT) 0) - >> (HOST_BITS_PER_WIDE_INT - bits) >> 1; - } - else - { - hi = (~(unsigned HOST_WIDE_INT) 0) - >> (2 * HOST_BITS_PER_WIDE_INT - bits) >> 1; - lo = ~(unsigned HOST_WIDE_INT) 0; - } + hi = ((~(unsigned HOST_WIDE_INT) 0) + >> (2 * HOST_BITS_PER_WIDE_INT - prec)); + lo = ~(unsigned HOST_WIDE_INT) 0; } - return fold_convert (outer, - build_int_cst_wide (inner, lo, hi)); + return build_int_cst_wide (outer, lo, hi); } /* Returns the smallest value obtainable by casting something in INNER type to @@ -6460,23 +7076,39 @@ tree lower_bound_in_type (tree outer, tree inner) { unsigned HOST_WIDE_INT lo, hi; - unsigned bits = TYPE_PRECISION (inner); - - if (TYPE_UNSIGNED (outer) || TYPE_UNSIGNED (inner)) + unsigned oprec = TYPE_PRECISION (outer); + unsigned iprec = TYPE_PRECISION (inner); + + /* If OUTER type is unsigned, we can definitely cast 0 to OUTER type + and obtain 0. */ + if (TYPE_UNSIGNED (outer) + /* If we are widening something of an unsigned type, OUTER type + 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; - else if (bits <= HOST_BITS_PER_WIDE_INT) - { - hi = ~(unsigned HOST_WIDE_INT) 0; - lo = (~(unsigned HOST_WIDE_INT) 0) << (bits - 1); - } else { - hi = (~(unsigned HOST_WIDE_INT) 0) << (bits - HOST_BITS_PER_WIDE_INT - 1); - lo = 0; + /* If we are widening a signed type to another signed type, we + want to obtain -2^^(iprec-1). If we are keeping the + precision or narrowing to a signed type, we want to obtain + -2^(oprec-1). */ + unsigned prec = oprec > iprec ? iprec : oprec; + + if (prec <= HOST_BITS_PER_WIDE_INT) + { + hi = ~(unsigned HOST_WIDE_INT) 0; + lo = (~(unsigned HOST_WIDE_INT) 0) << (prec - 1); + } + else + { + hi = ((~(unsigned HOST_WIDE_INT) 0) + << (prec - HOST_BITS_PER_WIDE_INT - 1)); + lo = 0; + } } - return fold_convert (outer, - build_int_cst_wide (inner, lo, hi)); + return build_int_cst_wide (outer, lo, hi); } /* Return nonzero if two operands that are suitable for PHI nodes are @@ -6611,7 +7243,6 @@ walk_type_fields (tree type, walk_tree_fn func, void *data, case BOOLEAN_TYPE: case ENUMERAL_TYPE: case INTEGER_TYPE: - case CHAR_TYPE: case REAL_TYPE: WALK_SUBTREE (TYPE_MIN_VALUE (type)); WALK_SUBTREE (TYPE_MAX_VALUE (type)); @@ -6674,9 +7305,11 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset) interesting below this point in the tree. */ if (!walk_subtrees) { + /* But we still need to check our siblings. */ if (code == TREE_LIST) - /* But we still need to check our siblings. */ WALK_SUBTREE_TAIL (TREE_CHAIN (*tp)); + else if (code == OMP_CLAUSE) + WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp)); else return NULL_TREE; } @@ -6686,181 +7319,207 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset) if (result || ! walk_subtrees) return result; - /* If this is a DECL_EXPR, walk into various fields of the type that it's - defining. We only want to walk into these fields of a type in this - case. Note that decls get walked as part of the processing of a - BIND_EXPR. - - ??? Precisely which fields of types that we are supposed to walk in - this case vs. the normal case aren't well defined. */ - if (code == DECL_EXPR - && TREE_CODE (DECL_EXPR_DECL (*tp)) == TYPE_DECL - && TREE_CODE (TREE_TYPE (DECL_EXPR_DECL (*tp))) != ERROR_MARK) + switch (code) { - tree *type_p = &TREE_TYPE (DECL_EXPR_DECL (*tp)); + case ERROR_MARK: + case IDENTIFIER_NODE: + case INTEGER_CST: + case REAL_CST: + case VECTOR_CST: + case STRING_CST: + case BLOCK: + case PLACEHOLDER_EXPR: + case SSA_NAME: + case FIELD_DECL: + case RESULT_DECL: + /* None of these have subtrees other than those already walked + above. */ + break; - /* Call the function for the type. See if it returns anything or - doesn't want us to continue. If we are to continue, walk both - the normal fields and those for the declaration case. */ - result = (*func) (type_p, &walk_subtrees, data); - if (result || !walk_subtrees) - return NULL_TREE; + case TREE_LIST: + WALK_SUBTREE (TREE_VALUE (*tp)); + WALK_SUBTREE_TAIL (TREE_CHAIN (*tp)); + break; - result = walk_type_fields (*type_p, func, data, pset); - if (result) - return result; + case TREE_VEC: + { + int len = TREE_VEC_LENGTH (*tp); - WALK_SUBTREE (TYPE_SIZE (*type_p)); - WALK_SUBTREE (TYPE_SIZE_UNIT (*type_p)); + if (len == 0) + break; - /* 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) - { - tree field; + /* Walk all elements but the first. */ + while (--len) + WALK_SUBTREE (TREE_VEC_ELT (*tp, len)); - for (field = TYPE_FIELDS (*type_p); field; - field = TREE_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 to elsewhere - in the tree. Also, ignore things that aren't fields. */ - if (TREE_CODE (field) != FIELD_DECL) - continue; - - WALK_SUBTREE (DECL_FIELD_OFFSET (field)); - WALK_SUBTREE (DECL_SIZE (field)); - WALK_SUBTREE (DECL_SIZE_UNIT (field)); - if (TREE_CODE (*type_p) == QUAL_UNION_TYPE) - WALK_SUBTREE (DECL_QUALIFIER (field)); - } - } - } + /* Now walk the first one as a tail call. */ + WALK_SUBTREE_TAIL (TREE_VEC_ELT (*tp, 0)); + } - else if (code != SAVE_EXPR - && code != BIND_EXPR - && IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))) - { - int i, len; - - /* Walk over all the sub-trees of this operand. */ - len = TREE_CODE_LENGTH (code); - /* TARGET_EXPRs are peculiar: operands 1 and 3 can be the same. - But, we only want to walk once. */ - if (code == TARGET_EXPR - && TREE_OPERAND (*tp, 3) == TREE_OPERAND (*tp, 1)) - --len; - - /* Go through the subtrees. We need to do this in forward order so - that the scope of a FOR_EXPR is handled properly. */ -#ifdef DEBUG_WALK_TREE - for (i = 0; i < len; ++i) - WALK_SUBTREE (TREE_OPERAND (*tp, i)); -#else - for (i = 0; i < len - 1; ++i) - WALK_SUBTREE (TREE_OPERAND (*tp, i)); + case COMPLEX_CST: + WALK_SUBTREE (TREE_REALPART (*tp)); + WALK_SUBTREE_TAIL (TREE_IMAGPART (*tp)); - if (len) - { - /* The common case is that we may tail recurse here. */ - if (code != BIND_EXPR - && !TREE_CHAIN (*tp)) - WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len - 1)); - else - WALK_SUBTREE (TREE_OPERAND (*tp, len - 1)); - } -#endif - } + case CONSTRUCTOR: + { + unsigned HOST_WIDE_INT idx; + constructor_elt *ce; - /* If this is a type, walk the needed fields in the type. */ - else if (TYPE_P (*tp)) - { - result = walk_type_fields (*tp, func, data, pset); - if (result) - return result; - } - else - { - /* Not one of the easy cases. We must explicitly go through the - children. */ - switch (code) - { - case ERROR_MARK: - case IDENTIFIER_NODE: - case INTEGER_CST: - case REAL_CST: - case VECTOR_CST: - case STRING_CST: - case BLOCK: - case PLACEHOLDER_EXPR: - case SSA_NAME: - case FIELD_DECL: - case RESULT_DECL: - /* None of these have subtrees other than those already walked - above. */ - break; + for (idx = 0; + VEC_iterate(constructor_elt, CONSTRUCTOR_ELTS (*tp), idx, ce); + idx++) + WALK_SUBTREE (ce->value); + } + break; - case TREE_LIST: - WALK_SUBTREE (TREE_VALUE (*tp)); - WALK_SUBTREE_TAIL (TREE_CHAIN (*tp)); - break; + case SAVE_EXPR: + WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 0)); - case TREE_VEC: + case BIND_EXPR: + { + tree decl; + for (decl = BIND_EXPR_VARS (*tp); decl; decl = TREE_CHAIN (decl)) { - int len = TREE_VEC_LENGTH (*tp); - - if (len == 0) - break; + /* Walk the DECL_INITIAL and DECL_SIZE. We don't want to walk + into declarations that are just mentioned, rather than + declared; they don't really belong to this part of the tree. + And, we can see cycles: the initializer for a declaration + can refer to the declaration itself. */ + WALK_SUBTREE (DECL_INITIAL (decl)); + WALK_SUBTREE (DECL_SIZE (decl)); + WALK_SUBTREE (DECL_SIZE_UNIT (decl)); + } + WALK_SUBTREE_TAIL (BIND_EXPR_BODY (*tp)); + } - /* Walk all elements but the first. */ - while (--len) - WALK_SUBTREE (TREE_VEC_ELT (*tp, len)); + case STATEMENT_LIST: + { + tree_stmt_iterator i; + for (i = tsi_start (*tp); !tsi_end_p (i); tsi_next (&i)) + WALK_SUBTREE (*tsi_stmt_ptr (i)); + } + break; - /* Now walk the first one as a tail call. */ - WALK_SUBTREE_TAIL (TREE_VEC_ELT (*tp, 0)); + case OMP_CLAUSE: + switch (OMP_CLAUSE_CODE (*tp)) + { + case OMP_CLAUSE_PRIVATE: + case OMP_CLAUSE_SHARED: + case OMP_CLAUSE_FIRSTPRIVATE: + case OMP_CLAUSE_LASTPRIVATE: + case OMP_CLAUSE_COPYIN: + case OMP_CLAUSE_COPYPRIVATE: + case OMP_CLAUSE_IF: + case OMP_CLAUSE_NUM_THREADS: + case OMP_CLAUSE_SCHEDULE: + WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, 0)); + /* FALLTHRU */ + + case OMP_CLAUSE_NOWAIT: + case OMP_CLAUSE_ORDERED: + case OMP_CLAUSE_DEFAULT: + WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp)); + + case OMP_CLAUSE_REDUCTION: + { + int i; + for (i = 0; i < 4; i++) + WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, i)); + WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp)); } - case COMPLEX_CST: - WALK_SUBTREE (TREE_REALPART (*tp)); - WALK_SUBTREE_TAIL (TREE_IMAGPART (*tp)); + default: + gcc_unreachable (); + } + break; + + case TARGET_EXPR: + { + int i, len; + + /* TARGET_EXPRs are peculiar: operands 1 and 3 can be the same. + But, we only want to walk once. */ + len = (TREE_OPERAND (*tp, 3) == TREE_OPERAND (*tp, 1)) ? 2 : 3; + for (i = 0; i < len; ++i) + WALK_SUBTREE (TREE_OPERAND (*tp, i)); + WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len)); + } - case CONSTRUCTOR: - WALK_SUBTREE_TAIL (CONSTRUCTOR_ELTS (*tp)); + case DECL_EXPR: + /* Walk into various fields of the type that it's defining. We only + want to walk into these fields of a type in this case. Note that + decls get walked as part of the processing of a BIND_EXPR. - case SAVE_EXPR: - WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 0)); + ??? Precisely which fields of types that we are supposed to walk in + this case vs. the normal case aren't well defined. */ + if (TREE_CODE (DECL_EXPR_DECL (*tp)) == TYPE_DECL + && TREE_CODE (TREE_TYPE (DECL_EXPR_DECL (*tp))) != ERROR_MARK) + { + tree *type_p = &TREE_TYPE (DECL_EXPR_DECL (*tp)); - case BIND_EXPR: - { - tree decl; - for (decl = BIND_EXPR_VARS (*tp); decl; decl = TREE_CHAIN (decl)) - { - /* Walk the DECL_INITIAL and DECL_SIZE. We don't want to walk - into declarations that are just mentioned, rather than - declared; they don't really belong to this part of the tree. - And, we can see cycles: the initializer for a declaration - can refer to the declaration itself. */ - WALK_SUBTREE (DECL_INITIAL (decl)); - WALK_SUBTREE (DECL_SIZE (decl)); - WALK_SUBTREE (DECL_SIZE_UNIT (decl)); - } - WALK_SUBTREE_TAIL (BIND_EXPR_BODY (*tp)); - } + /* Call the function for the type. See if it returns anything or + doesn't want us to continue. If we are to continue, walk both + the normal fields and those for the declaration case. */ + result = (*func) (type_p, &walk_subtrees, data); + if (result || !walk_subtrees) + return NULL_TREE; - case STATEMENT_LIST: - { - tree_stmt_iterator i; - for (i = tsi_start (*tp); !tsi_end_p (i); tsi_next (&i)) - WALK_SUBTREE (*tsi_stmt_ptr (i)); - } - break; + result = walk_type_fields (*type_p, func, data, pset); + if (result) + return result; - default: - /* ??? This could be a language-defined node. We really should make - a hook for it, but right now just ignore it. */ - break; + /* 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) + { + tree field; + + for (field = TYPE_FIELDS (*type_p); field; + field = TREE_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 + to elsewhere in the tree. Also, ignore things that + aren't fields. */ + if (TREE_CODE (field) != FIELD_DECL) + continue; + + WALK_SUBTREE (DECL_FIELD_OFFSET (field)); + WALK_SUBTREE (DECL_SIZE (field)); + WALK_SUBTREE (DECL_SIZE_UNIT (field)); + if (TREE_CODE (*type_p) == QUAL_UNION_TYPE) + WALK_SUBTREE (DECL_QUALIFIER (field)); + } + } + + WALK_SUBTREE (TYPE_SIZE (*type_p)); + WALK_SUBTREE_TAIL (TYPE_SIZE_UNIT (*type_p)); } + /* FALLTHRU */ + + default: + if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))) + { + int i, len; + + /* Walk over all the sub-trees of this operand. */ + len = TREE_CODE_LENGTH (code); + + /* Go through the subtrees. We need to do this in forward order so + that the scope of a FOR_EXPR is handled properly. */ + if (len) + { + for (i = 0; i < len - 1; ++i) + WALK_SUBTREE (TREE_OPERAND (*tp, i)); + WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len - 1)); + } + } + + /* If this is a type, walk the needed fields in the type. */ + else if (TYPE_P (*tp)) + return walk_type_fields (*tp, func, data, pset); + break; } /* We didn't find what we were looking for. */ @@ -6884,4 +7543,30 @@ walk_tree_without_duplicates (tree *tp, walk_tree_fn func, void *data) return result; } + +/* Return true if STMT is an empty statement or contains nothing but + empty statements. */ + +bool +empty_body_p (tree stmt) +{ + tree_stmt_iterator i; + tree body; + + if (IS_EMPTY_STMT (stmt)) + return true; + else if (TREE_CODE (stmt) == BIND_EXPR) + body = BIND_EXPR_BODY (stmt); + else if (TREE_CODE (stmt) == STATEMENT_LIST) + body = stmt; + else + return false; + + for (i = tsi_start (body); !tsi_end_p (i); tsi_next (&i)) + if (!empty_body_p (tsi_stmt (i))) + return false; + + return true; +} + #include "gt-tree.h"