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 fix using declarations, static initialization



This patch fixes a crash on member using declarations, and handles the
case of a function-scoped static object's constructor throwing an
exception correctly.

-- 
Mark Mitchell 			mark@markmitchell.com
Mark Mitchell Consulting	http://www.markmitchell.com

1998-12-03  Mark Mitchell  <mark@markmitchell.com>

	* class.c (handle_using_decl): Fix comment.  Don't lookup
	constructors in base classes.
	(validate_lhs): Fix typo in comment.
	* search.c (lookup_field_1): Don't return a USING_DECL.
	
	* cp-tree.h (DECL_ACCESS): Improve documentation.

	* decl.c (expand_static_init): Don't set the initialization-done
	flag until the initialization is done.
	
Index: testsuite/g++.old-deja/g++.other/init7.C
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/testsuite/g++.old-deja/g++.other/init7.C,v
retrieving revision 1.1
diff -c -p -r1.1 init7.C
*** init7.C	1998/10/07 20:41:38	1.1
--- init7.C	1998/12/04 00:44:32
***************
*** 4,11 ****
  // The initialization of a static local variable must be retried if a
  // previous try finished by throwing an exception [stmt.dcl]/4
  
- // execution test - XFAIL *-*-*
- 
  struct foo {
    foo() { throw true; }
  };
--- 4,9 ----
Index: testsuite/g++.old-deja/g++.other/singleton.C
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/testsuite/g++.old-deja/g++.other/singleton.C,v
retrieving revision 1.4
diff -c -p -r1.4 singleton.C
*** singleton.C	1998/09/14 11:09:07	1.4
--- singleton.C	1998/12/04 00:44:32
***************
*** 1,4 ****
- // execution test - re-initialization of statics XFAIL *-*-*
  // This tests two things:
  // 1. there is an annoying warning.
  // singleton.C:26: warning: `class singleton' only defines private constructors and has no friends
--- 1,3 ----
Index: testsuite/g++.old-deja/g++.other/using6.C
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/testsuite/g++.old-deja/g++.other/using6.C,v
retrieving revision 1.2
diff -c -p -r1.2 using6.C
*** using6.C	1998/10/10 11:50:21	1.2
--- using6.C	1998/12/04 00:44:32
***************
*** 3,15 ****
  // Based on bug report by Klaus-Georg Adams
  // <Klaus-Georg.Adams@chemie.uni-karlsruhe.de>
  
- // crash test - XFAIL *-*-*
- 
  struct bar {
    typedef bar t;
  };
  
  struct foo : bar {
    using bar::t;
!   t baz(); // gets bogus error - XFAIL *-*-*
  };
--- 3,13 ----
  // Based on bug report by Klaus-Georg Adams
  // <Klaus-Georg.Adams@chemie.uni-karlsruhe.de>
  
  struct bar {
    typedef bar t;
  };
  
  struct foo : bar {
    using bar::t;
!   t baz(); 
  };
Index: testsuite/g++.old-deja/g++.other/using7.C
===================================================================
RCS file: using7.C
diff -N using7.C
*** /tmp/cvs11620aaa	Thu Dec  3 16:47:53 1998
--- /dev/null	Mon Dec 31 20:00:00 1979
***************
*** 1,15 ****
- // Build don't link:
- 
- // Based on bug report by Klaus-Georg Adams
- // <Klaus-Georg.Adams@chemie.uni-karlsruhe.de>
- 
- // crash test - XFAIL *-*-*
- 
- struct bar {
-   typedef bar t;
- };
- 
- struct foo : bar {
-   using bar::t;
-   t baz; // gets bogus error - XFAIL *-*-*
- };
--- 0 ----
Index: testsuite/cp/class.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/class.c,v
retrieving revision 1.116
diff -c -p -r1.116 class.c
*** class.c	1998/11/24 21:28:41	1.116
--- class.c	1998/12/04 00:44:36
*************** alter_access (t, binfo, fdecl, access)
*** 1457,1464 ****
  }
  
  /* Process the USING_DECL, which is a member of T.  The METHOD_VEC, if
!    non-NULL, is the methods of T.  The FIELDS are the fields of T.
!    Returns 1 if the USING_DECL was valid, 0 otherwise.  */
  
  void
  handle_using_decl (using_decl, t, method_vec, fields)
--- 1457,1463 ----
  }
  
  /* Process the USING_DECL, which is a member of T.  The METHOD_VEC, if
!    non-NULL, is the methods of T.  The FIELDS are the fields of T.  */
  
  void
  handle_using_decl (using_decl, t, method_vec, fields)
*************** handle_using_decl (using_decl, t, method
*** 1485,1492 ****
    
    if (name == constructor_name (ctype)
        || name == constructor_name_full (ctype))
!     cp_error_at ("using-declaration for constructor", using_decl);
!   
    fdecl = lookup_member (binfo, name, 0, 0);
    
    if (!fdecl)
--- 1484,1494 ----
    
    if (name == constructor_name (ctype)
        || name == constructor_name_full (ctype))
!     {
!       cp_error_at ("using-declaration for constructor", using_decl);
!       return;
!     }
! 
    fdecl = lookup_member (binfo, name, 0, 0);
    
    if (!fdecl)
*************** validate_lhs (lhstype, complain)
*** 4994,5000 ****
  
  /* This function will instantiate the type of the expression given in
     RHS to match the type of LHSTYPE.  If errors exist, then return
!    error_mark_node.  If only complain is COMPLAIN is set.  If we are
     not complaining, never modify rhs, as overload resolution wants to
     try many possible instantiations, in hopes that at least one will
     work.
--- 4996,5002 ----
  
  /* This function will instantiate the type of the expression given in
     RHS to match the type of LHSTYPE.  If errors exist, then return
!    error_mark_node.  We only complain is COMPLAIN is set.  If we are
     not complaining, never modify rhs, as overload resolution wants to
     try many possible instantiations, in hopes that at least one will
     work.
Index: testsuite/cp/cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.176
diff -c -p -r1.176 cp-tree.h
*** cp-tree.h	1998/11/23 03:12:06	1.176
--- cp-tree.h	1998/12/04 00:44:39
*************** extern int flag_new_for_scope;
*** 1687,1694 ****
     NULL_TREE.  */
  #define DECL_FRIENDLIST(NODE)		(DECL_INITIAL (NODE))
  
! /* The DECL_ACCESS is used to record under which context
!    special access rules apply.  */
  #define DECL_ACCESS(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.access)
  
  /* C++: all of these are overloaded!
--- 1687,1698 ----
     NULL_TREE.  */
  #define DECL_FRIENDLIST(NODE)		(DECL_INITIAL (NODE))
  
! /* The DECL_ACCESS, if non-NULL, is a TREE_LIST.  The TREE_PURPOSE of
!    each node is a type; the TREE_VALUE is the access granted for this
!    DECL in that type.  The DECL_ACCESS is set by access declarations.
!    For example, if a member that would normally be public in a
!    derived class is made protected, then the derived class and the
!    protected_access_node will appear in the DECL_ACCESS for the node.  */
  #define DECL_ACCESS(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.access)
  
  /* C++: all of these are overloaded!
Index: testsuite/cp/decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.276
diff -c -p -r1.276 decl.c
*** decl.c	1998/11/29 18:27:10	1.276
--- decl.c	1998/12/04 00:44:48
*************** expand_static_init (decl, init)
*** 7869,7882 ****
        /* Remember this information until end of file.  */
        push_obstacks (&permanent_obstack, &permanent_obstack);
  
!       /* Emit code to perform this initialization but once.  */
        temp = get_temp_name (integer_type_node, 1);
        rest_of_decl_compilation (temp, NULL_PTR, 0, 0);
        expand_start_cond (build_binary_op (EQ_EXPR, temp,
  					  integer_zero_node, 1), 0);
        expand_start_target_temps ();
  
!       expand_assignment (temp, integer_one_node, 0, 0);
        if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
  	  || (init && TREE_CODE (init) == TREE_LIST))
  	{
--- 7869,7907 ----
        /* Remember this information until end of file.  */
        push_obstacks (&permanent_obstack, &permanent_obstack);
  
!       /* Emit code to perform this initialization but once.  This code
! 	 looks like:
! 
!            static int temp = 0;
!            if (!temp) {
!              // Do initialization.
! 	     temp = 1;
! 	     // Register variable for destruction at end of program.
! 	   }
! 
! 	 Note that the `temp' variable is only set to 1 *after* the
! 	 initialization is complete.  This ensures that an exception,
! 	 thrown during the construction, will cause the variable to
! 	 reinitialized when we pass through this code again, as per:
! 	 
! 	   [stmt.dcl]
! 
! 	   If the initialization exits by throwing an exception, the
! 	   initialization is not complete, so it will be tried again
! 	   the next time control enters the declaration.
! 
!          In theory, this process should be thread-safe, too; multiple
! 	 threads should not be able to initialize the variable more
! 	 than once.  We don't yet attempt to ensure thread-safety.  */
        temp = get_temp_name (integer_type_node, 1);
        rest_of_decl_compilation (temp, NULL_PTR, 0, 0);
+ 
+       /* Begin the conditional initialization.  */
        expand_start_cond (build_binary_op (EQ_EXPR, temp,
  					  integer_zero_node, 1), 0);
        expand_start_target_temps ();
  
!       /* Do the initialization itself.  */
        if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
  	  || (init && TREE_CODE (init) == TREE_LIST))
  	{
*************** expand_static_init (decl, init)
*** 7885,7894 ****
  	}
        else if (init)
  	expand_assignment (decl, init, 0, 0);
  
!       /* Cleanup any temporaries needed for the initial value.  */
        expand_end_target_temps ();
  
        if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl)))
  	{
  	  tree cleanup, fcall;
--- 7910,7927 ----
  	}
        else if (init)
  	expand_assignment (decl, init, 0, 0);
+ 
+       /* Set TEMP to 1.  */
+       expand_assignment (temp, integer_one_node, 0, 0);
  
!       /* Cleanup any temporaries needed for the initial value.  If
! 	 destroying one of the temporaries causes an exception to be
! 	 thrown, then the object itself has still been fully
! 	 constructed.  */
        expand_end_target_temps ();
  
+       /* Use atexit to register a function for destroying this static
+ 	 variable.  */
        if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl)))
  	{
  	  tree cleanup, fcall;
Index: testsuite/cp/search.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/search.c,v
retrieving revision 1.74
diff -c -p -r1.74 search.c
*** search.c	1998/11/24 21:28:45	1.74
--- search.c	1998/12/04 00:44:57
*************** lookup_field_1 (type, name)
*** 523,529 ****
  	  if (temp)
  	    return temp;
  	}
!       if (DECL_NAME (field) == name)
  	{
  	  if ((TREE_CODE(field) == VAR_DECL || TREE_CODE(field) == CONST_DECL)
  	      && DECL_ASSEMBLER_NAME (field) != NULL)
--- 523,536 ----
  	  if (temp)
  	    return temp;
  	}
!       if (TREE_CODE (field) == USING_DECL)
! 	/* For now, we're just treating member using declarations as
! 	   old ARM-style access declarations.  Thus, there's no reason
! 	   to return a USING_DECL, and the rest of the compiler can't
! 	   handle it.  Once the class is defined, these are purged
! 	   from TYPE_FIELDS anyhow; see handle_using_decl.  */
! 	;
!       else if (DECL_NAME (field) == name)
  	{
  	  if ((TREE_CODE(field) == VAR_DECL || TREE_CODE(field) == CONST_DECL)
  	      && DECL_ASSEMBLER_NAME (field) != NULL)


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