From: Mark Mitchell Date: Fri, 24 Sep 1999 20:54:08 +0000 (+0000) Subject: cp-tree.h (CPTI_CLEANUP_TYPE): New macro. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b3ab27f3c3564665232fc000d9a4fc7dfc54f608;p=platform%2Fupstream%2Fgcc.git cp-tree.h (CPTI_CLEANUP_TYPE): New macro. * cp-tree.h (CPTI_CLEANUP_TYPE): New macro. (cleanup_type): Likewise. (search_tree): Change prototype. * decl.c (local_variable_p): Adjust for new interface to search_tree. (check_default_argument): Likewise. * error.c (dump_expr): Handle INIT_EXPR. * except.c (expand_throw): Don't make cleanup_type a local static. * expr.c (cplus_expand_expr): Don't handle NEW_EXPR. * init.c (build_new): Call build_new_1 directly, rather than building a NEW_EXPR. (build_new_1): Tidy. Don't build a VEC_INIT_EXPR except when processing file-scope initializers. * lex.c (init_parse): Add an opname_tab entry for INIT_EXPR. * tree.c: Include splay-tree.h (no_linkage_helper): Adjust for new interface to search_tree. (search_tree): Pass around pointers to tree nodes, rather than the nodes themselves. Handle VEC_INIT_EXPR. (no_linkage_check): Adjust for new interface to search_tree. (mapcar): Handle VEC_INIT_EXPR. (target_remap): New variable. (bot_manip): Use it. (bot_replace): New function. (break_out_target_exprs): Use it to remap all variables used in a default argument expression. * typeck.c (build_modify_expr): Don't crash when outside a function and presented with an INIT_EXPR assignment * Makefile.in (tree.o): Depend on splay-tree.h. From-SVN: r29659 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ee850ce..19485a5 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,34 @@ +1999-09-24 Mark Mitchell + + * cp-tree.h (CPTI_CLEANUP_TYPE): New macro. + (cleanup_type): Likewise. + (search_tree): Change prototype. + * decl.c (local_variable_p): Adjust for new interface to + search_tree. + (check_default_argument): Likewise. + * error.c (dump_expr): Handle INIT_EXPR. + * except.c (expand_throw): Don't make cleanup_type a local static. + * expr.c (cplus_expand_expr): Don't handle NEW_EXPR. + * init.c (build_new): Call build_new_1 directly, rather than + building a NEW_EXPR. + (build_new_1): Tidy. Don't build a VEC_INIT_EXPR except when + processing file-scope initializers. + * lex.c (init_parse): Add an opname_tab entry for INIT_EXPR. + * tree.c: Include splay-tree.h + (no_linkage_helper): Adjust for new interface to search_tree. + (search_tree): Pass around pointers to tree nodes, rather than the + nodes themselves. Handle VEC_INIT_EXPR. + (no_linkage_check): Adjust for new interface to search_tree. + (mapcar): Handle VEC_INIT_EXPR. + (target_remap): New variable. + (bot_manip): Use it. + (bot_replace): New function. + (break_out_target_exprs): Use it to remap all variables used in a + default argument expression. + * typeck.c (build_modify_expr): Don't crash when outside a + function and presented with an INIT_EXPR assignment + * Makefile.in (tree.o): Depend on splay-tree.h. + Fri Sep 24 10:48:10 1999 Bernd Schmidt * decl.c (duplicate_decls): Use DECL_BUILT_IN_CLASS rather than diff --git a/gcc/cp/Makefile.in b/gcc/cp/Makefile.in index db32e7f..5f0b118 100644 --- a/gcc/cp/Makefile.in +++ b/gcc/cp/Makefile.in @@ -274,7 +274,8 @@ cvt.o : cvt.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../system.h decl.h \ search.o : search.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../stack.h \ $(srcdir)/../flags.h $(srcdir)/../system.h $(srcdir)/../toplev.h $(RTL_H) tree.o : tree.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \ - $(srcdir)/../system.h $(srcdir)/../toplev.h $(srcdir)/../ggc.h $(RTL_H) + $(srcdir)/../system.h $(srcdir)/../toplev.h $(srcdir)/../ggc.h $(RTL_H) \ + $(srcdir)/../../include/splay-tree.h ptree.o : ptree.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../system.h rtti.o : rtti.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \ $(srcdir)/../system.h $(srcdir)/../toplev.h diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index cb46071..584600e 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -408,6 +408,7 @@ enum cp_tree_index CPTI_WCHAR_DECL, CPTI_VTABLE_ENTRY_TYPE, CPTI_DELTA_TYPE, + CPTI_CLEANUP_TYPE, CPTI_TP_DESC_TYPE, CPTI_ACCESS_MODE_TYPE, @@ -560,6 +561,9 @@ extern tree cp_global_trees[CPTI_MAX]; /* The declaration for `std::atexit'. */ #define atexit_node cp_global_trees[CPTI_ATEXIT] +/* The type of a destructor. */ +#define cleanup_type cp_global_trees[CPTI_CLEANUP_TYPE] + /* Global state. */ struct saved_scope { @@ -3855,7 +3859,7 @@ 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))); +extern tree search_tree PROTO((tree *, tree (*)(tree *))); 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 b3e676b..f456dbb 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -149,7 +149,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 *)); static tree find_binding PROTO((tree, tree)); static tree select_decl PROTO((tree, int)); static int lookup_flags PROTO((int, int)); @@ -11188,13 +11188,15 @@ require_complete_types_for_parms (parms) } } -/* Returns DECL if DECL is a local variable (or parameter). Returns +/* Returns *TP if *TP is a local variable (or parameter). Returns NULL_TREE otherwise. */ static tree -local_variable_p (t) - tree t; +local_variable_p (tp) + tree *tp; { + tree t = *tp; + if ((TREE_CODE (t) == VAR_DECL /* A VAR_DECL with a context that is a _TYPE is a static data member. */ @@ -11273,7 +11275,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 = search_tree (&arg, local_variable_p); if (var) { cp_error ("default argument `%E' uses local variable `%D'", diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 5bf5f0f..883a2e5 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -1476,6 +1476,7 @@ dump_expr (t, nop) dump_expr (TREE_OPERAND (t, 1), 0); break; + case INIT_EXPR: case MODIFY_EXPR: case PLUS_EXPR: case MINUS_EXPR: diff --git a/gcc/cp/except.c b/gcc/cp/except.c index 9bfc7a2..a078e65 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -830,7 +830,6 @@ expand_throw (exp) tree exp; { tree fn; - static tree cleanup_type; if (! doing_eh (1)) return; diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c index 0eb5de4..741174e 100644 --- a/gcc/cp/expr.c +++ b/gcc/cp/expr.c @@ -239,9 +239,6 @@ cplus_expand_expr (exp, target, tmode, modifier) integer_one_node), TREE_OPERAND (exp, 1), 0), target, tmode, modifier); - case NEW_EXPR: - return expand_expr (build_new_1 (exp), target, tmode, modifier); - case STMT_EXPR: { tree rtl_expr = begin_stmt_expr (); diff --git a/gcc/cp/init.c b/gcc/cp/init.c index c98324e..19d8c74 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -2065,6 +2065,9 @@ build_new (placement, decl, init, use_global_new) rval = build (NEW_EXPR, build_pointer_type (type), placement, t, init); NEW_EXPR_USE_GLOBAL (rval) = use_global_new; TREE_SIDE_EFFECTS (rval) = 1; + rval = build_new_1 (rval); + if (rval == error_mark_node) + return error_mark_node; /* Wrap it in a NOP_EXPR so warn_if_unused_value doesn't complain. */ rval = build1 (NOP_EXPR, TREE_TYPE (rval), rval); @@ -2188,11 +2191,7 @@ build_new_1 (exp) && TREE_TYPE (TREE_VALUE (placement)) == ptr_type_node)); if (use_cookie) - { - tree extra = BI_header_size; - - size = size_binop (PLUS_EXPR, size, extra); - } + size = size_binop (PLUS_EXPR, size, BI_header_size); if (has_array) { @@ -2378,6 +2377,13 @@ build_new_1 (exp) rval = newrval; TREE_HAS_CONSTRUCTOR (rval) = 1; } + else if (current_function_decl) + rval = (build_vec_init + (NULL_TREE, + save_expr (rval), + build_binary_op (MINUS_EXPR, nelts, integer_one_node), + init, + /*from_array=*/0)); else rval = build (VEC_INIT_EXPR, TREE_TYPE (rval), save_expr (rval), init, nelts); diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index c396a50..b61cad4 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -795,6 +795,7 @@ init_parse (filename) opname_tab[(int) INDIRECT_REF] = "*"; opname_tab[(int) ARRAY_REF] = "[]"; opname_tab[(int) MODIFY_EXPR] = "="; + opname_tab[(int) INIT_EXPR] = "="; opname_tab[(int) NEW_EXPR] = "new"; opname_tab[(int) DELETE_EXPR] = "delete"; opname_tab[(int) VEC_NEW_EXPR] = "new []"; diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 0805092..1253c94 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -28,8 +28,10 @@ Boston, MA 02111-1307, USA. */ #include "rtl.h" #include "toplev.h" #include "ggc.h" +#include "splay-tree.h" static tree bot_manip PROTO((tree)); +static tree bot_replace PROTO((tree *)); 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)); @@ -37,7 +39,7 @@ 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 *)); static tree build_srcloc PROTO((char *, int)); static void mark_list_hash PROTO ((void *)); @@ -1529,19 +1531,20 @@ copy_template_template_parm (t) non-null, return that value. */ tree -search_tree (t, func) - tree t; - tree (*func) PROTO((tree)); +search_tree (tp, func) + tree *tp; + tree (*func) PROTO((tree *)); { -#define TRY(ARG) if (tmp=search_tree (ARG, func), tmp != NULL_TREE) return tmp +#define TRY(ARG) if (tmp=search_tree (&ARG, func), tmp != NULL_TREE) return tmp + tree t = *tp; tree tmp; enum tree_code code; - + if (t == NULL_TREE) - return t; + return NULL_TREE; - tmp = func (t); + tmp = func (tp); if (tmp) return tmp; @@ -1618,6 +1621,7 @@ search_tree (t, func) case TARGET_EXPR: case AGGR_INIT_EXPR: case NEW_EXPR: + case VEC_INIT_EXPR: TRY (TREE_OPERAND (t, 0)); TRY (TREE_OPERAND (t, 1)); TRY (TREE_OPERAND (t, 2)); @@ -1737,9 +1741,11 @@ search_tree (t, func) /* Passed to search_tree. Checks for the use of types with no linkage. */ static tree -no_linkage_helper (t) - tree t; +no_linkage_helper (tp) + tree *tp; { + tree t = *tp; + if (TYPE_P (t) && (IS_AGGR_TYPE (t) || TREE_CODE (t) == ENUMERAL_TYPE) && (decl_function_context (TYPE_MAIN_DECL (t)) @@ -1760,7 +1766,7 @@ no_linkage_check (t) if (processing_template_decl) return NULL_TREE; - t = search_tree (t, no_linkage_helper); + t = search_tree (&t, no_linkage_helper); if (t != error_mark_node) return t; return NULL_TREE; @@ -1986,6 +1992,7 @@ mapcar (t, func) return t; case NEW_EXPR: + case VEC_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); @@ -2093,8 +2100,19 @@ array_type_nelts_total (type) return sz; } -static -tree +/* 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; { @@ -2102,16 +2120,26 @@ bot_manip (t) return t; else if (TREE_CODE (t) == TARGET_EXPR) { + tree u; + if (TREE_CODE (TREE_OPERAND (t, 1)) == AGGR_INIT_EXPR) { mark_used (TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (t, 1), 0), 0)); - return build_cplus_new + u = build_cplus_new (TREE_TYPE (t), break_out_target_exprs (TREE_OPERAND (t, 1))); } - t = copy_node (t); - TREE_OPERAND (t, 0) = build (VAR_DECL, TREE_TYPE (t)); - layout_decl (TREE_OPERAND (t, 0), 0); - return t; + else + { + u = copy_node (t); + TREE_OPERAND (u, 0) = build (VAR_DECL, TREE_TYPE (t)); + layout_decl (TREE_OPERAND (u, 0), 0); + } + + /* Map the old variable to the new one. */ + splay_tree_insert (target_remap, + (splay_tree_key) TREE_OPERAND (t, 0), + (splay_tree_value) TREE_OPERAND (u, 0)); + return u; } else if (TREE_CODE (t) == CALL_EXPR) mark_used (TREE_OPERAND (TREE_OPERAND (t, 0), 0)); @@ -2119,13 +2147,43 @@ bot_manip (t) return NULL_TREE; } +/* Replace all remapped VAR_DECLs in T with their new equivalents. */ + +static tree +bot_replace (t) + tree *t; +{ + if (TREE_CODE (*t) == VAR_DECL) + { + splay_tree_node n = splay_tree_lookup (target_remap, + (splay_tree_key) *t); + if (n) + *t = (tree) n->value; + } + + return NULL_TREE; +} + /* Actually, we'll just clean out the target exprs for the moment. */ tree break_out_target_exprs (t) tree t; { - return mapcar (t, bot_manip); + 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); + + if (!--target_remap_count) + { + splay_tree_delete (target_remap); + target_remap = NULL; + } + + return t; } /* Obstack used for allocating nodes in template function and variable diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 3803a42..80be5f8 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -5877,7 +5877,8 @@ build_modify_expr (lhs, modifycode, rhs) { newrhs = convert_for_initialization (lhs, lhstype, newrhs, LOOKUP_NORMAL, "assignment", NULL_TREE, 0); - if (lhs == DECL_RESULT (current_function_decl)) + if (current_function_decl && + lhs == DECL_RESULT (current_function_decl)) { if (DECL_INITIAL (lhs)) warning ("return value from function receives multiple initializations");