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: PR 21336


This patch fixes a rejects-valid regression.  While in B::m, below, we
instantiate a template operator new; that mistakenly caused us to mark
"B" as having a member operator new.  Fixed by making sure that we're
looking at the DECL_CONTEXT of the operator, rather than relying on
current_class_type.

Tested on x86_64-unknown-linux-gnu, applied on the mainline, 4.0, and
3.4 branches. 

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


2005-06-03  Mark Mitchell  <mark@codesourcery.com>

	PR c++/21336
	* cp-tree.h (grok_op_properties): Remove friendp parameter.
	* decl.c (grokfndecl): Adjust call.
	(grok_op_properties): Determine the class of which the function is
	a member by looking at its DECL_CONTEXT, not current_class_type.
	* pt.c (tsubst_decl): Adjust call to grok_op_properties.

2005-06-03  Mark Mitchell  <mark@codesourcery.com>

	PR c++/21336
	* g++.dg/template/new2.C: New test.

Index: gcc/testsuite/g++.dg/template/new2.C
===================================================================
RCS file: gcc/testsuite/g++.dg/template/new2.C
diff -N gcc/testsuite/g++.dg/template/new2.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- gcc/testsuite/g++.dg/template/new2.C	3 Jun 2005 02:19:45 -0000
***************
*** 0 ****
--- 1,14 ----
+ // PR c++/21336
+ 
+ typedef __SIZE_TYPE__ size_t;
+ template<class _T> void* operator new( size_t Size, _T&);
+ struct B {
+   int a;
+   int* m() {
+     return new(a) int;
+   }
+ };
+ B* n() {
+   return new B();
+ }
+ 
Index: gcc/cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.1139
diff -c -5 -p -r1.1139 cp-tree.h
*** gcc/cp/cp-tree.h	28 May 2005 01:38:10 -0000	1.1139
--- gcc/cp/cp-tree.h	3 Jun 2005 02:19:46 -0000
*************** extern tree build_ptrmem_type           
*** 3764,3774 ****
  /* the grokdeclarator prototype is in decl.h */
  extern int copy_fn_p				(tree);
  extern tree get_scope_of_declarator             (const cp_declarator *);
  extern void grok_special_member_properties	(tree);
  extern int grok_ctor_properties			(tree, tree);
! extern void grok_op_properties			(tree, int, bool);
  extern tree xref_tag				(enum tag_types, tree, tag_scope, bool);
  extern tree xref_tag_from_type			(tree, tree, tag_scope);
  extern void xref_basetypes			(tree, tree);
  extern tree start_enum				(tree);
  extern void finish_enum				(tree);
--- 3764,3774 ----
  /* the grokdeclarator prototype is in decl.h */
  extern int copy_fn_p				(tree);
  extern tree get_scope_of_declarator             (const cp_declarator *);
  extern void grok_special_member_properties	(tree);
  extern int grok_ctor_properties			(tree, tree);
! extern void grok_op_properties			(tree, bool);
  extern tree xref_tag				(enum tag_types, tree, tag_scope, bool);
  extern tree xref_tag_from_type			(tree, tree, tag_scope);
  extern void xref_basetypes			(tree, tree);
  extern tree start_enum				(tree);
  extern void finish_enum				(tree);
Index: gcc/cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1399
diff -c -5 -p -r1.1399 decl.c
*** gcc/cp/decl.c	27 May 2005 23:17:08 -0000	1.1399
--- gcc/cp/decl.c	3 Jun 2005 02:19:46 -0000
*************** grokfndecl (tree ctype,
*** 5607,5617 ****
  	     (ctype ? "static " : "non-"), decl);
        quals = TYPE_UNQUALIFIED;
      }
  
    if (IDENTIFIER_OPNAME_P (DECL_NAME (decl)))
!     grok_op_properties (decl, friendp, /*complain=*/true);
  
    if (ctype && decl_function_context (decl))
      DECL_NO_STATIC_CHAIN (decl) = 1;
  
    for (t = TYPE_ARG_TYPES (TREE_TYPE (decl)); t; t = TREE_CHAIN (t))
--- 5607,5617 ----
  	     (ctype ? "static " : "non-"), decl);
        quals = TYPE_UNQUALIFIED;
      }
  
    if (IDENTIFIER_OPNAME_P (DECL_NAME (decl)))
!     grok_op_properties (decl, /*complain=*/true);
  
    if (ctype && decl_function_context (decl))
      DECL_NO_STATIC_CHAIN (decl) = 1;
  
    for (t = TYPE_ARG_TYPES (TREE_TYPE (decl)); t; t = TREE_CHAIN (t))
*************** unary_op_p (enum tree_code code)
*** 8605,8631 ****
  
  /* DECL is a declaration for an overloaded operator.  If COMPLAIN is true,
     errors are issued for invalid declarations.  */
  
  void
! grok_op_properties (tree decl, int friendp, bool complain)
  {
    tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
    tree argtype;
    int methodp = (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE);
    tree name = DECL_NAME (decl);
    enum tree_code operator_code;
    int arity;
  
    /* Count the number of arguments.  */
    for (argtype = argtypes, arity = 0;
         argtype && argtype != void_list_node;
         argtype = TREE_CHAIN (argtype))
      ++arity;
  
!   if (current_class_type == NULL_TREE)
!     friendp = 1;
  
    if (DECL_CONV_FN_P (decl))
      operator_code = TYPE_EXPR;
    else
      do
--- 8605,8633 ----
  
  /* DECL is a declaration for an overloaded operator.  If COMPLAIN is true,
     errors are issued for invalid declarations.  */
  
  void
! grok_op_properties (tree decl, bool complain)
  {
    tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
    tree argtype;
    int methodp = (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE);
    tree name = DECL_NAME (decl);
    enum tree_code operator_code;
    int arity;
+   tree class_type;
  
    /* Count the number of arguments.  */
    for (argtype = argtypes, arity = 0;
         argtype && argtype != void_list_node;
         argtype = TREE_CHAIN (argtype))
      ++arity;
  
!   class_type = DECL_CONTEXT (decl);
!   if (class_type && !CLASS_TYPE_P (class_type))
!     class_type = NULL_TREE;
  
    if (DECL_CONV_FN_P (decl))
      operator_code = TYPE_EXPR;
    else
      do
*************** grok_op_properties (tree decl, int frien
*** 8650,8683 ****
        }
      while (0);
    gcc_assert (operator_code != LAST_CPLUS_TREE_CODE);
    SET_OVERLOADED_OPERATOR_CODE (decl, operator_code);
  
!   if (! friendp)
!     {
!       switch (operator_code)
! 	{
! 	case NEW_EXPR:
! 	  TYPE_HAS_NEW_OPERATOR (current_class_type) = 1;
! 	  break;
  
! 	case DELETE_EXPR:
! 	  TYPE_GETS_DELETE (current_class_type) |= 1;
! 	  break;
  
! 	case VEC_NEW_EXPR:
! 	  TYPE_HAS_ARRAY_NEW_OPERATOR (current_class_type) = 1;
! 	  break;
  
! 	case VEC_DELETE_EXPR:
! 	  TYPE_GETS_DELETE (current_class_type) |= 2;
! 	  break;
  
! 	default:
! 	  break;
! 	}
!     }
  
      /* [basic.std.dynamic.allocation]/1:
  
         A program is ill-formed if an allocation function is declared
         in a namespace scope other than global scope or declared static
--- 8652,8683 ----
        }
      while (0);
    gcc_assert (operator_code != LAST_CPLUS_TREE_CODE);
    SET_OVERLOADED_OPERATOR_CODE (decl, operator_code);
  
!   if (class_type)
!     switch (operator_code)
!       {
!       case NEW_EXPR:
! 	TYPE_HAS_NEW_OPERATOR (class_type) = 1;
! 	break;
  
!       case DELETE_EXPR:
! 	TYPE_GETS_DELETE (class_type) |= 1;
! 	break;
  
!       case VEC_NEW_EXPR:
! 	TYPE_HAS_ARRAY_NEW_OPERATOR (class_type) = 1;
! 	break;
  
!       case VEC_DELETE_EXPR:
! 	TYPE_GETS_DELETE (class_type) |= 2;
! 	break;
  
!       default:
! 	break;
!       }
  
      /* [basic.std.dynamic.allocation]/1:
  
         A program is ill-formed if an allocation function is declared
         in a namespace scope other than global scope or declared static
*************** grok_op_properties (tree decl, int frien
*** 8752,8787 ****
        /* There are no restrictions on the arguments to an overloaded
  	 "operator ()".  */
        if (operator_code == CALL_EXPR)
  	return;
  
!       if (IDENTIFIER_TYPENAME_P (name) && ! DECL_TEMPLATE_INFO (decl))
  	{
  	  tree t = TREE_TYPE (name);
! 	  if (! friendp)
! 	    {
! 	      int ref = (TREE_CODE (t) == REFERENCE_TYPE);
! 	      const char *what = 0;
  
! 	      if (ref)
! 		t = TYPE_MAIN_VARIANT (TREE_TYPE (t));
  
! 	      if (TREE_CODE (t) == VOID_TYPE)
! 	        what = "void";
! 	      else if (t == current_class_type)
  		what = "the same type";
  	      /* Don't force t to be complete here.  */
  	      else if (IS_AGGR_TYPE (t)
  		       && COMPLETE_TYPE_P (t)
! 		       && DERIVED_FROM_P (t, current_class_type))
  		what = "a base class";
- 
- 	      if (what && warn_conversion)
- 		warning (0, "conversion to %s%s will never use a type "
-                          "conversion operator",
- 			 ref ? "a reference to " : "", what);
  	    }
  	}
        if (operator_code == COND_EXPR)
  	{
  	  /* 13.4.0.3 */
  	  error ("ISO C++ prohibits overloading operator ?:");
--- 8752,8789 ----
        /* There are no restrictions on the arguments to an overloaded
  	 "operator ()".  */
        if (operator_code == CALL_EXPR)
  	return;
  
!       if (IDENTIFIER_TYPENAME_P (name) 
! 	  && ! DECL_TEMPLATE_INFO (decl)
! 	  && warn_conversion)
  	{
  	  tree t = TREE_TYPE (name);
! 	  int ref = (TREE_CODE (t) == REFERENCE_TYPE);
! 	  const char *what = 0;
  
! 	  if (ref)
! 	    t = TYPE_MAIN_VARIANT (TREE_TYPE (t));
  
! 	  if (TREE_CODE (t) == VOID_TYPE)
! 	    what = "void";
! 	  else if (class_type)
! 	    {
! 	      if (t == class_type)
  		what = "the same type";
  	      /* Don't force t to be complete here.  */
  	      else if (IS_AGGR_TYPE (t)
  		       && COMPLETE_TYPE_P (t)
! 		       && DERIVED_FROM_P (t, class_type))
  		what = "a base class";
  	    }
+ 
+ 	  if (what)
+ 	    warning (0, "conversion to %s%s will never use a type "
+ 		     "conversion operator",
+ 		     ref ? "a reference to " : "", what);
  	}
        if (operator_code == COND_EXPR)
  	{
  	  /* 13.4.0.3 */
  	  error ("ISO C++ prohibits overloading operator ?:");
Index: gcc/cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.1000
diff -c -5 -p -r1.1000 pt.c
*** gcc/cp/pt.c	27 May 2005 23:17:17 -0000	1.1000
--- gcc/cp/pt.c	3 Jun 2005 02:19:46 -0000
*************** tsubst_decl (tree t, tree args, tsubst_f
*** 6492,6503 ****
  	       clone_constructors_and_destructors.  */
  	    if (PRIMARY_TEMPLATE_P (gen_tmpl))
  	      clone_function_decl (r, /*update_method_vec_p=*/0);
  	  }
  	else if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
! 	  grok_op_properties (r, DECL_FRIEND_P (r),
! 			      (complain & tf_error) != 0);
  
  	if (DECL_FRIEND_P (t) && DECL_FRIEND_CONTEXT (t))
  	  SET_DECL_FRIEND_CONTEXT (r,
  				   tsubst (DECL_FRIEND_CONTEXT (t),
  					    args, complain, in_decl));
--- 6492,6502 ----
  	       clone_constructors_and_destructors.  */
  	    if (PRIMARY_TEMPLATE_P (gen_tmpl))
  	      clone_function_decl (r, /*update_method_vec_p=*/0);
  	  }
  	else if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
! 	  grok_op_properties (r, (complain & tf_error) != 0);
  
  	if (DECL_FRIEND_P (t) && DECL_FRIEND_CONTEXT (t))
  	  SET_DECL_FRIEND_CONTEXT (r,
  				   tsubst (DECL_FRIEND_CONTEXT (t),
  					    args, complain, in_decl));


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