This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

C++ PATCH to static reference temporaries


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.  */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]