This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH for `new'
- To: gcc-patches at gcc dot gnu dot org
- Subject: C++ PATCH for `new'
- From: Mark Mitchell <mark at codesourcery dot com>
- Date: Fri, 24 Sep 1999 13:57:41 -0700
- Organization: CodeSourcery, LLC
This patch moves the semantic analysis of new-expressions to
semantic-analysis time, instead of RTL-generation time. In addition,
I spotted an unmarked GC root, and marked it.
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
1999-09-24 Mark Mitchell <mark@codesourcery.com>
* 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.
Index: Makefile.in
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/Makefile.in,v
retrieving revision 1.70
diff -c -p -r1.70 Makefile.in
*** Makefile.in 1999/09/20 20:19:04 1.70
--- Makefile.in 1999/09/24 20:48:15
*************** cvt.o : cvt.c $(CONFIG_H) $(CXX_TREE_H)
*** 274,280 ****
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)
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
--- 274,281 ----
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)/../../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
Index: cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.316
diff -c -p -r1.316 cp-tree.h
*** cp-tree.h 1999/09/24 01:29:28 1.316
--- cp-tree.h 1999/09/24 20:48:18
*************** enum cp_tree_index
*** 408,413 ****
--- 408,414 ----
CPTI_WCHAR_DECL,
CPTI_VTABLE_ENTRY_TYPE,
CPTI_DELTA_TYPE,
+ CPTI_CLEANUP_TYPE,
CPTI_TP_DESC_TYPE,
CPTI_ACCESS_MODE_TYPE,
*************** extern tree cp_global_trees[CPTI_MAX];
*** 560,565 ****
--- 561,569 ----
/* 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 {
*************** extern void push_permanent_obstack
*** 3855,3861 ****
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 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));
--- 3859,3865 ----
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 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));
Index: decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.467
diff -c -p -r1.467 decl.c
*** decl.c 1999/09/24 08:03:42 1.467
--- decl.c 1999/09/24 20:48:27
*************** static boolean typename_compare PROTO((h
*** 149,155 ****
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 find_binding PROTO((tree, tree));
static tree select_decl PROTO((tree, int));
static int lookup_flags PROTO((int, int));
--- 149,155 ----
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 find_binding PROTO((tree, tree));
static tree select_decl PROTO((tree, int));
static int lookup_flags PROTO((int, int));
*************** require_complete_types_for_parms (parms)
*** 11190,11202 ****
}
}
! /* Returns DECL if DECL is a local variable (or parameter). Returns
NULL_TREE otherwise. */
static tree
! local_variable_p (t)
! tree t;
{
if ((TREE_CODE (t) == VAR_DECL
/* A VAR_DECL with a context that is a _TYPE is a static data
member. */
--- 11190,11204 ----
}
}
! /* Returns *TP if *TP is a local variable (or parameter). Returns
NULL_TREE otherwise. */
static tree
! 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. */
*************** check_default_argument (decl, arg)
*** 11275,11281 ****
The keyword `this' shall not be used in a default argument of a
member function. */
! var = search_tree (arg, local_variable_p);
if (var)
{
cp_error ("default argument `%E' uses local variable `%D'",
--- 11277,11283 ----
The keyword `this' shall not be used in a default argument of a
member function. */
! var = search_tree (&arg, local_variable_p);
if (var)
{
cp_error ("default argument `%E' uses local variable `%D'",
Index: error.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/error.c,v
retrieving revision 1.89
diff -c -p -r1.89 error.c
*** error.c 1999/09/17 01:49:29 1.89
--- error.c 1999/09/24 20:48:28
*************** dump_expr (t, nop)
*** 1476,1481 ****
--- 1476,1482 ----
dump_expr (TREE_OPERAND (t, 1), 0);
break;
+ case INIT_EXPR:
case MODIFY_EXPR:
case PLUS_EXPR:
case MINUS_EXPR:
Index: except.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/except.c,v
retrieving revision 1.82
diff -c -p -r1.82 except.c
*** except.c 1999/09/18 01:22:54 1.82
--- except.c 1999/09/24 20:48:28
*************** expand_throw (exp)
*** 830,836 ****
tree exp;
{
tree fn;
- static tree cleanup_type;
if (! doing_eh (1))
return;
--- 830,835 ----
Index: expr.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/expr.c,v
retrieving revision 1.31
diff -c -p -r1.31 expr.c
*** expr.c 1999/09/20 21:26:05 1.31
--- expr.c 1999/09/24 20:48:29
*************** cplus_expand_expr (exp, target, tmode, m
*** 239,247 ****
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 ();
--- 239,244 ----
Index: init.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/init.c,v
retrieving revision 1.138
diff -c -p -r1.138 init.c
*** init.c 1999/09/20 21:26:05 1.138
--- init.c 1999/09/24 20:48:31
*************** build_new (placement, decl, init, use_gl
*** 2065,2070 ****
--- 2065,2073 ----
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);
*************** build_new_1 (exp)
*** 2188,2198 ****
&& TREE_TYPE (TREE_VALUE (placement)) == ptr_type_node));
if (use_cookie)
! {
! tree extra = BI_header_size;
!
! size = size_binop (PLUS_EXPR, size, extra);
! }
if (has_array)
{
--- 2191,2197 ----
&& TREE_TYPE (TREE_VALUE (placement)) == ptr_type_node));
if (use_cookie)
! size = size_binop (PLUS_EXPR, size, BI_header_size);
if (has_array)
{
*************** build_new_1 (exp)
*** 2378,2383 ****
--- 2377,2389 ----
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);
Index: lex.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/lex.c,v
retrieving revision 1.155
diff -c -p -r1.155 lex.c
*** lex.c 1999/09/23 21:04:10 1.155
--- lex.c 1999/09/24 20:48:33
*************** init_parse (filename)
*** 795,800 ****
--- 795,801 ----
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 []";
Index: tree.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/tree.c,v
retrieving revision 1.151
diff -c -p -r1.151 tree.c
*** tree.c 1999/09/15 22:49:33 1.151
--- tree.c 1999/09/24 20:48:34
*************** Boston, MA 02111-1307, USA. */
*** 28,35 ****
--- 28,37 ----
#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));
*************** static tree list_hash_lookup PROTO((int,
*** 37,43 ****
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 build_srcloc PROTO((char *, int));
static void mark_list_hash PROTO ((void *));
--- 39,45 ----
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 build_srcloc PROTO((char *, int));
static void mark_list_hash PROTO ((void *));
*************** copy_template_template_parm (t)
*** 1529,1547 ****
non-null, return that value. */
tree
! search_tree (t, func)
! tree t;
! tree (*func) PROTO((tree));
{
! #define TRY(ARG) if (tmp=search_tree (ARG, func), tmp != NULL_TREE) return tmp
tree tmp;
enum tree_code code;
!
if (t == NULL_TREE)
! return t;
! tmp = func (t);
if (tmp)
return tmp;
--- 1531,1550 ----
non-null, return that value. */
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
+ tree t = *tp;
tree tmp;
enum tree_code code;
!
if (t == NULL_TREE)
! return NULL_TREE;
! tmp = func (tp);
if (tmp)
return tmp;
*************** search_tree (t, func)
*** 1618,1623 ****
--- 1621,1627 ----
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));
*************** search_tree (t, func)
*** 1737,1745 ****
/* Passed to search_tree. Checks for the use of types with no linkage. */
static tree
! no_linkage_helper (t)
! tree t;
{
if (TYPE_P (t)
&& (IS_AGGR_TYPE (t) || TREE_CODE (t) == ENUMERAL_TYPE)
&& (decl_function_context (TYPE_MAIN_DECL (t))
--- 1741,1751 ----
/* Passed to search_tree. Checks for the use of types with no linkage. */
static tree
! 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))
*************** no_linkage_check (t)
*** 1760,1766 ****
if (processing_template_decl)
return NULL_TREE;
! t = search_tree (t, no_linkage_helper);
if (t != error_mark_node)
return t;
return NULL_TREE;
--- 1766,1772 ----
if (processing_template_decl)
return NULL_TREE;
! t = search_tree (&t, no_linkage_helper);
if (t != error_mark_node)
return t;
return NULL_TREE;
*************** mapcar (t, func)
*** 1986,1991 ****
--- 1992,1998 ----
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);
*************** array_type_nelts_total (type)
*** 2093,2100 ****
return sz;
}
! static
! tree
bot_manip (t)
tree t;
{
--- 2100,2118 ----
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 (t)
*** 2102,2117 ****
return t;
else if (TREE_CODE (t) == TARGET_EXPR)
{
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
(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 if (TREE_CODE (t) == CALL_EXPR)
mark_used (TREE_OPERAND (TREE_OPERAND (t, 0), 0));
--- 2120,2145 ----
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));
! u = build_cplus_new
(TREE_TYPE (t), break_out_target_exprs (TREE_OPERAND (t, 1)));
}
! 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));
*************** bot_manip (t)
*** 2119,2131 ****
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);
}
/* Obstack used for allocating nodes in template function and variable
--- 2147,2189 ----
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;
{
! 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
Index: typeck.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/typeck.c,v
retrieving revision 1.216
diff -c -p -r1.216 typeck.c
*** typeck.c 1999/09/24 01:17:25 1.216
--- typeck.c 1999/09/24 20:48:39
*************** build_modify_expr (lhs, modifycode, rhs)
*** 5877,5883 ****
{
newrhs = convert_for_initialization (lhs, lhstype, newrhs, LOOKUP_NORMAL,
"assignment", NULL_TREE, 0);
! if (lhs == DECL_RESULT (current_function_decl))
{
if (DECL_INITIAL (lhs))
warning ("return value from function receives multiple initializations");
--- 5877,5884 ----
{
newrhs = convert_for_initialization (lhs, lhstype, newrhs, LOOKUP_NORMAL,
"assignment", NULL_TREE, 0);
! if (current_function_decl &&
! lhs == DECL_RESULT (current_function_decl))
{
if (DECL_INITIAL (lhs))
warning ("return value from function receives multiple initializations");