X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ftree.c;h=8bf2b7718afa065674a5a4fb168a4dd019cf8b0c;hb=9fed75026cca1c2bf8cbf67920c15fe52489d1c9;hp=92d2ba8769b6f3d4a20cd4e42e489e8d5b4b47f8;hpb=f8fd23c043e25507321039cc26eaa28d6d1f63f1;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/tree.c b/gcc/tree.c index 92d2ba8769b..8bf2b7718af 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -1,6 +1,6 @@ /* Language-independent node constructors for parse phase of GNU compiler. Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. This file is part of GCC. @@ -177,7 +177,7 @@ unsigned const char omp_clause_num_ops[] = 1, /* OMP_CLAUSE_PRIVATE */ 1, /* OMP_CLAUSE_SHARED */ 1, /* OMP_CLAUSE_FIRSTPRIVATE */ - 1, /* OMP_CLAUSE_LASTPRIVATE */ + 2, /* OMP_CLAUSE_LASTPRIVATE */ 4, /* OMP_CLAUSE_REDUCTION */ 1, /* OMP_CLAUSE_COPYIN */ 1, /* OMP_CLAUSE_COPYPRIVATE */ @@ -186,7 +186,9 @@ unsigned const char omp_clause_num_ops[] = 1, /* OMP_CLAUSE_SCHEDULE */ 0, /* OMP_CLAUSE_NOWAIT */ 0, /* OMP_CLAUSE_ORDERED */ - 0 /* OMP_CLAUSE_DEFAULT */ + 0, /* OMP_CLAUSE_DEFAULT */ + 3, /* OMP_CLAUSE_COLLAPSE */ + 0 /* OMP_CLAUSE_UNTIED */ }; const char * const omp_clause_code_name[] = @@ -204,7 +206,9 @@ const char * const omp_clause_code_name[] = "schedule", "nowait", "ordered", - "default" + "default", + "collapse", + "untied" }; /* Init tree.c. */ @@ -263,17 +267,14 @@ 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[MEMORY_PARTITION_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[MEMORY_PARTITION_TAG][TS_MEMORY_TAG] = 1; - tree_contains_struct[STRUCT_FIELD_TAG][TS_STRUCT_FIELD_TAG] = 1; tree_contains_struct[MEMORY_PARTITION_TAG][TS_MEMORY_PARTITION_TAG] = 1; tree_contains_struct[VAR_DECL][TS_DECL_WITH_VIS] = 1; @@ -370,8 +371,6 @@ tree_code_size (enum tree_code code) 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); case MEMORY_PARTITION_TAG: return sizeof (struct tree_memory_partition_tag); default: @@ -621,7 +620,6 @@ make_node_stat (enum tree_code code MEM_STAT_DECL) case tcc_constant: TREE_CONSTANT (t) = 1; - TREE_INVARIANT (t) = 1; break; case tcc_expression: @@ -1192,10 +1190,9 @@ 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 (CONST_CAST (TREE_STRING_POINTER (s)), str, len); - ((char *) CONST_CAST (TREE_STRING_POINTER (s)))[len] = '\0'; + memcpy (s->string.str, str, len); + s->string.str[len] = '\0'; return s; } @@ -1605,8 +1602,7 @@ int really_constant_p (const_tree exp) { /* This is not quite the same as STRIP_NOPS. It does more. */ - while (TREE_CODE (exp) == NOP_EXPR - || TREE_CODE (exp) == CONVERT_EXPR + while (CONVERT_EXPR_P (exp) || TREE_CODE (exp) == NON_LVALUE_EXPR) exp = TREE_OPERAND (exp, 0); return TREE_CONSTANT (exp); @@ -1925,7 +1921,7 @@ expr_align (const_tree t) switch (TREE_CODE (t)) { - case NOP_EXPR: case CONVERT_EXPR: case NON_LVALUE_EXPR: + CASE_CONVERT: case NON_LVALUE_EXPR: /* If we have conversions, we know that the alignment of the object must meet each of the alignments of the types. */ align0 = expr_align (TREE_OPERAND (t, 0)); @@ -2056,7 +2052,111 @@ staticp (tree arg) return NULL; } } + + + +/* Return whether OP is a DECL whose address is function-invariant. */ + +bool +decl_address_invariant_p (const_tree op) +{ + /* The conditions below are slightly less strict than the one in + staticp. */ + + switch (TREE_CODE (op)) + { + case PARM_DECL: + case RESULT_DECL: + case LABEL_DECL: + case FUNCTION_DECL: + return true; + + case VAR_DECL: + if (((TREE_STATIC (op) || DECL_EXTERNAL (op)) + && !DECL_DLLIMPORT_P (op)) + || DECL_THREAD_LOCAL_P (op) + || DECL_CONTEXT (op) == current_function_decl + || decl_function_context (op) == current_function_decl) + return true; + break; + + case CONST_DECL: + if ((TREE_STATIC (op) || DECL_EXTERNAL (op)) + || decl_function_context (op) == current_function_decl) + return true; + break; + + default: + break; + } + + return false; +} + + +/* Return true if T is function-invariant (internal function, does + not handle arithmetic; that's handled in skip_simple_arithmetic and + tree_invariant_p). */ + +static bool tree_invariant_p (tree t); + +static bool +tree_invariant_p_1 (tree t) +{ + tree op; + + if (TREE_CONSTANT (t) + || (TREE_READONLY (t) && !TREE_SIDE_EFFECTS (t))) + return true; + + switch (TREE_CODE (t)) + { + case SAVE_EXPR: + return true; + + case ADDR_EXPR: + op = TREE_OPERAND (t, 0); + while (handled_component_p (op)) + { + switch (TREE_CODE (op)) + { + case ARRAY_REF: + case ARRAY_RANGE_REF: + if (!tree_invariant_p (TREE_OPERAND (op, 1)) + || TREE_OPERAND (op, 2) != NULL_TREE + || TREE_OPERAND (op, 3) != NULL_TREE) + return false; + break; + + case COMPONENT_REF: + if (TREE_OPERAND (op, 2) != NULL_TREE) + return false; + break; + + default:; + } + op = TREE_OPERAND (op, 0); + } + + return CONSTANT_CLASS_P (op) || decl_address_invariant_p (op); + + default: + break; + } + + return false; +} + +/* Return true if T is function-invariant. */ + +static bool +tree_invariant_p (tree t) +{ + tree inner = skip_simple_arithmetic (t); + return tree_invariant_p_1 (inner); +} + /* Wrap a SAVE_EXPR around EXPR, if appropriate. Do this to any expression which may be used in more than one place, but must be evaluated only once. @@ -2091,11 +2191,10 @@ save_expr (tree expr) Since it is no problem to reevaluate literals, we just return the literal node. */ inner = skip_simple_arithmetic (t); + if (TREE_CODE (inner) == ERROR_MARK) + return inner; - if (TREE_INVARIANT (inner) - || (TREE_READONLY (inner) && ! TREE_SIDE_EFFECTS (inner)) - || TREE_CODE (inner) == SAVE_EXPR - || TREE_CODE (inner) == ERROR_MARK) + if (tree_invariant_p_1 (inner)) return t; /* If INNER contains a PLACEHOLDER_EXPR, we must evaluate it each time, since @@ -2116,7 +2215,6 @@ save_expr (tree expr) value was computed on both sides of the jump. So make sure it isn't eliminated as dead. */ TREE_SIDE_EFFECTS (t) = 1; - TREE_INVARIANT (t) = 1; return t; } @@ -2144,9 +2242,9 @@ skip_simple_arithmetic (tree expr) inner = TREE_OPERAND (inner, 0); else if (BINARY_CLASS_P (inner)) { - if (TREE_INVARIANT (TREE_OPERAND (inner, 1))) + if (tree_invariant_p (TREE_OPERAND (inner, 1))) inner = TREE_OPERAND (inner, 0); - else if (TREE_INVARIANT (TREE_OPERAND (inner, 0))) + else if (tree_invariant_p (TREE_OPERAND (inner, 0))) inner = TREE_OPERAND (inner, 1); else break; @@ -2189,7 +2287,6 @@ tree_node_structure (const_tree t) return TS_FUNCTION_DECL; case SYMBOL_MEMORY_TAG: case NAME_MEMORY_TAG: - case STRUCT_FIELD_TAG: case MEMORY_PARTITION_TAG: return TS_MEMORY_TAG; default: @@ -2423,8 +2520,7 @@ substitute_in_expr (tree exp, tree f, tree r) { enum tree_code code = TREE_CODE (exp); tree op0, op1, op2, op3; - tree new; - tree inner; + tree new, inner; /* We handle TREE_LIST and COMPONENT_REF separately. */ if (code == TREE_LIST) @@ -2530,22 +2626,25 @@ substitute_in_expr (tree exp, tree f, tree r) { tree copy = NULL_TREE; int i; - int n = TREE_OPERAND_LENGTH (exp); - for (i = 1; i < n; i++) + + for (i = 1; i < TREE_OPERAND_LENGTH (exp); i++) { tree op = TREE_OPERAND (exp, i); - tree newop = SUBSTITUTE_IN_EXPR (op, f, r); - if (newop != op) + tree new_op = SUBSTITUTE_IN_EXPR (op, f, r); + if (new_op != op) { - copy = copy_node (exp); - TREE_OPERAND (copy, i) = newop; + if (!copy) + copy = copy_node (exp); + TREE_OPERAND (copy, i) = new_op; } } + if (copy) new = fold (copy); else return exp; } + break; default: gcc_unreachable (); @@ -2683,18 +2782,19 @@ substitute_placeholder_in_expr (tree exp, tree obj) { tree copy = NULL_TREE; int i; - int n = TREE_OPERAND_LENGTH (exp); - for (i = 1; i < n; i++) + + for (i = 1; i < TREE_OPERAND_LENGTH (exp); i++) { tree op = TREE_OPERAND (exp, i); - tree newop = SUBSTITUTE_PLACEHOLDER_IN_EXPR (op, obj); - if (newop != op) + tree new_op = SUBSTITUTE_PLACEHOLDER_IN_EXPR (op, obj); + if (new_op != op) { if (!copy) copy = copy_node (exp); - TREE_OPERAND (copy, i) = newop; + TREE_OPERAND (copy, i) = new_op; } } + if (copy) return fold (copy); else @@ -2728,8 +2828,7 @@ stabilize_reference (tree ref) /* No action is needed in this case. */ return ref; - case NOP_EXPR: - case CONVERT_EXPR: + CASE_CONVERT: case FLOAT_EXPR: case FIX_TRUNC_EXPR: result = build_nt (code, stabilize_reference (TREE_OPERAND (ref, 0))); @@ -2814,7 +2913,7 @@ stabilize_reference_1 (tree e) ignore things that are actual constant or that already have been handled by this function. */ - if (TREE_INVARIANT (e)) + if (tree_invariant_p (e)) return e; switch (TREE_CODE_CLASS (code)) @@ -2867,7 +2966,6 @@ stabilize_reference_1 (tree e) TREE_READONLY (result) = TREE_READONLY (e); TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (e); TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (e); - TREE_INVARIANT (result) = 1; return result; } @@ -2875,13 +2973,13 @@ stabilize_reference_1 (tree e) /* Low-level constructors for expressions. */ /* A helper function for build1 and constant folders. Set TREE_CONSTANT, - TREE_INVARIANT, and TREE_SIDE_EFFECTS for an ADDR_EXPR. */ + and TREE_SIDE_EFFECTS for an ADDR_EXPR. */ void recompute_tree_invariant_for_addr_expr (tree t) { tree node; - bool tc = true, ti = true, se = false; + bool tc = true, se = false; /* We started out assuming this address is both invariant and constant, but does not have side effects. Now go down any handled components and see if @@ -2891,9 +2989,8 @@ recompute_tree_invariant_for_addr_expr (tree t) ??? Note that this code makes no attempt to deal with the case where taking the address of something causes a copy due to misalignment. */ -#define UPDATE_TITCSE(NODE) \ +#define UPDATE_FLAGS(NODE) \ do { tree _node = (NODE); \ - if (_node && !TREE_INVARIANT (_node)) ti = false; \ if (_node && !TREE_CONSTANT (_node)) tc = false; \ if (_node && TREE_SIDE_EFFECTS (_node)) se = true; } while (0) @@ -2907,11 +3004,11 @@ do { tree _node = (NODE); \ || TREE_CODE (node) == ARRAY_RANGE_REF) && TREE_CODE (TREE_TYPE (TREE_OPERAND (node, 0))) == ARRAY_TYPE) { - UPDATE_TITCSE (TREE_OPERAND (node, 1)); + UPDATE_FLAGS (TREE_OPERAND (node, 1)); if (TREE_OPERAND (node, 2)) - UPDATE_TITCSE (TREE_OPERAND (node, 2)); + UPDATE_FLAGS (TREE_OPERAND (node, 2)); if (TREE_OPERAND (node, 3)) - UPDATE_TITCSE (TREE_OPERAND (node, 3)); + UPDATE_FLAGS (TREE_OPERAND (node, 3)); } /* Likewise, just because this is a COMPONENT_REF doesn't mean we have a FIELD_DECL, apparently. The G++ front end can put something else @@ -2920,46 +3017,35 @@ do { tree _node = (NODE); \ && TREE_CODE (TREE_OPERAND (node, 1)) == FIELD_DECL) { if (TREE_OPERAND (node, 2)) - UPDATE_TITCSE (TREE_OPERAND (node, 2)); + UPDATE_FLAGS (TREE_OPERAND (node, 2)); } else if (TREE_CODE (node) == BIT_FIELD_REF) - UPDATE_TITCSE (TREE_OPERAND (node, 2)); + UPDATE_FLAGS (TREE_OPERAND (node, 2)); } - node = lang_hooks.expr_to_decl (node, &tc, &ti, &se); + node = lang_hooks.expr_to_decl (node, &tc, &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 - a decl in the current function. Taking the address of a volatile variable - is not volatile. If it's a constant, the address is both invariant and - constant. Otherwise it's neither. */ + the address, since &(*a)->b is a form of addition. If it's a constant, the + address is constant too. If it's a decl, its address is constant if the + decl is static. Everything else is not constant and, furthermore, + taking the address of a volatile variable is not volatile. */ if (TREE_CODE (node) == INDIRECT_REF) - UPDATE_TITCSE (TREE_OPERAND (node, 0)); - else if (DECL_P (node)) - { - if (staticp (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_P (node))) - tc = false; - else - ti = tc = false; - } + UPDATE_FLAGS (TREE_OPERAND (node, 0)); else if (CONSTANT_CLASS_P (node)) ; + else if (DECL_P (node)) + tc &= (staticp (node) != NULL_TREE); else { - ti = tc = false; + tc = false; se |= TREE_SIDE_EFFECTS (node); } + TREE_CONSTANT (t) = tc; - TREE_INVARIANT (t) = ti; TREE_SIDE_EFFECTS (t) = se; -#undef UPDATE_TITCSE +#undef UPDATE_FLAGS } /* Build an expression of code CODE, data type TYPE, and operands as @@ -3018,11 +3104,7 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL) TREE_SET_CODE (t, code); TREE_TYPE (t) = type; -#ifdef USE_MAPPED_LOCATION SET_EXPR_LOCATION (t, UNKNOWN_LOCATION); -#else - SET_EXPR_LOCUS (t, NULL); -#endif TREE_OPERAND (t, 0) = node; TREE_BLOCK (t) = NULL_TREE; if (node && !TYPE_P (node)) @@ -3060,9 +3142,6 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL) && node && !TYPE_P (node) && TREE_CONSTANT (node)) TREE_CONSTANT (t) = 1; - 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 && node && TREE_THIS_VOLATILE (node)) TREE_THIS_VOLATILE (t) = 1; @@ -3083,15 +3162,13 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL) read_only = 0; \ if (!TREE_CONSTANT (arg##N)) \ constant = 0; \ - if (!TREE_INVARIANT (arg##N)) \ - invariant = 0; \ } \ } while (0) tree build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL) { - bool constant, read_only, side_effects, invariant; + bool constant, read_only, side_effects; tree t; gcc_assert (TREE_CODE_LENGTH (code) == 2); @@ -3128,14 +3205,12 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL) || TREE_CODE_CLASS (code) == tcc_binary); read_only = 1; side_effects = TREE_SIDE_EFFECTS (t); - invariant = constant; PROCESS_ARG(0); PROCESS_ARG(1); TREE_READONLY (t) = read_only; TREE_CONSTANT (t) = constant; - TREE_INVARIANT (t) = invariant; TREE_SIDE_EFFECTS (t) = side_effects; TREE_THIS_VOLATILE (t) = (TREE_CODE_CLASS (code) == tcc_reference @@ -3164,7 +3239,7 @@ tree build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1, tree arg2 MEM_STAT_DECL) { - bool constant, read_only, side_effects, invariant; + bool constant, read_only, side_effects; tree t; gcc_assert (TREE_CODE_LENGTH (code) == 3); @@ -3200,7 +3275,7 @@ tree build4_stat (enum tree_code code, tree tt, tree arg0, tree arg1, tree arg2, tree arg3 MEM_STAT_DECL) { - bool constant, read_only, side_effects, invariant; + bool constant, read_only, side_effects; tree t; gcc_assert (TREE_CODE_LENGTH (code) == 4); @@ -3227,7 +3302,7 @@ 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; + bool constant, read_only, side_effects; tree t; gcc_assert (TREE_CODE_LENGTH (code) == 5); @@ -3256,7 +3331,7 @@ 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) { - bool constant, read_only, side_effects, invariant; + bool constant, read_only, side_effects; tree t; gcc_assert (code == TARGET_MEM_REF); @@ -3384,13 +3459,6 @@ build_block (tree vars, tree subblocks, tree supercontext, tree chain) return block; } -#if 1 /* ! defined(USE_MAPPED_LOCATION) */ -/* ??? gengtype doesn't handle conditionals */ -static GTY(()) source_locus last_annotated_node; -#endif - -#ifdef USE_MAPPED_LOCATION - expanded_location expand_location (source_location loc) { @@ -3403,7 +3471,7 @@ expand_location (source_location loc) } else { - const struct line_map *map = linemap_lookup (&line_table, loc); + const struct line_map *map = linemap_lookup (line_table, loc); xloc.file = map->to_file; xloc.line = SOURCE_LINE (map, loc); xloc.column = SOURCE_COLUMN (map, loc); @@ -3411,50 +3479,6 @@ expand_location (source_location loc) return xloc; } -#else - -/* Record the exact location where an expression or an identifier were - encountered. */ - -void -annotate_with_file_line (tree node, const char *file, int line) -{ - /* Roughly one percent of the calls to this function are to annotate - 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))) - { - last_annotated_node = EXPR_LOCUS (node); - return; - } - - /* In heavily macroized code (such as GCC itself) this single - entry cache can reduce the number of allocations by more - than half. */ - if (last_annotated_node - && last_annotated_node->line == line - && (last_annotated_node->file == file - || !strcmp (last_annotated_node->file, file))) - { - 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 = EXPR_LOCUS (node); -} - -void -annotate_with_locus (tree node, location_t locus) -{ - annotate_with_file_line (node, locus.file, locus.line); -} -#endif /* Source location accessor functions. */ @@ -3465,71 +3489,39 @@ annotate_with_locus (tree node, location_t locus) location_t expr_location (const_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 (const_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 (const_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 + return CONST_CAST (source_location *, &GIMPLE_STMT_LOCUS (node)); + return (EXPR_P (node) + ? CONST_CAST (source_location *, &node->exp.locus) + : (source_location *) NULL); } void -set_expr_locus (tree node, -#ifdef USE_MAPPED_LOCATION - source_location *loc -#else - source_locus loc -#endif - ) +set_expr_locus (tree node, source_location *loc) { -#ifdef USE_MAPPED_LOCATION if (loc == NULL) { if (GIMPLE_STMT_P (node)) @@ -3544,41 +3536,26 @@ set_expr_locus (tree node, 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 ** +/* Return the file name of the location of NODE. */ +const char * expr_filename (const_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 + return LOCATION_FILE (GIMPLE_STMT_LOCUS (node)); + return LOCATION_FILE (EXPR_CHECK (node)->exp.locus); } -int * +/* Return the line number of the location of NODE. */ +int expr_lineno (const_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 LOCATION_LINE (GIMPLE_STMT_LOCUS (node)); + return LOCATION_LINE (EXPR_CHECK (node)->exp.locus); } + /* Return a declaration like DDECL except that its DECL_ATTRIBUTES is ATTRIBUTE. */ @@ -3672,21 +3649,26 @@ build_type_attribute_qual_variant (tree ttype, tree attribute, int quals) tree ntype; enum tree_code code = TREE_CODE (ttype); - ntype = copy_node (ttype); - - TYPE_POINTER_TO (ntype) = 0; - TYPE_REFERENCE_TO (ntype) = 0; - TYPE_ATTRIBUTES (ntype) = attribute; + /* Building a distinct copy of a tagged type is inappropriate; it + causes breakage in code that expects there to be a one-to-one + relationship between a struct and its fields. + build_duplicate_type is another solution (as used in + handle_transparent_union_attribute), but that doesn't play well + with the stronger C++ type identity model. */ + if (TREE_CODE (ttype) == RECORD_TYPE + || TREE_CODE (ttype) == UNION_TYPE + || TREE_CODE (ttype) == QUAL_UNION_TYPE + || TREE_CODE (ttype) == ENUMERAL_TYPE) + { + warning (OPT_Wattributes, + "ignoring attributes applied to %qT after definition", + TYPE_MAIN_VARIANT (ttype)); + return build_qualified_type (ttype, quals); + } - if (TYPE_STRUCTURAL_EQUALITY_P (ttype)) - SET_TYPE_STRUCTURAL_EQUALITY (ntype); - else - TYPE_CANONICAL (ntype) - = build_qualified_type (TYPE_CANONICAL (ttype), quals); + ntype = build_distinct_type_copy (ttype); - /* Create a new main variant of TYPE. */ - TYPE_MAIN_VARIANT (ntype) = ntype; - TYPE_NEXT_VARIANT (ntype) = 0; + TYPE_ATTRIBUTES (ntype) = attribute; set_type_quals (ntype, TYPE_UNQUALIFIED); hashcode = iterative_hash_object (code, hashcode); @@ -3701,8 +3683,9 @@ build_type_attribute_qual_variant (tree ttype, tree attribute, int quals) hashcode = type_hash_list (TYPE_ARG_TYPES (ntype), hashcode); break; case ARRAY_TYPE: - hashcode = iterative_hash_object (TYPE_HASH (TYPE_DOMAIN (ntype)), - hashcode); + if (TYPE_DOMAIN (ntype)) + hashcode = iterative_hash_object (TYPE_HASH (TYPE_DOMAIN (ntype)), + hashcode); break; case INTEGER_TYPE: hashcode = iterative_hash_object @@ -3726,11 +3709,17 @@ build_type_attribute_qual_variant (tree ttype, tree attribute, int quals) /* If the target-dependent attributes make NTYPE different from its canonical type, we will need to use structural equality checks for this qualified type. */ - if (!targetm.comp_type_attributes (ntype, ttype)) + ttype = build_qualified_type (ttype, TYPE_UNQUALIFIED); + if (TYPE_STRUCTURAL_EQUALITY_P (ttype) + || !targetm.comp_type_attributes (ntype, ttype)) SET_TYPE_STRUCTURAL_EQUALITY (ntype); + else + TYPE_CANONICAL (ntype) = TYPE_CANONICAL (ttype); ttype = build_qualified_type (ntype, quals); } + else if (TYPE_QUALS (ttype) != quals) + ttype = build_qualified_type (ttype, quals); return ttype; } @@ -3823,7 +3812,6 @@ lookup_attribute (const char *attr_name, tree list) if (is_attribute_with_length_p (attr_name, attr_len, TREE_PURPOSE (l))) return l; } - return NULL_TREE; } @@ -3962,7 +3950,7 @@ merge_dllimport_decl_attributes (tree old, tree new) } else if (DECL_DLLIMPORT_P (old) && !DECL_DLLIMPORT_P (new)) { - /* Warn about overriding a symbol that has already been used. eg: + /* Warn about overriding a symbol that has already been used, e.g.: extern int __attribute__ ((dllimport)) foo; int* bar () {return &foo;} int foo; @@ -3973,8 +3961,7 @@ merge_dllimport_decl_attributes (tree old, tree new) "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. + decl may already have had 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)) @@ -4061,6 +4048,16 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags, return NULL_TREE; } + if (TREE_CODE (node) == TYPE_DECL + && TREE_CODE (TREE_TYPE (node)) != RECORD_TYPE + && TREE_CODE (TREE_TYPE (node)) != UNION_TYPE) + { + *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. */ else if (is_attribute_p ("dllimport", name)) @@ -4148,7 +4145,7 @@ set_type_quals (tree type, int type_quals) TYPE_RESTRICT (type) = (type_quals & TYPE_QUAL_RESTRICT) != 0; } -/* Returns true iff cand is equivalent to base with type_quals. */ +/* Returns true iff CAND is equivalent to BASE with TYPE_QUALS. */ bool check_qualified_type (const_tree cand, const_tree base, int type_quals) @@ -4315,9 +4312,6 @@ decl_init_priority_lookup (tree decl) struct tree_map_base in; gcc_assert (VAR_OR_FUNCTION_DECL_P (decl)); - gcc_assert (TREE_CODE (decl) == VAR_DECL - ? DECL_HAS_INIT_PRIORITY_P (decl) - : DECL_STATIC_CONSTRUCTOR (decl)); in.from = decl; h = htab_find (init_priority_for_decl, &in); return h ? h->init : DEFAULT_INIT_PRIORITY; @@ -4332,7 +4326,6 @@ decl_fini_priority_lookup (tree decl) struct tree_map_base in; gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); - gcc_assert (DECL_STATIC_DESTRUCTOR (decl)); in.from = decl; h = htab_find (init_priority_for_decl, &in); return h ? h->fini : DEFAULT_INIT_PRIORITY; @@ -4617,17 +4610,24 @@ type_hash_eq (const void *va, const void *vb) TYPE_FIELDS (b->type)))); case FUNCTION_TYPE: - return (TYPE_ARG_TYPES (a->type) == TYPE_ARG_TYPES (b->type) - || (TYPE_ARG_TYPES (a->type) - && TREE_CODE (TYPE_ARG_TYPES (a->type)) == TREE_LIST - && TYPE_ARG_TYPES (b->type) - && TREE_CODE (TYPE_ARG_TYPES (b->type)) == TREE_LIST - && type_list_equal (TYPE_ARG_TYPES (a->type), - TYPE_ARG_TYPES (b->type)))); + if (TYPE_ARG_TYPES (a->type) == TYPE_ARG_TYPES (b->type) + || (TYPE_ARG_TYPES (a->type) + && TREE_CODE (TYPE_ARG_TYPES (a->type)) == TREE_LIST + && TYPE_ARG_TYPES (b->type) + && TREE_CODE (TYPE_ARG_TYPES (b->type)) == TREE_LIST + && type_list_equal (TYPE_ARG_TYPES (a->type), + TYPE_ARG_TYPES (b->type)))) + break; + return 0; default: return 0; } + + if (lang_hooks.types.type_hash_eq != NULL) + return lang_hooks.types.type_hash_eq (a->type, b->type); + + return 1; } /* Return the cached hash value. */ @@ -4672,7 +4672,7 @@ type_hash_add (hashval_t hashcode, tree type) h->hash = hashcode; h->type = type; loc = htab_find_slot_with_hash (type_hash_table, h, hashcode, INSERT); - *(struct type_hash **) loc = h; + *loc = (void *)h; } /* Given TYPE, and HASHCODE its hash code, return the canonical @@ -4757,7 +4757,7 @@ attribute_hash_list (const_tree list, hashval_t hashcode) equivalent to l1. */ int -attribute_list_equal (tree l1, tree l2) +attribute_list_equal (const_tree l1, const_tree l2) { return attribute_list_contained (l1, l2) && attribute_list_contained (l2, l1); @@ -4772,9 +4772,9 @@ attribute_list_equal (tree l1, tree l2) correctly. */ int -attribute_list_contained (tree l1, tree l2) +attribute_list_contained (const_tree l1, const_tree l2) { - tree t1, t2; + const_tree t1, t2; /* First check the obvious, maybe the lists are identical. */ if (l1 == l2) @@ -4793,8 +4793,12 @@ attribute_list_contained (tree l1, tree l2) for (; t2 != 0; t2 = TREE_CHAIN (t2)) { - tree attr; - for (attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)), l1); + const_tree attr; + /* This CONST_CAST is okay because lookup_attribute does not + modify its argument and the return value is assigned to a + const_tree. */ + for (attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)), + CONST_CAST_TREE(l1)); attr != NULL_TREE; attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)), TREE_CHAIN (attr))) @@ -4936,7 +4940,9 @@ host_integerp (const_tree t, int pos) && (HOST_WIDE_INT) TREE_INT_CST_LOW (t) >= 0) || (! pos && TREE_INT_CST_HIGH (t) == -1 && (HOST_WIDE_INT) TREE_INT_CST_LOW (t) < 0 - && !TYPE_UNSIGNED (TREE_TYPE (t))) + && (!TYPE_UNSIGNED (TREE_TYPE (t)) + || (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE + && TYPE_IS_SIZETYPE (TREE_TYPE (t))))) || (pos && TREE_INT_CST_HIGH (t) == 0))); } @@ -5680,14 +5686,12 @@ build_array_type (tree elt_type, tree index_type) return t; } -/* Return the TYPE of the elements comprising - the innermost dimension of ARRAY. */ +/* Recursively examines the array elements of TYPE, until a non-array + element type is found. */ tree -get_inner_array_type (const_tree array) +strip_array_types (tree type) { - tree type = TREE_TYPE (array); - while (TREE_CODE (type) == ARRAY_TYPE) type = TREE_TYPE (type); @@ -5946,10 +5950,10 @@ build_offset_type (tree basetype, tree type) if (TYPE_STRUCTURAL_EQUALITY_P (basetype) || TYPE_STRUCTURAL_EQUALITY_P (type)) SET_TYPE_STRUCTURAL_EQUALITY (t); - else if (TYPE_CANONICAL (basetype) != basetype + else if (TYPE_CANONICAL (TYPE_MAIN_VARIANT (basetype)) != basetype || TYPE_CANONICAL (type) != type) TYPE_CANONICAL (t) - = build_offset_type (TYPE_CANONICAL (basetype), + = build_offset_type (TYPE_CANONICAL (TYPE_MAIN_VARIANT (basetype)), TYPE_CANONICAL (type)); } @@ -5985,10 +5989,8 @@ build_complex_type (tree component_type) = build_complex_type (TYPE_CANONICAL (component_type)); } - /* If we are writing Dwarf2 output we need to create a name, - since complex is a fundamental type. */ - if ((write_symbols == DWARF2_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG) - && ! TYPE_NAME (t)) + /* We need to create a name, since complex is a fundamental type. */ + if (! TYPE_NAME (t)) { const char *name; if (component_type == char_type_node) @@ -6029,11 +6031,6 @@ build_complex_type (tree component_type) If FOR_TYPE is nonzero, we return a value which, if converted to type FOR_TYPE, would be equivalent to converting OP to type FOR_TYPE. - If FOR_TYPE is nonzero, unaligned bit-field references may be changed to the - narrowest type that can hold the value, even if they don't exactly fit. - Otherwise, bit-field references are changed to a narrower type - only if they can be fetched directly from memory in that type. - OP must have integer, real or enumeral type. Pointers are not allowed! There are some cases where the obvious value we could return @@ -6059,8 +6056,7 @@ get_unwidened (tree op, tree for_type) && TYPE_UNSIGNED (type)); tree win = op; - while (TREE_CODE (op) == NOP_EXPR - || TREE_CODE (op) == CONVERT_EXPR) + while (CONVERT_EXPR_P (op)) { int bitschange; @@ -6098,8 +6094,7 @@ get_unwidened (tree op, tree for_type) Let's avoid computing it if it does not affect WIN and if UNS will not be needed again. */ if ((uns - || TREE_CODE (op) == NOP_EXPR - || TREE_CODE (op) == CONVERT_EXPR) + || CONVERT_EXPR_P (op)) && TYPE_UNSIGNED (TREE_TYPE (op))) { uns = 1; @@ -6108,38 +6103,6 @@ get_unwidened (tree op, tree for_type) } } - if (TREE_CODE (op) == COMPONENT_REF - /* Since type_for_size always gives an integer type. */ - && TREE_CODE (type) != REAL_TYPE - && TREE_CODE (type) != FIXED_POINT_TYPE - /* Don't crash if field not laid out yet. */ - && DECL_SIZE (TREE_OPERAND (op, 1)) != 0 - && host_integerp (DECL_SIZE (TREE_OPERAND (op, 1)), 1)) - { - unsigned int innerprec - = tree_low_cst (DECL_SIZE (TREE_OPERAND (op, 1)), 1); - int unsignedp = (DECL_UNSIGNED (TREE_OPERAND (op, 1)) - || TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op, 1)))); - type = lang_hooks.types.type_for_size (innerprec, unsignedp); - - /* We can get this structure field in the narrowest type it fits in. - If FOR_TYPE is 0, do this only for a field that matches the - narrower type exactly and is aligned for it - The resulting extension to its nominal type (a fullword type) - must fit the same conditions as for other extensions. */ - - if (type != 0 - && INT_CST_LT_UNSIGNED (TYPE_SIZE (type), TYPE_SIZE (TREE_TYPE (op))) - && (for_type || ! DECL_BIT_FIELD (TREE_OPERAND (op, 1))) - && (! uns || final_prec <= innerprec || unsignedp)) - { - win = build3 (COMPONENT_REF, type, TREE_OPERAND (op, 0), - TREE_OPERAND (op, 1), NULL_TREE); - TREE_SIDE_EFFECTS (win) = TREE_SIDE_EFFECTS (op); - TREE_THIS_VOLATILE (win) = TREE_THIS_VOLATILE (op); - } - } - return win; } @@ -6354,6 +6317,19 @@ get_type_static_bounds (const_tree type, mpz_t min, mpz_t max) } } +/* auto_var_in_fn_p is called to determine whether VAR is an automatic + variable defined in function FN. */ + +bool +auto_var_in_fn_p (const_tree var, const_tree fn) +{ + return (DECL_P (var) && DECL_CONTEXT (var) == fn + && (((TREE_CODE (var) == VAR_DECL || TREE_CODE (var) == PARM_DECL) + && ! TREE_STATIC (var)) + || TREE_CODE (var) == LABEL_DECL + || TREE_CODE (var) == RESULT_DECL)); +} + /* Subprogram of following function. Called by walk_tree. Return *TP if it is an automatic variable or parameter of the @@ -6368,7 +6344,7 @@ find_var_from_fn (tree *tp, int *walk_subtrees, void *data) *walk_subtrees = 0; else if (DECL_P (*tp) - && lang_hooks.tree_inlining.auto_var_in_fn_p (*tp, fn)) + && auto_var_in_fn_p (*tp, fn)) return *tp; return NULL_TREE; @@ -7391,7 +7367,9 @@ local_define_builtin (const char *name, tree type, enum built_in_function code, if (ecf_flags & ECF_CONST) TREE_READONLY (decl) = 1; if (ecf_flags & ECF_PURE) - DECL_IS_PURE (decl) = 1; + DECL_PURE_P (decl) = 1; + if (ecf_flags & ECF_LOOPING_CONST_OR_PURE) + DECL_LOOPING_CONST_OR_PURE_P (decl) = 1; if (ecf_flags & ECF_NORETURN) TREE_THIS_VOLATILE (decl) = 1; if (ecf_flags & ECF_NOTHROW) @@ -7606,13 +7584,15 @@ reconstruct_complex_type (tree type, tree bottom) inner, TREE_CHAIN (TYPE_ARG_TYPES (type))); } + else if (TREE_CODE (type) == OFFSET_TYPE) + { + inner = reconstruct_complex_type (TREE_TYPE (type), bottom); + outer = build_offset_type (TYPE_OFFSET_BASETYPE (type), inner); + } else return bottom; - TYPE_READONLY (outer) = TYPE_READONLY (type); - TYPE_VOLATILE (outer) = TYPE_VOLATILE (type); - - return outer; + return build_qualified_type (outer, TYPE_QUALS (type)); } /* Returns a vector tree node given a mode (integer, vector, or BLKmode) and @@ -7782,7 +7762,7 @@ process_call_operands (tree t) /* Calls have side-effects, except those to const or pure functions. */ i = call_expr_flags (t); - if (!(i & (ECF_CONST | ECF_PURE))) + if ((i & ECF_LOOPING_CONST_OR_PURE) || !(i & (ECF_CONST | ECF_PURE))) side_effects = 1; } TREE_SIDE_EFFECTS (t) = side_effects; @@ -7962,7 +7942,7 @@ range_in_array_bounds_p (tree ref) location. */ bool -needs_to_live_in_memory (tree t) +needs_to_live_in_memory (const_tree t) { if (TREE_CODE (t) == SSA_NAME) t = SSA_NAME_VAR (t); @@ -8017,21 +7997,26 @@ find_compatible_field (tree record, tree orig_field) return orig_field; } -/* Return value of a constant X. */ +/* Return value of a constant X and sign-extend it. */ HOST_WIDE_INT int_cst_value (const_tree x) { unsigned bits = TYPE_PRECISION (TREE_TYPE (x)); unsigned HOST_WIDE_INT val = TREE_INT_CST_LOW (x); - bool negative = ((val >> (bits - 1)) & 1) != 0; - gcc_assert (bits <= HOST_BITS_PER_WIDE_INT); + /* Make sure the sign-extended value will fit in a HOST_WIDE_INT. */ + gcc_assert (TREE_INT_CST_HIGH (x) == 0 + || TREE_INT_CST_HIGH (x) == -1); - if (negative) - val |= (~(unsigned HOST_WIDE_INT) 0) << (bits - 1) << 1; - else - val &= ~((~(unsigned HOST_WIDE_INT) 0) << (bits - 1) << 1); + if (bits < HOST_BITS_PER_WIDE_INT) + { + bool negative = ((val >> (bits - 1)) & 1) != 0; + if (negative) + val |= (~(unsigned HOST_WIDE_INT) 0) << (bits - 1) << 1; + else + val &= ~((~(unsigned HOST_WIDE_INT) 0) << (bits - 1) << 1); + } return val; } @@ -8236,7 +8221,7 @@ num_ending_zeros (const_tree x) #define WALK_SUBTREE(NODE) \ do \ { \ - result = walk_tree (&(NODE), func, data, pset); \ + result = walk_tree_1 (&(NODE), func, data, pset, lh); \ if (result) \ return result; \ } \ @@ -8248,7 +8233,7 @@ num_ending_zeros (const_tree x) static tree walk_type_fields (tree type, walk_tree_fn func, void *data, - struct pointer_set_t *pset) + struct pointer_set_t *pset, walk_tree_lh lh) { tree result = NULL_TREE; @@ -8328,7 +8313,8 @@ walk_type_fields (tree type, walk_tree_fn func, void *data, and to avoid visiting a node more than once. */ tree -walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset) +walk_tree_1 (tree *tp, walk_tree_fn func, void *data, + struct pointer_set_t *pset, walk_tree_lh lh) { enum tree_code code; int walk_subtrees; @@ -8375,10 +8361,12 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset) return NULL_TREE; } - result = lang_hooks.tree_inlining.walk_subtrees (tp, &walk_subtrees, func, - data, pset); - if (result || !walk_subtrees) - return result; + if (lh) + { + result = (*lh) (tp, &walk_subtrees, func, data, pset); + if (result || !walk_subtrees) + return result; + } switch (code) { @@ -8468,7 +8456,6 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset) 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: @@ -8480,8 +8467,22 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset) case OMP_CLAUSE_NOWAIT: case OMP_CLAUSE_ORDERED: case OMP_CLAUSE_DEFAULT: + case OMP_CLAUSE_UNTIED: WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp)); + case OMP_CLAUSE_LASTPRIVATE: + WALK_SUBTREE (OMP_CLAUSE_DECL (*tp)); + WALK_SUBTREE (OMP_CLAUSE_LASTPRIVATE_STMT (*tp)); + WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp)); + + case OMP_CLAUSE_COLLAPSE: + { + int i; + for (i = 0; i < 3; i++) + WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, i)); + WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp)); + } + case OMP_CLAUSE_REDUCTION: { int i; @@ -8532,7 +8533,7 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset) if (result || !walk_subtrees) return result; - result = walk_type_fields (*type_p, func, data, pset); + result = walk_type_fields (*type_p, func, data, pset, lh); if (result) return result; @@ -8597,7 +8598,7 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset) } /* 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); + return walk_type_fields (*tp, func, data, pset, lh); break; } @@ -8611,13 +8612,14 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset) /* Like walk_tree, but does not walk duplicate nodes more than once. */ tree -walk_tree_without_duplicates (tree *tp, walk_tree_fn func, void *data) +walk_tree_without_duplicates_1 (tree *tp, walk_tree_fn func, void *data, + walk_tree_lh lh) { tree result; struct pointer_set_t *pset; pset = pointer_set_create (); - result = walk_tree (tp, func, data, pset); + result = walk_tree_1 (tp, func, data, pset, lh); pointer_set_destroy (pset); return result; } @@ -8692,4 +8694,92 @@ call_expr_arglist (tree exp) return arglist; } +/* Return true if TYPE has a variable argument list. */ + +bool +stdarg_p (tree fntype) +{ + function_args_iterator args_iter; + tree n = NULL_TREE, t; + + if (!fntype) + return false; + + FOREACH_FUNCTION_ARGS(fntype, t, args_iter) + { + n = t; + } + + return n != NULL_TREE && n != void_type_node; +} + +/* Return true if TYPE has a prototype. */ + +bool +prototype_p (tree fntype) +{ + tree t; + + gcc_assert (fntype != NULL_TREE); + + t = TYPE_ARG_TYPES (fntype); + return (t != NULL_TREE); +} + +/* Return the number of arguments that a function has. */ + +int +function_args_count (tree fntype) +{ + function_args_iterator args_iter; + tree t; + int num = 0; + + if (fntype) + { + FOREACH_FUNCTION_ARGS(fntype, t, args_iter) + { + num++; + } + } + + return num; +} + +/* If BLOCK is inlined from an __attribute__((__artificial__)) + routine, return pointer to location from where it has been + called. */ +location_t * +block_nonartificial_location (tree block) +{ + location_t *ret = NULL; + + while (block && TREE_CODE (block) == BLOCK + && BLOCK_ABSTRACT_ORIGIN (block)) + { + tree ao = BLOCK_ABSTRACT_ORIGIN (block); + + while (TREE_CODE (ao) == BLOCK && BLOCK_ABSTRACT_ORIGIN (ao)) + ao = BLOCK_ABSTRACT_ORIGIN (ao); + + if (TREE_CODE (ao) == FUNCTION_DECL) + { + /* If AO is an artificial inline, point RET to the + call site locus at which it has been inlined and continue + the loop, in case AO's caller is also an artificial + inline. */ + if (DECL_DECLARED_INLINE_P (ao) + && lookup_attribute ("artificial", DECL_ATTRIBUTES (ao))) + ret = &BLOCK_SOURCE_LOCATION (block); + else + break; + } + else if (TREE_CODE (ao) != BLOCK) + break; + + block = BLOCK_SUPERCONTEXT (block); + } + return ret; +} + #include "gt-tree.h"