X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ftree.c;h=81c54d0edf49f6fa70548976dcc988bf1f1ee2ca;hb=f5ef996258725dd451733c21e2bba88c87019646;hp=c0cd2ae2ba50a2e4897207a43467d3f4a2e9cac6;hpb=dc6fafc62cf3863e622effaa3ec828cbfc830679;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/tree.c b/gcc/tree.c index c0cd2ae2ba5..81c54d0edf4 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -7,7 +7,7 @@ This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2, or (at your option) any later +Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY @@ -16,9 +16,8 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to the Free -Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301, USA. */ +along with GCC; see the file COPYING3. If not see +. */ /* This file contains the low level primitives for operating on tree nodes, including allocation, list operations, interning of identifiers, @@ -51,6 +50,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "tree-flow.h" #include "params.h" #include "pointer-set.h" +#include "fixed-value.h" /* Each tree code class has an associated string representation. These must correspond to the tree_code_class entries. */ @@ -162,8 +162,8 @@ static void print_type_hash_statistics (void); static void print_debug_expr_statistics (void); static void print_value_expr_statistics (void); 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); +static unsigned int type_hash_list (const_tree, hashval_t); +static unsigned int attribute_hash_list (const_tree, hashval_t); tree global_trees[TI_MAX]; tree integer_types[itk_none]; @@ -400,6 +400,7 @@ tree_code_size (enum tree_code code) { case INTEGER_CST: return sizeof (struct tree_int_cst); case REAL_CST: return sizeof (struct tree_real_cst); + case FIXED_CST: return sizeof (struct tree_fixed_cst); case COMPLEX_CST: return sizeof (struct tree_complex); case VECTOR_CST: return sizeof (struct tree_vector); case STRING_CST: gcc_unreachable (); @@ -439,9 +440,9 @@ tree_code_size (enum tree_code code) /* Compute the number of bytes occupied by NODE. This routine only looks at TREE_CODE, except for those nodes that have variable sizes. */ size_t -tree_size (tree node) +tree_size (const_tree node) { - enum tree_code code = TREE_CODE (node); + const enum tree_code code = TREE_CODE (node); switch (code) { case PHI_NODE: @@ -588,9 +589,13 @@ make_node_stat (enum tree_code code MEM_STAT_DECL) DECL_IN_SYSTEM_HEADER (t) = in_system_header; if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON)) { - if (code != FUNCTION_DECL) + if (code == FUNCTION_DECL) + { + DECL_ALIGN (t) = FUNCTION_BOUNDARY; + DECL_MODE (t) = FUNCTION_MODE; + } + else 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; } @@ -807,7 +812,7 @@ build_int_cst_wide_type (tree type, static hashval_t int_cst_hash_hash (const void *x) { - tree t = (tree) x; + const_tree const t = (const_tree) x; return (TREE_INT_CST_HIGH (t) ^ TREE_INT_CST_LOW (t) ^ htab_hash_pointer (TREE_TYPE (t))); @@ -819,8 +824,8 @@ int_cst_hash_hash (const void *x) static int int_cst_hash_eq (const void *x, const void *y) { - tree xt = (tree) x; - tree yt = (tree) y; + const_tree const xt = (const_tree) x; + const_tree const yt = (const_tree) y; return (TREE_TYPE (xt) == TREE_TYPE (yt) && TREE_INT_CST_HIGH (xt) == TREE_INT_CST_HIGH (yt) @@ -977,7 +982,7 @@ build_low_bits_mask (tree type, unsigned bits) HOST_WIDE_INT without loss of precision. */ bool -cst_and_fits_in_hwi (tree x) +cst_and_fits_in_hwi (const_tree x) { if (TREE_CODE (x) != INTEGER_CST) return false; @@ -1092,6 +1097,22 @@ build_constructor_from_list (tree type, tree vals) return t; } +/* Return a new FIXED_CST node whose type is TYPE and value is F. */ + +tree +build_fixed (tree type, FIXED_VALUE_TYPE f) +{ + tree v; + FIXED_VALUE_TYPE *fp; + + v = make_node (FIXED_CST); + fp = ggc_alloc (sizeof (FIXED_VALUE_TYPE)); + memcpy (fp, &f, sizeof (FIXED_VALUE_TYPE)); + + TREE_TYPE (v) = type; + TREE_FIXED_CST_PTR (v) = fp; + return v; +} /* Return a new REAL_CST node whose type is TYPE and value is D. */ @@ -1119,7 +1140,7 @@ build_real (tree type, REAL_VALUE_TYPE d) and whose value is the integer value of the INTEGER_CST node I. */ REAL_VALUE_TYPE -real_value_from_int_cst (tree type, tree i) +real_value_from_int_cst (const_tree type, const_tree i) { REAL_VALUE_TYPE d; @@ -1137,7 +1158,7 @@ real_value_from_int_cst (tree type, tree i) representing the same value as a floating-point constant of type TYPE. */ tree -build_real_from_int_cst (tree type, tree i) +build_real_from_int_cst (tree type, const_tree i) { tree v; int overflow = TREE_OVERFLOW (i); @@ -1173,8 +1194,8 @@ build_string (int len, const char *str) TREE_CONSTANT (s) = 1; TREE_INVARIANT (s) = 1; TREE_STRING_LENGTH (s) = len; - memcpy ((char *) TREE_STRING_POINTER (s), str, len); - ((char *) TREE_STRING_POINTER (s))[len] = '\0'; + memcpy (s->string.str, str, len); + s->string.str[len] = '\0'; return s; } @@ -1212,6 +1233,11 @@ build_one_cst (tree type) case REAL_TYPE: return build_real (type, dconst1); + case FIXED_POINT_TYPE: + /* We can only generate 1 for accum types. */ + gcc_assert (ALL_SCALAR_ACCUM_MODE_P (TYPE_MODE (type))); + return build_fixed (type, FCONST1(TYPE_MODE (type))); + case VECTOR_TYPE: { tree scalar, cst; @@ -1290,7 +1316,7 @@ make_tree_vec_stat (int len MEM_STAT_DECL) of zero. */ int -integer_zerop (tree expr) +integer_zerop (const_tree expr) { STRIP_NOPS (expr); @@ -1306,7 +1332,7 @@ integer_zerop (tree expr) complex constant. */ int -integer_onep (tree expr) +integer_onep (const_tree expr) { STRIP_NOPS (expr); @@ -1322,7 +1348,7 @@ integer_onep (tree expr) it contains. Likewise for the corresponding complex constant. */ int -integer_all_onesp (tree expr) +integer_all_onesp (const_tree expr) { int prec; int uns; @@ -1374,7 +1400,7 @@ integer_all_onesp (tree expr) one bit on). */ int -integer_pow2p (tree expr) +integer_pow2p (const_tree expr) { int prec; HOST_WIDE_INT high, low; @@ -1419,7 +1445,7 @@ integer_pow2p (tree expr) complex constant other than zero. */ int -integer_nonzerop (tree expr) +integer_nonzerop (const_tree expr) { STRIP_NOPS (expr); @@ -1431,11 +1457,20 @@ integer_nonzerop (tree expr) || integer_nonzerop (TREE_IMAGPART (expr))))); } +/* Return 1 if EXPR is the fixed-point constant zero. */ + +int +fixed_zerop (const_tree expr) +{ + return (TREE_CODE (expr) == FIXED_CST + && double_int_zero_p (TREE_FIXED_CST (expr).data)); +} + /* Return the power of two represented by a tree node known to be a power of two. */ int -tree_log2 (tree expr) +tree_log2 (const_tree expr) { int prec; HOST_WIDE_INT high, low; @@ -1473,7 +1508,7 @@ tree_log2 (tree expr) than or equal to EXPR. */ int -tree_floor_log2 (tree expr) +tree_floor_log2 (const_tree expr) { int prec; HOST_WIDE_INT high, low; @@ -1511,7 +1546,7 @@ tree_floor_log2 (tree expr) /* Return 1 if EXPR is the real constant zero. */ int -real_zerop (tree expr) +real_zerop (const_tree expr) { STRIP_NOPS (expr); @@ -1525,7 +1560,7 @@ real_zerop (tree expr) /* Return 1 if EXPR is the real constant one in real or complex form. */ int -real_onep (tree expr) +real_onep (const_tree expr) { STRIP_NOPS (expr); @@ -1539,7 +1574,7 @@ real_onep (tree expr) /* Return 1 if EXPR is the real constant two. */ int -real_twop (tree expr) +real_twop (const_tree expr) { STRIP_NOPS (expr); @@ -1553,7 +1588,7 @@ real_twop (tree expr) /* Return 1 if EXPR is the real constant minus one. */ int -real_minus_onep (tree expr) +real_minus_onep (const_tree expr) { STRIP_NOPS (expr); @@ -1567,7 +1602,7 @@ real_minus_onep (tree expr) /* Nonzero if EXP is a constant or a cast of a constant. */ int -really_constant_p (tree exp) +really_constant_p (const_tree exp) { /* This is not quite the same as STRIP_NOPS. It does more. */ while (TREE_CODE (exp) == NOP_EXPR @@ -1596,7 +1631,7 @@ value_member (tree elem, tree list) Return 0 if ELEM is not in LIST. */ tree -purpose_member (tree elem, tree list) +purpose_member (const_tree elem, tree list) { while (list) { @@ -1610,7 +1645,7 @@ purpose_member (tree elem, tree list) /* Return nonzero if ELEM is part of the chain CHAIN. */ int -chain_member (tree elem, tree chain) +chain_member (const_tree elem, const_tree chain) { while (chain) { @@ -1627,11 +1662,11 @@ chain_member (tree elem, tree chain) This is the Lisp primitive `length'. */ int -list_length (tree t) +list_length (const_tree t) { - tree p = t; + const_tree p = t; #ifdef ENABLE_TREE_CHECKING - tree q = t; + const_tree q = t; #endif int len = 0; @@ -1652,7 +1687,7 @@ list_length (tree t) /* Returns the number of FIELD_DECLs in TYPE. */ int -fields_length (tree type) +fields_length (const_tree type) { tree t = TYPE_FIELDS (type); int count = 0; @@ -1766,7 +1801,7 @@ tree_cons_stat (tree purpose, tree value, tree chain MEM_STAT_DECL) make_unsigned_type). */ tree -size_in_bytes (tree type) +size_in_bytes (const_tree type) { tree t; @@ -1789,7 +1824,7 @@ size_in_bytes (tree type) or return -1 if the size can vary or is larger than an integer. */ HOST_WIDE_INT -int_size_in_bytes (tree type) +int_size_in_bytes (const_tree type) { tree t; @@ -1812,7 +1847,7 @@ int_size_in_bytes (tree type) or return -1 if the size can vary or is larger than an integer. */ HOST_WIDE_INT -max_int_size_in_bytes (tree type) +max_int_size_in_bytes (const_tree type) { HOST_WIDE_INT size = -1; tree size_tree; @@ -1845,7 +1880,7 @@ max_int_size_in_bytes (tree type) This is a tree of type bitsizetype. */ tree -bit_position (tree field) +bit_position (const_tree field) { return bit_from_pos (DECL_FIELD_OFFSET (field), DECL_FIELD_BIT_OFFSET (field)); @@ -1856,7 +1891,7 @@ bit_position (tree field) option of returning -1 like int_size_in_byte can. */ HOST_WIDE_INT -int_bit_position (tree field) +int_bit_position (const_tree field) { return tree_low_cst (bit_position (field), 0); } @@ -1865,7 +1900,7 @@ int_bit_position (tree field) This is a tree of type sizetype. */ tree -byte_position (tree field) +byte_position (const_tree field) { return byte_from_pos (DECL_FIELD_OFFSET (field), DECL_FIELD_BIT_OFFSET (field)); @@ -1876,7 +1911,7 @@ byte_position (tree field) option of returning -1 like int_size_in_byte can. */ HOST_WIDE_INT -int_byte_position (tree field) +int_byte_position (const_tree field) { return tree_low_cst (byte_position (field), 0); } @@ -1884,7 +1919,7 @@ int_byte_position (tree field) /* Return the strictest alignment, in bits, that T is known to have. */ unsigned int -expr_align (tree t) +expr_align (const_tree t) { unsigned int align0, align1; @@ -1914,14 +1949,13 @@ expr_align (tree t) align1 = expr_align (TREE_OPERAND (t, 2)); return MIN (align0, align1); + /* FIXME: LABEL_DECL and CONST_DECL never have DECL_ALIGN set + meaningfully, it's always 1. */ case LABEL_DECL: case CONST_DECL: case VAR_DECL: case PARM_DECL: case RESULT_DECL: - if (DECL_ALIGN (t) != 0) - return DECL_ALIGN (t); - break; - case FUNCTION_DECL: - return FUNCTION_BOUNDARY; + gcc_assert (DECL_ALIGN (t) != 0); + return DECL_ALIGN (t); default: break; @@ -1935,7 +1969,7 @@ expr_align (tree t) ARRAY_TYPE) minus one. This counts only elements of the top array. */ tree -array_type_nelts (tree type) +array_type_nelts (const_tree type) { tree index_type, min, max; @@ -2127,9 +2161,9 @@ skip_simple_arithmetic (tree expr) /* Return which tree structure is used by T. */ enum tree_node_structure_enum -tree_node_structure (tree t) +tree_node_structure (const_tree t) { - enum tree_code code = TREE_CODE (t); + const enum tree_code code = TREE_CODE (t); switch (TREE_CODE_CLASS (code)) { @@ -2182,6 +2216,7 @@ tree_node_structure (tree t) /* tcc_constant cases. */ case INTEGER_CST: return TS_INT_CST; case REAL_CST: return TS_REAL_CST; + case FIXED_CST: return TS_FIXED_CST; case COMPLEX_CST: return TS_COMPLEX; case VECTOR_CST: return TS_VECTOR; case STRING_CST: return TS_STRING; @@ -2211,7 +2246,7 @@ tree_node_structure (tree t) or offset that depends on a field within a record. */ bool -contains_placeholder_p (tree exp) +contains_placeholder_p (const_tree exp) { enum tree_code code; @@ -2272,9 +2307,9 @@ contains_placeholder_p (tree exp) { case CALL_EXPR: { - tree arg; - call_expr_arg_iterator iter; - FOR_EACH_CALL_EXPR_ARG (arg, iter, exp) + const_tree arg; + const_call_expr_arg_iterator iter; + FOR_EACH_CONST_CALL_EXPR_ARG (arg, iter, exp) if (CONTAINS_PLACEHOLDER_P (arg)) return 1; return 0; @@ -2294,7 +2329,7 @@ contains_placeholder_p (tree exp) (for QUAL_UNION_TYPE) and field positions. */ static bool -type_contains_placeholder_1 (tree type) +type_contains_placeholder_1 (const_tree type) { /* If the size contains a placeholder or the parent type (component type in the case of arrays) type involves a placeholder, this type does. */ @@ -2322,6 +2357,7 @@ type_contains_placeholder_1 (tree type) case INTEGER_TYPE: case REAL_TYPE: + case FIXED_POINT_TYPE: /* Here we just check the bounds. */ return (CONTAINS_PLACEHOLDER_P (TYPE_MIN_VALUE (type)) || CONTAINS_PLACEHOLDER_P (TYPE_MAX_VALUE (type))); @@ -3069,6 +3105,15 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL) gcc_assert (code != GIMPLE_MODIFY_STMT); #endif + if ((code == MINUS_EXPR || code == PLUS_EXPR || code == MULT_EXPR) + && arg0 && arg1 && tt && POINTER_TYPE_P (tt)) + gcc_assert (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST); + + if (code == POINTER_PLUS_EXPR && arg0 && arg1 && tt) + gcc_assert (POINTER_TYPE_P (tt) && POINTER_TYPE_P (TREE_TYPE (arg0)) + && INTEGRAL_TYPE_P (TREE_TYPE (arg1)) + && useless_type_conversion_p (sizetype, TREE_TYPE (arg1))); + t = make_node_stat (code PASS_MEM_STAT); TREE_TYPE (t) = tt; @@ -3128,7 +3173,16 @@ build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1, t = make_node_stat (code PASS_MEM_STAT); TREE_TYPE (t) = tt; - side_effects = TREE_SIDE_EFFECTS (t); + /* As a special exception, if COND_EXPR has NULL branches, we + assume that it is a gimple statement and always consider + it to have side effects. */ + if (code == COND_EXPR + && tt == void_type_node + && arg1 == NULL_TREE + && arg2 == NULL_TREE) + side_effects = true; + else + side_effects = TREE_SIDE_EFFECTS (t); PROCESS_ARG(0); PROCESS_ARG(1); @@ -3293,8 +3347,6 @@ build_decl_stat (enum tree_code code, tree name, tree type MEM_STAT_DECL) if (code == VAR_DECL || code == PARM_DECL || code == RESULT_DECL) layout_decl (t, 0); - else if (code == FUNCTION_DECL) - DECL_MODE (t) = FUNCTION_MODE; return t; } @@ -3351,7 +3403,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); @@ -3367,6 +3419,8 @@ expand_location (source_location loc) void annotate_with_file_line (tree node, const char *file, int line) { + location_t *new_loc; + /* 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. */ @@ -3391,10 +3445,11 @@ annotate_with_file_line (tree node, const char *file, int line) return; } - SET_EXPR_LOCUS (node, ggc_alloc (sizeof (location_t))); - EXPR_LINENO (node) = line; - EXPR_FILENAME (node) = file; - last_annotated_node = EXPR_LOCUS (node); + new_loc = GGC_NEW (location_t); + new_loc->file = file; + new_loc->line = line; + SET_EXPR_LOCUS (node, new_loc); + last_annotated_node = new_loc; } void @@ -3411,7 +3466,7 @@ annotate_with_locus (tree node, location_t locus) decls and constants can be shared among multiple locations, so return nothing. */ location_t -expr_location (tree node) +expr_location (const_tree node) { #ifdef USE_MAPPED_LOCATION if (GIMPLE_STMT_P (node)) @@ -3439,7 +3494,7 @@ set_expr_location (tree node, location_t locus) } bool -expr_has_location (tree node) +expr_has_location (const_tree node) { #ifdef USE_MAPPED_LOCATION return expr_location (node) != UNKNOWN_LOCATION; @@ -3453,17 +3508,17 @@ source_location * #else source_locus #endif -expr_locus (tree node) +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; + return CONST_CAST (source_location *, &GIMPLE_STMT_LOCUS (node)); + return (EXPR_P (node) + ? CONST_CAST (source_location *, &node->exp.locus) + : (source_location *) 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 } @@ -3500,33 +3555,24 @@ set_expr_locus (tree node, #endif } -const char ** -expr_filename (tree node) +/* 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 (location_from_locus (GIMPLE_STMT_LOCUS (node))); + return LOCATION_FILE (location_from_locus (EXPR_CHECK (node)->exp.locus)); } -int * -expr_lineno (tree node) +/* 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 (location_from_locus (GIMPLE_STMT_LOCUS (node))); + return LOCATION_LINE (location_from_locus (EXPR_CHECK (node)->exp.locus)); } + /* Return a declaration like DDECL except that its DECL_ATTRIBUTES is ATTRIBUTE. */ @@ -3566,7 +3612,7 @@ iterative_hash_hashval_t (hashval_t val, hashval_t val2) /* Produce good hash value combining PTR and VAL2. */ static inline hashval_t -iterative_hash_pointer (void *ptr, hashval_t val2) +iterative_hash_pointer (const void *ptr, hashval_t val2) { if (sizeof (ptr) == sizeof (hashval_t)) return iterative_hash_hashval_t ((size_t) ptr, val2); @@ -3626,12 +3672,6 @@ build_type_attribute_qual_variant (tree ttype, tree attribute, int quals) TYPE_REFERENCE_TO (ntype) = 0; TYPE_ATTRIBUTES (ntype) = attribute; - if (TYPE_STRUCTURAL_EQUALITY_P (ttype)) - SET_TYPE_STRUCTURAL_EQUALITY (ntype); - else - TYPE_CANONICAL (ntype) - = build_qualified_type (TYPE_CANONICAL (ttype), quals); - /* Create a new main variant of TYPE. */ TYPE_MAIN_VARIANT (ntype) = ntype; TYPE_NEXT_VARIANT (ntype) = 0; @@ -3659,6 +3699,7 @@ build_type_attribute_qual_variant (tree ttype, tree attribute, int quals) (TREE_INT_CST_HIGH (TYPE_MAX_VALUE (ntype)), hashcode); break; case REAL_TYPE: + case FIXED_POINT_TYPE: { unsigned int precision = TYPE_PRECISION (ntype); hashcode = iterative_hash_object (precision, hashcode); @@ -3673,8 +3714,12 @@ 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); } @@ -3704,7 +3749,7 @@ build_type_attribute_variant (tree ttype, tree attribute) their canonicalized form. */ static int -is_attribute_with_length_p (const char *attr, int attr_len, tree ident) +is_attribute_with_length_p (const char *attr, int attr_len, const_tree ident) { int ident_len; const char *p; @@ -3747,7 +3792,7 @@ is_attribute_with_length_p (const char *attr, int attr_len, tree ident) We try both `text' and `__text__', ATTR may be either one. */ int -is_attribute_p (const char *attr, tree ident) +is_attribute_p (const char *attr, const_tree ident) { return is_attribute_with_length_p (attr, strlen (attr), ident); } @@ -3770,7 +3815,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; } @@ -3982,18 +4026,25 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags, *no_add_attrs = true; return tree_cons (name, args, NULL_TREE); } - if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE) + if (TREE_CODE (node) == RECORD_TYPE + || TREE_CODE (node) == UNION_TYPE) + { + node = TYPE_NAME (node); + if (!node) + return NULL_TREE; + } + else { warning (OPT_Wattributes, "%qs attribute ignored", IDENTIFIER_POINTER (name)); *no_add_attrs = true; + return NULL_TREE; } - - return NULL_TREE; } if (TREE_CODE (node) != FUNCTION_DECL - && TREE_CODE (node) != VAR_DECL) + && TREE_CODE (node) != VAR_DECL + && TREE_CODE (node) != TYPE_DECL) { *no_add_attrs = true; warning (OPT_Wattributes, "%qs attribute ignored", @@ -4056,6 +4107,22 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags, *no_add_attrs = true; } + /* A dllexport'd entity must have default visibility so that other + program units (shared libraries or the main executable) can see + it. A dllimport'd entity must have default visibility so that + the linker knows that undefined references within this program + unit can be resolved by the dynamic linker. */ + if (!*no_add_attrs) + { + if (DECL_VISIBILITY_SPECIFIED (node) + && DECL_VISIBILITY (node) != VISIBILITY_DEFAULT) + error ("%qs implies default visibility, but %qD has already " + "been declared with a different visibility", + IDENTIFIER_POINTER (name), node); + DECL_VISIBILITY (node) = VISIBILITY_DEFAULT; + DECL_VISIBILITY_SPECIFIED (node) = 1; + } + return NULL_TREE; } @@ -4075,7 +4142,7 @@ set_type_quals (tree type, int type_quals) /* Returns true iff cand is equivalent to base with type_quals. */ bool -check_qualified_type (tree cand, tree base, int type_quals) +check_qualified_type (const_tree cand, const_tree base, int type_quals) { return (TYPE_QUALS (cand) == type_quals && TYPE_NAME (cand) == TYPE_NAME (base) @@ -4164,7 +4231,11 @@ build_distinct_type_copy (tree type) /* Make it its own variant. */ TYPE_MAIN_VARIANT (t) = t; TYPE_NEXT_VARIANT (t) = 0; - + + /* Note that it is now possible for TYPE_MIN_VALUE to be a value + whose TREE_TYPE is not t. This can also happen in the Ada + frontend when using subtypes. */ + return t; } @@ -4198,7 +4269,7 @@ build_variant_type_copy (tree type) int tree_map_base_eq (const void *va, const void *vb) { - const struct tree_map_base *a = va, *b = vb; + const struct tree_map_base *const a = va, *const b = vb; return (a->from == b->from); } @@ -4217,7 +4288,7 @@ tree_map_base_hash (const void *item) int tree_map_base_marked_p (const void *p) { - return ggc_marked_p (((struct tree_map_base *) p)->from); + return ggc_marked_p (((const struct tree_map_base *) p)->from); } unsigned int @@ -4235,9 +4306,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; @@ -4252,7 +4320,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; @@ -4441,10 +4508,10 @@ decl_value_expr_insert (tree from, tree to) with types in the TREE_VALUE slots), by adding the hash codes of the individual types. */ -unsigned int -type_hash_list (tree list, hashval_t hashcode) +static unsigned int +type_hash_list (const_tree list, hashval_t hashcode) { - tree tail; + const_tree tail; for (tail = list; tail; tail = TREE_CHAIN (tail)) if (TREE_VALUE (tail) != error_mark_node) @@ -4461,7 +4528,7 @@ type_hash_list (tree list, hashval_t hashcode) static int type_hash_eq (const void *va, const void *vb) { - const struct type_hash *a = va, *b = vb; + const struct type_hash *const a = va, *const b = vb; /* First test the things that are the same for all types. */ if (a->hash != b->hash @@ -4506,6 +4573,9 @@ type_hash_eq (const void *va, const void *vb) || tree_int_cst_equal (TYPE_MIN_VALUE (a->type), TYPE_MIN_VALUE (b->type)))); + case FIXED_POINT_TYPE: + return TYPE_SATURATING (a->type) == TYPE_SATURATING (b->type); + case OFFSET_TYPE: return TYPE_OFFSET_BASETYPE (a->type) == TYPE_OFFSET_BASETYPE (b->type); @@ -4534,17 +4604,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. */ @@ -4640,7 +4717,7 @@ type_hash_canon (unsigned int hashcode, tree type) static int type_hash_marked_p (const void *p) { - tree type = ((struct type_hash *) p)->type; + const_tree const type = ((const struct type_hash *) p)->type; return ggc_marked_p (type) || TYPE_SYMTAB_POINTER (type); } @@ -4658,10 +4735,10 @@ print_type_hash_statistics (void) with names in the TREE_PURPOSE slots and args in the TREE_VALUE slots), by adding the hash codes of the individual attributes. */ -unsigned int -attribute_hash_list (tree list, hashval_t hashcode) +static unsigned int +attribute_hash_list (const_tree list, hashval_t hashcode) { - tree tail; + const_tree tail; for (tail = list; tail; tail = TREE_CHAIN (tail)) /* ??? Do we want to add in TREE_VALUE too? */ @@ -4674,7 +4751,7 @@ attribute_hash_list (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); @@ -4689,9 +4766,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) @@ -4710,8 +4787,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))) @@ -4742,9 +4823,9 @@ attribute_list_contained (tree l1, tree l2) Also, the TREE_PURPOSEs must match. */ int -type_list_equal (tree l1, tree l2) +type_list_equal (const_tree l1, const_tree l2) { - tree t1, t2; + const_tree t1, t2; for (t1 = l1, t2 = l2; t1 && t2; t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2)) if (TREE_VALUE (t1) != TREE_VALUE (t2) @@ -4762,7 +4843,7 @@ type_list_equal (tree l1, tree l2) then this function counts only the ordinary arguments. */ int -type_num_arguments (tree type) +type_num_arguments (const_tree type) { int i = 0; tree t; @@ -4782,7 +4863,7 @@ type_num_arguments (tree type) represent the same constant value. */ int -tree_int_cst_equal (tree t1, tree t2) +tree_int_cst_equal (const_tree t1, const_tree t2) { if (t1 == t2) return 1; @@ -4803,7 +4884,7 @@ tree_int_cst_equal (tree t1, tree t2) The precise way of comparison depends on their data type. */ int -tree_int_cst_lt (tree t1, tree t2) +tree_int_cst_lt (const_tree t1, const_tree t2) { if (t1 == t2) return 0; @@ -4830,7 +4911,7 @@ tree_int_cst_lt (tree t1, tree t2) /* Returns -1 if T1 < T2, 0 if T1 == T2, and 1 if T1 > T2. */ int -tree_int_cst_compare (tree t1, tree t2) +tree_int_cst_compare (const_tree t1, const_tree t2) { if (tree_int_cst_lt (t1, t2)) return -1; @@ -4846,14 +4927,15 @@ tree_int_cst_compare (tree t1, tree t2) be represented in a single unsigned HOST_WIDE_INT. */ int -host_integerp (tree t, int pos) +host_integerp (const_tree t, int pos) { return (TREE_CODE (t) == INTEGER_CST && ((TREE_INT_CST_HIGH (t) == 0 && (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)) + || TYPE_IS_SIZETYPE (TREE_TYPE (t)))) || (pos && TREE_INT_CST_HIGH (t) == 0))); } @@ -4862,7 +4944,7 @@ host_integerp (tree t, int pos) be non-negative. We must be able to satisfy the above conditions. */ HOST_WIDE_INT -tree_low_cst (tree t, int pos) +tree_low_cst (const_tree t, int pos) { gcc_assert (host_integerp (t, pos)); return TREE_INT_CST_LOW (t); @@ -4871,7 +4953,7 @@ tree_low_cst (tree t, int pos) /* Return the most significant bit of the integer constant T. */ int -tree_int_cst_msb (tree t) +tree_int_cst_msb (const_tree t) { int prec; HOST_WIDE_INT h; @@ -4890,7 +4972,7 @@ tree_int_cst_msb (tree t) Note that -1 will never be returned if T's type is unsigned. */ int -tree_int_cst_sgn (tree t) +tree_int_cst_sgn (const_tree t) { if (TREE_INT_CST_LOW (t) == 0 && TREE_INT_CST_HIGH (t) == 0) return 0; @@ -4906,7 +4988,7 @@ tree_int_cst_sgn (tree t) are known to be equal; otherwise return 0. */ int -simple_cst_list_equal (tree l1, tree l2) +simple_cst_list_equal (const_tree l1, const_tree l2) { while (l1 != NULL_TREE && l2 != NULL_TREE) { @@ -4927,7 +5009,7 @@ simple_cst_list_equal (tree l1, tree l2) this function. */ int -simple_cst_equal (tree t1, tree t2) +simple_cst_equal (const_tree t1, const_tree t2) { enum tree_code code1, code2; int cmp; @@ -4966,6 +5048,9 @@ simple_cst_equal (tree t1, tree t2) case REAL_CST: return REAL_VALUES_IDENTICAL (TREE_REAL_CST (t1), TREE_REAL_CST (t2)); + case FIXED_CST: + return FIXED_VALUES_IDENTICAL (TREE_FIXED_CST (t1), TREE_FIXED_CST (t2)); + case STRING_CST: return (TREE_STRING_LENGTH (t1) == TREE_STRING_LENGTH (t2) && ! memcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2), @@ -4998,13 +5083,13 @@ simple_cst_equal (tree t1, tree t2) if (call_expr_nargs (t1) != call_expr_nargs (t2)) return 0; { - tree arg1, arg2; - call_expr_arg_iterator iter1, iter2; - for (arg1 = first_call_expr_arg (t1, &iter1), - arg2 = first_call_expr_arg (t2, &iter2); + const_tree arg1, arg2; + const_call_expr_arg_iterator iter1, iter2; + for (arg1 = first_const_call_expr_arg (t1, &iter1), + arg2 = first_const_call_expr_arg (t2, &iter2); arg1 && arg2; - arg1 = next_call_expr_arg (&iter1), - arg2 = next_call_expr_arg (&iter2)) + arg1 = next_const_call_expr_arg (&iter1), + arg2 = next_const_call_expr_arg (&iter2)) { cmp = simple_cst_equal (arg1, arg2); if (cmp <= 0) @@ -5091,7 +5176,7 @@ simple_cst_equal (tree t1, tree t2) than U, respectively. */ int -compare_tree_int (tree t, unsigned HOST_WIDE_INT u) +compare_tree_int (const_tree t, unsigned HOST_WIDE_INT u) { if (tree_int_cst_sgn (t) < 0) return -1; @@ -5165,7 +5250,7 @@ commutative_tree_code (enum tree_code code) would compare equal using operand_equal_p. */ hashval_t -iterative_hash_expr (tree t, hashval_t val) +iterative_hash_expr (const_tree t, hashval_t val) { int i; enum tree_code code; @@ -5189,6 +5274,12 @@ iterative_hash_expr (tree t, hashval_t val) return iterative_hash_hashval_t (val2, val); } + case FIXED_CST: + { + unsigned int val2 = fixed_hash (TREE_FIXED_CST_PTR (t)); + + return iterative_hash_hashval_t (val2, val); + } case STRING_CST: return iterative_hash (TREE_STRING_POINTER (t), TREE_STRING_LENGTH (t), val); @@ -5592,7 +5683,7 @@ build_array_type (tree elt_type, tree index_type) the innermost dimension of ARRAY. */ tree -get_inner_array_type (tree array) +get_inner_array_type (const_tree array) { tree type = TREE_TYPE (array); @@ -5602,6 +5693,78 @@ get_inner_array_type (tree array) return type; } +/* Computes the canonical argument types from the argument type list + ARGTYPES. + + Upon return, *ANY_STRUCTURAL_P will be true iff either it was true + on entry to this function, or if any of the ARGTYPES are + structural. + + Upon return, *ANY_NONCANONICAL_P will be true iff either it was + true on entry to this function, or if any of the ARGTYPES are + non-canonical. + + Returns a canonical argument list, which may be ARGTYPES when the + canonical argument list is unneeded (i.e., *ANY_STRUCTURAL_P is + true) or would not differ from ARGTYPES. */ + +static tree +maybe_canonicalize_argtypes(tree argtypes, + bool *any_structural_p, + bool *any_noncanonical_p) +{ + tree arg; + bool any_noncanonical_argtypes_p = false; + + for (arg = argtypes; arg && !(*any_structural_p); arg = TREE_CHAIN (arg)) + { + if (!TREE_VALUE (arg) || TREE_VALUE (arg) == error_mark_node) + /* Fail gracefully by stating that the type is structural. */ + *any_structural_p = true; + else if (TYPE_STRUCTURAL_EQUALITY_P (TREE_VALUE (arg))) + *any_structural_p = true; + else if (TYPE_CANONICAL (TREE_VALUE (arg)) != TREE_VALUE (arg) + || TREE_PURPOSE (arg)) + /* If the argument has a default argument, we consider it + non-canonical even though the type itself is canonical. + That way, different variants of function and method types + with default arguments will all point to the variant with + no defaults as their canonical type. */ + any_noncanonical_argtypes_p = true; + } + + if (*any_structural_p) + return argtypes; + + if (any_noncanonical_argtypes_p) + { + /* Build the canonical list of argument types. */ + tree canon_argtypes = NULL_TREE; + bool is_void = false; + + for (arg = argtypes; arg; arg = TREE_CHAIN (arg)) + { + if (arg == void_list_node) + is_void = true; + else + canon_argtypes = tree_cons (NULL_TREE, + TYPE_CANONICAL (TREE_VALUE (arg)), + canon_argtypes); + } + + canon_argtypes = nreverse (canon_argtypes); + if (is_void) + canon_argtypes = chainon (canon_argtypes, void_list_node); + + /* There is a non-canonical type. */ + *any_noncanonical_p = true; + return canon_argtypes; + } + + /* The canonical argument types are the same as ARGTYPES. */ + return argtypes; +} + /* Construct, lay out and return the type of functions returning type VALUE_TYPE given arguments of types ARG_TYPES. @@ -5614,6 +5777,8 @@ build_function_type (tree value_type, tree arg_types) { tree t; hashval_t hashcode = 0; + bool any_structural_p, any_noncanonical_p; + tree canon_argtypes; if (TREE_CODE (value_type) == FUNCTION_TYPE) { @@ -5626,14 +5791,23 @@ build_function_type (tree value_type, tree arg_types) TREE_TYPE (t) = value_type; TYPE_ARG_TYPES (t) = arg_types; - /* We don't have canonicalization of function types, yet. */ - SET_TYPE_STRUCTURAL_EQUALITY (t); - /* If we already have such a type, use the old one. */ hashcode = iterative_hash_object (TYPE_HASH (value_type), hashcode); hashcode = type_hash_list (arg_types, hashcode); t = type_hash_canon (hashcode, t); + /* Set up the canonical type. */ + any_structural_p = TYPE_STRUCTURAL_EQUALITY_P (value_type); + any_noncanonical_p = TYPE_CANONICAL (value_type) != value_type; + canon_argtypes = maybe_canonicalize_argtypes (arg_types, + &any_structural_p, + &any_noncanonical_p); + if (any_structural_p) + SET_TYPE_STRUCTURAL_EQUALITY (t); + else if (any_noncanonical_p) + TYPE_CANONICAL (t) = build_function_type (TYPE_CANONICAL (value_type), + canon_argtypes); + if (!COMPLETE_TYPE_P (t)) layout_type (t); return t; @@ -5683,6 +5857,8 @@ build_method_type_directly (tree basetype, tree t; tree ptype; int hashcode = 0; + bool any_structural_p, any_noncanonical_p; + tree canon_argtypes; /* Make a node of the sort we want. */ t = make_node (METHOD_TYPE); @@ -5696,15 +5872,29 @@ build_method_type_directly (tree basetype, argtypes = tree_cons (NULL_TREE, ptype, argtypes); TYPE_ARG_TYPES (t) = argtypes; - /* We don't have canonicalization of method types yet. */ - SET_TYPE_STRUCTURAL_EQUALITY (t); - /* If we already have such a type, use the old one. */ hashcode = iterative_hash_object (TYPE_HASH (basetype), hashcode); hashcode = iterative_hash_object (TYPE_HASH (rettype), hashcode); hashcode = type_hash_list (argtypes, hashcode); t = type_hash_canon (hashcode, t); + /* Set up the canonical type. */ + any_structural_p + = (TYPE_STRUCTURAL_EQUALITY_P (basetype) + || TYPE_STRUCTURAL_EQUALITY_P (rettype)); + any_noncanonical_p + = (TYPE_CANONICAL (basetype) != basetype + || TYPE_CANONICAL (rettype) != rettype); + canon_argtypes = maybe_canonicalize_argtypes (TREE_CHAIN (argtypes), + &any_structural_p, + &any_noncanonical_p); + if (any_structural_p) + SET_TYPE_STRUCTURAL_EQUALITY (t); + else if (any_noncanonical_p) + TYPE_CANONICAL (t) + = build_method_type_directly (TYPE_CANONICAL (basetype), + TYPE_CANONICAL (rettype), + canon_argtypes); if (!COMPLETE_TYPE_P (t)) layout_type (t); @@ -5755,10 +5945,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)); } @@ -5794,10 +5984,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) @@ -5826,7 +6014,7 @@ build_complex_type (tree component_type) name = 0; if (name != 0) - TYPE_NAME (t) = get_identifier (name); + TYPE_NAME (t) = build_decl (TYPE_DECL, get_identifier (name), t); } return build_qualified_type (t, TYPE_QUALS (component_type)); @@ -5920,6 +6108,7 @@ 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)) @@ -6011,6 +6200,7 @@ get_narrower (tree op, int *unsignedp_ptr) if (TREE_CODE (op) == COMPONENT_REF /* Since type_for_size always gives an integer type. */ && TREE_CODE (TREE_TYPE (op)) != REAL_TYPE + && TREE_CODE (TREE_TYPE (op)) != FIXED_POINT_TYPE /* Ensure field is laid out already. */ && DECL_SIZE (TREE_OPERAND (op, 1)) != 0 && host_integerp (DECL_SIZE (TREE_OPERAND (op, 1)), 1)) @@ -6048,7 +6238,7 @@ get_narrower (tree op, int *unsignedp_ptr) for type TYPE (an INTEGER_TYPE). */ int -int_fits_type_p (tree c, tree type) +int_fits_type_p (const_tree c, const_tree type) { tree type_low_bound = TYPE_MIN_VALUE (type); tree type_high_bound = TYPE_MAX_VALUE (type); @@ -6120,6 +6310,60 @@ int_fits_type_p (tree c, tree type) return !fit_double_type (low, high, &low, &high, type); } +/* Stores bounds of an integer TYPE in MIN and MAX. If TYPE has non-constant + bounds or is a POINTER_TYPE, the maximum and/or minimum values that can be + represented (assuming two's-complement arithmetic) within the bit + precision of the type are returned instead. */ + +void +get_type_static_bounds (const_tree type, mpz_t min, mpz_t max) +{ + if (!POINTER_TYPE_P (type) && TYPE_MIN_VALUE (type) + && TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST) + mpz_set_double_int (min, tree_to_double_int (TYPE_MIN_VALUE (type)), + TYPE_UNSIGNED (type)); + else + { + if (TYPE_UNSIGNED (type)) + mpz_set_ui (min, 0); + else + { + double_int mn; + mn = double_int_mask (TYPE_PRECISION (type) - 1); + mn = double_int_sext (double_int_add (mn, double_int_one), + TYPE_PRECISION (type)); + mpz_set_double_int (min, mn, false); + } + } + + if (!POINTER_TYPE_P (type) && TYPE_MAX_VALUE (type) + && TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST) + mpz_set_double_int (max, tree_to_double_int (TYPE_MAX_VALUE (type)), + TYPE_UNSIGNED (type)); + else + { + if (TYPE_UNSIGNED (type)) + mpz_set_double_int (max, double_int_mask (TYPE_PRECISION (type)), + true); + else + mpz_set_double_int (max, double_int_mask (TYPE_PRECISION (type) - 1), + true); + } +} + +/* 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 @@ -6134,7 +6378,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; @@ -6193,6 +6437,7 @@ variably_modified_type_p (tree type, tree fn) case INTEGER_TYPE: case REAL_TYPE: + case FIXED_POINT_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE: /* Scalar types are variably modified if their end points @@ -6242,7 +6487,7 @@ variably_modified_type_p (tree type, tree fn) NULL_TREE if there is no containing scope. */ tree -get_containing_scope (tree t) +get_containing_scope (const_tree t) { return (TYPE_P (t) ? TYPE_CONTEXT (t) : DECL_CONTEXT (t)); } @@ -6251,7 +6496,7 @@ get_containing_scope (tree t) a FUNCTION_DECL, or zero if none. */ tree -decl_function_context (tree decl) +decl_function_context (const_tree decl) { tree context; @@ -6287,7 +6532,7 @@ decl_function_context (tree decl) TYPE_DECLs and FUNCTION_DECLs are transparent to this function. */ tree -decl_type_context (tree decl) +decl_type_context (const_tree decl) { tree context = DECL_CONTEXT (decl); @@ -6324,12 +6569,12 @@ decl_type_context (tree decl) determined. */ tree -get_callee_fndecl (tree call) +get_callee_fndecl (const_tree call) { tree addr; if (call == error_mark_node) - return call; + return error_mark_node; /* It's invalid to call this function with anything but a CALL_EXPR. */ @@ -6521,11 +6766,11 @@ get_file_function_name (const char *type) are of the caller. */ void -tree_check_failed (const tree node, const char *file, +tree_check_failed (const_tree node, const char *file, int line, const char *function, ...) { va_list args; - char *buffer; + const char *buffer; unsigned length = 0; int code; @@ -6535,23 +6780,24 @@ tree_check_failed (const tree node, const char *file, va_end (args); if (length) { + char *tmp; va_start (args, function); length += strlen ("expected "); - buffer = alloca (length); + buffer = tmp = alloca (length); length = 0; while ((code = va_arg (args, int))) { const char *prefix = length ? " or " : "expected "; - strcpy (buffer + length, prefix); + strcpy (tmp + length, prefix); length += strlen (prefix); - strcpy (buffer + length, tree_code_name[code]); + strcpy (tmp + length, tree_code_name[code]); length += strlen (tree_code_name[code]); } va_end (args); } else - buffer = (char *)"unexpected node"; + buffer = "unexpected node"; internal_error ("tree check: %s, have %s in %s, at %s:%d", buffer, tree_code_name[TREE_CODE (node)], @@ -6563,7 +6809,7 @@ tree_check_failed (const tree node, const char *file, the caller. */ void -tree_not_check_failed (const tree node, const char *file, +tree_not_check_failed (const_tree node, const char *file, int line, const char *function, ...) { va_list args; @@ -6599,7 +6845,7 @@ tree_not_check_failed (const tree node, const char *file, code, given in CL. */ void -tree_class_check_failed (const tree node, const enum tree_code_class cl, +tree_class_check_failed (const_tree node, const enum tree_code_class cl, const char *file, int line, const char *function) { internal_error @@ -6613,7 +6859,7 @@ tree_class_check_failed (const tree node, const enum tree_code_class cl, dozen codes, use the knowledge that they're all sequential. */ void -tree_range_check_failed (const tree node, const char *file, int line, +tree_range_check_failed (const_tree node, const char *file, int line, const char *function, enum tree_code c1, enum tree_code c2) { @@ -6648,7 +6894,7 @@ tree_range_check_failed (const tree node, const char *file, int line, not have the specified code, given in CL. */ void -tree_not_class_check_failed (const tree node, const enum tree_code_class cl, +tree_not_class_check_failed (const_tree node, const enum tree_code_class cl, const char *file, int line, const char *function) { internal_error @@ -6662,7 +6908,7 @@ tree_not_class_check_failed (const tree node, const enum tree_code_class cl, /* Similar to tree_check_failed but applied to OMP_CLAUSE codes. */ void -omp_clause_check_failed (const tree node, const char *file, int line, +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", @@ -6674,7 +6920,7 @@ omp_clause_check_failed (const tree node, const char *file, int 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, +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) { @@ -6719,7 +6965,7 @@ static const char *ts_enum_names[] = { whether CODE contains the tree structure identified by EN. */ void -tree_contains_struct_check_failed (const tree node, +tree_contains_struct_check_failed (const_tree node, const enum tree_node_structure_enum en, const char *file, int line, const char *function) @@ -6759,7 +7005,7 @@ phi_node_elt_check_failed (int idx, int len, const char *file, int line, vector of an expression node EXP. */ void -tree_operand_check_failed (int idx, tree exp, const char *file, +tree_operand_check_failed (int idx, const_tree exp, const char *file, int line, const char *function) { int code = TREE_CODE (exp); @@ -6773,7 +7019,7 @@ tree_operand_check_failed (int idx, tree exp, const char *file, operands of an OMP_CLAUSE node. */ void -omp_clause_operand_check_failed (int idx, tree t, const char *file, +omp_clause_operand_check_failed (int idx, const_tree t, const char *file, int line, const char *function) { internal_error @@ -6862,6 +7108,80 @@ make_or_reuse_type (unsigned size, int unsignedp) return make_signed_type (size); } +/* Create or reuse a fract type by SIZE, UNSIGNEDP, and SATP. */ + +static tree +make_or_reuse_fract_type (unsigned size, int unsignedp, int satp) +{ + if (satp) + { + if (size == SHORT_FRACT_TYPE_SIZE) + return unsignedp ? sat_unsigned_short_fract_type_node + : sat_short_fract_type_node; + if (size == FRACT_TYPE_SIZE) + return unsignedp ? sat_unsigned_fract_type_node : sat_fract_type_node; + if (size == LONG_FRACT_TYPE_SIZE) + return unsignedp ? sat_unsigned_long_fract_type_node + : sat_long_fract_type_node; + if (size == LONG_LONG_FRACT_TYPE_SIZE) + return unsignedp ? sat_unsigned_long_long_fract_type_node + : sat_long_long_fract_type_node; + } + else + { + if (size == SHORT_FRACT_TYPE_SIZE) + return unsignedp ? unsigned_short_fract_type_node + : short_fract_type_node; + if (size == FRACT_TYPE_SIZE) + return unsignedp ? unsigned_fract_type_node : fract_type_node; + if (size == LONG_FRACT_TYPE_SIZE) + return unsignedp ? unsigned_long_fract_type_node + : long_fract_type_node; + if (size == LONG_LONG_FRACT_TYPE_SIZE) + return unsignedp ? unsigned_long_long_fract_type_node + : long_long_fract_type_node; + } + + return make_fract_type (size, unsignedp, satp); +} + +/* Create or reuse an accum type by SIZE, UNSIGNEDP, and SATP. */ + +static tree +make_or_reuse_accum_type (unsigned size, int unsignedp, int satp) +{ + if (satp) + { + if (size == SHORT_ACCUM_TYPE_SIZE) + return unsignedp ? sat_unsigned_short_accum_type_node + : sat_short_accum_type_node; + if (size == ACCUM_TYPE_SIZE) + return unsignedp ? sat_unsigned_accum_type_node : sat_accum_type_node; + if (size == LONG_ACCUM_TYPE_SIZE) + return unsignedp ? sat_unsigned_long_accum_type_node + : sat_long_accum_type_node; + if (size == LONG_LONG_ACCUM_TYPE_SIZE) + return unsignedp ? sat_unsigned_long_long_accum_type_node + : sat_long_long_accum_type_node; + } + else + { + if (size == SHORT_ACCUM_TYPE_SIZE) + return unsignedp ? unsigned_short_accum_type_node + : short_accum_type_node; + if (size == ACCUM_TYPE_SIZE) + return unsignedp ? unsigned_accum_type_node : accum_type_node; + if (size == LONG_ACCUM_TYPE_SIZE) + return unsignedp ? unsigned_long_accum_type_node + : long_accum_type_node; + if (size == LONG_LONG_ACCUM_TYPE_SIZE) + return unsignedp ? unsigned_long_long_accum_type_node + : long_long_accum_type_node; + } + + return make_accum_type (size, unsignedp, satp); +} + /* Create nodes for all integer types (and error_mark_node) using the sizes of C datatypes. The caller should call set_sizetype soon after calling this function to select one of the types as sizetype. */ @@ -7004,21 +7324,54 @@ build_common_tree_nodes_2 (int short_double) 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); - - complex_float_type_node = make_node (COMPLEX_TYPE); - TREE_TYPE (complex_float_type_node) = float_type_node; - layout_type (complex_float_type_node); - - complex_double_type_node = make_node (COMPLEX_TYPE); - TREE_TYPE (complex_double_type_node) = double_type_node; - layout_type (complex_double_type_node); - - complex_long_double_type_node = make_node (COMPLEX_TYPE); - TREE_TYPE (complex_long_double_type_node) = long_double_type_node; - layout_type (complex_long_double_type_node); + complex_integer_type_node = build_complex_type (integer_type_node); + complex_float_type_node = build_complex_type (float_type_node); + complex_double_type_node = build_complex_type (double_type_node); + complex_long_double_type_node = build_complex_type (long_double_type_node); + +/* Make fixed-point nodes based on sat/non-sat and signed/unsigned. */ +#define MAKE_FIXED_TYPE_NODE(KIND,WIDTH,SIZE) \ + sat_ ## WIDTH ## KIND ## _type_node = \ + make_sat_signed_ ## KIND ## _type (SIZE); \ + sat_unsigned_ ## WIDTH ## KIND ## _type_node = \ + make_sat_unsigned_ ## KIND ## _type (SIZE); \ + WIDTH ## KIND ## _type_node = make_signed_ ## KIND ## _type (SIZE); \ + unsigned_ ## WIDTH ## KIND ## _type_node = \ + make_unsigned_ ## KIND ## _type (SIZE); + +/* Make fixed-point type nodes based on four different widths. */ +#define MAKE_FIXED_TYPE_NODE_FAMILY(N1,N2) \ + MAKE_FIXED_TYPE_NODE (N1, short_, SHORT_ ## N2 ## _TYPE_SIZE) \ + MAKE_FIXED_TYPE_NODE (N1, , N2 ## _TYPE_SIZE) \ + MAKE_FIXED_TYPE_NODE (N1, long_, LONG_ ## N2 ## _TYPE_SIZE) \ + MAKE_FIXED_TYPE_NODE (N1, long_long_, LONG_LONG_ ## N2 ## _TYPE_SIZE) + +/* Make fixed-point mode nodes based on sat/non-sat and signed/unsigned. */ +#define MAKE_FIXED_MODE_NODE(KIND,NAME,MODE) \ + NAME ## _type_node = \ + make_or_reuse_signed_ ## KIND ## _type (GET_MODE_BITSIZE (MODE ## mode)); \ + u ## NAME ## _type_node = \ + make_or_reuse_unsigned_ ## KIND ## _type \ + (GET_MODE_BITSIZE (U ## MODE ## mode)); \ + sat_ ## NAME ## _type_node = \ + make_or_reuse_sat_signed_ ## KIND ## _type \ + (GET_MODE_BITSIZE (MODE ## mode)); \ + sat_u ## NAME ## _type_node = \ + make_or_reuse_sat_unsigned_ ## KIND ## _type \ + (GET_MODE_BITSIZE (U ## MODE ## mode)); + + /* Fixed-point type and mode nodes. */ + MAKE_FIXED_TYPE_NODE_FAMILY (fract, FRACT) + MAKE_FIXED_TYPE_NODE_FAMILY (accum, ACCUM) + MAKE_FIXED_MODE_NODE (fract, qq, QQ) + MAKE_FIXED_MODE_NODE (fract, hq, HQ) + MAKE_FIXED_MODE_NODE (fract, sq, SQ) + MAKE_FIXED_MODE_NODE (fract, dq, DQ) + MAKE_FIXED_MODE_NODE (fract, tq, TQ) + MAKE_FIXED_MODE_NODE (accum, ha, HA) + MAKE_FIXED_MODE_NODE (accum, sa, SA) + MAKE_FIXED_MODE_NODE (accum, da, DA) + MAKE_FIXED_MODE_NODE (accum, ta, TA) { tree t = targetm.build_builtin_va_list (); @@ -7229,11 +7582,18 @@ tree reconstruct_complex_type (tree type, tree bottom) { tree inner, outer; - - if (POINTER_TYPE_P (type)) + + if (TREE_CODE (type) == POINTER_TYPE) { inner = reconstruct_complex_type (TREE_TYPE (type), bottom); - outer = build_pointer_type (inner); + outer = build_pointer_type_for_mode (inner, TYPE_MODE (type), + TYPE_REF_CAN_ALIAS_ALL (type)); + } + else if (TREE_CODE (type) == REFERENCE_TYPE) + { + inner = reconstruct_complex_type (TREE_TYPE (type), bottom); + outer = build_reference_type_for_mode (inner, TYPE_MODE (type), + TYPE_REF_CAN_ALIAS_ALL (type)); } else if (TREE_CODE (type) == ARRAY_TYPE) { @@ -7247,23 +7607,19 @@ reconstruct_complex_type (tree type, tree bottom) } else if (TREE_CODE (type) == METHOD_TYPE) { - tree argtypes; inner = reconstruct_complex_type (TREE_TYPE (type), bottom); /* The build_method_type_directly() routine prepends 'this' to argument list, so we must compensate by getting rid of it. */ - argtypes = TYPE_ARG_TYPES (type); - outer = build_method_type_directly (TYPE_METHOD_BASETYPE (type), - inner, - TYPE_ARG_TYPES (type)); - TYPE_ARG_TYPES (outer) = argtypes; + outer + = build_method_type_directly + (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (type))), + inner, + TREE_CHAIN (TYPE_ARG_TYPES (type))); } 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 @@ -7277,6 +7633,10 @@ build_vector_type_for_mode (tree innertype, enum machine_mode mode) { case MODE_VECTOR_INT: case MODE_VECTOR_FLOAT: + case MODE_VECTOR_FRACT: + case MODE_VECTOR_UFRACT: + case MODE_VECTOR_ACCUM: + case MODE_VECTOR_UACCUM: nunits = GET_MODE_NUNITS (mode); break; @@ -7319,7 +7679,7 @@ build_resx (int region_number) /* Given an initializer INIT, return TRUE if INIT is zero or some aggregate of zeros. Otherwise return FALSE. */ bool -initializer_zerop (tree init) +initializer_zerop (const_tree init) { tree elt; @@ -7337,6 +7697,9 @@ initializer_zerop (tree init) return real_zerop (init) && ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (init)); + case FIXED_CST: + return fixed_zerop (init); + case COMPLEX_CST: return integer_zerop (init) || (real_zerop (init) @@ -7606,7 +7969,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); @@ -7622,7 +7985,7 @@ needs_to_live_in_memory (tree t) are compatible. It is assumed that the parent records are compatible. */ bool -fields_compatible_p (tree f1, tree f2) +fields_compatible_p (const_tree f1, const_tree f2) { if (!operand_equal_p (DECL_FIELD_BIT_OFFSET (f1), DECL_FIELD_BIT_OFFSET (f2), OEP_ONLY_CONST)) @@ -7632,7 +7995,7 @@ fields_compatible_p (tree f1, tree f2) DECL_FIELD_OFFSET (f2), OEP_ONLY_CONST)) return false; - if (!lang_hooks.types_compatible_p (TREE_TYPE (f1), TREE_TYPE (f2))) + if (!types_compatible_p (TREE_TYPE (f1), TREE_TYPE (f2))) return false; return true; @@ -7664,7 +8027,7 @@ find_compatible_field (tree record, tree orig_field) /* Return value of a constant X. */ HOST_WIDE_INT -int_cst_value (tree x) +int_cst_value (const_tree x) { unsigned bits = TYPE_PRECISION (TREE_TYPE (x)); unsigned HOST_WIDE_INT val = TREE_INT_CST_LOW (x); @@ -7680,15 +8043,29 @@ int_cst_value (tree x) return val; } +/* If TYPE is an integral type, return an equivalent type which is + unsigned iff UNSIGNEDP is true. If TYPE is not an integral type, + return TYPE itself. */ + +tree +signed_or_unsigned_type_for (int unsignedp, tree type) +{ + tree t = type; + if (POINTER_TYPE_P (type)) + t = size_type_node; + + if (!INTEGRAL_TYPE_P (t) || TYPE_UNSIGNED (t) == unsignedp) + return t; + + return lang_hooks.types.type_for_size (TYPE_PRECISION (t), unsignedp); +} /* Returns unsigned variant of TYPE. */ 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); + return signed_or_unsigned_type_for (1, type); } /* Returns signed variant of TYPE. */ @@ -7696,9 +8073,7 @@ 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); + return signed_or_unsigned_type_for (0, type); } /* Returns the largest value obtainable by casting something in INNER type to @@ -7817,7 +8192,7 @@ lower_bound_in_type (tree outer, tree inner) and get the same result, only slower. */ int -operand_equal_for_phi_arg_p (tree arg0, tree arg1) +operand_equal_for_phi_arg_p (const_tree arg0, const_tree arg1) { if (arg0 == arg1) return 1; @@ -7831,7 +8206,7 @@ operand_equal_for_phi_arg_p (tree arg0, tree arg1) ??? Use ffs if available? */ tree -num_ending_zeros (tree x) +num_ending_zeros (const_tree x) { unsigned HOST_WIDE_INT fr, nfr; unsigned num, abits; @@ -7868,7 +8243,7 @@ num_ending_zeros (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; \ } \ @@ -7880,7 +8255,7 @@ num_ending_zeros (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; @@ -7960,7 +8335,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; @@ -8007,10 +8383,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) { @@ -8018,6 +8396,7 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset) case IDENTIFIER_NODE: case INTEGER_CST: case REAL_CST: + case FIXED_CST: case VECTOR_CST: case STRING_CST: case BLOCK: @@ -8163,7 +8542,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; @@ -8196,6 +8575,7 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset) else if (TREE_CODE (*type_p) == BOOLEAN_TYPE || TREE_CODE (*type_p) == ENUMERAL_TYPE || TREE_CODE (*type_p) == INTEGER_TYPE + || TREE_CODE (*type_p) == FIXED_POINT_TYPE || TREE_CODE (*type_p) == REAL_TYPE) { WALK_SUBTREE (TYPE_MIN_VALUE (*type_p)); @@ -8227,7 +8607,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; } @@ -8241,13 +8621,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; } @@ -8322,4 +8703,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"