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++ PATCHes: PR c++/13113, c++/13854, c++/13907


This patch fixes several regressions:

(1) We forgot to issue such nice error messages about invalid attempts
    to form a pointer-to-member using a parenthesized member function
    name.  We now issue that message again.  We still issue another
    message afterwards -- but at least the first message is the
    helpful one we want.  It's not easy to get rid of the second
    message, and I don't consider that a regression, really.

(2) We were mishandling interaction betweens exceptions and
    attributes.  For a function type to be "the same" in the C++ front
    end we need to have both the same set of exceptions and the same
    set of attributes; in some places we checked one condition and in
    some the other!

(3) We were forgetting that a bad user-defined conversion as the first
    part of a conversion sequence makes the entire sequence bad.

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

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

2004-01-30  Mark Mitchell  <mark@codesourcery.com>

	PR c++/13113
	* init.c (build_offset_ref): Improve error recovery for invalid
	uses of non-static member functions.

	PR c++/13854
	* cp-tree.h (cp_build_type_attribute_variant): New function.
	* class.c (build_clone): Use cp_build_type_attribute_variant.
	* decl.c (duplicate_decls): Likewise.
	* pt.c (copy_default_args_to_explicit_spec): Likewise.
	(tsubst_function_type): Likewise.
	* tree.c (build_exception_variant): Check attributes before
	concluding that two types are the same.
	(cp_build_type-attribute_variant): New method.
	* typeck.c (merge_types): Use cp_build_type_attribute_variant.

	PR c++/13907
	* call.c (convert_class_to_reference): Keep better track of
	pedantically invalid user-defined conversions.

2004-02-02  Mark Mitchell  <mark@codesourcery.com>

	PR c++/13113
	* g++.old-deja/g++.mike/net36.C: Adjust error messages.

	PR c++/13854
	* g++.dg/ext/attrib13.C: New test.

	PR c++/13907
	* g++.dg/conversion/op2.C: New test.

Index: cp/call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.452.2.4
diff -c -5 -p -r1.452.2.4 call.c
*** cp/call.c	30 Jan 2004 16:21:24 -0000	1.452.2.4
--- cp/call.c	2 Feb 2004 16:11:55 -0000
*************** convert_class_to_reference (tree t, tree
*** 826,844 ****
  					   TYPE_BINFO (s), 	
  					   TREE_PURPOSE (conversions),
  					   LOOKUP_NORMAL);
  	  
  	  if (cand)
! 	    /* Build a standard conversion sequence indicating the
! 	       binding from the reference type returned by the
! 	       function to the desired REFERENCE_TYPE.  */
! 	    cand->second_conv
! 	      = (direct_reference_binding 
! 		 (reference_type, 
! 		  build1 (IDENTITY_CONV, 
! 			  TREE_TYPE (TREE_TYPE (TREE_TYPE (cand->fn))),
! 			  NULL_TREE)));
  	}
        conversions = TREE_CHAIN (conversions);
      }
  
    candidates = splice_viable (candidates, pedantic, &any_viable_p);
--- 826,848 ----
  					   TYPE_BINFO (s), 	
  					   TREE_PURPOSE (conversions),
  					   LOOKUP_NORMAL);
  	  
  	  if (cand)
! 	    {
! 	      /* Build a standard conversion sequence indicating the
! 		 binding from the reference type returned by the
! 		 function to the desired REFERENCE_TYPE.  */
! 	      cand->second_conv
! 		= (direct_reference_binding 
! 		   (reference_type, 
! 		    build1 (IDENTITY_CONV, 
! 			    TREE_TYPE (TREE_TYPE (TREE_TYPE (cand->fn))),
! 			    NULL_TREE)));
! 	      ICS_BAD_FLAG (cand->second_conv) 
! 		|= ICS_BAD_FLAG (TREE_VEC_ELT (cand->convs, 0));
! 	    }
  	}
        conversions = TREE_CHAIN (conversions);
      }
  
    candidates = splice_viable (candidates, pedantic, &any_viable_p);
Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.595.4.3
diff -c -5 -p -r1.595.4.3 class.c
*** cp/class.c	26 Jan 2004 17:45:58 -0000	1.595.4.3
--- cp/class.c	2 Feb 2004 16:11:55 -0000
*************** build_clone (tree fn, tree name)
*** 3871,3882 ****
  				      parmtypes);
        if (exceptions)
  	TREE_TYPE (clone) = build_exception_variant (TREE_TYPE (clone),
  						     exceptions);
        TREE_TYPE (clone) 
! 	= build_type_attribute_variant (TREE_TYPE (clone),
! 					TYPE_ATTRIBUTES (TREE_TYPE (fn)));
      }
  
    /* Copy the function parameters.  But, DECL_ARGUMENTS on a TEMPLATE_DECL
       aren't function parameters; those are the template parameters.  */
    if (TREE_CODE (clone) != TEMPLATE_DECL)
--- 3871,3882 ----
  				      parmtypes);
        if (exceptions)
  	TREE_TYPE (clone) = build_exception_variant (TREE_TYPE (clone),
  						     exceptions);
        TREE_TYPE (clone) 
! 	= cp_build_type_attribute_variant (TREE_TYPE (clone),
! 					   TYPE_ATTRIBUTES (TREE_TYPE (fn)));
      }
  
    /* Copy the function parameters.  But, DECL_ARGUMENTS on a TEMPLATE_DECL
       aren't function parameters; those are the template parameters.  */
    if (TREE_CODE (clone) != TEMPLATE_DECL)
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.946.4.2
diff -c -5 -p -r1.946.4.2 cp-tree.h
*** cp/cp-tree.h	27 Jan 2004 02:35:20 -0000	1.946.4.2
--- cp/cp-tree.h	2 Feb 2004 16:11:55 -0000
*************** extern void debug_binfo				(tree);
*** 4152,4161 ****
--- 4152,4162 ----
  extern tree build_dummy_object			(tree);
  extern tree maybe_dummy_object			(tree, tree *);
  extern int is_dummy_object			(tree);
  extern const struct attribute_spec cxx_attribute_table[];
  extern tree make_ptrmem_cst                     (tree, tree);
+ extern tree cp_build_type_attribute_variant     (tree, tree);
  extern tree cp_build_qualified_type_real        (tree, int, tsubst_flags_t);
  #define cp_build_qualified_type(TYPE, QUALS) \
    cp_build_qualified_type_real ((TYPE), (QUALS), tf_error | tf_warning)
  extern tree build_shared_int_cst                (int);
  extern special_function_kind special_function_p (tree);
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1174.2.2
diff -c -5 -p -r1.1174.2.2 decl.c
*** cp/decl.c	23 Jan 2004 23:10:22 -0000	1.1174.2.2
--- cp/decl.c	2 Feb 2004 16:11:56 -0000
*************** duplicate_decls (tree newdecl, tree oldd
*** 1264,1274 ****
  	{
  	  tree type = TREE_TYPE (newdecl);
  	  tree attribs = (*targetm.merge_type_attributes)
  	    (TREE_TYPE (olddecl), type);
  
! 	  type = build_type_attribute_variant (type, attribs);
  	  TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = type;
  	}
  
        /* Whether or not the builtin can throw exceptions has no
  	 bearing on this declarator.  */
--- 1264,1274 ----
  	{
  	  tree type = TREE_TYPE (newdecl);
  	  tree attribs = (*targetm.merge_type_attributes)
  	    (TREE_TYPE (olddecl), type);
  
! 	  type = cp_build_type_attribute_variant (type, attribs);
  	  TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = type;
  	}
  
        /* Whether or not the builtin can throw exceptions has no
  	 bearing on this declarator.  */
Index: cp/init.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/init.c,v
retrieving revision 1.356.2.3
diff -c -5 -p -r1.356.2.3 init.c
*** cp/init.c	26 Jan 2004 17:46:00 -0000	1.356.2.3
--- cp/init.c	2 Feb 2004 16:11:57 -0000
*************** build_offset_ref (tree type, tree name, 
*** 1557,1576 ****
  
  	   -- in a mem-initializer for a constructor for that class or for
  	   a class derived from that class (_class.base.init_).  */
        if (DECL_NONSTATIC_MEMBER_FUNCTION_P (member))
  	{
  	  /* In Microsoft mode, treat a non-static member function as if
  	     it were a pointer-to-member.  */
  	  if (flag_ms_extensions)
  	    {
- 	      member = build (OFFSET_REF, TREE_TYPE (member), decl, member);
  	      PTRMEM_OK_P (member) = 1;
  	      return build_unary_op (ADDR_EXPR, member, 0);
  	    }
! 	  error ("invalid use of non-static member function `%D'", member);
! 	  return error_mark_node;
  	}
        else if (TREE_CODE (member) == FIELD_DECL)
  	{
  	  error ("invalid use of non-static data member `%D'", member);
  	  return error_mark_node;
--- 1557,1580 ----
  
  	   -- in a mem-initializer for a constructor for that class or for
  	   a class derived from that class (_class.base.init_).  */
        if (DECL_NONSTATIC_MEMBER_FUNCTION_P (member))
  	{
+ 	  /* Build a representation of a the qualified name suitable
+ 	     for use as the operand to "&" -- even though the "&" is
+ 	     not actually present.  */
+ 	  member = build (OFFSET_REF, TREE_TYPE (member), decl, member);
  	  /* In Microsoft mode, treat a non-static member function as if
  	     it were a pointer-to-member.  */
  	  if (flag_ms_extensions)
  	    {
  	      PTRMEM_OK_P (member) = 1;
  	      return build_unary_op (ADDR_EXPR, member, 0);
  	    }
! 	  error ("invalid use of non-static member function `%D'", 
! 		 TREE_OPERAND (member, 1));
! 	  return member;
  	}
        else if (TREE_CODE (member) == FIELD_DECL)
  	{
  	  error ("invalid use of non-static data member `%D'", member);
  	  return error_mark_node;
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.816.2.5
diff -c -5 -p -r1.816.2.5 pt.c
*** cp/pt.c	26 Jan 2004 17:46:01 -0000	1.816.2.5
--- cp/pt.c	2 Feb 2004 16:11:57 -0000
*************** copy_default_args_to_explicit_spec (tree
*** 1524,1535 ****
  					     new_spec_types);
      }
    else
      new_type = build_function_type (TREE_TYPE (old_type),
  				    new_spec_types);
!   new_type = build_type_attribute_variant (new_type,
! 					   TYPE_ATTRIBUTES (old_type));
    new_type = build_exception_variant (new_type,
  				      TYPE_RAISES_EXCEPTIONS (old_type));
    TREE_TYPE (decl) = new_type;
  }
  
--- 1524,1535 ----
  					     new_spec_types);
      }
    else
      new_type = build_function_type (TREE_TYPE (old_type),
  				    new_spec_types);
!   new_type = cp_build_type_attribute_variant (new_type,
! 					      TYPE_ATTRIBUTES (old_type));
    new_type = build_exception_variant (new_type,
  				      TYPE_RAISES_EXCEPTIONS (old_type));
    TREE_TYPE (decl) = new_type;
  }
  
*************** tsubst_function_type (tree t, 
*** 6474,6484 ****
        
        fntype = build_method_type_directly (r, return_type, 
  					   TREE_CHAIN (arg_types));
      }
    fntype = cp_build_qualified_type_real (fntype, TYPE_QUALS (t), complain);
!   fntype = build_type_attribute_variant (fntype, TYPE_ATTRIBUTES (t));
    
    return fntype;  
  }
  
  /* Substitute into the PARMS of a call-declarator.  */
--- 6474,6484 ----
        
        fntype = build_method_type_directly (r, return_type, 
  					   TREE_CHAIN (arg_types));
      }
    fntype = cp_build_qualified_type_real (fntype, TYPE_QUALS (t), complain);
!   fntype = cp_build_type_attribute_variant (fntype, TYPE_ATTRIBUTES (t));
    
    return fntype;  
  }
  
  /* Substitute into the PARMS of a call-declarator.  */
Index: cp/tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/tree.c,v
retrieving revision 1.360
diff -c -5 -p -r1.360 tree.c
*** cp/tree.c	30 Dec 2003 10:07:10 -0000	1.360
--- cp/tree.c	2 Feb 2004 16:11:57 -0000
*************** build_exception_variant (tree type, tree
*** 983,993 ****
    tree v = TYPE_MAIN_VARIANT (type);
    int type_quals = TYPE_QUALS (type);
  
    for (; v; v = TYPE_NEXT_VARIANT (v))
      if (TYPE_QUALS (v) == type_quals
!         && comp_except_specs (raises, TYPE_RAISES_EXCEPTIONS (v), 1))
        return v;
  
    /* Need to build a new variant.  */
    v = build_type_copy (type);
    TYPE_RAISES_EXCEPTIONS (v) = raises;
--- 983,994 ----
    tree v = TYPE_MAIN_VARIANT (type);
    int type_quals = TYPE_QUALS (type);
  
    for (; v; v = TYPE_NEXT_VARIANT (v))
      if (TYPE_QUALS (v) == type_quals
!         && comp_except_specs (raises, TYPE_RAISES_EXCEPTIONS (v), 1)
! 	&& (*targetm.comp_type_attributes) (type, v))
        return v;
  
    /* Need to build a new variant.  */
    v = build_type_copy (type);
    TYPE_RAISES_EXCEPTIONS (v) = raises;
*************** make_ptrmem_cst (tree type, tree member)
*** 1952,1961 ****
--- 1953,1979 ----
       TREE_CONSTANT for things of class `c', but it does not.  */
    TREE_CONSTANT (ptrmem_cst) = 1;
    TREE_TYPE (ptrmem_cst) = type;
    PTRMEM_CST_MEMBER (ptrmem_cst) = member;
    return ptrmem_cst;
+ }
+ 
+ /* Build a variant of TYPE that has the indicated ATTRIBUTES.  May
+    return an existing type of an appropriate type already exists.  */
+ 
+ tree
+ cp_build_type_attribute_variant (tree type, tree attributes)
+ {
+   tree new_type;
+ 
+   new_type = build_type_attribute_variant (type, attributes);
+   if (TREE_CODE (new_type) == FUNCTION_TYPE
+       && (TYPE_RAISES_EXCEPTIONS (new_type) 
+ 	  != TYPE_RAISES_EXCEPTIONS (type)))
+     new_type = build_exception_variant (new_type,
+ 					TYPE_RAISES_EXCEPTIONS (type));
+   return new_type;
  }
  
  /* Apply FUNC to all language-specific sub-trees of TP in a pre-order
     traversal.  Called from walk_tree().  */
  
Index: cp/typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.519.2.3
diff -c -5 -p -r1.519.2.3 typeck.c
*** cp/typeck.c	29 Jan 2004 02:22:51 -0000	1.519.2.3
--- cp/typeck.c	2 Feb 2004 16:11:58 -0000
*************** merge_types (tree t1, tree t2)
*** 664,692 ****
  	tree p2 = TYPE_ARG_TYPES (t2);
  	tree rval, raises;
  
  	/* Save space: see if the result is identical to one of the args.  */
  	if (valtype == TREE_TYPE (t1) && ! p2)
! 	  return build_type_attribute_variant (t1, attributes);
  	if (valtype == TREE_TYPE (t2) && ! p1)
! 	  return build_type_attribute_variant (t2, attributes);
  
  	/* Simple way if one arg fails to specify argument types.  */
  	if (p1 == NULL_TREE || TREE_VALUE (p1) == void_type_node)
  	  {
  	    rval = build_function_type (valtype, p2);
  	    if ((raises = TYPE_RAISES_EXCEPTIONS (t2)))
  	      rval = build_exception_variant (rval, raises);
! 	    return build_type_attribute_variant (rval, attributes);
  	  }
  	raises = TYPE_RAISES_EXCEPTIONS (t1);
  	if (p2 == NULL_TREE || TREE_VALUE (p2) == void_type_node)
  	  {
  	    rval = build_function_type (valtype, p1);
  	    if (raises)
  	      rval = build_exception_variant (rval, raises);
! 	    return build_type_attribute_variant (rval, attributes);
  	  }
  
  	rval = build_function_type (valtype, commonparms (p1, p2));
  	t1 = build_exception_variant (rval, raises);
  	break;
--- 664,692 ----
  	tree p2 = TYPE_ARG_TYPES (t2);
  	tree rval, raises;
  
  	/* Save space: see if the result is identical to one of the args.  */
  	if (valtype == TREE_TYPE (t1) && ! p2)
! 	  return cp_build_type_attribute_variant (t1, attributes);
  	if (valtype == TREE_TYPE (t2) && ! p1)
! 	  return cp_build_type_attribute_variant (t2, attributes);
  
  	/* Simple way if one arg fails to specify argument types.  */
  	if (p1 == NULL_TREE || TREE_VALUE (p1) == void_type_node)
  	  {
  	    rval = build_function_type (valtype, p2);
  	    if ((raises = TYPE_RAISES_EXCEPTIONS (t2)))
  	      rval = build_exception_variant (rval, raises);
! 	    return cp_build_type_attribute_variant (rval, attributes);
  	  }
  	raises = TYPE_RAISES_EXCEPTIONS (t1);
  	if (p2 == NULL_TREE || TREE_VALUE (p2) == void_type_node)
  	  {
  	    rval = build_function_type (valtype, p1);
  	    if (raises)
  	      rval = build_exception_variant (rval, raises);
! 	    return cp_build_type_attribute_variant (rval, attributes);
  	  }
  
  	rval = build_function_type (valtype, commonparms (p1, p2));
  	t1 = build_exception_variant (rval, raises);
  	break;
*************** merge_types (tree t1, tree t2)
*** 720,730 ****
  	 attributes result from the instantiation.  */
        return t1;
  
      default:;
      }
!   return build_type_attribute_variant (t1, attributes);
  }
  
  /* Return the common type of two types.
     We assume that comptypes has already been done and returned 1;
     if that isn't so, this may crash.
--- 720,730 ----
  	 attributes result from the instantiation.  */
        return t1;
  
      default:;
      }
!   return cp_build_type_attribute_variant (t1, attributes);
  }
  
  /* Return the common type of two types.
     We assume that comptypes has already been done and returned 1;
     if that isn't so, this may crash.
Index: testsuite/g++.dg/conversion/op2.C
===================================================================
RCS file: testsuite/g++.dg/conversion/op2.C
diff -N testsuite/g++.dg/conversion/op2.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/conversion/op2.C	2 Feb 2004 16:12:01 -0000
***************
*** 0 ****
--- 1,16 ----
+ // PR c++/13907
+ 
+ struct A {
+   operator int & ();
+   operator const int & () const;
+ };
+                                                                                
+           
+ void f(int &);
+ void f(const int &);
+                                                                                
+           
+ int main() {
+   const A x = A();
+   f(x);
+ }
Index: testsuite/g++.dg/ext/attrib13.C
===================================================================
RCS file: testsuite/g++.dg/ext/attrib13.C
diff -N testsuite/g++.dg/ext/attrib13.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/ext/attrib13.C	2 Feb 2004 16:12:01 -0000
***************
*** 0 ****
--- 1,4 ----
+ // PR c++/13854
+ 
+ extern char *rindex (__const char *__s, int __c) throw () __attribute__ ((__pure__));
+ extern char *rindex (__const char *__s, int __c) throw () __attribute__ ((__pure__));
Index: testsuite/g++.old-deja/g++.mike/net36.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.old-deja/g++.mike/net36.C,v
retrieving revision 1.7
diff -c -5 -p -r1.7 net36.C
*** testsuite/g++.old-deja/g++.mike/net36.C	4 Jul 2003 05:05:19 -0000	1.7
--- testsuite/g++.old-deja/g++.mike/net36.C	2 Feb 2004 16:12:02 -0000
*************** public:
*** 9,19 ****
  
  typedef void (A::*handler) (X*);
  
  class B {
  public:
!   void setHandler(handler);
  };
  
  void f(B* b) {
    b->setHandler(A::handlerFn);	// { dg-error "" } 
  }
--- 9,19 ----
  
  typedef void (A::*handler) (X*);
  
  class B {
  public:
!   void setHandler(handler); // { dg-error "candidate" }
  };
  
  void f(B* b) {
    b->setHandler(A::handlerFn);	// { dg-error "" } 
  }


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