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]
Other format: [Raw text]

PATCH for c++/13764


13764 is a bug report about there being an extra binding level/block for all functions in C++, when it's only really needed for [cd]tors. Fixed thus. The c-common change fixes a latent bug exposed by the other changes.

Tested x86_64-pc-linux-gnu, applied to trunk.
2005-09-26  Jason Merrill  <jason@redhat.com>

	PR c++/13764
	* c-common.c (finish_fname_decls): Use append_to_statement_list_force.
	* cp/cp-tree.h (FUNCTION_NEEDS_BODY_BLOCK): New macro.
	* cp/name-lookup.c (pushdecl_maybe_friend): Check it.
	* cp/decl.c (begin_function_body): Do nothing if it's false.
	(finish_function_body): Ditto.
	(outer_curly_brace_block): New fn.
	(finish_function): Use it.

*** ./testsuite/g++.dg/tree-ssa/block1.C.~1~	2005-09-26 22:56:37.000000000 -0400
--- ./testsuite/g++.dg/tree-ssa/block1.C	2005-09-26 22:55:43.000000000 -0400
***************
*** 0 ****
--- 1,11 ----
+ // PR 13764: We were inserting an extra body block in all functions, but
+ // it's only really necessary for [cd]tors.
+ // { dg-options "-fdump-tree-gimple" }
+ 
+ void bar (void)
+ {
+   int a;
+ }
+ 
+ // { dg-final { scan-tree-dump-times "\{" 1 "gimple" } }
+ // { dg-final { cleanup-tree-dump "gimple" } }
*** ./c-common.c.~1~	2005-09-26 01:45:55.000000000 -0400
--- ./c-common.c	2005-09-26 17:41:14.000000000 -0400
*************** finish_fname_decls (void)
*** 695,701 ****
        if (TREE_CODE (*bodyp) == BIND_EXPR)
  	bodyp = &BIND_EXPR_BODY (*bodyp);
  
!       append_to_statement_list (*bodyp, &stmts);
        *bodyp = stmts;
      }
  
--- 695,701 ----
        if (TREE_CODE (*bodyp) == BIND_EXPR)
  	bodyp = &BIND_EXPR_BODY (*bodyp);
  
!       append_to_statement_list_force (*bodyp, &stmts);
        *bodyp = stmts;
      }
  
*** ./cp/cp-tree.h.~1~	2005-09-14 13:14:19.000000000 -0400
--- ./cp/cp-tree.h	2005-09-26 15:56:31.000000000 -0400
*************** typedef struct ptrmem_cst * ptrmem_cst_t
*** 255,260 ****
--- 255,262 ----
  /* Used to mark the block around the member initializers and cleanups.  */
  #define BIND_EXPR_BODY_BLOCK(NODE) \
    TREE_LANG_FLAG_3 (BIND_EXPR_CHECK (NODE))
+ #define FUNCTION_NEEDS_BODY_BLOCK(NODE) \
+   (DECL_CONSTRUCTOR_P (NODE) || DECL_DESTRUCTOR_P (NODE))
  
  #define STATEMENT_LIST_NO_SCOPE(NODE) \
    TREE_LANG_FLAG_0 (STATEMENT_LIST_CHECK (NODE))
*** ./cp/name-lookup.c.~1~	2005-09-14 13:14:20.000000000 -0400
--- ./cp/name-lookup.c	2005-09-26 16:30:39.000000000 -0400
*************** pushdecl_maybe_friend (tree x, bool is_f
*** 935,942 ****
  		     them there.  */
  		  struct cp_binding_level *b = current_binding_level->level_chain;
  
! 		  /* Skip the ctor/dtor cleanup level.  */
! 		  b = b->level_chain;
  
  		  /* ARM $8.3 */
  		  if (b->kind == sk_function_parms)
--- 935,943 ----
  		     them there.  */
  		  struct cp_binding_level *b = current_binding_level->level_chain;
  
! 		  if (FUNCTION_NEEDS_BODY_BLOCK (current_function_decl))
! 		    /* Skip the ctor/dtor cleanup level.  */
! 		    b = b->level_chain;
  
  		  /* ARM $8.3 */
  		  if (b->kind == sk_function_parms)
*** ./cp/decl.c.~1~	2005-09-15 21:54:18.000000000 -0400
--- ./cp/decl.c	2005-09-26 15:57:14.000000000 -0400
*************** finish_destructor_body (void)
*** 10656,10669 ****
  /* Do the necessary processing for the beginning of a function body, which
     in this case includes member-initializers, but not the catch clauses of
     a function-try-block.  Currently, this means opening a binding level
!    for the member-initializers (in a ctor) and member cleanups (in a dtor).
!    In other functions, this isn't necessary, but it doesn't hurt.  */
  
  tree
  begin_function_body (void)
  {
    tree stmt;
  
    if (processing_template_decl)
      /* Do nothing now.  */;
    else
--- 10656,10671 ----
  /* Do the necessary processing for the beginning of a function body, which
     in this case includes member-initializers, but not the catch clauses of
     a function-try-block.  Currently, this means opening a binding level
!    for the member-initializers (in a ctor) and member cleanups (in a dtor).  */
  
  tree
  begin_function_body (void)
  {
    tree stmt;
  
+   if (! FUNCTION_NEEDS_BODY_BLOCK (current_function_decl))
+     return NULL_TREE;
+ 
    if (processing_template_decl)
      /* Do nothing now.  */;
    else
*************** begin_function_body (void)
*** 10694,10699 ****
--- 10696,10704 ----
  void
  finish_function_body (tree compstmt)
  {
+   if (compstmt == NULL_TREE)
+     return;
+   
    /* Close the block.  */
    finish_compound_stmt (compstmt);
  
*************** finish_function_body (tree compstmt)
*** 10705,10710 ****
--- 10710,10729 ----
      finish_destructor_body ();
  }
  
+ /* Given a function, returns the BLOCK corresponding to the outermost level
+    of curly braces, skipping the artificial block created for constructor
+    initializers.  */
+ 
+ static tree
+ outer_curly_brace_block (tree fndecl)
+ {
+   tree block = BLOCK_SUBBLOCKS (DECL_INITIAL (fndecl));
+   if (FUNCTION_NEEDS_BODY_BLOCK (current_function_decl))
+     /* Skip the artificial function body block.  */
+     block = BLOCK_SUBBLOCKS (block);
+   return block;
+ }
+ 
  /* Finish up a function declaration and compile that function
     all the way to assembler language output.  The free the storage
     for the function definition.
*************** finish_function (int flags)
*** 10836,10844 ****
  	     the function so we know that their lifetime always ends with a
  	     return; see g++.dg/opt/nrv6.C.  We could be more flexible if
  	     we were to do this optimization in tree-ssa.  */
! 	  && (outer = BLOCK_SUBBLOCKS (DECL_INITIAL (fndecl)))
! 	  /* Skip the artificial function body block.  */
! 	  && (outer = BLOCK_SUBBLOCKS (outer))
  	  && chain_member (r, BLOCK_VARS (outer)))
  	finalize_nrv (&DECL_SAVED_TREE (fndecl), r, DECL_RESULT (fndecl));
  
--- 10855,10861 ----
  	     the function so we know that their lifetime always ends with a
  	     return; see g++.dg/opt/nrv6.C.  We could be more flexible if
  	     we were to do this optimization in tree-ssa.  */
! 	  && (outer = outer_curly_brace_block (fndecl))
  	  && chain_member (r, BLOCK_VARS (outer)))
  	finalize_nrv (&DECL_SAVED_TREE (fndecl), r, DECL_RESULT (fndecl));
  

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