X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ftree.c;h=68aa58f9619e4533eb7468093feac4c8c51faf3c;hb=979f9661a4e43d3b5eb87272b4b10cc3e826732b;hp=6a97e4109940f35a128f3794022aa1fb1eb2772f;hpb=c1f8b3321d711be668f4e4e958b5edacdc50e382;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/tree.c b/gcc/tree.c index 6a97e410994..68aa58f9619 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. @@ -96,7 +97,9 @@ static const char * const tree_node_kind_names[] = { "constructors", "random kinds", "lang_decl kinds", - "lang_type kinds" + "lang_type kinds", + "omp clauses", + "gimple statements" }; #endif /* GATHER_STATISTICS */ @@ -163,7 +166,6 @@ static int int_cst_hash_eq (const void *, const void *); static void print_type_hash_statistics (void); 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 unsigned int type_hash_list (tree, hashval_t); static unsigned int attribute_hash_list (tree, hashval_t); @@ -172,13 +174,49 @@ 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. */ void init_ttree (void) { - /* Initialize the hash table of types. */ type_hash_table = htab_create_ggc (TYPE_HASH_INITIAL_SIZE, type_hash_hash, type_hash_eq, 0); @@ -230,6 +268,15 @@ init_ttree (void) 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; @@ -288,6 +335,11 @@ tree_code_size (enum tree_code code) 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); } @@ -305,6 +357,10 @@ tree_code_size (enum tree_code code) return (sizeof (struct tree_exp) + (TREE_CODE_LENGTH (code) - 1) * sizeof (char *)); + case tcc_gimple_stmt: + return (sizeof (struct gimple_stmt) + + (TREE_CODE_LENGTH (code) - 1) * sizeof (char *)); + case tcc_constant: /* a constant */ switch (code) { @@ -327,6 +383,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); @@ -366,7 +423,12 @@ tree_size (tree node) + (TREE_VEC_LENGTH (node) - 1) * sizeof(char *)); case STRING_CST: - return sizeof (struct tree_string) + TREE_STRING_LENGTH (node) - 1; + return TREE_STRING_LENGTH (node) + offsetof (struct tree_string, str) + 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); @@ -375,8 +437,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. */ @@ -418,6 +481,10 @@ make_node_stat (enum tree_code code MEM_STAT_DECL) kind = c_kind; break; + case tcc_gimple_stmt: + kind = gimple_stmt_kind; + break; + case tcc_exceptional: /* something random, like an identifier. */ switch (code) { @@ -479,13 +546,16 @@ 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; if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS)) DECL_IN_SYSTEM_HEADER (t) = in_system_header; - /* We have not yet computed the alias set for this declaration. */ - DECL_POINTER_ALIAS_SET (t) = -1; + 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++; @@ -530,6 +600,17 @@ make_node_stat (enum tree_code code MEM_STAT_DECL) } break; + case tcc_gimple_stmt: + switch (code) + { + case GIMPLE_MODIFY_STMT: + TREE_SIDE_EFFECTS (t) = 1; + break; + + default: + break; + } + default: /* Other classes need no special treatment. */ break; @@ -554,10 +635,11 @@ copy_node_stat (tree node MEM_STAT_DECL) t = ggc_alloc_zone_pass_stat (length, &tree_zone); memcpy (t, node, length); - TREE_CHAIN (t) = 0; + if (!GIMPLE_TUPLE_P (node)) + TREE_CHAIN (t) = 0; TREE_ASM_WRITTEN (t) = 0; TREE_VISITED (t) = 0; - t->common.ann = 0; + t->base.ann = 0; if (TREE_CODE_CLASS (code) == tcc_declaration) { @@ -765,7 +847,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)) { @@ -784,8 +865,12 @@ build_int_cst_wide (tree type, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi) ix = 0; } break; - default: + + case ENUMERAL_TYPE: break; + + default: + gcc_unreachable (); } if (ix >= 0) @@ -909,6 +994,10 @@ build_vector (tree type, tree vals) { tree value = TREE_VALUE (link); + /* Don't crash if we get an address constant. */ + if (!CONSTANT_CLASS_P (value)) + continue; + over1 |= TREE_OVERFLOW (value); over2 |= TREE_CONSTANT_OVERFLOW (value); } @@ -952,13 +1041,16 @@ build_constructor_single (tree type, tree index, tree value) { VEC(constructor_elt,gc) *v; constructor_elt *elt; + tree t; 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); + t = build_constructor (type, v); + TREE_CONSTANT (t) = TREE_CONSTANT (value); + return t; } @@ -967,8 +1059,9 @@ build_constructor_single (tree type, tree index, tree value) tree build_constructor_from_list (tree type, tree vals) { - tree t; + tree t, val; VEC(constructor_elt,gc) *v = NULL; + bool constant_p = true; if (vals) { @@ -976,12 +1069,17 @@ build_constructor_from_list (tree type, tree vals) for (t = vals; t; t = TREE_CHAIN (t)) { constructor_elt *elt = VEC_quick_push (constructor_elt, v, NULL); + val = TREE_VALUE (t); elt->index = TREE_PURPOSE (t); - elt->value = TREE_VALUE (t); + elt->value = val; + if (!TREE_CONSTANT (val)) + constant_p = false; } } - return build_constructor (type, v); + t = build_constructor (type, v); + TREE_CONSTANT (t) = constant_p; + return t; } @@ -1050,8 +1148,9 @@ build_string (int len, const char *str) { tree s; size_t length; - - length = len + sizeof (struct tree_string); + + /* Do not waste bytes provided by padding of struct tree_string. */ + length = len + offsetof (struct tree_string, str) + 1; #ifdef GATHER_STATISTICS tree_node_counts[(int) c_kind]++; @@ -1090,6 +1189,47 @@ build_complex (tree type, tree real, tree imag) return t; } +/* Return a constant of arithmetic type TYPE which is the + multiplicative identity of the set TYPE. */ + +tree +build_one_cst (tree type) +{ + switch (TREE_CODE (type)) + { + case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE: + case POINTER_TYPE: case REFERENCE_TYPE: + case OFFSET_TYPE: + return build_int_cst (type, 1); + + case REAL_TYPE: + return build_real (type, dconst1); + + case VECTOR_TYPE: + { + tree scalar, cst; + int i; + + scalar = build_one_cst (TREE_TYPE (type)); + + /* Create 'vect_cst_ = {cst,cst,...,cst}' */ + cst = NULL_TREE; + for (i = TYPE_VECTOR_SUBPARTS (type); --i >= 0; ) + cst = tree_cons (NULL_TREE, scalar, cst); + + return build_vector (type, cst); + } + + case COMPLEX_TYPE: + return build_complex (type, + build_one_cst (TREE_TYPE (type)), + fold_convert (TREE_TYPE (type), integer_zero_node)); + + default: + gcc_unreachable (); + } +} + /* Build a BINFO with LEN language slots. */ tree @@ -1148,7 +1288,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 @@ -1165,7 +1304,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 @@ -1189,14 +1327,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. */ @@ -1240,7 +1379,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)) @@ -1278,7 +1417,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 @@ -1371,7 +1509,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)) @@ -1386,7 +1523,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)) @@ -1401,7 +1537,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)) @@ -1416,7 +1551,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)) @@ -1662,7 +1796,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) @@ -1670,6 +1803,39 @@ int_size_in_bytes (tree type) return TREE_INT_CST_LOW (t); } + +/* Return the maximum size of TYPE (in bytes) as a wide integer + or return -1 if the size can vary or is larger than an integer. */ + +HOST_WIDE_INT +max_int_size_in_bytes (tree type) +{ + HOST_WIDE_INT size = -1; + tree size_tree; + + /* If this is an array type, check for a possible MAX_SIZE attached. */ + + if (TREE_CODE (type) == ARRAY_TYPE) + { + size_tree = TYPE_ARRAY_MAX_SIZE (type); + + if (size_tree && host_integerp (size_tree, 1)) + size = tree_low_cst (size_tree, 1); + } + + /* If we still haven't been able to get a size, see if the language + can compute a maximum size. */ + + if (size == -1) + { + size_tree = lang_hooks.types.max_size (type); + + if (size_tree && host_integerp (size_tree, 1)) + size = tree_low_cst (size_tree, 1); + } + + return size; +} /* Return the bit position of FIELD, in bits from the start of the record. This is a tree of type bitsizetype. */ @@ -1727,7 +1893,14 @@ expr_align (tree t) align1 = TYPE_ALIGN (TREE_TYPE (t)); return MAX (align0, align1); - case SAVE_EXPR: case COMPOUND_EXPR: case MODIFY_EXPR: + case MODIFY_EXPR: + /* FIXME tuples: It is unclear to me if this function, which + is only called from ADA, is called on gimple or non gimple + trees. Let's assume it's from gimple trees unless we hit + this abort. */ + gcc_unreachable (); + + case SAVE_EXPR: case COMPOUND_EXPR: case GIMPLE_MODIFY_STMT: case INIT_EXPR: case TARGET_EXPR: case WITH_CLEANUP_EXPR: case CLEANUP_POINT_EXPR: /* These don't change the alignment of an object. */ @@ -1979,6 +2152,10 @@ tree_node_structure (tree t) 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; } @@ -1992,6 +2169,8 @@ tree_node_structure (tree t) case tcc_expression: case tcc_statement: return TS_EXP; + case tcc_gimple_stmt: + return TS_GIMPLE_STATEMENT; default: /* tcc_constant and tcc_exceptional */ break; } @@ -2004,6 +2183,8 @@ tree_node_structure (tree t) case VECTOR_CST: return TS_VECTOR; case STRING_CST: return TS_STRING; /* tcc_exceptional cases. */ + /* FIXME tuples: eventually this should be TS_BASE. For now, nothing + returns TS_BASE. */ case ERROR_MARK: return TS_COMMON; case IDENTIFIER_NODE: return TS_IDENTIFIER; case TREE_LIST: return TS_LIST; @@ -2016,6 +2197,7 @@ tree_node_structure (tree t) 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 (); @@ -2114,7 +2296,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: @@ -2454,9 +2635,6 @@ stabilize_reference (tree ref) case CONVERT_EXPR: case FLOAT_EXPR: case FIX_TRUNC_EXPR: - case FIX_FLOOR_EXPR: - case FIX_ROUND_EXPR: - case FIX_CEIL_EXPR: result = build_nt (code, stabilize_reference (TREE_OPERAND (ref, 0))); break; @@ -2602,7 +2780,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; @@ -2777,15 +2955,15 @@ 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: - if (TREE_CODE_CLASS (code) == tcc_unary + if ((TREE_CODE_CLASS (code) == tcc_unary || code == VIEW_CONVERT_EXPR) && node && !TYPE_P (node) && TREE_CONSTANT (node)) TREE_CONSTANT (t) = 1; - if (TREE_CODE_CLASS (code) == tcc_unary + if ((TREE_CODE_CLASS (code) == tcc_unary || code == VIEW_CONVERT_EXPR) && node && TREE_INVARIANT (node)) TREE_INVARIANT (t) = 1; if (TREE_CODE_CLASS (code) == tcc_reference @@ -2821,6 +2999,17 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL) gcc_assert (TREE_CODE_LENGTH (code) == 2); + if (code == MODIFY_EXPR && cfun && cfun->gimplified) + { + /* We should be talking GIMPLE_MODIFY_STMT by now. */ + gcc_unreachable (); + } + + /* FIXME tuples: For now let's be lazy; later we must rewrite all + build2 calls to build2_gimple calls. */ + if (TREE_CODE_CLASS (code) == tcc_gimple_stmt) + return build2_gimple (code, arg0, arg1); + t = make_node_stat (code PASS_MEM_STAT); TREE_TYPE (t) = tt; @@ -2851,6 +3040,35 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL) return t; } + +/* Similar as build2_stat, but for GIMPLE tuples. For convenience's sake, + arguments and return type are trees. */ + +tree +build2_gimple_stat (enum tree_code code, tree arg0, tree arg1 MEM_STAT_DECL) +{ + bool side_effects; + tree t; + + gcc_assert (TREE_CODE_LENGTH (code) == 2); + + t = make_node_stat (code PASS_MEM_STAT); + + side_effects = TREE_SIDE_EFFECTS (t); + + /* ?? We don't care about setting flags for tuples... */ + GIMPLE_STMT_OPERAND (t, 0) = arg0; + GIMPLE_STMT_OPERAND (t, 1) = arg1; + + /* ...except perhaps side_effects and volatility. ?? */ + TREE_SIDE_EFFECTS (t) = side_effects; + TREE_THIS_VOLATILE (t) = (TREE_CODE_CLASS (code) == tcc_reference + && arg0 && TREE_THIS_VOLATILE (arg0)); + + + return t; +} + tree build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1, tree arg2 MEM_STAT_DECL) @@ -2925,6 +3143,34 @@ build4_stat (enum tree_code code, tree tt, tree arg0, tree arg1, } tree +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 (TREE_CODE_LENGTH (code) == 5); + + 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); + + TREE_SIDE_EFFECTS (t) = side_effects; + TREE_THIS_VOLATILE (t) + = (TREE_CODE_CLASS (code) == tcc_reference + && arg0 && TREE_THIS_VOLATILE (arg0)); + + return t; +} + +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) @@ -3004,14 +3250,6 @@ build_decl_stat (enum tree_code code, tree name, tree type MEM_STAT_DECL) else if (code == FUNCTION_DECL) DECL_MODE (t) = FUNCTION_MODE; - 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; } @@ -3050,7 +3288,7 @@ build_block (tree vars, tree subblocks, tree supercontext, tree chain) #if 1 /* ! defined(USE_MAPPED_LOCATION) */ /* ??? gengtype doesn't handle conditionals */ -static GTY(()) location_t *last_annotated_node; +static GTY(()) source_locus last_annotated_node; #endif #ifdef USE_MAPPED_LOCATION @@ -3059,7 +3297,12 @@ expanded_location expand_location (source_location loc) { expanded_location xloc; - if (loc == 0) { xloc.file = NULL; xloc.line = 0; xloc.column = 0; } + if (loc == 0) + { + xloc.file = NULL; + xloc.line = 0; + xloc.column = 0; + } else { const struct line_map *map = linemap_lookup (&line_table, loc); @@ -3115,6 +3358,130 @@ annotate_with_locus (tree node, location_t locus) } #endif +/* Source location accessor functions. */ + + +/* The source location of this expression. Non-tree_exp nodes such as + decls and constants can be shared among multiple locations, so + return nothing. */ +location_t +expr_location (tree node) +{ +#ifdef USE_MAPPED_LOCATION + if (GIMPLE_STMT_P (node)) + return GIMPLE_STMT_LOCUS (node); + return EXPR_P (node) ? node->exp.locus : UNKNOWN_LOCATION; +#else + if (GIMPLE_STMT_P (node)) + return EXPR_HAS_LOCATION (node) + ? *GIMPLE_STMT_LOCUS (node) : UNKNOWN_LOCATION; + return EXPR_HAS_LOCATION (node) ? *node->exp.locus : UNKNOWN_LOCATION; +#endif +} + +void +set_expr_location (tree node, location_t locus) +{ +#ifdef USE_MAPPED_LOCATION + if (GIMPLE_STMT_P (node)) + GIMPLE_STMT_LOCUS (node) = locus; + else + EXPR_CHECK (node)->exp.locus = locus; +#else + annotate_with_locus (node, locus); +#endif +} + +bool +expr_has_location (tree node) +{ +#ifdef USE_MAPPED_LOCATION + return expr_location (node) != UNKNOWN_LOCATION; +#else + return expr_locus (node) != NULL; +#endif +} + +#ifdef USE_MAPPED_LOCATION +source_location * +#else +source_locus +#endif +expr_locus (tree node) +{ +#ifdef USE_MAPPED_LOCATION + if (GIMPLE_STMT_P (node)) + return &GIMPLE_STMT_LOCUS (node); + return EXPR_P (node) ? &node->exp.locus : (location_t *) NULL; +#else + if (GIMPLE_STMT_P (node)) + return GIMPLE_STMT_LOCUS (node); + /* ?? The cast below was originally "(location_t *)" in the macro, + but that makes no sense. ?? */ + return EXPR_P (node) ? node->exp.locus : (source_locus) NULL; +#endif +} + +void +set_expr_locus (tree node, +#ifdef USE_MAPPED_LOCATION + source_location *loc +#else + source_locus loc +#endif + ) +{ +#ifdef USE_MAPPED_LOCATION + if (loc == NULL) + { + if (GIMPLE_STMT_P (node)) + GIMPLE_STMT_LOCUS (node) = UNKNOWN_LOCATION; + else + EXPR_CHECK (node)->exp.locus = UNKNOWN_LOCATION; + } + else + { + if (GIMPLE_STMT_P (node)) + GIMPLE_STMT_LOCUS (node) = *loc; + else + EXPR_CHECK (node)->exp.locus = *loc; + } +#else + if (GIMPLE_STMT_P (node)) + GIMPLE_STMT_LOCUS (node) = loc; + else + EXPR_CHECK (node)->exp.locus = loc; +#endif +} + +const char ** +expr_filename (tree node) +{ +#ifdef USE_MAPPED_LOCATION + if (GIMPLE_STMT_P (node)) + return &LOCATION_FILE (GIMPLE_STMT_LOCUS (node)); + return &LOCATION_FILE (EXPR_CHECK (node)->exp.locus); +#else + if (GIMPLE_STMT_P (node)) + return &GIMPLE_STMT_LOCUS (node)->file; + return &(EXPR_CHECK (node)->exp.locus->file); +#endif +} + +int * +expr_lineno (tree node) +{ +#ifdef USE_MAPPED_LOCATION + if (GIMPLE_STMT_P (node)) + return &LOCATION_LINE (GIMPLE_STMT_LOCUS (node)); + return &LOCATION_LINE (EXPR_CHECK (node)->exp.locus); +#else + if (GIMPLE_STMT_P (node)) + return &GIMPLE_STMT_LOCUS (node)->line; + return &EXPR_CHECK (node)->exp.locus->line; +#endif +} + /* Return a declaration like DDECL except that its DECL_ATTRIBUTES is ATTRIBUTE. */ @@ -3194,12 +3561,12 @@ iterative_hash_host_wide_int (HOST_WIDE_INT val, hashval_t val2) } /* Return a type like TTYPE except that its TYPE_ATTRIBUTE - is ATTRIBUTE. + is ATTRIBUTE and its qualifiers are QUALS. Record such modified types already made so we don't make duplicates. */ -tree -build_type_attribute_variant (tree ttype, tree attribute) +static tree +build_type_attribute_qual_variant (tree ttype, tree attribute, int quals) { if (! attribute_list_equal (TYPE_ATTRIBUTES (ttype), attribute)) { @@ -3250,13 +3617,25 @@ build_type_attribute_variant (tree ttype, tree attribute) } ntype = type_hash_canon (hashcode, ntype); - ttype = build_qualified_type (ntype, TYPE_QUALS (ttype)); + ttype = build_qualified_type (ntype, 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)); +} + /* Return nonzero if IDENT is a valid name for attribute ATTR, or zero if not. @@ -3287,7 +3666,6 @@ is_attribute_with_length_p (const char *attr, int attr_len, tree ident) gcc_assert (attr[1] == '_'); gcc_assert (attr[attr_len - 2] == '_'); gcc_assert (attr[attr_len - 1] == '_'); - gcc_assert (attr[1] == '_'); if (ident_len == attr_len - 4 && strncmp (attr + 2, p, attr_len - 4) == 0) return 1; @@ -3337,6 +3715,28 @@ lookup_attribute (const char *attr_name, tree list) return NULL_TREE; } +/* Remove any instances of attribute ATTR_NAME in LIST and return the + modified list. */ + +tree +remove_attribute (const char *attr_name, tree list) +{ + tree *p; + size_t attr_len = strlen (attr_name); + + for (p = &list; *p; ) + { + tree l = *p; + gcc_assert (TREE_CODE (TREE_PURPOSE (l)) == IDENTIFIER_NODE); + if (is_attribute_with_length_p (attr_name, attr_len, TREE_PURPOSE (l))) + *p = TREE_CHAIN (l); + else + p = &TREE_CHAIN (l); + } + + return list; +} + /* Return an attribute list that is the union of a1 and a2. */ tree @@ -3371,7 +3771,17 @@ merge_attributes (tree a1, tree a2) a = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)), TREE_CHAIN (a))) { - if (simple_cst_equal (TREE_VALUE (a), TREE_VALUE (a2)) == 1) + if (TREE_VALUE (a) != NULL + && TREE_CODE (TREE_VALUE (a)) == TREE_LIST + && TREE_VALUE (a2) != NULL + && TREE_CODE (TREE_VALUE (a2)) == TREE_LIST) + { + if (simple_cst_list_equal (TREE_VALUE (a), + TREE_VALUE (a2)) == 1) + break; + } + else if (simple_cst_equal (TREE_VALUE (a), + TREE_VALUE (a2)) == 1) break; } if (a == NULL_TREE) @@ -3523,9 +3933,18 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags, return NULL_TREE; } + if (TREE_CODE (node) != FUNCTION_DECL + && TREE_CODE (node) != VAR_DECL) + { + *no_add_attrs = true; + warning (OPT_Wattributes, "%qs attribute ignored", + IDENTIFIER_POINTER (name)); + return NULL_TREE; + } + /* Report error on dllimport ambiguities seen now before they cause any damage. */ - if (is_attribute_p ("dllimport", name)) + else if (is_attribute_p ("dllimport", name)) { /* Honor any target-specific overrides. */ if (!targetm.valid_dllimport_attribute_p (node)) @@ -3645,20 +4064,6 @@ build_qualified_type (tree type, int type_quals) { t = build_variant_type_copy (type); set_type_quals (t, type_quals); - - /* If it's a pointer type, the new variant points to the same type. */ - if (TREE_CODE (type) == POINTER_TYPE) - { - TYPE_NEXT_PTR_TO (t) = TYPE_NEXT_PTR_TO (type); - TYPE_NEXT_PTR_TO (type) = t; - } - - /* Same for a reference type. */ - else if (TREE_CODE (type) == REFERENCE_TYPE) - { - TYPE_NEXT_REF_TO (t) = TYPE_NEXT_REF_TO (type); - TYPE_NEXT_REF_TO (type) = t; - } } return t; @@ -3979,7 +4384,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))) @@ -4197,15 +4601,21 @@ attribute_list_contained (tree l1, tree l2) attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)), TREE_CHAIN (attr))) { - if (simple_cst_equal (TREE_VALUE (t2), TREE_VALUE (attr)) == 1) + if (TREE_VALUE (t2) != NULL + && TREE_CODE (TREE_VALUE (t2)) == TREE_LIST + && TREE_VALUE (attr) != NULL + && TREE_CODE (TREE_VALUE (attr)) == TREE_LIST) + { + if (simple_cst_list_equal (TREE_VALUE (t2), + TREE_VALUE (attr)) == 1) + break; + } + else if (simple_cst_equal (TREE_VALUE (t2), TREE_VALUE (attr)) == 1) break; } if (attr == 0) return 0; - - if (simple_cst_equal (TREE_VALUE (t2), TREE_VALUE (attr)) != 1) - return 0; } return 1; @@ -4324,7 +4734,6 @@ 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 @@ -4698,8 +5107,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 { @@ -4774,12 +5183,10 @@ build_pointer_type_for_mode (tree to_type, enum machine_mode mode, && TREE_CODE (TYPE_POINTER_TO (to_type)) != POINTER_TYPE) return TYPE_POINTER_TO (to_type); - /* First, if we already have an unqualified type for pointers to TO_TYPE - and it's the proper mode, use it. */ + /* First, if we already have a type for pointers to TO_TYPE and it's + the proper mode, use it. */ for (t = TYPE_POINTER_TO (to_type); t; t = TYPE_NEXT_PTR_TO (t)) - if (TYPE_MODE (t) == mode - && !TYPE_QUALS (t) - && TYPE_REF_CAN_ALIAS_ALL (t) == can_alias_all) + if (TYPE_MODE (t) == mode && TYPE_REF_CAN_ALIAS_ALL (t) == can_alias_all) return t; t = make_node (POINTER_TYPE); @@ -4825,12 +5232,10 @@ build_reference_type_for_mode (tree to_type, enum machine_mode mode, && TREE_CODE (TYPE_REFERENCE_TO (to_type)) != REFERENCE_TYPE) return TYPE_REFERENCE_TO (to_type); - /* First, if we already have an unqualified type for references to TO_TYPE - and it's the proper mode, use it. */ + /* First, if we already have a type for pointers to TO_TYPE and it's + the proper mode, use it. */ for (t = TYPE_REFERENCE_TO (to_type); t; t = TYPE_NEXT_REF_TO (t)) - if (TYPE_MODE (t) == mode - && !TYPE_QUALS (t) - && TYPE_REF_CAN_ALIAS_ALL (t) == can_alias_all) + if (TYPE_MODE (t) == mode && TYPE_REF_CAN_ALIAS_ALL (t) == can_alias_all) return t; t = make_node (REFERENCE_TYPE); @@ -4933,9 +5338,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) @@ -4946,8 +5350,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); @@ -4995,7 +5399,11 @@ build_array_type (tree elt_type, tree index_type) if (index_type == 0) { - layout_type (t); + tree save = t; + hashcode = iterative_hash_object (TYPE_HASH (elt_type), hashcode); + t = type_hash_canon (hashcode, t); + if (save == t) + layout_type (t); return t; } @@ -5537,8 +5945,10 @@ find_var_from_fn (tree *tp, int *walk_subtrees, void *data) } /* Returns true if T is, contains, or refers to a type with variable - size. If FN is nonzero, only return true if a modifier of the type - or position of FN is a variable or parameter inside FN. + size. For METHOD_TYPEs and FUNCTION_TYPEs we exclude the + arguments, but not the return type. If FN is nonzero, only return + true if a modifier of the type or position of FN is a variable or + parameter inside FN. This concept is more general than that of C99 'variably modified types': in C99, a struct type is never variably modified because a VLA may not @@ -5564,19 +5974,14 @@ variably_modified_type_p (tree type, tree fn) if (type == error_mark_node) return false; - /* If TYPE itself has variable size, it is variably modified. - - We do not yet have a representation of the C99 '[*]' syntax. - When a representation is chosen, this function should be modified - to test for that case as well. */ + /* If TYPE itself has variable size, it is variably modified. */ RETURN_TRUE_IF_VAR (TYPE_SIZE (type)); - RETURN_TRUE_IF_VAR (TYPE_SIZE_UNIT(type)); + RETURN_TRUE_IF_VAR (TYPE_SIZE_UNIT (type)); switch (TREE_CODE (type)) { case POINTER_TYPE: case REFERENCE_TYPE: - case ARRAY_TYPE: case VECTOR_TYPE: if (variably_modified_type_p (TREE_TYPE (type), fn)) return true; @@ -5584,23 +5989,16 @@ variably_modified_type_p (tree type, tree fn) case FUNCTION_TYPE: case METHOD_TYPE: - /* If TYPE is a function type, it is variably modified if any of the - parameters or the return type are variably modified. */ + /* If TYPE is a function type, it is variably modified if the + return type is variably modified. */ if (variably_modified_type_p (TREE_TYPE (type), fn)) return true; - - for (t = TYPE_ARG_TYPES (type); - t && t != void_list_node; - t = TREE_CHAIN (t)) - if (variably_modified_type_p (TREE_VALUE (t), fn)) - return true; break; case INTEGER_TYPE: 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)); @@ -5610,7 +6008,7 @@ variably_modified_type_p (tree type, tree fn) case RECORD_TYPE: case UNION_TYPE: case QUAL_UNION_TYPE: - /* We can't see if any of the field are variably-modified by the + /* We can't see if any of the fields are variably-modified by the definition we normally use, since that would produce infinite recursion via pointers. */ /* This is variably modified if some field's type is. */ @@ -5626,6 +6024,13 @@ variably_modified_type_p (tree type, tree fn) } break; + case ARRAY_TYPE: + /* Do not call ourselves to avoid infinite recursion. This is + variably modified if the element type is. */ + RETURN_TRUE_IF_VAR (TYPE_SIZE (TREE_TYPE (type))); + RETURN_TRUE_IF_VAR (TYPE_SIZE_UNIT (TREE_TYPE (type))); + break; + default: break; } @@ -5727,6 +6132,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); @@ -5835,22 +6243,48 @@ clean_symbol_name (char *p) *p = '_'; } -/* Generate a name for a function unique to this translation unit. +/* Generate a name for a special-purpose function function. + The generated name may need to be unique across the whole link. TYPE is some string to identify the purpose of this function to the - linker or collect2. */ + linker or collect2; it must start with an uppercase letter, + one of: + I - for constructors + D - for destructors + N - for C++ anonymous namespaces + F - for DWARF unwind frame information. */ tree -get_file_function_name_long (const char *type) +get_file_function_name (const char *type) { char *buf; const char *p; char *q; + /* If we already have a name we know to be unique, just use that. */ if (first_global_object_name) p = first_global_object_name; + /* If the target is handling the constructors/destructors, they + will be local to this file and the name is only necessary for + debugging purposes. */ + else if ((type[0] == 'I' || type[0] == 'D') && targetm.have_ctors_dtors) + { + const char *file = main_input_filename; + if (! file) + file = input_filename; + /* Just use the file's basename, because the full pathname + might be quite long. */ + p = strrchr (file, '/'); + if (p) + p++; + else + p = file; + p = q = ASTRDUP (p); + clean_symbol_name (q); + } else { - /* We don't have anything that we know to be unique to this translation + /* Otherwise, the name must be unique across the entire link. + We don't have anything that we know to be unique to this translation unit, so use what we do have and throw in some randomness. */ unsigned len; const char *name = weak_global_object_name; @@ -5882,20 +6316,6 @@ get_file_function_name_long (const char *type) return get_identifier (buf); } - -/* If KIND=='I', return a suitable global initializer (constructor) name. - If KIND=='D', return a suitable global clean-up (destructor) name. */ - -tree -get_file_function_name (int kind) -{ - char p[2]; - - p[0] = kind; - p[1] = 0; - - return get_file_function_name_long (p); -} #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007) @@ -5992,6 +6412,103 @@ tree_class_check_failed (const tree node, const enum tree_code_class 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, 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, @@ -6054,6 +6571,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, @@ -6063,8 +6594,19 @@ tree_operand_check_failed (int idx, enum tree_code code, const char *file, static tree make_vector_type (tree innertype, int nunits, enum machine_mode mode) { - tree t = make_node (VECTOR_TYPE); + 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); TYPE_MODE (t) = mode; @@ -6089,17 +6631,10 @@ make_vector_type (tree innertype, int nunits, enum machine_mode mode) TYPE_UID (rt) = TYPE_UID (t); } - /* Build our main variant, based on the main variant of the inner type. */ - if (TYPE_MAIN_VARIANT (innertype) != innertype) - { - tree innertype_main_variant = TYPE_MAIN_VARIANT (innertype); - unsigned int hash = TYPE_HASH (innertype_main_variant); - TYPE_MAIN_VARIANT (t) - = type_hash_canon (hash, make_vector_type (innertype_main_variant, - nunits, mode)); - } - - return t; + hashcode = iterative_hash_host_wide_int (VECTOR_TYPE, hashcode); + hashcode = iterative_hash_host_wide_int (mode, hashcode); + hashcode = iterative_hash_object (TYPE_HASH (innertype), hashcode); + return type_hash_canon (hashcode, t); } static tree @@ -6137,7 +6672,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. */ @@ -6145,6 +6682,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); @@ -6239,6 +6777,29 @@ 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); + /* Fixed size integer types. */ + uint32_type_node = build_nonstandard_integer_type (32, true); + uint64_type_node = build_nonstandard_integer_type (64, true); + + /* 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); @@ -6278,8 +6839,8 @@ local_define_builtin (const char *name, tree type, enum built_in_function code, { tree decl; - decl = lang_hooks.builtin_function (name, type, code, BUILT_IN_NORMAL, - library_name, NULL_TREE); + decl = add_builtin_function (name, type, code, BUILT_IN_NORMAL, + library_name, NULL_TREE); if (ecf_flags & ECF_CONST) TREE_READONLY (decl) = 1; if (ecf_flags & ECF_PURE) @@ -6371,6 +6932,26 @@ build_common_builtin_nodes (void) "__builtin_nonlocal_goto", ECF_NORETURN | ECF_NOTHROW); + tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node); + tmp = tree_cons (NULL_TREE, ptr_type_node, tmp); + ftype = build_function_type (void_type_node, tmp); + local_define_builtin ("__builtin_setjmp_setup", ftype, + BUILT_IN_SETJMP_SETUP, + "__builtin_setjmp_setup", ECF_NOTHROW); + + tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node); + ftype = build_function_type (ptr_type_node, tmp); + local_define_builtin ("__builtin_setjmp_dispatcher", ftype, + BUILT_IN_SETJMP_DISPATCHER, + "__builtin_setjmp_dispatcher", + ECF_PURE | ECF_NOTHROW); + + tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node); + ftype = build_function_type (void_type_node, tmp); + local_define_builtin ("__builtin_setjmp_receiver", ftype, + BUILT_IN_SETJMP_RECEIVER, + "__builtin_setjmp_receiver", ECF_NOTHROW); + ftype = build_function_type (ptr_type_node, void_list_node); local_define_builtin ("__builtin_stack_save", ftype, BUILT_IN_STACK_SAVE, "__builtin_stack_save", ECF_NOTHROW); @@ -6520,6 +7101,7 @@ build_vector_type (tree innertype, int nunits) return make_vector_type (innertype, nunits, VOIDmode); } + /* Build RESX_EXPR with given REGION_NUMBER. */ tree build_resx (int region_number) @@ -6578,16 +7160,6 @@ initializer_zerop (tree init) } } -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 @@ -6597,6 +7169,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. */ @@ -6625,12 +7222,48 @@ in_array_bounds_p (tree ref) return true; } +/* Returns true if it is possible to prove that the range of + an array access REF (an ARRAY_RANGE_REF expression) falls + into the array bounds. */ + +bool +range_in_array_bounds_p (tree ref) +{ + tree domain_type = TYPE_DOMAIN (TREE_TYPE (ref)); + tree range_min, range_max, min, max; + + range_min = TYPE_MIN_VALUE (domain_type); + range_max = TYPE_MAX_VALUE (domain_type); + if (!range_min + || !range_max + || TREE_CODE (range_min) != INTEGER_CST + || TREE_CODE (range_max) != INTEGER_CST) + return false; + + min = array_ref_low_bound (ref); + max = array_ref_up_bound (ref); + if (!min + || !max + || TREE_CODE (min) != INTEGER_CST + || TREE_CODE (max) != INTEGER_CST) + return false; + + if (tree_int_cst_lt (range_min, min) + || tree_int_cst_lt (max, range_max)) + return false; + + return true; +} + /* Return true if T (assumed to be a DECL) is a global variable. */ 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 @@ -6728,11 +7361,11 @@ tree_fold_gcd (tree a, tree b) if (tree_int_cst_sgn (a) == -1) a = fold_build2 (MULT_EXPR, type, a, - convert (type, integer_minus_one_node)); + 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)); + build_int_cst (type, -1)); while (1) { @@ -6752,6 +7385,8 @@ tree_fold_gcd (tree a, tree b) tree unsigned_type_for (tree type) { + if (POINTER_TYPE_P (type)) + return lang_hooks.types.unsigned_type (size_type_node); return lang_hooks.types.unsigned_type (type); } @@ -6760,6 +7395,8 @@ unsigned_type_for (tree type) tree signed_type_for (tree type) { + if (POINTER_TYPE_P (type)) + return lang_hooks.types.signed_type (size_type_node); return lang_hooks.types.signed_type (type); } @@ -7001,15 +7638,6 @@ walk_type_fields (tree type, walk_tree_fn func, void *data, WALK_SUBTREE (TYPE_DOMAIN (type)); break; - 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)); - break; - case OFFSET_TYPE: WALK_SUBTREE (TREE_TYPE (type)); WALK_SUBTREE (TYPE_OFFSET_BASETYPE (type)); @@ -7067,202 +7695,237 @@ 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; } result = lang_hooks.tree_inlining.walk_subtrees (tp, &walk_subtrees, func, data, pset); - if (result || ! walk_subtrees) + 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 CONSTRUCTOR: - { - unsigned HOST_WIDE_INT idx; - constructor_elt *ce; + 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)); + } - for (idx = 0; - VEC_iterate(constructor_elt, CONSTRUCTOR_ELTS (*tp), idx, ce); - idx++) - WALK_SUBTREE (ce->value); - } - break; + case DECL_EXPR: + /* If this is a TYPE_DECL, walk into the fields of the type that it's + defining. We only want to walk into these fields of a type in this + case and not in the general case of a mere reference to the type. - case SAVE_EXPR: - WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 0)); + The criterion is as follows: if the field can be an expression, it + must be walked only here. This should be in keeping with the fields + 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) + { + tree *type_p = &TREE_TYPE (DECL_EXPR_DECL (*tp)); + if (TREE_CODE (*type_p) == ERROR_MARK) + return NULL_TREE; + + /* 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 result; - 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)); - } + result = walk_type_fields (*type_p, func, data, pset); + if (result) + return result; - 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; + /* 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; - default: - /* ??? This could be a language-defined node. We really should make - a hook for it, but right now just ignore it. */ - break; + 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)); + } + } + + /* Same for scalar types. */ + else if (TREE_CODE (*type_p) == BOOLEAN_TYPE + || TREE_CODE (*type_p) == ENUMERAL_TYPE + || TREE_CODE (*type_p) == INTEGER_TYPE + || TREE_CODE (*type_p) == REAL_TYPE) + { + WALK_SUBTREE (TYPE_MIN_VALUE (*type_p)); + WALK_SUBTREE (TYPE_MAX_VALUE (*type_p)); + } + + 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)) + || IS_GIMPLE_STMT_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 (GENERIC_TREE_OPERAND (*tp, i)); + WALK_SUBTREE_TAIL (GENERIC_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. */ @@ -7286,4 +7949,59 @@ 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; +} + +tree * +tree_block (tree t) +{ + char const c = TREE_CODE_CLASS (TREE_CODE (t)); + + if (IS_EXPR_CODE_CLASS (c)) + return &t->exp.block; + else if (IS_GIMPLE_STMT_CODE_CLASS (c)) + return &GIMPLE_STMT_BLOCK (t); + gcc_unreachable (); + return NULL; +} + +tree * +generic_tree_operand (tree node, int i) +{ + if (GIMPLE_STMT_P (node)) + return &GIMPLE_STMT_OPERAND (node, i); + return &TREE_OPERAND (node, i); +} + +tree * +generic_tree_type (tree node) +{ + if (GIMPLE_STMT_P (node)) + return &void_type_node; + return &TREE_TYPE (node); +} + #include "gt-tree.h"