diff options
author | Mark Mitchell <mark@codesourcery.com> | 1999-11-05 09:26:11 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 1999-11-05 09:26:11 +0000 |
commit | 8dfaeb6384f2630d761cd174c9ed1048f2d70ff9 (patch) | |
tree | 2bcac642768c7fd2d983046a13ba0c097ac83b2e | |
parent | 71144a650c7723a6548f4795eb7c09304c242a03 (diff) | |
download | gcc-8dfaeb6384f2630d761cd174c9ed1048f2d70ff9.zip gcc-8dfaeb6384f2630d761cd174c9ed1048f2d70ff9.tar.gz gcc-8dfaeb6384f2630d761cd174c9ed1048f2d70ff9.tar.bz2 |
Makefile.in (typeck2.o): Depend on output.h.
* Makefile.in (typeck2.o): Depend on output.h.
* typeck2.c: Include output.h.
* decl.c (flag_ansi): Remove declaration.
* pt.c (tinst_level_tick): Make it static.
(last_template_error_tick): Likewise.
* cp-tree.h (mapcar): Remove declaration.
(search_tree): Likewise.
(walk_tree_fn): New typedef.
(walk_tree): New function.
* tree.c (bot_manip): Change prototype. Adjust to be called via
walk_tree.
(bot_replace): Likewise.
(no_linkage_helper): Likewise.
(copy_tree_r): New function.
(search_tree): Rename, and adjust, to become ...
(walk_tree): New function.
(mapcar): Remove.
(target_remap): Remove.
(target_remap_count): Likewise.
(break_out_target_exprs): Use walk_tree.
* decl.c (local_variable_p): Change prototype.
(check_default_argument): Use walk_tree.
* pt.c (for_each_template_parm_r): New function, split out from ...
(for_each_template_parm): Here. Use it, via walk_tree.
From-SVN: r30412
-rw-r--r-- | gcc/cp/ChangeLog | 2 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 4 | ||||
-rw-r--r-- | gcc/cp/decl.c | 13 | ||||
-rw-r--r-- | gcc/cp/pt.c | 290 | ||||
-rw-r--r-- | gcc/cp/tree.c | 604 |
5 files changed, 294 insertions, 619 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 19e5c97..1882c28 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -19,7 +19,7 @@ (copy_tree_r): New function. (search_tree): Rename, and adjust, to become ... (walk_tree): New function. - (mapcar): Rtemove. + (mapcar): Remove. (target_remap): Remove. (target_remap_count): Likewise. (break_out_target_exprs): Use walk_tree. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 882ca04..6f8f1b7 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -3986,7 +3986,6 @@ extern int varargs_function_p PROTO((tree)); extern int really_overloaded_fn PROTO((tree)); extern int cp_tree_equal PROTO((tree, tree)); extern int can_free PROTO((struct obstack *, tree)); -extern tree mapcar PROTO((tree, tree (*) (tree))); extern tree no_linkage_check PROTO((tree)); extern void debug_binfo PROTO((tree)); extern void push_expression_obstack PROTO((void)); @@ -3994,7 +3993,8 @@ extern void push_permanent_obstack PROTO((void)); extern tree build_dummy_object PROTO((tree)); extern tree maybe_dummy_object PROTO((tree, tree *)); extern int is_dummy_object PROTO((tree)); -extern tree search_tree PROTO((tree *, tree (*)(tree *))); +typedef tree (*walk_tree_fn) PROTO((tree *, int *, void *)); +extern tree walk_tree PROTO((tree *, walk_tree_fn, void *)); extern int cp_valid_lang_attribute PROTO((tree, tree, tree, tree)); extern tree make_ptrmem_cst PROTO((tree, tree)); extern tree cp_build_qualified_type_real PROTO((tree, int, int)); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 40d1396..80aec15 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -141,7 +141,7 @@ static boolean typename_compare PROTO((hash_table_key, hash_table_key)); static void push_binding PROTO((tree, tree, struct binding_level*)); static int add_binding PROTO((tree, tree)); static void pop_binding PROTO((tree, tree)); -static tree local_variable_p PROTO((tree *)); +static tree local_variable_p PROTO((tree *, int *, void *)); static tree find_binding PROTO((tree, tree)); static tree select_decl PROTO((tree, int)); static int lookup_flags PROTO((int, int)); @@ -349,11 +349,6 @@ extern int flag_no_builtin; extern int flag_no_nonansi_builtin; -/* Nonzero means enable obscure ANSI features and disable GNU extensions - that might cause ANSI-compliant code to be miscompiled. */ - -extern int flag_ansi; - /* Nonzero if we want to support huge (> 2^(sizeof(short)*8-1) bytes) objects. */ extern int flag_huge_objects; @@ -11189,8 +11184,10 @@ require_complete_types_for_parms (parms) NULL_TREE otherwise. */ static tree -local_variable_p (tp) +local_variable_p (tp, walk_subtrees, data) tree *tp; + int *walk_subtrees ATTRIBUTE_UNUSED; + void *data ATTRIBUTE_UNUSED; { tree t = *tp; @@ -11272,7 +11269,7 @@ check_default_argument (decl, arg) The keyword `this' shall not be used in a default argument of a member function. */ - var = search_tree (&arg, local_variable_p); + var = walk_tree (&arg, local_variable_p, NULL); if (var) { cp_error ("default argument `%E' uses local variable `%D'", diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index c96d032..c70147d 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -4032,83 +4032,56 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope) } } -/* For each TEMPLATE_TYPE_PARM, TEMPLATE_TEMPLATE_PARM, or - TEMPLATE_PARM_INDEX in T, call FN with the parameter and the DATA. - If FN returns non-zero, the iteration is terminated, and - for_each_template_parm returns 1. Otherwise, the iteration - continues. If FN never returns a non-zero value, the value - returned by for_each_template_parm is 0. If FN is NULL, it is - considered to be the function which always returns 1. */ - -static int -for_each_template_parm (t, fn, data) - tree t; - tree_fn_t fn; - void* data; +struct pair_fn_data { - if (!t) - return 0; + tree_fn_t fn; + void *data; +}; + +/* Called from for_each_template_parm via walk_tree. */ +static tree +for_each_template_parm_r (tp, walk_subtrees, d) + tree *tp; + int *walk_subtrees; + void *d; +{ + tree t = *tp; + struct pair_fn_data *pfd = (struct pair_fn_data *) d; + tree_fn_t fn = pfd->fn; + void *data = pfd->data; + if (TREE_CODE_CLASS (TREE_CODE (t)) == 't' && for_each_template_parm (TYPE_CONTEXT (t), fn, data)) - return 1; + return error_mark_node; switch (TREE_CODE (t)) { - case ARRAY_REF: - case OFFSET_REF: - return (for_each_template_parm (TREE_OPERAND (t, 0), fn, data) - || for_each_template_parm (TREE_OPERAND (t, 1), fn, data)); - - case IDENTIFIER_NODE: - if (!IDENTIFIER_TEMPLATE (t)) - return 0; - my_friendly_abort (42); - - /* aggregates of tree nodes */ - case TREE_VEC: - { - int i = TREE_VEC_LENGTH (t); - while (i--) - if (for_each_template_parm (TREE_VEC_ELT (t, i), fn, data)) - return 1; - return 0; - } - case TREE_LIST: - if (for_each_template_parm (TREE_PURPOSE (t), fn, data) - || for_each_template_parm (TREE_VALUE (t), fn, data)) - return 1; - return for_each_template_parm (TREE_CHAIN (t), fn, data); - - case OVERLOAD: - if (for_each_template_parm (OVL_FUNCTION (t), fn, data)) - return 1; - return for_each_template_parm (OVL_CHAIN (t), fn, data); - - /* constructed type nodes */ - case POINTER_TYPE: - case REFERENCE_TYPE: - return for_each_template_parm (TREE_TYPE (t), fn, data); - case RECORD_TYPE: if (TYPE_PTRMEMFUNC_FLAG (t)) - return for_each_template_parm (TYPE_PTRMEMFUNC_FN_TYPE (t), - fn, data); + break; /* Fall through. */ case UNION_TYPE: case ENUMERAL_TYPE: - if (! TYPE_TEMPLATE_INFO (t)) - return 0; - return for_each_template_parm (TREE_VALUE - (TYPE_TEMPLATE_INFO (t)), - fn, data); + if (!TYPE_TEMPLATE_INFO (t)) + *walk_subtrees = 0; + else if (for_each_template_parm (TREE_VALUE (TYPE_TEMPLATE_INFO (t)), + fn, data)) + return error_mark_node; + break; + case METHOD_TYPE: + /* Since we're not going to walk subtrees, we have to do this + explicitly here. */ if (for_each_template_parm (TYPE_METHOD_BASETYPE (t), fn, data)) - return 1; - /* Fall through. */ + return error_mark_node; case FUNCTION_TYPE: + /* Check the return type. */ + if (for_each_template_parm (TREE_TYPE (t), fn, data)) + return error_mark_node; + /* Check the parameter types. Since default arguments are not instantiated until they are needed, the TYPE_ARG_TYPES may contain expressions that involve template parameters. But, @@ -4120,132 +4093,72 @@ for_each_template_parm (t, fn, data) for (parm = TYPE_ARG_TYPES (t); parm; parm = TREE_CHAIN (parm)) if (for_each_template_parm (TREE_VALUE (parm), fn, data)) - return 1; - } - - /* Check the return type, too. */ - return for_each_template_parm (TREE_TYPE (t), fn, data); - - case ARRAY_TYPE: - if (for_each_template_parm (TYPE_DOMAIN (t), fn, data)) - return 1; - return for_each_template_parm (TREE_TYPE (t), fn, data); - case OFFSET_TYPE: - if (for_each_template_parm (TYPE_OFFSET_BASETYPE (t), fn, data)) - return 1; - return for_each_template_parm (TREE_TYPE (t), fn, data); - - /* decl nodes */ - case TYPE_DECL: - return for_each_template_parm (TREE_TYPE (t), fn, data); + return error_mark_node; - case TEMPLATE_DECL: - /* A template template parameter is encountered */ - if (DECL_TEMPLATE_TEMPLATE_PARM_P (t)) - return for_each_template_parm (TREE_TYPE (t), fn, data); - /* Already substituted template template parameter */ - return 0; - - case CONST_DECL: - if (for_each_template_parm (DECL_INITIAL (t), fn, data)) - return 1; - goto check_type_and_context; + /* Since we've already handled the TYPE_ARG_TYPES, we don't + want walk_tree walking into them itself. */ + *walk_subtrees = 0; + } + break; case FUNCTION_DECL: case VAR_DECL: if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t) && for_each_template_parm (DECL_TI_ARGS (t), fn, data)) - return 1; - /* fall through */ + return error_mark_node; + /* Fall through. */ + + case CONST_DECL: case PARM_DECL: - check_type_and_context: - if (for_each_template_parm (TREE_TYPE (t), fn, data)) - return 1; if (DECL_CONTEXT (t) && for_each_template_parm (DECL_CONTEXT (t), fn, data)) - return 1; - return 0; - - case CALL_EXPR: - return (for_each_template_parm (TREE_OPERAND (t, 0), fn, data) - || for_each_template_parm (TREE_OPERAND (t, 1), fn, data)); - - case ADDR_EXPR: - return for_each_template_parm (TREE_OPERAND (t, 0), fn, data); + return error_mark_node; + break; - /* template parm nodes */ case TEMPLATE_TEMPLATE_PARM: /* Record template parameters such as `T' inside `TT<T>'. */ if (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t) && for_each_template_parm (TYPE_TI_ARGS (t), fn, data)) - return 1; + return error_mark_node; + /* Fall through. */ + case TEMPLATE_TYPE_PARM: case TEMPLATE_PARM_INDEX: - if (fn) - return (*fn)(t, data); - else - return 1; - - /* simple type nodes */ - case INTEGER_TYPE: - if (for_each_template_parm (TYPE_MIN_VALUE (t), fn, data)) - return 1; - return for_each_template_parm (TYPE_MAX_VALUE (t), fn, data); - - case REAL_TYPE: - case COMPLEX_TYPE: - case VOID_TYPE: - case BOOLEAN_TYPE: - case NAMESPACE_DECL: - case FIELD_DECL: - return 0; - - /* constants */ - case INTEGER_CST: - case REAL_CST: - case STRING_CST: - return 0; - - case ERROR_MARK: - /* Non-error_mark_node ERROR_MARKs are bad things. */ - my_friendly_assert (t == error_mark_node, 274); - /* NOTREACHED */ - return 0; - - case PTRMEM_CST: - return for_each_template_parm (TREE_TYPE (t), fn, data); - - case SCOPE_REF: - return for_each_template_parm (TREE_OPERAND (t, 0), fn, data); + if (fn && (*fn)(t, data)) + return error_mark_node; + else if (!fn) + return error_mark_node; + break; - case CONSTRUCTOR: - if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t))) - return for_each_template_parm (TYPE_PTRMEMFUNC_FN_TYPE - (TREE_TYPE (t)), fn, data); - return for_each_template_parm (TREE_OPERAND (t, 1), fn, data); + case TEMPLATE_DECL: + /* A template template parameter is encountered */ + if (DECL_TEMPLATE_TEMPLATE_PARM_P (t) + && for_each_template_parm (TREE_TYPE (t), fn, data)) + return error_mark_node; - case SIZEOF_EXPR: - case ALIGNOF_EXPR: - return for_each_template_parm (TREE_OPERAND (t, 0), fn, data); + /* Already substituted template template parameter */ + *walk_subtrees = 0; + break; case TYPENAME_TYPE: - if (!fn) - return 1; - return (for_each_template_parm (TYPE_CONTEXT (t), fn, data) - || for_each_template_parm (TYPENAME_TYPE_FULLNAME (t), - fn, data)); + if (!fn || for_each_template_parm (TYPENAME_TYPE_FULLNAME (t), fn, data)) + return error_mark_node; + break; + case CONSTRUCTOR: + if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t)) + && for_each_template_parm (TYPE_PTRMEMFUNC_FN_TYPE + (TREE_TYPE (t)), fn, data)) + return error_mark_node; + break; + case INDIRECT_REF: case COMPONENT_REF: /* If there's no type, then this thing must be some expression involving template parameters. */ if (!fn && !TREE_TYPE (t)) - return 1; - if (TREE_CODE (t) == COMPONENT_REF) - return (for_each_template_parm (TREE_OPERAND (t, 0), fn, data) - || for_each_template_parm (TREE_OPERAND (t, 1), fn, data)); - else - return for_each_template_parm (TREE_OPERAND (t, 0), fn, data); + return error_mark_node; + break; case MODOP_EXPR: case CAST_EXPR: @@ -4259,32 +4172,39 @@ for_each_template_parm (t, fn, data) case LOOKUP_EXPR: case PSEUDO_DTOR_EXPR: if (!fn) - return 1; - /* Fall through. */ + return error_mark_node; + break; default: - switch (TREE_CODE_CLASS (TREE_CODE (t))) - { - case '1': - case '2': - case 'e': - case '<': - { - int i; - for (i = first_rtl_op (TREE_CODE (t)); --i >= 0;) - if (for_each_template_parm (TREE_OPERAND (t, i), fn, data)) - return 1; - return 0; - } - default: - break; - } - sorry ("testing %s for template parms", - tree_code_name [(int) TREE_CODE (t)]); - my_friendly_abort (82); - /* NOTREACHED */ - return 0; + break; } + + /* We didn't find any template parameters we liked. */ + return NULL_TREE; +} + +/* For each TEMPLATE_TYPE_PARM, TEMPLATE_TEMPLATE_PARM, or + TEMPLATE_PARM_INDEX in T, call FN with the parameter and the DATA. + If FN returns non-zero, the iteration is terminated, and + for_each_template_parm returns 1. Otherwise, the iteration + continues. If FN never returns a non-zero value, the value + returned by for_each_template_parm is 0. If FN is NULL, it is + considered to be the function which always returns 1. */ + +static int +for_each_template_parm (t, fn, data) + tree t; + tree_fn_t fn; + void* data; +{ + struct pair_fn_data pfd; + + /* Set up. */ + pfd.fn = fn; + pfd.data = data; + + /* Walk the tree. */ + return walk_tree (&t, for_each_template_parm_r, &pfd) != NULL_TREE; } int @@ -4301,8 +4221,8 @@ extern int max_tinst_depth; #ifdef GATHER_STATISTICS int depth_reached; #endif -int tinst_level_tick; -int last_template_error_tick; +static int tinst_level_tick; +static int last_template_error_tick; /* Print out all the template instantiations that we are currently working on. If ERR, we are being called from cp_thing, so do diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 0dbc539..d1b725b 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -30,8 +30,8 @@ Boston, MA 02111-1307, USA. */ #include "ggc.h" #include "splay-tree.h" -static tree bot_manip PROTO((tree)); -static tree bot_replace PROTO((tree *)); +static tree bot_manip PROTO((tree *, int *, void *)); +static tree bot_replace PROTO((tree *, int *, void *)); static tree build_cplus_array_type_1 PROTO((tree, tree)); static void list_hash_add PROTO((int, tree)); static int list_hash PROTO((tree, tree, tree)); @@ -39,9 +39,10 @@ static tree list_hash_lookup PROTO((int, tree, tree, tree)); static void propagate_binfo_offsets PROTO((tree, tree)); static int avoid_overlap PROTO((tree, tree)); static cp_lvalue_kind lvalue_p_1 PROTO((tree, int)); -static tree no_linkage_helper PROTO((tree *)); +static tree no_linkage_helper PROTO((tree *, int *, void *)); static tree build_srcloc PROTO((char *, int)); static void mark_list_hash PROTO ((void *)); +static tree copy_tree_r PROTO ((tree *, int *, void *)); #define CEIL(x,y) (((x) + (y) - 1) / (y)) @@ -1524,221 +1525,181 @@ copy_template_template_parm (t) return t2; } -/* Walk through the tree structure T, applying func. If func ever returns - non-null, return that value. */ +/* Apply FUNC to all the sub-trees of TP in a pre-order traversal. + FUNC is called with the DATA and the address of each sub-tree. If + FUNC returns a non-NULL value, the traversal is aborted, and the + value returned by FUNC is returned. */ -tree -search_tree (tp, func) +tree +walk_tree (tp, func, data) tree *tp; - tree (*func) PROTO((tree *)); + walk_tree_fn func; + void *data; { -#define TRY(ARG) if (tmp=search_tree (&ARG, func), tmp != NULL_TREE) return tmp - - tree t = *tp; - tree tmp; - enum tree_code code; + enum tree_code code; + int walk_subtrees; + tree result; - if (t == NULL_TREE) +#define WALK_SUBTREE(NODE) \ + do \ + { \ + result = walk_tree (&(NODE), func, data); \ + if (result) \ + return result; \ + } \ + while (0) + + /* Skip empty subtrees. */ + if (!*tp) return NULL_TREE; - - tmp = func (tp); - if (tmp) - return tmp; - /* Handle some common cases up front. */ - code = TREE_CODE (t); - if (TREE_CODE_CLASS (code) == '1') + /* Call the function. */ + walk_subtrees = 1; + result = (*func) (tp, &walk_subtrees, data); + + /* If we found something, return it. */ + if (result) + return result; + + /* Even if we didn't, FUNC may have decided that there was nothing + interesting below this point in the tree. */ + if (!walk_subtrees) + return NULL_TREE; + + code = TREE_CODE (*tp); + + /* Handle commmon cases up front. */ + if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)) + || TREE_CODE_CLASS (code) == 'r') { - TRY (TREE_OPERAND (t, 0)); + int i; + + /* Walk over all the sub-trees of this operand. */ + for (i = first_rtl_op (code) - 1; i >= 0; --i) + WALK_SUBTREE (TREE_OPERAND (*tp, i)); + + /* We didn't find what we were looking for. */ return NULL_TREE; } - else if (TREE_CODE_CLASS (code) == '2' || TREE_CODE_CLASS (code) == '<') + else if (TREE_CODE_CLASS (code) == 'd') { - TRY (TREE_OPERAND (t, 0)); - TRY (TREE_OPERAND (t, 1)); + WALK_SUBTREE (TREE_TYPE (*tp)); + WALK_SUBTREE (DECL_INITIAL (*tp)); + WALK_SUBTREE (DECL_SIZE (*tp)); + + /* We didn't find what we were looking for. */ return NULL_TREE; } + /* Not one of the easy cases. We must explicitly go through the + children. */ switch (code) { case ERROR_MARK: - break; - case IDENTIFIER_NODE: + case INTEGER_CST: + case REAL_CST: + case STRING_CST: + case DEFAULT_ARG: + case TEMPLATE_TEMPLATE_PARM: + case TEMPLATE_PARM_INDEX: + case TEMPLATE_TYPE_PARM: + case REAL_TYPE: + case COMPLEX_TYPE: + case VOID_TYPE: + case BOOLEAN_TYPE: + case TYPENAME_TYPE: + case UNION_TYPE: + case ENUMERAL_TYPE: + case TYPEOF_TYPE: + case BLOCK: + /* None of thse have subtrees other than those already walked + above. */ break; - case VAR_DECL: - case FUNCTION_DECL: - case CONST_DECL: - case TEMPLATE_DECL: - case NAMESPACE_DECL: - break; - - case TYPE_DECL: - TRY (TREE_TYPE (t)); + case PTRMEM_CST: + WALK_SUBTREE (TREE_TYPE (*tp)); break; - case PARM_DECL: - TRY (TREE_TYPE (t)); - TRY (TREE_CHAIN (t)); + case POINTER_TYPE: + case REFERENCE_TYPE: + WALK_SUBTREE (TREE_TYPE (*tp)); break; case TREE_LIST: - TRY (TREE_PURPOSE (t)); - TRY (TREE_VALUE (t)); - TRY (TREE_CHAIN (t)); + WALK_SUBTREE (TREE_PURPOSE (*tp)); + WALK_SUBTREE (TREE_VALUE (*tp)); + WALK_SUBTREE (TREE_CHAIN (*tp)); break; case OVERLOAD: - TRY (OVL_FUNCTION (t)); - TRY (OVL_CHAIN (t)); + WALK_SUBTREE (OVL_FUNCTION (*tp)); + WALK_SUBTREE (OVL_CHAIN (*tp)); break; case TREE_VEC: { - int len = TREE_VEC_LENGTH (t); - - t = copy_node (t); + int len = TREE_VEC_LENGTH (*tp); while (len--) - TRY (TREE_VEC_ELT (t, len)); + WALK_SUBTREE (TREE_VEC_ELT (*tp, len)); } break; - case INTEGER_CST: - case REAL_CST: - case STRING_CST: - case DEFAULT_ARG: - break; - - case PTRMEM_CST: - TRY (TREE_TYPE (t)); - break; - - case COND_EXPR: - case TARGET_EXPR: - case AGGR_INIT_EXPR: - case NEW_EXPR: - TRY (TREE_OPERAND (t, 0)); - TRY (TREE_OPERAND (t, 1)); - TRY (TREE_OPERAND (t, 2)); - break; - - case TRUTH_AND_EXPR: - case TRUTH_OR_EXPR: - case TRUTH_XOR_EXPR: - case TRUTH_ANDIF_EXPR: - case TRUTH_ORIF_EXPR: - case PREDECREMENT_EXPR: - case PREINCREMENT_EXPR: - case POSTDECREMENT_EXPR: - case POSTINCREMENT_EXPR: - case ARRAY_REF: - case SCOPE_REF: - case TRY_CATCH_EXPR: - case WITH_CLEANUP_EXPR: - case CALL_EXPR: - case COMPOUND_EXPR: - case MODIFY_EXPR: - case INIT_EXPR: - case OFFSET_REF: - TRY (TREE_OPERAND (t, 0)); - TRY (TREE_OPERAND (t, 1)); - break; - - case SAVE_EXPR: - case ADDR_EXPR: - case INDIRECT_REF: - case TRUTH_NOT_EXPR: - case COMPONENT_REF: - case CLEANUP_POINT_EXPR: - case LOOKUP_EXPR: - case THROW_EXPR: - case EXIT_EXPR: - case LOOP_EXPR: - case BIT_FIELD_REF: - case VA_ARG_EXPR: - TRY (TREE_OPERAND (t, 0)); - break; - - case MODOP_EXPR: - case ARROW_EXPR: - case DOTSTAR_EXPR: - case TYPEID_EXPR: - case PSEUDO_DTOR_EXPR: - break; - case COMPLEX_CST: - TRY (TREE_REALPART (t)); - TRY (TREE_IMAGPART (t)); + WALK_SUBTREE (TREE_REALPART (*tp)); + WALK_SUBTREE (TREE_IMAGPART (*tp)); break; case CONSTRUCTOR: - TRY (CONSTRUCTOR_ELTS (t)); - break; - - case TEMPLATE_TEMPLATE_PARM: - case TEMPLATE_PARM_INDEX: - case TEMPLATE_TYPE_PARM: - break; - - case BIND_EXPR: - case STMT_EXPR: - break; - - case REAL_TYPE: - case COMPLEX_TYPE: - case VOID_TYPE: - case BOOLEAN_TYPE: - case TYPENAME_TYPE: - case UNION_TYPE: - case ENUMERAL_TYPE: - case TYPEOF_TYPE: + WALK_SUBTREE (CONSTRUCTOR_ELTS (*tp)); break; - case POINTER_TYPE: - case REFERENCE_TYPE: - TRY (TREE_TYPE (t)); - break; + case METHOD_TYPE: + WALK_SUBTREE (TYPE_METHOD_BASETYPE (*tp)); + /* Fall through. */ case FUNCTION_TYPE: - case METHOD_TYPE: - TRY (TREE_TYPE (t)); - TRY (TYPE_ARG_TYPES (t)); + WALK_SUBTREE (TREE_TYPE (*tp)); + WALK_SUBTREE (TYPE_ARG_TYPES (*tp)); break; case ARRAY_TYPE: - TRY (TREE_TYPE (t)); - TRY (TYPE_DOMAIN (t)); + WALK_SUBTREE (TREE_TYPE (*tp)); + WALK_SUBTREE (TYPE_DOMAIN (*tp)); break; case INTEGER_TYPE: - TRY (TYPE_MAX_VALUE (t)); + WALK_SUBTREE (TYPE_MIN_VALUE (*tp)); + WALK_SUBTREE (TYPE_MAX_VALUE (*tp)); break; case OFFSET_TYPE: - TRY (TREE_TYPE (t)); - TRY (TYPE_OFFSET_BASETYPE (t)); + WALK_SUBTREE (TREE_TYPE (*tp)); + WALK_SUBTREE (TYPE_OFFSET_BASETYPE (*tp)); break; case RECORD_TYPE: - if (TYPE_PTRMEMFUNC_P (t)) - TRY (TYPE_PTRMEMFUNC_FN_TYPE (t)); + if (TYPE_PTRMEMFUNC_P (*tp)) + WALK_SUBTREE (TYPE_PTRMEMFUNC_FN_TYPE (*tp)); break; default: my_friendly_abort (19990803); } + /* We didn't find what we were looking for. */ return NULL_TREE; -#undef TRY +#undef WALK_SUBTREE } -/* Passed to search_tree. Checks for the use of types with no linkage. */ +/* Passed to walk_tree. Checks for the use of types with no linkage. */ static tree -no_linkage_helper (tp) +no_linkage_helper (tp, walk_subtrees, data) tree *tp; + int *walk_subtrees ATTRIBUTE_UNUSED; + void *data ATTRIBUTE_UNUSED; { tree t = *tp; @@ -1762,269 +1723,47 @@ no_linkage_check (t) if (processing_template_decl) return NULL_TREE; - t = search_tree (&t, no_linkage_helper); + t = walk_tree (&t, no_linkage_helper, NULL); if (t != error_mark_node) return t; return NULL_TREE; } +/* Passed to walk_tree. Copies the node pointed to, if appropriate. */ -/* Make copies of all the nodes below T. If FUNC is non-NULL, call it - for each node. */ - -tree -mapcar (t, func) - tree t; - tree (*func) PROTO((tree)); -{ - tree tmp; - enum tree_code code; - - if (t == NULL_TREE) - return t; - - if (func) - { - tmp = func (t); - if (tmp) - return tmp; - } - - /* Handle some common cases up front. */ - code = TREE_CODE (t); - if (TREE_CODE_CLASS (code) == '1') - { - t = copy_node (t); - TREE_TYPE (t) = mapcar (TREE_TYPE (t), func); - TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func); - return t; - } - else if (TREE_CODE_CLASS (code) == '2' || TREE_CODE_CLASS (code) == '<') - { - t = copy_node (t); - TREE_TYPE (t) = mapcar (TREE_TYPE (t), func); - TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func); - TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func); - return t; - } - - switch (TREE_CODE (t)) +static tree +copy_tree_r (tp, walk_subtrees, data) + tree *tp; + int *walk_subtrees ATTRIBUTE_UNUSED; + void *data ATTRIBUTE_UNUSED; +{ + enum tree_code code = TREE_CODE (*tp); + + /* We make copies of most nodes. */ + if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)) + || TREE_CODE_CLASS (code) == 'r' + || TREE_CODE_CLASS (code) == 'c' + || code == PARM_DECL + || code == TREE_LIST + || code == TREE_VEC + || code == OVERLOAD) { - case ERROR_MARK: - return error_mark_node; - - case VAR_DECL: - case FUNCTION_DECL: - case CONST_DECL: - /* Rather than aborting, return error_mark_node. This allows us - to report a sensible error message on code like this: - - void g() { int i; f<i>(7); } - - In a case like: - - void g() { const int i = 7; f<i>(7); } - - however, we must actually return the constant initializer. */ - if (TREE_READONLY_DECL_P (t)) - { - tmp = decl_constant_value (t); - if (tmp != t) - return mapcar (tmp, func); - } - return error_mark_node; - - case PARM_DECL: - { - tree chain = TREE_CHAIN (t); - t = copy_node (t); - TREE_CHAIN (t) = mapcar (chain, func); - TREE_TYPE (t) = mapcar (TREE_TYPE (t), func); - DECL_INITIAL (t) = mapcar (DECL_INITIAL (t), func); - DECL_SIZE (t) = mapcar (DECL_SIZE (t), func); - return t; - } - - case TREE_LIST: - { - tree chain = TREE_CHAIN (t); - t = copy_node (t); - TREE_PURPOSE (t) = mapcar (TREE_PURPOSE (t), func); - TREE_VALUE (t) = mapcar (TREE_VALUE (t), func); - TREE_CHAIN (t) = mapcar (chain, func); - return t; - } - - case OVERLOAD: - { - tree chain = OVL_CHAIN (t); - t = copy_node (t); - OVL_FUNCTION (t) = mapcar (OVL_FUNCTION (t), func); - OVL_CHAIN (t) = mapcar (chain, func); - return t; - } - - case TREE_VEC: - { - int len = TREE_VEC_LENGTH (t); - - t = copy_node (t); - while (len--) - TREE_VEC_ELT (t, len) = mapcar (TREE_VEC_ELT (t, len), func); - return t; - } + /* Because the chain gets clobbered when we make a copy, we save it + here. */ + tree chain = TREE_CHAIN (*tp); - case INTEGER_CST: - case REAL_CST: - case STRING_CST: - return copy_node (t); - - case PTRMEM_CST: - t = copy_node (t); - TREE_TYPE (t) = mapcar (TREE_TYPE (t), func); - PTRMEM_CST_MEMBER (t) = mapcar (PTRMEM_CST_MEMBER (t), func); - return t; - - case COND_EXPR: - case TARGET_EXPR: - case AGGR_INIT_EXPR: - t = copy_node (t); - TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func); - TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func); - TREE_OPERAND (t, 2) = mapcar (TREE_OPERAND (t, 2), func); - return t; - - case TRUTH_AND_EXPR: - case TRUTH_OR_EXPR: - case TRUTH_XOR_EXPR: - case TRUTH_ANDIF_EXPR: - case TRUTH_ORIF_EXPR: - case PREDECREMENT_EXPR: - case PREINCREMENT_EXPR: - case POSTDECREMENT_EXPR: - case POSTINCREMENT_EXPR: - case ARRAY_REF: - case SCOPE_REF: - case TRY_CATCH_EXPR: - case WITH_CLEANUP_EXPR: - case COMPOUND_EXPR: - case MODIFY_EXPR: - case INIT_EXPR: - case OFFSET_REF: - t = copy_node (t); - TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func); - TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func); - return t; - - case CALL_EXPR: - t = copy_node (t); - TREE_TYPE (t) = mapcar (TREE_TYPE (t), func); - TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func); - TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func); - TREE_OPERAND (t, 2) = NULL_TREE; - return t; + /* Copy the node. */ + *tp = copy_node (*tp); - case SAVE_EXPR: - case ADDR_EXPR: - case INDIRECT_REF: - case TRUTH_NOT_EXPR: - case COMPONENT_REF: - case CLEANUP_POINT_EXPR: - case THROW_EXPR: - case STMT_EXPR: - case VA_ARG_EXPR: - t = copy_node (t); - TREE_TYPE (t) = mapcar (TREE_TYPE (t), func); - TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func); - return t; - - case POINTER_TYPE: - tmp = build_pointer_type (mapcar (TREE_TYPE (t), func)); - return cp_build_qualified_type (tmp, TYPE_QUALS (t)); - case REFERENCE_TYPE: - tmp = build_reference_type (mapcar (TREE_TYPE (t), func)); - return cp_build_qualified_type (tmp, TYPE_QUALS (t)); - case FUNCTION_TYPE: - tmp = build_function_type (mapcar (TREE_TYPE (t), func), - mapcar (TYPE_ARG_TYPES (t), func)); - return cp_build_qualified_type (tmp, TYPE_QUALS (t)); - case ARRAY_TYPE: - tmp = build_cplus_array_type (mapcar (TREE_TYPE (t), func), - mapcar (TYPE_DOMAIN (t), func)); - return cp_build_qualified_type (tmp, CP_TYPE_QUALS (t)); - case INTEGER_TYPE: - tmp = build_index_type (mapcar (TYPE_MAX_VALUE (t), func)); - return cp_build_qualified_type (tmp, TYPE_QUALS (t)); - case OFFSET_TYPE: - tmp = build_offset_type (mapcar (TYPE_OFFSET_BASETYPE (t), func), - mapcar (TREE_TYPE (t), func)); - return cp_build_qualified_type (tmp, TYPE_QUALS (t)); - case METHOD_TYPE: - tmp = build_cplus_method_type - (mapcar (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))), func), - mapcar (TREE_TYPE (t), func), - mapcar (TREE_CHAIN (TYPE_ARG_TYPES (t)), func)); - return cp_build_qualified_type (tmp, TYPE_QUALS (t)); - - case COMPLEX_CST: - t = copy_node (t); - TREE_REALPART (t) = mapcar (TREE_REALPART (t), func); - TREE_IMAGPART (t) = mapcar (TREE_REALPART (t), func); - return t; - - case CONSTRUCTOR: - t = copy_node (t); - CONSTRUCTOR_ELTS (t) = mapcar (CONSTRUCTOR_ELTS (t), func); - return t; - - case TEMPLATE_TEMPLATE_PARM: - return copy_template_template_parm (t); - - case BIND_EXPR: - t = copy_node (t); - TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func); - TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func); - TREE_OPERAND (t, 2) = NULL_TREE; - return t; - - case NEW_EXPR: - t = copy_node (t); - TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func); - TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func); - TREE_OPERAND (t, 2) = mapcar (TREE_OPERAND (t, 2), func); - return t; - - case BIT_FIELD_REF: - t = copy_node (t); - TREE_TYPE (t) = mapcar (TREE_TYPE (t), func); - TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func); - TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func); - TREE_OPERAND (t, 2) = mapcar (TREE_OPERAND (t, 2), func); - return t; - - case LOOKUP_EXPR: - case EXIT_EXPR: - case LOOP_EXPR: - t = copy_node (t); - TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func); - return t; - - case RTL_EXPR: - t = copy_node (t); - TREE_TYPE (t) = mapcar (TREE_TYPE (t), func); - return t; - - case RECORD_TYPE: - if (TYPE_PTRMEMFUNC_P (t)) - return build_ptrmemfunc_type - (mapcar (TYPE_PTRMEMFUNC_FN_TYPE (t), func)); - /* else fall through */ - - default: - my_friendly_abort (19990815); + /* Now, restore the chain, if appropriate. That will cause + walk_tree to walk into the chain as well. */ + if (code == PARM_DECL || code == TREE_LIST || code == OVERLOAD) + TREE_CHAIN (*tp) = chain; } - my_friendly_abort (107); - /* NOTREACHED */ + else if (code == TEMPLATE_TEMPLATE_PARM) + /* These must be copied specially. */ + *tp = copy_template_template_parm (*tp); + return NULL_TREE; } @@ -2092,24 +1831,23 @@ array_type_nelts_total (type) return sz; } -/* When we parse a default argument expression, we may create - temporary variables via TARGET_EXPRs. When we actually use the - default-argument expression, we make a copy of the expression, but - we must relpace the temporaries with appropriate local versions. */ - -/* A map from VAR_DECLs declared in TARGET_EXPRs in a default argument - to corresponding "instantiations" of those variables. */ -static splay_tree target_remap; -static int target_remap_count; - /* Called from break_out_target_exprs via mapcar. */ static tree -bot_manip (t) - tree t; +bot_manip (tp, walk_subtrees, data) + tree *tp; + int *walk_subtrees; + void *data; { + splay_tree target_remap = ((splay_tree) data); + tree t = *tp; + if (TREE_CODE (t) != TREE_LIST && ! TREE_SIDE_EFFECTS (t)) - return t; + { + /* There can't be any TARGET_EXPRs below this point. */ + *walk_subtrees = 0; + return NULL_TREE; + } else if (TREE_CODE (t) == TARGET_EXPR) { tree u; @@ -2131,20 +1869,34 @@ bot_manip (t) splay_tree_insert (target_remap, (splay_tree_key) TREE_OPERAND (t, 0), (splay_tree_value) TREE_OPERAND (u, 0)); - return u; + + /* Replace the old expression with the new version. */ + *tp = u; + /* We don't have to go below this point; the recursive call to + break_out_target_exprs will have handled anything below this + point. */ + *walk_subtrees = 0; + return NULL_TREE; } else if (TREE_CODE (t) == CALL_EXPR) mark_used (TREE_OPERAND (TREE_OPERAND (t, 0), 0)); - return NULL_TREE; + /* Make a copy of this node. */ + return copy_tree_r (tp, walk_subtrees, NULL); } -/* Replace all remapped VAR_DECLs in T with their new equivalents. */ +/* Replace all remapped VAR_DECLs in T with their new equivalents. + DATA is really a splay-tree mapping old variables to new + variables. */ static tree -bot_replace (t) +bot_replace (t, walk_subtrees, data) tree *t; + int *walk_subtrees ATTRIBUTE_UNUSED; + void *data; { + splay_tree target_remap = ((splay_tree) data); + if (TREE_CODE (*t) == VAR_DECL) { splay_tree_node n = splay_tree_lookup (target_remap, @@ -2156,18 +1908,24 @@ bot_replace (t) return NULL_TREE; } -/* Actually, we'll just clean out the target exprs for the moment. */ +/* When we parse a default argument expression, we may create + temporary variables via TARGET_EXPRs. When we actually use the + default-argument expression, we make a copy of the expression, but + we must replace the temporaries with appropriate local versions. */ tree break_out_target_exprs (t) tree t; { + static int target_remap_count; + static splay_tree target_remap; + if (!target_remap_count++) target_remap = splay_tree_new (splay_tree_compare_pointers, /*splay_tree_delete_key_fn=*/NULL, /*splay_tree_delete_value_fn=*/NULL); - t = mapcar (t, bot_manip); - search_tree (&t, bot_replace); + walk_tree (&t, bot_manip, target_remap); + walk_tree (&t, bot_replace, target_remap); if (!--target_remap_count) { |