This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH to static reference temporaries
- To: Gcc Patch List <gcc-patches at gcc dot gnu dot org>
- Subject: C++ PATCH to static reference temporaries
- From: Jason Merrill <jason_merrill at redhat dot com>
- Date: 25 Jul 2001 13:50:14 +0100
Fixes g++.dg/other/init-ref2.C; reference temps for static references are
now also static, and the refs themselves are statically initialized.
To keep the grok_refrence_init change from breaking non-static refs, I had
to change cp_finish_decl so that the DECL_STMT for the new decl is added
after the initializer has been analyzed, so that the DECL_STMT for the ref
temp would be expanded first. I think this makes sense; anyone disagree?
2001-07-24 Jason Merrill <jason_merrill@redhat.com>
* cvt.c (build_up_reference): Take DECL parm. Check TREE_STATIC on
it rather than toplevel_bindings_p. Give it a mangled name if static.
(convert_to_reference): Adjust.
* decl2.c (get_temp_name): Lose.
* mangle.c (mangle_ref_init_variable): New fn.
(mangle_guard_variable): Strip the ref-init header.
* cp-tree.h: Adjust.
* decl.c (cp_finish_decl): Add the DECL_STMT after processing the
initializer.
(grok_reference_init): Always use DECL_INITIAL.
*** cp-tree.h.~1~ Wed Jul 25 02:18:30 2001
--- cp-tree.h Tue Jul 24 15:08:04 2001
*************** extern void cplus_decl_attributes PARAM
*** 3783,3789 ****
extern tree constructor_name_full PARAMS ((tree));
extern tree constructor_name PARAMS ((tree));
extern void defer_fn PARAMS ((tree));
- extern tree get_temp_name PARAMS ((tree));
extern void finish_anon_union PARAMS ((tree));
extern tree finish_table PARAMS ((tree, tree, tree, int));
extern void finish_builtin_type PARAMS ((tree, const char *,
--- 3783,3788 ----
*************** extern tree mangle_ctor_vtbl_for_type
*** 4384,4389 ****
--- 4383,4389 ----
extern tree mangle_thunk PARAMS ((tree, tree, tree));
extern tree mangle_conv_op_name_for_type PARAMS ((tree));
extern tree mangle_guard_variable PARAMS ((tree));
+ extern tree mangle_ref_init_variable PARAMS ((tree));
/* in dump.c */
extern int cp_dump_tree PARAMS ((dump_info_p, tree));
*** cvt.c.~1~ Wed Jul 25 02:18:30 2001
--- cvt.c Tue Jul 24 15:08:04 2001
*************** Boston, MA 02111-1307, USA. */
*** 37,43 ****
static tree cp_convert_to_pointer PARAMS ((tree, tree, int));
static tree convert_to_pointer_force PARAMS ((tree, tree));
! static tree build_up_reference PARAMS ((tree, tree, int));
static void warn_ref_binding PARAMS ((tree, tree, tree));
/* Change of width--truncation and extension of integers or reals--
--- 37,43 ----
static tree cp_convert_to_pointer PARAMS ((tree, tree, int));
static tree convert_to_pointer_force PARAMS ((tree, tree));
! static tree build_up_reference PARAMS ((tree, tree, int, tree));
static void warn_ref_binding PARAMS ((tree, tree, tree));
/* Change of width--truncation and extension of integers or reals--
*************** convert_to_pointer_force (type, expr)
*** 358,368 ****
value we have to begin with is in ARG.
FLAGS controls how we manage access checking.
! DIRECT_BIND in FLAGS controls how any temporaries are generated. */
static tree
! build_up_reference (type, arg, flags)
! tree type, arg;
int flags;
{
tree rval;
--- 358,369 ----
value we have to begin with is in ARG.
FLAGS controls how we manage access checking.
! DIRECT_BIND in FLAGS controls how any temporaries are generated.
! If DIRECT_BIND is set, DECL is the reference we're binding to. */
static tree
! build_up_reference (type, arg, flags, decl)
! tree type, arg, decl;
int flags;
{
tree rval;
*************** build_up_reference (type, arg, flags)
*** 374,388 ****
if ((flags & DIRECT_BIND) && ! real_lvalue_p (arg))
{
! /* Create a new temporary variable. */
tree targ = arg;
! if (toplevel_bindings_p ())
! arg = get_temp_name (argtype);
else
{
maybe_push_cleanup_level (argtype);
! arg = pushdecl (build_decl (VAR_DECL, NULL_TREE, argtype));
! DECL_ARTIFICIAL (arg) = 1;
}
/* Process the initializer for the declaration. */
--- 375,402 ----
if ((flags & DIRECT_BIND) && ! real_lvalue_p (arg))
{
! /* Create a new temporary variable. We can't just use a TARGET_EXPR
! here because it needs to live as long as DECL. */
tree targ = arg;
!
! arg = build_decl (VAR_DECL, NULL_TREE, argtype);
! DECL_ARTIFICIAL (arg) = 1;
! TREE_USED (arg) = 1;
! TREE_STATIC (arg) = TREE_STATIC (decl);
!
! if (TREE_STATIC (decl))
! {
! /* Namespace-scope or local static; give it a mangled name. */
! tree name = mangle_ref_init_variable (decl);
! DECL_NAME (arg) = name;
! SET_DECL_ASSEMBLER_NAME (arg, name);
! arg = pushdecl_top_level (arg);
! }
else
{
+ /* automatic; make sure we handle the cleanup properly. */
maybe_push_cleanup_level (argtype);
! arg = pushdecl (arg);
}
/* Process the initializer for the declaration. */
*************** build_up_reference (type, arg, flags)
*** 393,399 ****
else if (!(flags & DIRECT_BIND) && ! lvalue_p (arg))
return get_target_expr (arg);
! /* If we had a way to wrap this up, and say, if we ever needed it's
address, transform all occurrences of the register, into a memory
reference we could win better. */
rval = build_unary_op (ADDR_EXPR, arg, 1);
--- 407,413 ----
else if (!(flags & DIRECT_BIND) && ! lvalue_p (arg))
return get_target_expr (arg);
! /* If we had a way to wrap this up, and say, if we ever needed its
address, transform all occurrences of the register, into a memory
reference we could win better. */
rval = build_unary_op (ADDR_EXPR, arg, 1);
*************** convert_to_reference (reftype, expr, con
*** 531,537 ****
ttr, reftype);
}
! return build_up_reference (reftype, expr, flags);
}
else if ((convtype & CONV_REINTERPRET) && lvalue_p (expr))
{
--- 545,551 ----
ttr, reftype);
}
! return build_up_reference (reftype, expr, flags, decl);
}
else if ((convtype & CONV_REINTERPRET) && lvalue_p (expr))
{
*************** convert_to_reference (reftype, expr, con
*** 562,568 ****
if (rval == NULL_TREE || rval == error_mark_node)
return rval;
warn_ref_binding (reftype, intype, decl);
! rval = build_up_reference (reftype, rval, flags);
}
if (rval)
--- 576,582 ----
if (rval == NULL_TREE || rval == error_mark_node)
return rval;
warn_ref_binding (reftype, intype, decl);
! rval = build_up_reference (reftype, rval, flags, decl);
}
if (rval)
*** decl2.c.~1~ Wed Jul 25 02:18:30 2001
--- decl2.c Tue Jul 24 15:08:12 2001
*************** defer_fn (fn)
*** 1946,1986 ****
VARRAY_PUSH_TREE (deferred_fns, fn);
}
- /* Hand off a unique name which can be used for variable we don't really
- want to know about anyway, for example, the anonymous variables which
- are needed to make references work. Declare this thing so we can use it.
- The variable created will be of type TYPE, and will have internal
- linkage. */
-
- tree
- get_temp_name (type)
- tree type;
- {
- char buf[sizeof (AUTO_TEMP_FORMAT) + 20];
- tree decl;
- int toplev = toplevel_bindings_p ();
-
- sprintf (buf, AUTO_TEMP_FORMAT, global_temp_name_counter++);
- decl = build_decl (VAR_DECL, get_identifier (buf), type);
- DECL_ARTIFICIAL (decl) = 1;
- TREE_USED (decl) = 1;
- TREE_STATIC (decl) = 1;
-
- decl = pushdecl_top_level (decl);
-
- /* If this is a local variable, then lay out its rtl now.
- Otherwise, callers of this function are responsible for dealing
- with this variable's rtl. */
- if (! toplev)
- {
- expand_decl (decl);
- my_friendly_assert (DECL_INITIAL (decl) == NULL_TREE,
- 19990826);
- }
-
- return decl;
- }
-
/* Hunts through the global anonymous union ANON_DECL, building
appropriate VAR_DECLs. Stores cleanups on the list of ELEMS, and
returns a VAR_DECL whose size is the same as the size of the
--- 1946,1951 ----
*** decl.c.~1~ Wed Jul 25 02:18:30 2001
--- decl.c Tue Jul 24 15:08:10 2001
*************** grok_reference_init (decl, type, init)
*** 7386,7399 ****
if (TREE_STATIC (decl) && !TREE_CONSTANT (tmp))
return tmp;
! if (building_stmt_tree ())
! {
! /* Initialize the declaration. */
! tmp = build (INIT_EXPR, TREE_TYPE (decl), decl, tmp);
! finish_expr_stmt (tmp);
! }
! else
! DECL_INITIAL (decl) = tmp;
return NULL_TREE;
}
--- 7386,7392 ----
if (TREE_STATIC (decl) && !TREE_CONSTANT (tmp))
return tmp;
! DECL_INITIAL (decl) = tmp;
return NULL_TREE;
}
*************** cp_finish_decl (decl, init, asmspec_tree
*** 8010,8026 ****
if (type == error_mark_node)
return;
- /* Add this declaration to the statement-tree. */
- if (building_stmt_tree ()
- && at_function_scope_p ()
- && TREE_CODE (decl) != RESULT_DECL)
- add_decl_stmt (decl);
-
if (TYPE_HAS_MUTABLE_P (type))
TREE_READONLY (decl) = 0;
if (processing_template_decl)
{
if (init && DECL_INITIAL (decl))
DECL_INITIAL (decl) = init;
goto finish_end0;
--- 8003,8018 ----
if (type == error_mark_node)
return;
if (TYPE_HAS_MUTABLE_P (type))
TREE_READONLY (decl) = 0;
if (processing_template_decl)
{
+ /* Add this declaration to the statement-tree. */
+ if (at_function_scope_p ()
+ && TREE_CODE (decl) != RESULT_DECL)
+ add_decl_stmt (decl);
+
if (init && DECL_INITIAL (decl))
DECL_INITIAL (decl) = init;
goto finish_end0;
*************** cp_finish_decl (decl, init, asmspec_tree
*** 8088,8093 ****
--- 8080,8091 ----
init = check_initializer (decl, init);
GNU_xref_decl (current_function_decl, decl);
+
+ /* Add this declaration to the statement-tree. */
+ if (building_stmt_tree ()
+ && at_function_scope_p ()
+ && TREE_CODE (decl) != RESULT_DECL)
+ add_decl_stmt (decl);
if (TREE_CODE (decl) == VAR_DECL)
layout_var_decl (decl);
*** mangle.c.~1~ Wed Jul 25 02:18:30 2001
--- mangle.c Tue Jul 24 15:08:13 2001
*************** mangle_guard_variable (variable)
*** 2420,2429 ****
{
start_mangling ();
write_string ("_ZGV");
! write_name (variable, /*ignore_local_scope=*/0);
return get_identifier (finish_mangling ());
}
/* Foreign language type mangling section. */
--- 2420,2447 ----
{
start_mangling ();
write_string ("_ZGV");
! if (strncmp (IDENTIFIER_POINTER (DECL_NAME (variable)), "_ZGR", 4) == 0)
! /* The name of a guard variable for a reference temporary should refer
! to the reference, not the temporary. */
! write_string (IDENTIFIER_POINTER (DECL_NAME (variable)) + 4);
! else
! write_name (variable, /*ignore_local_scope=*/0);
return get_identifier (finish_mangling ());
}
+ /* Return an identifier for the name of a temporary variable used to
+ initialize a static reference. This isn't part of the ABI, but we might
+ as well call them something readable. */
+
+ tree
+ mangle_ref_init_variable (variable)
+ tree variable;
+ {
+ start_mangling ();
+ write_string ("_ZGR");
+ write_name (variable, /*ignore_local_scope=*/0);
+ return get_identifier (finish_mangling ());
+ }
/* Foreign language type mangling section. */