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]

C++ PATCH: Last batch of regressions fixes


This is the last batch of fixes from testsuite runs done at
CodeSourcery.  There are some more serious wrong-code regressions in
this bunch, such as calling the wrong deallocation function when an
allocation fails, and calling the wrong function due to an incorrect
optimization relating to Koenig lookup.

Tested on i686-pc-linux-gnu, applied on the mainline and on the 3.4
branch.

On to 14616...

--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com

2004-03-19  Mark Mitchell  <mark@codesourcery.com>

	* call.c (build_op_delete_call): Do not forget the placement
	arguments when iterating through mutiple delete operators.

	* cp-tree.h (svaed_scope): Remove last_parms.
	(NEW_DELETE_OPNAME_P): New macro.
	(last_function_parms): Remove.
	(do_friend): Adjust prototype.
	* decl.c (grokparms): Return the PARM_DECLs directly, rather than
	using last_function_parms.
	(grokfndecl): Take the PARM_DECLs as an argument, rather than
	using last_function_parms.
	(grokdeclarator): Adjust accordingly.  Do not form METHOD_TYPEs
	for class-specific operator new and operator delete.
	(grok_op_properties): Do not look for allocation functions with
	METHOD_TYPEs.
	(start_function): Use DECL_ARGUMENTS instead of
	last_function_parms.
	* decl.h (last_function_parms): Do not declare.
	* decl2.c (grokclassfn): Do not use last_function_parms.
	* friend.c (do_friend): Remove parmdecls parameter.
	* name-lookup.c (push_to_top_level): Do not save last_function_parms.
	(pop_from_top_level): Do not restore it.
	* pt.c (check_explicit_specialization): Do not adjust
	last_function_parms.

	* name-lookup.c (do_local_using_decl): Create a local binding for
	types brought in via using declarations.

	* name-lookup.c (lookup_arg_dependent): Handle block-scope
	function declarations correctly.

	* semantics.c (finish_id_expression): Correct handling of
	conversion operators to dependent types.

	* typeck.c (lookup_destructor): Allow the use of destructors from
	base classes.
	
2004-03-19  Mark Mitchell  <mark@codesourcery.com>

	* g++.dg/init/placement3.C: New test.

	* g++.dg/template/spec13.C: New test.

	* g++.dg/lookup/using11.C: New test.
	
	* g++.dg/lookup/koenig3.C: New test.

	* g++.dg/template/operator2.C: New test.
	
	* g++.dg/expr/dtor3.C: New test.
	* g++.old-deja/g++.brendan/crash15.C: Remove incorrect dg-error
	marker.
	* g++.old-deja/g++.law/visibility28.C: Likewise.

Index: cp/call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.452.2.15
diff -c -5 -p -r1.452.2.15 call.c
*** cp/call.c	19 Mar 2004 07:13:31 -0000	1.452.2.15
--- cp/call.c	20 Mar 2004 00:06:07 -0000
*************** build_op_delete_call (enum tree_code cod
*** 3768,3786 ****
  	    continue;
  	  t = TREE_CHAIN (t);
  	  /* On the first pass, check the rest of the arguments.  */
  	  if (pass == 0)
  	    {
! 	      while (argtypes && t)
  		{
! 		  if (!same_type_p (TREE_VALUE (argtypes),
! 				    TREE_VALUE (t)))
  		    break;
! 		  argtypes = TREE_CHAIN (argtypes);
  		  t = TREE_CHAIN (t);
  		}
! 	      if (!argtypes && !t)
  		break;
  	    }
  	  /* On the second pass, the second argument must be
  	     "size_t".  */
  	  else if (pass == 1
--- 3768,3786 ----
  	    continue;
  	  t = TREE_CHAIN (t);
  	  /* On the first pass, check the rest of the arguments.  */
  	  if (pass == 0)
  	    {
! 	      tree a = argtypes;
! 	      while (a && t)
  		{
! 		  if (!same_type_p (TREE_VALUE (a), TREE_VALUE (t)))
  		    break;
! 		  a = TREE_CHAIN (a);
  		  t = TREE_CHAIN (t);
  		}
! 	      if (!a && !t)
  		break;
  	    }
  	  /* On the second pass, the second argument must be
  	     "size_t".  */
  	  else if (pass == 1
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.946.4.10
diff -c -5 -p -r1.946.4.10 cp-tree.h
*** cp/cp-tree.h	16 Mar 2004 21:35:06 -0000	1.946.4.10
--- cp/cp-tree.h	20 Mar 2004 00:06:07 -0000
*************** struct saved_scope GTY(())
*** 698,708 ****
    tree lang_name;
    tree template_parms;
    tree x_previous_class_type;
    tree x_previous_class_values;
    tree x_saved_tree;
-   tree last_parms;
  
    HOST_WIDE_INT x_processing_template_decl;
    int x_processing_specialization;
    bool x_processing_explicit_instantiation;
    int need_pop_function_context;
--- 698,707 ----
*************** struct language_function GTY(())
*** 856,865 ****
--- 855,872 ----
     otherwise, for use by the automatic named return value optimization.  */
  
  #define current_function_return_value \
    (cp_function_chain->x_return_value)
  
+ /* True if NAME is the IDENTIFIER_NODE for an overloaded "operator
+    new" or "operator delete".  */
+ #define NEW_DELETE_OPNAME_P(NAME)		\
+   ((NAME) == ansi_opname (NEW_EXPR) 		\
+    || (NAME) == ansi_opname (VEC_NEW_EXPR) 	\
+    || (NAME) == ansi_opname (DELETE_EXPR) 	\
+    || (NAME) == ansi_opname (VEC_DELETE_EXPR))
+ 
  #define ansi_opname(CODE) \
    (operator_name_info[(int) (CODE)].identifier)
  #define ansi_assopname(CODE) \
    (assignment_operator_name_info[(int) (CODE)].identifier)
  
*************** extern tree cp_fname_init			(const char 
*** 3703,3713 ****
  extern tree check_elaborated_type_specifier     (enum tag_types, tree, bool);
  extern tree cxx_builtin_type_decls              (void);
  extern void warn_extern_redeclared_static (tree, tree);
  
  extern bool have_extern_spec;
- extern GTY(()) tree last_function_parms;
  
  /* in decl2.c */
  extern bool check_java_method (tree);
  extern int grok_method_quals (tree, tree, tree);
  extern void grok_x_components (tree);
--- 3710,3719 ----
*************** extern tree cplus_expand_constant       
*** 3784,3794 ****
  
  /* friend.c */
  extern int is_friend				(tree, tree);
  extern void make_friend_class			(tree, tree, bool);
  extern void add_friend                          (tree, tree, bool);
! extern tree do_friend				(tree, tree, tree, tree, tree, enum overload_flags, tree, int);
  
  /* in init.c */
  extern tree expand_member_init			(tree);
  extern void emit_mem_initializers		(tree);
  extern tree build_aggr_init			(tree, tree, int);
--- 3790,3800 ----
  
  /* friend.c */
  extern int is_friend				(tree, tree);
  extern void make_friend_class			(tree, tree, bool);
  extern void add_friend                          (tree, tree, bool);
! extern tree do_friend				(tree, tree, tree, tree, enum overload_flags, tree, int);
  
  /* in init.c */
  extern tree expand_member_init			(tree);
  extern void emit_mem_initializers		(tree);
  extern tree build_aggr_init			(tree, tree, int);
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1174.2.15
diff -c -5 -p -r1.1174.2.15 decl.c
*** cp/decl.c	19 Mar 2004 07:13:31 -0000	1.1174.2.15
--- cp/decl.c	20 Mar 2004 00:06:09 -0000
*************** Boston, MA 02111-1307, USA.  */
*** 50,69 ****
  #include "c-pragma.h"
  #include "diagnostic.h"
  #include "debug.h"
  #include "timevar.h"
  
! static tree grokparms (tree);
  static const char *redeclaration_error_message (tree, tree);
  
  static int decl_jump_unsafe (tree);
  static void require_complete_types_for_parms (tree);
  static int ambi_op_p (enum tree_code);
  static int unary_op_p (enum tree_code);
  static void push_local_name (tree);
  static tree grok_reference_init (tree, tree, tree, tree *);
! static tree grokfndecl (tree, tree, tree, tree, int,
  			enum overload_flags, tree,
  			tree, int, int, int, int, int, int, tree);
  static tree grokvardecl (tree, tree, RID_BIT_TYPE *, int, int, tree);
  static void record_unknown_type (tree, const char *);
  static tree builtin_function_1 (const char *, tree, tree, int,
--- 50,69 ----
  #include "c-pragma.h"
  #include "diagnostic.h"
  #include "debug.h"
  #include "timevar.h"
  
! static tree grokparms (tree, tree *);
  static const char *redeclaration_error_message (tree, tree);
  
  static int decl_jump_unsafe (tree);
  static void require_complete_types_for_parms (tree);
  static int ambi_op_p (enum tree_code);
  static int unary_op_p (enum tree_code);
  static void push_local_name (tree);
  static tree grok_reference_init (tree, tree, tree, tree *);
! static tree grokfndecl (tree, tree, tree, tree, tree, int,
  			enum overload_flags, tree,
  			tree, int, int, int, int, int, int, tree);
  static tree grokvardecl (tree, tree, RID_BIT_TYPE *, int, int, tree);
  static void record_unknown_type (tree, const char *);
  static tree builtin_function_1 (const char *, tree, tree, int,
*************** tree static_aggregates;
*** 205,217 ****
  
  /* A node for the integer constants 2, and 3.  */
  
  tree integer_two_node, integer_three_node;
  
- /* Similar, for last_function_parm_tags.  */
- tree last_function_parms;
- 
  /* A list of all LABEL_DECLs in the function that have names.  Here so
     we can clear out their names' definitions at the end of the
     function, and so we can check the validity of jumps to these labels.  */
  
  struct named_label_list GTY(())
--- 205,214 ----
*************** bad_specifiers (tree object,
*** 5483,5492 ****
--- 5480,5490 ----
  
  /* CTYPE is class type, or null if non-class.
     TYPE is type this FUNCTION_DECL should have, either FUNCTION_TYPE
     or METHOD_TYPE.
     DECLARATOR is the function's name.
+    PARMS is a chain of PARM_DECLs for the function.
     VIRTUALP is truthvalue of whether the function is virtual or not.
     FLAGS are to be passed through to `grokclassfn'.
     QUALS are qualifiers indicating whether the function is `const'
     or `volatile'.
     RAISES is a list of exceptions that this function can raise.
*************** bad_specifiers (tree object,
*** 5498,5507 ****
--- 5496,5506 ----
  
  static tree
  grokfndecl (tree ctype, 
              tree type,
              tree declarator,
+ 	    tree parms,
              tree orig_declarator,
              int virtualp,
              enum overload_flags flags,
              tree quals, 
              tree raises,
*************** grokfndecl (tree ctype, 
*** 5520,5529 ****
--- 5519,5529 ----
  
    if (raises)
      type = build_exception_variant (type, raises);
  
    decl = build_lang_decl (FUNCTION_DECL, declarator, type);
+   DECL_ARGUMENTS (decl) = parms;
    /* Propagate volatile out from type to decl.  */
    if (TYPE_VOLATILE (type))
      TREE_THIS_VOLATILE (decl) = 1;
  
    /* If this decl has namespace scope, set that up.  */
*************** grokfndecl (tree ctype, 
*** 5745,5760 ****
  	   really a template that's being returned.  */
  	old_decl = DECL_TEMPLATE_RESULT (old_decl);
  
        if (old_decl && DECL_STATIC_FUNCTION_P (old_decl)
  	  && TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
! 	{
! 	  /* Remove the `this' parm added by grokclassfn.
! 	     XXX Isn't this done in start_function, too?  */
! 	  revert_static_member_fn (decl);
! 	  last_function_parms = TREE_CHAIN (last_function_parms);
! 	}
        if (old_decl && DECL_ARTIFICIAL (old_decl))
  	error ("definition of implicitly-declared `%D'", old_decl);
  
        if (old_decl)
  	{
--- 5745,5757 ----
  	   really a template that's being returned.  */
  	old_decl = DECL_TEMPLATE_RESULT (old_decl);
  
        if (old_decl && DECL_STATIC_FUNCTION_P (old_decl)
  	  && TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
! 	/* Remove the `this' parm added by grokclassfn.
! 	   XXX Isn't this done in start_function, too?  */
! 	revert_static_member_fn (decl);
        if (old_decl && DECL_ARTIFICIAL (old_decl))
  	error ("definition of implicitly-declared `%D'", old_decl);
  
        if (old_decl)
  	{
*************** grokdeclarator (tree declarator,
*** 6392,6401 ****
--- 6389,6399 ----
    tree raises = NULL_TREE;
    int template_count = 0;
    tree in_namespace = NULL_TREE;
    tree returned_attrs = NULL_TREE;
    tree scope = NULL_TREE;
+   tree parms = NULL_TREE;
  
    RIDBIT_RESET_ALL (specbits);
    if (decl_context == FUNCDEF)
      funcdef_flag = 1, decl_context = NORMAL;
    else if (decl_context == MEMFUNCDEF)
*************** grokdeclarator (tree declarator,
*** 7464,7474 ****
  	    /* Construct the function type and go to the next
  	       inner layer of declarator.  */
  
  	    declarator = TREE_OPERAND (declarator, 0);
  
! 	    arg_types = grokparms (inner_parms);
  
  	    if (declarator && flags == DTOR_FLAG)
  	      {
  		/* A destructor declared in the body of a class will
  		   be represented as a BIT_NOT_EXPR.  But, we just
--- 7462,7472 ----
  	    /* Construct the function type and go to the next
  	       inner layer of declarator.  */
  
  	    declarator = TREE_OPERAND (declarator, 0);
  
! 	    arg_types = grokparms (inner_parms, &parms);
  
  	    if (declarator && flags == DTOR_FLAG)
  	      {
  		/* A destructor declared in the body of a class will
  		   be represented as a BIT_NOT_EXPR.  But, we just
*************** grokdeclarator (tree declarator,
*** 7478,7488 ****
  
                  if (arg_types != void_list_node)
  		  {
  		    error ("destructors may not have parameters");
  		    arg_types = void_list_node;
! 		    last_function_parms = NULL_TREE;
  		  }
  	      }
  
  	    /* ANSI says that `const int foo ();'
  	       does not make the function foo const.  */
--- 7476,7486 ----
  
                  if (arg_types != void_list_node)
  		  {
  		    error ("destructors may not have parameters");
  		    arg_types = void_list_node;
! 		    parms = NULL_TREE;
  		  }
  	      }
  
  	    /* ANSI says that `const int foo ();'
  	       does not make the function foo const.  */
*************** grokdeclarator (tree declarator,
*** 7645,7655 ****
  		      pedwarn ("extra qualification `%T::' on member `%s' ignored",
  				  ctype, name);
  		  }
  		else if (TREE_CODE (type) == FUNCTION_TYPE)
  		  {
! 		    if (current_class_type == NULL_TREE || friendp)
  		      type 
  			= build_method_type_directly (ctype, 
  						      TREE_TYPE (type),
  						      TYPE_ARG_TYPES (type));
  		    else
--- 7643,7657 ----
  		      pedwarn ("extra qualification `%T::' on member `%s' ignored",
  				  ctype, name);
  		  }
  		else if (TREE_CODE (type) == FUNCTION_TYPE)
  		  {
! 		    if (NEW_DELETE_OPNAME_P (sname))
! 		      /* Overloaded operator new and operator delete
! 			 are always static functions.  */
! 		      ;
! 		    else if (current_class_type == NULL_TREE || friendp)
  		      type 
  			= build_method_type_directly (ctype, 
  						      TREE_TYPE (type),
  						      TYPE_ARG_TYPES (type));
  		    else
*************** grokdeclarator (tree declarator,
*** 7904,7915 ****
        && TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type)
        && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (typedef_type))
      type = build_cplus_array_type (TREE_TYPE (type), NULL_TREE);
  
    /* Detect where we're using a typedef of function type to declare a
!      function. last_function_parms will not be set, so we must create
!      it now.  */
    
    if (type == typedef_type && TREE_CODE (type) == FUNCTION_TYPE)
      {
        tree decls = NULL_TREE;
        tree args;
--- 7906,7916 ----
        && TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type)
        && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (typedef_type))
      type = build_cplus_array_type (TREE_TYPE (type), NULL_TREE);
  
    /* Detect where we're using a typedef of function type to declare a
!      function. PARMS will not be set, so we must create it now.  */
    
    if (type == typedef_type && TREE_CODE (type) == FUNCTION_TYPE)
      {
        tree decls = NULL_TREE;
        tree args;
*************** grokdeclarator (tree declarator,
*** 7920,7930 ****
  
  	  TREE_CHAIN (decl) = decls;
  	  decls = decl;
  	}
        
!       last_function_parms = nreverse (decls);
      }
  
    /* If this is a type name (such as, in a cast or sizeof),
       compute the type and return it now.  */
  
--- 7921,7931 ----
  
  	  TREE_CHAIN (decl) = decls;
  	  decls = decl;
  	}
        
!       parms = nreverse (decls);
      }
  
    /* If this is a type name (such as, in a cast or sizeof),
       compute the type and return it now.  */
  
*************** grokdeclarator (tree declarator,
*** 8114,8127 ****
  		    error ("function `%D' declared virtual inside a union",
  			      declarator);
  		    return void_type_node;
  		  }
  
! 		if (declarator == ansi_opname (NEW_EXPR)
! 		    || declarator == ansi_opname (VEC_NEW_EXPR)
! 		    || declarator == ansi_opname (DELETE_EXPR)
! 		    || declarator == ansi_opname (VEC_DELETE_EXPR))
  		  {
  		    if (virtualp)
  		      {
  			error ("`%D' cannot be declared virtual, since it is always static",
  				  declarator);
--- 8115,8125 ----
  		    error ("function `%D' declared virtual inside a union",
  			      declarator);
  		    return void_type_node;
  		  }
  
! 		if (NEW_DELETE_OPNAME_P (declarator))
  		  {
  		    if (virtualp)
  		      {
  			error ("`%D' cannot be declared virtual, since it is always static",
  				  declarator);
*************** grokdeclarator (tree declarator,
*** 8140,8149 ****
--- 8138,8148 ----
  	    publicp = (! friendp || ! staticp)
  	      && function_context == NULL_TREE;
  	    decl = grokfndecl (ctype, type,
  			       TREE_CODE (declarator) != TEMPLATE_ID_EXPR
  			       ? declarator : dname,
+ 			       parms,
  			       declarator,
  			       virtualp, flags, quals, raises,
  			       friendp ? -1 : 0, friendp, publicp, inlinep,
  			       funcdef_flag, template_count, in_namespace);
  	    if (decl == NULL_TREE)
*************** grokdeclarator (tree declarator,
*** 8186,8195 ****
--- 8185,8195 ----
  	    /* All method decls are public, so tell grokfndecl to set
  	       TREE_PUBLIC, also.  */
  	    decl = grokfndecl (ctype, type,
  			       TREE_CODE (declarator) != TEMPLATE_ID_EXPR
  			       ? declarator : dname,
+ 			       parms,
  			       declarator,
  			       virtualp, flags, quals, raises,
  			       friendp ? -1 : 0, friendp, 1, 0, funcdef_flag,
  			       template_count, in_namespace);
  	    if (decl == NULL_TREE)
*************** grokdeclarator (tree declarator,
*** 8243,8254 ****
  		    if (decl == error_mark_node)
  		      return error_mark_node;
  		  }
  		
  		decl = do_friend (ctype, declarator, decl,
! 				  last_function_parms, *attrlist,
! 				  flags, quals, funcdef_flag);
  		return decl;
  	      }
  	    else
  	      return void_type_node;
  	  }
--- 8243,8253 ----
  		    if (decl == error_mark_node)
  		      return error_mark_node;
  		  }
  		
  		decl = do_friend (ctype, declarator, decl,
! 				  *attrlist, flags, quals, funcdef_flag);
  		return decl;
  	      }
  	    else
  	      return void_type_node;
  	  }
*************** grokdeclarator (tree declarator,
*** 8357,8377 ****
  	      {
  		error ("virtual non-class function `%s'", name);
  		virtualp = 0;
  	      }
  	  }
! 	else if (TREE_CODE (type) == FUNCTION_TYPE && staticp < 2)
  	  type = build_method_type_directly (ctype, 
  					     TREE_TYPE (type),
  					     TYPE_ARG_TYPES (type));
  
  	/* Record presence of `static'.  */
  	publicp = (ctype != NULL_TREE
  		   || RIDBIT_SETP (RID_EXTERN, specbits)
  		   || !RIDBIT_SETP (RID_STATIC, specbits));
  
! 	decl = grokfndecl (ctype, type, original_name, declarator,
  			   virtualp, flags, quals, raises,
  			   1, friendp,
  			   publicp, inlinep, funcdef_flag,
  			   template_count, in_namespace);
  	if (decl == NULL_TREE)
--- 8356,8377 ----
  	      {
  		error ("virtual non-class function `%s'", name);
  		virtualp = 0;
  	      }
  	  }
! 	else if (TREE_CODE (type) == FUNCTION_TYPE && staticp < 2
! 		 && !NEW_DELETE_OPNAME_P (original_name))
  	  type = build_method_type_directly (ctype, 
  					     TREE_TYPE (type),
  					     TYPE_ARG_TYPES (type));
  
  	/* Record presence of `static'.  */
  	publicp = (ctype != NULL_TREE
  		   || RIDBIT_SETP (RID_EXTERN, specbits)
  		   || !RIDBIT_SETP (RID_STATIC, specbits));
  
! 	decl = grokfndecl (ctype, type, original_name, parms, declarator,
  			   virtualp, flags, quals, raises,
  			   1, friendp,
  			   publicp, inlinep, funcdef_flag,
  			   template_count, in_namespace);
  	if (decl == NULL_TREE)
*************** check_default_argument (tree decl, tree 
*** 8605,8618 ****
  
     We determine whether ellipsis parms are used by PARMLIST_ELLIPSIS_P
     flag. If unset, we append void_list_node. A parmlist declared
     as `(void)' is accepted as the empty parmlist.
  
!    Also set last_function_parms to the chain of PARM_DECLs.  */
  
  static tree
! grokparms (tree first_parm)
  {
    tree result = NULL_TREE;
    tree decls = NULL_TREE;
    int ellipsis = !first_parm || PARMLIST_ELLIPSIS_P (first_parm);
    tree parm, chain;
--- 8605,8618 ----
  
     We determine whether ellipsis parms are used by PARMLIST_ELLIPSIS_P
     flag. If unset, we append void_list_node. A parmlist declared
     as `(void)' is accepted as the empty parmlist.
  
!    *PARMS is set to the chain of PARM_DECLs created.  */
  
  static tree
! grokparms (tree first_parm, tree *parms)
  {
    tree result = NULL_TREE;
    tree decls = NULL_TREE;
    int ellipsis = !first_parm || PARMLIST_ELLIPSIS_P (first_parm);
    tree parm, chain;
*************** grokparms (tree first_parm)
*** 8714,8724 ****
      }
    decls = nreverse (decls);
    result = nreverse (result);
    if (!ellipsis)
      result = chainon (result, void_list_node);
!   last_function_parms = decls;
  
    return result;
  }
  
  
--- 8714,8724 ----
      }
    decls = nreverse (decls);
    result = nreverse (result);
    if (!ellipsis)
      result = chainon (result, void_list_node);
!   *parms = decls;
  
    return result;
  }
  
  
*************** grok_op_properties (tree decl, int frien
*** 8968,8992 ****
  	  break;
  	}
      }
  
    if (operator_code == NEW_EXPR || operator_code == VEC_NEW_EXPR)
!     {
!       /* When the compiler encounters the definition of A::operator new, it
! 	 doesn't look at the class declaration to find out if it's static.  */
!       if (methodp)
! 	revert_static_member_fn (decl);
! 
!       TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl));
!     }
    else if (operator_code == DELETE_EXPR || operator_code == VEC_DELETE_EXPR)
!     {
!       if (methodp)
! 	revert_static_member_fn (decl);
! 
!       TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl));
!     }
    else
      {
        /* An operator function must either be a non-static member function
  	 or have at least one parameter of a class, a reference to a class,
  	 an enumeration, or a reference to an enumeration.  13.4.0.6 */
--- 8968,8980 ----
  	  break;
  	}
      }
  
    if (operator_code == NEW_EXPR || operator_code == VEC_NEW_EXPR)
!     TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl));
    else if (operator_code == DELETE_EXPR || operator_code == VEC_DELETE_EXPR)
!     TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl));
    else
      {
        /* An operator function must either be a non-static member function
  	 or have at least one parameter of a class, a reference to a class,
  	 an enumeration, or a reference to an enumeration.  13.4.0.6 */
*************** start_function (tree declspecs, tree dec
*** 10093,10104 ****
  	  if (ctype && TREE_CODE (ctype) != RECORD_TYPE)
  	    ctype = NULL_TREE;
  	  else
  	    doing_friend = 1;
  	}
- 
-       last_function_parms = DECL_ARGUMENTS (decl1);
      }
    else
      {
        decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, &attrs);
        /* If the declarator is not suitable for a function definition,
--- 10081,10090 ----
*************** start_function (tree declspecs, tree dec
*** 10145,10155 ****
       build a METHOD_TYPE for it.  Fix that up now.  */
    if (ctype != NULL_TREE && DECL_STATIC_FUNCTION_P (decl1)
        && TREE_CODE (TREE_TYPE (decl1)) == METHOD_TYPE)
      {
        revert_static_member_fn (decl1);
-       last_function_parms = TREE_CHAIN (last_function_parms);
        ctype = NULL_TREE;
      }
  
    /* Warn if function was previously implicitly declared
       (but not if we warned then).  */
--- 10131,10140 ----
*************** start_function (tree declspecs, tree dec
*** 10198,10208 ****
    /* We are now in the scope of the function being defined.  */
    current_function_decl = decl1;
  
    /* Save the parm names or decls from this function's declarator
       where store_parm_decls will find them.  */
!   current_function_parms = last_function_parms;
  
    /* Make sure the parameter and return types are reasonable.  When
       you declare a function, these types can be incomplete, but they
       must be complete when you define the function.  */
    if (! processing_template_decl)
--- 10183,10193 ----
    /* We are now in the scope of the function being defined.  */
    current_function_decl = decl1;
  
    /* Save the parm names or decls from this function's declarator
       where store_parm_decls will find them.  */
!   current_function_parms = DECL_ARGUMENTS (decl1);
  
    /* Make sure the parameter and return types are reasonable.  When
       you declare a function, these types can be incomplete, but they
       must be complete when you define the function.  */
    if (! processing_template_decl)
Index: cp/decl.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.h,v
retrieving revision 1.11
diff -c -5 -p -r1.11 decl.h
*** cp/decl.h	20 Jun 2003 00:48:38 -0000	1.11
--- cp/decl.h	20 Mar 2004 00:06:09 -0000
*************** enum decl_context
*** 31,43 ****
  };
  
  /* We need this in here to get the decl_context definition.  */
  extern tree grokdeclarator (tree, tree, enum decl_context, int, tree*);
  
- /* Parsing a function declarator leaves a list of parameter names
-    or a chain or parameter decls here.  */
- extern GTY(()) tree last_function_parms;
- 
  #ifdef DEBUG_CP_BINDING_LEVELS
  /* Purely for debugging purposes.  */
  extern int debug_bindings_indentation;
  #endif
--- 31,39 ----
Index: cp/decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.695.4.5
diff -c -5 -p -r1.695.4.5 decl2.c
*** cp/decl2.c	16 Mar 2004 21:35:07 -0000	1.695.4.5
--- cp/decl2.c	20 Mar 2004 00:06:09 -0000
*************** grokclassfn (tree ctype, tree function, 
*** 334,348 ****
  	 assigned to.  */
        this_quals |= TYPE_QUAL_CONST;
        qual_type = cp_build_qualified_type (type, this_quals);
        parm = build_artificial_parm (this_identifier, qual_type);
        c_apply_type_quals_to_decl (this_quals, parm);
!       TREE_CHAIN (parm) = last_function_parms;
!       last_function_parms = parm;
      }
  
-   DECL_ARGUMENTS (function) = last_function_parms;
    DECL_CONTEXT (function) = ctype;
  
    if (flags == DTOR_FLAG)
      DECL_DESTRUCTOR_P (function) = 1;
  
--- 334,347 ----
  	 assigned to.  */
        this_quals |= TYPE_QUAL_CONST;
        qual_type = cp_build_qualified_type (type, this_quals);
        parm = build_artificial_parm (this_identifier, qual_type);
        c_apply_type_quals_to_decl (this_quals, parm);
!       TREE_CHAIN (parm) = DECL_ARGUMENTS (function);
!       DECL_ARGUMENTS (function) = parm;
      }
  
    DECL_CONTEXT (function) = ctype;
  
    if (flags == DTOR_FLAG)
      DECL_DESTRUCTOR_P (function) = 1;
  
Index: cp/friend.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/friend.c,v
retrieving revision 1.93
diff -c -5 -p -r1.93 friend.c
*** cp/friend.c	19 Dec 2003 23:28:06 -0000	1.93
--- cp/friend.c	20 Mar 2004 00:06:09 -0000
*************** make_friend_class (tree type, tree frien
*** 312,332 ****
  
     DECLARATOR is the name of the friend.
  
     DECL is the FUNCTION_DECL that the friend is.
  
-    In case we are parsing a friend which is part of an inline
-    definition, we will need to store PARM_DECL chain that comes
-    with it into the DECL_ARGUMENTS slot of the FUNCTION_DECL.
- 
     FLAGS is just used for `grokclassfn'.
  
     QUALS say what special qualifies should apply to the object
     pointed to by `this'.  */
  
  tree
! do_friend (tree ctype, tree declarator, tree decl, tree parmdecls,
  	   tree attrlist, enum overload_flags flags, tree quals,
  	   int funcdef_flag)
  {
    /* Every decl that gets here is a friend of something.  */
    DECL_FRIEND_P (decl) = 1;
--- 312,328 ----
  
     DECLARATOR is the name of the friend.
  
     DECL is the FUNCTION_DECL that the friend is.
  
     FLAGS is just used for `grokclassfn'.
  
     QUALS say what special qualifies should apply to the object
     pointed to by `this'.  */
  
  tree
! do_friend (tree ctype, tree declarator, tree decl,
  	   tree attrlist, enum overload_flags flags, tree quals,
  	   int funcdef_flag)
  {
    /* Every decl that gets here is a friend of something.  */
    DECL_FRIEND_P (decl) = 1;
*************** do_friend (tree ctype, tree declarator, 
*** 422,432 ****
        /* Friends must all go through the overload machinery,
  	 even though they may not technically be overloaded.
  
  	 Note that because classes all wind up being top-level
  	 in their scope, their friend wind up in top-level scope as well.  */
-       DECL_ARGUMENTS (decl) = parmdecls;
        if (funcdef_flag)
  	SET_DECL_FRIEND_CONTEXT (decl, current_class_type);
  
        if (! DECL_USE_TEMPLATE (decl))
  	{
--- 418,427 ----
Index: cp/name-lookup.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/name-lookup.c,v
retrieving revision 1.34.2.9
diff -c -5 -p -r1.34.2.9 name-lookup.c
*** cp/name-lookup.c	19 Mar 2004 07:13:33 -0000	1.34.2.9
--- cp/name-lookup.c	20 Mar 2004 00:06:09 -0000
*************** do_local_using_decl (tree decl, tree sco
*** 2293,2303 ****
  	}
        else
  	push_local_binding (name, newval, PUSH_USING);
      }
    if (newtype)
!     set_identifier_type_value (name, newtype);
  }
  
  /* Return the type that should be used when TYPE's name is preceded
     by a tag such as 'struct' or 'union', or null if the name cannot
     be used in this way.
--- 2293,2306 ----
  	}
        else
  	push_local_binding (name, newval, PUSH_USING);
      }
    if (newtype)
!     {
!       push_local_binding (name, newtype, PUSH_USING);
!       set_identifier_type_value (name, newtype);
!     }
  }
  
  /* Return the type that should be used when TYPE's name is preceded
     by a tag such as 'struct' or 'union', or null if the name cannot
     be used in this way.
*************** lookup_arg_dependent (tree name, tree fn
*** 4460,4474 ****
    /* We've already looked at some namespaces during normal unqualified
       lookup -- but we don't know exactly which ones.  If the functions
       we found were brought into the current namespace via a using
       declaration, we have not really checked the namespace from which
       they came.  Therefore, we check all namespaces here -- unless the
!      function we have is from the current namespace.  */
    if (fns)
      fn = OVL_CURRENT (fns);
    if (fn && TREE_CODE (fn) == FUNCTION_DECL 
!       && CP_DECL_CONTEXT (fn) != current_decl_namespace ())
      k.namespaces = NULL_TREE;
    else
      /* Setting NAMESPACES is purely an optimization; it prevents
         adding functions which are already in FNS.  Adding them would
         be safe -- "joust" will eliminate the duplicates -- but
--- 4463,4481 ----
    /* We've already looked at some namespaces during normal unqualified
       lookup -- but we don't know exactly which ones.  If the functions
       we found were brought into the current namespace via a using
       declaration, we have not really checked the namespace from which
       they came.  Therefore, we check all namespaces here -- unless the
!      function we have is from the current namespace.  Even then, we
!      must check all namespaces if the function is a local
!      declaration; any other declarations present at namespace scope
!      should be visible during argument-dependent lookup.  */
    if (fns)
      fn = OVL_CURRENT (fns);
    if (fn && TREE_CODE (fn) == FUNCTION_DECL 
!       && (CP_DECL_CONTEXT (fn) != current_decl_namespace ()
! 	  || DECL_LOCAL_FUNCTION_P (fn)))
      k.namespaces = NULL_TREE;
    else
      /* Setting NAMESPACES is purely an optimization; it prevents
         adding functions which are already in FNS.  Adding them would
         be safe -- "joust" will eliminate the duplicates -- but
*************** push_to_top_level (void)
*** 4821,4831 ****
    s->prev = scope_chain;
    s->old_bindings = old_bindings;
    s->bindings = b;
    s->need_pop_function_context = need_pop;
    s->function_decl = current_function_decl;
-   s->last_parms = last_function_parms;
  
    scope_chain = s;
    current_function_decl = NULL_TREE;
    VARRAY_TREE_INIT (current_lang_base, 10, "current_lang_base");
    current_lang_name = lang_name_cplusplus;
--- 4828,4837 ----
*************** pop_from_top_level (void)
*** 4859,4869 ****
    /* If we were in the middle of compiling a function, restore our
       state.  */
    if (s->need_pop_function_context)
      pop_function_context_from (NULL_TREE);
    current_function_decl = s->function_decl;
-   last_function_parms = s->last_parms;
    timevar_pop (TV_NAME_LOOKUP);
  }
  
  /* Pop off extraneous binding levels left over due to syntax errors.
  
--- 4865,4874 ----
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.816.2.19
diff -c -5 -p -r1.816.2.19 pt.c
*** cp/pt.c	16 Mar 2004 21:35:12 -0000	1.816.2.19
--- cp/pt.c	20 Mar 2004 00:06:10 -0000
*************** check_explicit_specialization (tree decl
*** 1908,1926 ****
  	      return instantiate_template (tmpl, targs, tf_error);
  	    }
  
  	  /* If we thought that the DECL was a member function, but it
  	     turns out to be specializing a static member function,
! 	     make DECL a static member function as well.  We also have
! 	     to adjust last_function_parms to avoid confusing
! 	     start_function later.  */
  	  if (DECL_STATIC_FUNCTION_P (tmpl)
  	      && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
! 	    {
! 	      revert_static_member_fn (decl);
! 	      last_function_parms = TREE_CHAIN (last_function_parms);
! 	    }
  
  	  /* If this is a specialization of a member template of a
  	     template class.  In we want to return the TEMPLATE_DECL,
  	     not the specialization of it.  */
  	  if (tsk == tsk_template)
--- 1908,1921 ----
  	      return instantiate_template (tmpl, targs, tf_error);
  	    }
  
  	  /* If we thought that the DECL was a member function, but it
  	     turns out to be specializing a static member function,
! 	     make DECL a static member function as well.  */
  	  if (DECL_STATIC_FUNCTION_P (tmpl)
  	      && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
! 	    revert_static_member_fn (decl);
  
  	  /* If this is a specialization of a member template of a
  	     template class.  In we want to return the TEMPLATE_DECL,
  	     not the specialization of it.  */
  	  if (tsk == tsk_template)
Index: cp/semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/semantics.c,v
retrieving revision 1.381.4.10
diff -c -5 -p -r1.381.4.10 semantics.c
*** cp/semantics.c	19 Mar 2004 07:13:37 -0000	1.381.4.10
--- cp/semantics.c	20 Mar 2004 00:06:10 -0000
*************** finish_id_expression (tree id_expression
*** 2362,2385 ****
    else 
      {
        if (decl == error_mark_node)
  	{
  	  /* Name lookup failed.  */
! 	  if (scope && (!TYPE_P (scope) || !dependent_type_p (scope)))
  	    {
! 	      /* Qualified name lookup failed, and the qualifying name
!       		 was not a dependent type.  That is always an
!       		 error.  */
  	      qualified_name_lookup_error (scope, id_expression);
  	      return error_mark_node;
  	    }
  	  else if (!scope)
  	    {
  	      /* It may be resolved via Koenig lookup.  */
  	      *idk = CP_ID_KIND_UNQUALIFIED;
  	      return id_expression;
  	    }
  	}
        /* If DECL is a variable that would be out of scope under
  	 ANSI/ISO rules, but in scope in the ARM, name lookup
  	 will succeed.  Issue a diagnostic here.  */
        else
--- 2362,2392 ----
    else 
      {
        if (decl == error_mark_node)
  	{
  	  /* Name lookup failed.  */
! 	  if (scope 
! 	      && (!TYPE_P (scope) 
! 		  || (!dependent_type_p (scope)
! 		      && !(TREE_CODE (id_expression) == IDENTIFIER_NODE
! 			   && IDENTIFIER_TYPENAME_P (id_expression)
! 			   && dependent_type_p (TREE_TYPE (id_expression))))))
  	    {
! 	      /* If the qualifying type is non-dependent (and the name
! 		 does not name a conversion operator to a dependent
! 		 type), issue an error.  */
  	      qualified_name_lookup_error (scope, id_expression);
  	      return error_mark_node;
  	    }
  	  else if (!scope)
  	    {
  	      /* It may be resolved via Koenig lookup.  */
  	      *idk = CP_ID_KIND_UNQUALIFIED;
  	      return id_expression;
  	    }
+ 	  else
+ 	    decl = id_expression;
  	}
        /* If DECL is a variable that would be out of scope under
  	 ANSI/ISO rules, but in scope in the ARM, name lookup
  	 will succeed.  Issue a diagnostic here.  */
        else
Index: cp/typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.519.2.12
diff -c -5 -p -r1.519.2.12 typeck.c
*** cp/typeck.c	19 Mar 2004 07:13:38 -0000	1.519.2.12
--- cp/typeck.c	20 Mar 2004 00:06:11 -0000
*************** build_class_member_access_expr (tree obj
*** 1786,1813 ****
  static tree
  lookup_destructor (tree object, tree scope, tree dtor_name)
  {
    tree object_type = TREE_TYPE (object);
    tree dtor_type = TREE_OPERAND (dtor_name, 0);
  
    if (scope && !check_dtor_name (scope, dtor_name))
      {
        error ("qualified type `%T' does not match destructor name `~%T'",
  	     scope, dtor_type);
        return error_mark_node;
      }
!   if (!same_type_p (dtor_type, TYPE_MAIN_VARIANT (object_type)))
      {
        error ("the type being destroyed is `%T', but the destructor refers to `%T'",
  	     TYPE_MAIN_VARIANT (object_type), dtor_type);
        return error_mark_node;
      }
!   if (!TYPE_HAS_DESTRUCTOR (object_type))
      return build (PSEUDO_DTOR_EXPR, void_type_node, object, scope,
  		  dtor_type);
!   return lookup_member (object_type, complete_dtor_identifier,
  			/*protect=*/1, /*want_type=*/false);
  }
  
  /* This function is called by the parser to process a class member
     access expression of the form OBJECT.NAME.  NAME is a node used by
     the parser to represent a name; it is not yet a DECL.  It may,
--- 1786,1817 ----
  static tree
  lookup_destructor (tree object, tree scope, tree dtor_name)
  {
    tree object_type = TREE_TYPE (object);
    tree dtor_type = TREE_OPERAND (dtor_name, 0);
+   tree expr;
  
    if (scope && !check_dtor_name (scope, dtor_name))
      {
        error ("qualified type `%T' does not match destructor name `~%T'",
  	     scope, dtor_type);
        return error_mark_node;
      }
!   if (!DERIVED_FROM_P (dtor_type, TYPE_MAIN_VARIANT (object_type)))
      {
        error ("the type being destroyed is `%T', but the destructor refers to `%T'",
  	     TYPE_MAIN_VARIANT (object_type), dtor_type);
        return error_mark_node;
      }
!   if (!TYPE_HAS_DESTRUCTOR (dtor_type))
      return build (PSEUDO_DTOR_EXPR, void_type_node, object, scope,
  		  dtor_type);
!   expr = lookup_member (dtor_type, complete_dtor_identifier,
  			/*protect=*/1, /*want_type=*/false);
+   expr = (adjust_result_of_qualified_name_lookup
+ 	  (expr, dtor_type, object_type));
+   return expr;
  }
  
  /* This function is called by the parser to process a class member
     access expression of the form OBJECT.NAME.  NAME is a node used by
     the parser to represent a name; it is not yet a DECL.  It may,
Index: testsuite/g++.dg/expr/dtor3.C
===================================================================
RCS file: testsuite/g++.dg/expr/dtor3.C
diff -N testsuite/g++.dg/expr/dtor3.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/expr/dtor3.C	20 Mar 2004 00:06:13 -0000
***************
*** 0 ****
--- 1,10 ----
+ struct B {
+   ~B();
+ };
+ struct D : public B {
+   ~D();
+ };
+ 
+ void f(D d) {
+   d.B::~B();
+ }
Index: testsuite/g++.dg/init/placement3.C
===================================================================
RCS file: testsuite/g++.dg/init/placement3.C
diff -N testsuite/g++.dg/init/placement3.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/init/placement3.C	20 Mar 2004 00:06:13 -0000
***************
*** 0 ****
--- 1,30 ----
+ typedef __SIZE_TYPE__ size_t;
+ extern "C" void *malloc (size_t);
+ 
+ int i;
+ 
+ struct S {
+   S(int) { 
+     throw 3; 
+   }
+ 
+   void *operator new(size_t s, int)  {
+     ++i;
+     return malloc (s);
+   }
+ 
+   void operator delete(void *, int)  {
+     --i;
+   }
+ 
+   void operator delete(void *, int, int) ;
+ };
+ 
+ int main () {
+   try {
+     new (7) S (12);
+   } catch (int) {
+     if (i)
+       return 1;
+   }
+ }
Index: testsuite/g++.dg/lookup/koenig3.C
===================================================================
RCS file: testsuite/g++.dg/lookup/koenig3.C
diff -N testsuite/g++.dg/lookup/koenig3.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/lookup/koenig3.C	20 Mar 2004 00:06:13 -0000
***************
*** 0 ****
--- 1,13 ----
+ extern "C" void abort ();
+ 
+ struct S {
+ };
+ void f(S, int) { abort(); }
+ void f(S, double) {}
+ 
+ S s;
+ 
+ int main() {
+   extern void f(S, int);
+   f(s, 3.0);
+ }
Index: testsuite/g++.dg/lookup/using11.C
===================================================================
RCS file: testsuite/g++.dg/lookup/using11.C
diff -N testsuite/g++.dg/lookup/using11.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/lookup/using11.C	20 Mar 2004 00:06:13 -0000
***************
*** 0 ****
--- 1,9 ----
+ namespace N1 {
+   enum e { a };
+   void e(char);
+ }
+ 
+ void f() {
+   using N1::e;
+   enum e x;
+ }
Index: testsuite/g++.dg/template/operator2.C
===================================================================
RCS file: testsuite/g++.dg/template/operator2.C
diff -N testsuite/g++.dg/template/operator2.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/operator2.C	20 Mar 2004 00:06:13 -0000
***************
*** 0 ****
--- 1,8 ----
+ template <typename T> struct A {};
+ 
+ struct B {
+   operator A<B>();
+ };
+ 
+ template <typename T>
+ void f() { B::operator A<T>; }
Index: testsuite/g++.dg/template/spec13.C
===================================================================
RCS file: testsuite/g++.dg/template/spec13.C
diff -N testsuite/g++.dg/template/spec13.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/spec13.C	20 Mar 2004 00:06:13 -0000
***************
*** 0 ****
--- 1,16 ----
+ // { dg-options "-w" }
+ 
+ template <typename T>
+ struct S {
+   int i;
+   template <typename U> void f(U) {}
+ };
+ 
+ template<> 
+ template <typename U>
+ void S<int>::f(U) { i; }
+ 
+ void f() {
+   S<int> s;
+   s.f<int>(3);
+ }
Index: testsuite/g++.old-deja/g++.brendan/crash15.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.old-deja/g++.brendan/crash15.C,v
retrieving revision 1.6
diff -c -5 -p -r1.6 crash15.C
*** testsuite/g++.old-deja/g++.brendan/crash15.C	1 May 2003 02:02:34 -0000	1.6
--- testsuite/g++.old-deja/g++.brendan/crash15.C	20 Mar 2004 00:06:14 -0000
*************** class B : public A {
*** 14,22 ****
  
  int
  main() {
    std::cout << "starting\n";
    B b;
!   b.~A();// { dg-error "" }  destructor
    std::cout << "done\n";
  }
  
--- 14,22 ----
  
  int
  main() {
    std::cout << "starting\n";
    B b;
!   b.~A();
    std::cout << "done\n";
  }
  
Index: testsuite/g++.old-deja/g++.law/visibility28.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.old-deja/g++.law/visibility28.C,v
retrieving revision 1.4
diff -c -5 -p -r1.4 visibility28.C
*** testsuite/g++.old-deja/g++.law/visibility28.C	1 May 2003 02:02:43 -0000	1.4
--- testsuite/g++.old-deja/g++.law/visibility28.C	20 Mar 2004 00:06:14 -0000
*************** public:
*** 9,19 ****
  };
  
  class D : public B {
  public:
          virtual ~D() { printf( "D::~D\n"); }
!   void operator = ( int i) { this->~B(); }// { dg-error "" } D has no ~B part to it
  };
  
  int
  main()
  {
--- 9,19 ----
  };
  
  class D : public B {
  public:
          virtual ~D() { printf( "D::~D\n"); }
!   void operator = ( int i) { this->~B(); }
  };
  
  int
  main()
  {


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