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: More 3.4 regressions


Here's another batch of small fixes for GCC 3.4 found by running
various tests.  These include:

- Failure to accept the use of pseudo-destructor names whose type is a
  cv-qualified variant of the object type being destroyed.

- A crash with a namespace-scope anonymous union.

- Mishandled overloaded resolution in the presence of using
  declarations.

- Totally forgetting the names of function parameters in friend
  templates. (!)

- Mishandling the use of "typename" in non-dependent contexts.

- Generating wrong code for certain conditional expressions.

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

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

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

	* semantics.c (finish_pseudo_destructor_expr): Allow differing
	cv-qualification between the type named by the
	pseudo-destructor-name and the object-type.

	* search.c (accessible_base_p): Handle non-proper bases.

	* name-lookup.c (do_nonmember_using_decl): If a using declaration
	refers to a single overloaded function, set the type of the
	function.
	* tree.c (lvalue_type): Simplify.
	* typeck.c (type_unknown_p): Do not assume all OVERLOADs have an
	unknown type.
	(build_unary_op): Handle OVERLOADs with known types.

	* decl.c (duplicate_decls): Do not destroy DECL_ARGUMENTS for
	function templates.

	* parser.c (cp_parser_postfix_expression): Handle the use of
	"typename" in non-dependent contexts.  Convert appropriately when
	when using a qualified name after "->" or ".".

	* call.c (conditional_conversion): Honor the requirement that some
	conversions refer to the original object.

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

	* g++.dg/expr/dtor2.C: New test.

	* g++.dg/lookup/anon4.C: New test.

	* g++.dg/overload/using1.C: New test.

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

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

	* g++.dg/expr/cond6.C: New test.

Index: cp/call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.452.2.14
diff -c -5 -p -r1.452.2.14 call.c
*** cp/call.c	19 Mar 2004 01:18:33 -0000	1.452.2.14
--- cp/call.c	19 Mar 2004 07:10:08 -0000
*************** conditional_conversion (tree e1, tree e2
*** 2899,2924 ****
       to match E2 if the class of T2 is the same type as, or a base
       class of, the class of T1, and the cv-qualification of T2 is the
       same cv-qualification as, or a greater cv-qualification than, the
       cv-qualification of T1.  If the conversion is applied, E1 is
       changed to an rvalue of type T2 that still refers to the original
!      source class object (or the appropriate subobject thereof).
! 
!      FIXME we can't express an rvalue that refers to the original object;
!      we have to create a new one.  */
    if (CLASS_TYPE_P (t1) && CLASS_TYPE_P (t2)
        && ((good_base = DERIVED_FROM_P (t2, t1)) || DERIVED_FROM_P (t1, t2)))
      {
        if (good_base && at_least_as_qualified_p (t2, t1))
  	{
  	  conv = build1 (IDENTITY_CONV, t1, e1);
  	  if (!same_type_p (TYPE_MAIN_VARIANT (t1), 
  			    TYPE_MAIN_VARIANT (t2)))
! 	    {
! 	      conv = build_conv (BASE_CONV, t2, conv);
! 	      NEED_TEMPORARY_P (conv) = 1;
! 	    }
  	  else
  	    conv = build_conv (RVALUE_CONV, t2, conv);
  	  return conv;
  	}
        else
--- 2899,2918 ----
       to match E2 if the class of T2 is the same type as, or a base
       class of, the class of T1, and the cv-qualification of T2 is the
       same cv-qualification as, or a greater cv-qualification than, the
       cv-qualification of T1.  If the conversion is applied, E1 is
       changed to an rvalue of type T2 that still refers to the original
!      source class object (or the appropriate subobject thereof).  */
    if (CLASS_TYPE_P (t1) && CLASS_TYPE_P (t2)
        && ((good_base = DERIVED_FROM_P (t2, t1)) || DERIVED_FROM_P (t1, t2)))
      {
        if (good_base && at_least_as_qualified_p (t2, t1))
  	{
  	  conv = build1 (IDENTITY_CONV, t1, e1);
  	  if (!same_type_p (TYPE_MAIN_VARIANT (t1), 
  			    TYPE_MAIN_VARIANT (t2)))
! 	    conv = build_conv (BASE_CONV, t2, conv);
  	  else
  	    conv = build_conv (RVALUE_CONV, t2, conv);
  	  return conv;
  	}
        else
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1174.2.14
diff -c -5 -p -r1.1174.2.14 decl.c
*** cp/decl.c	11 Mar 2004 08:37:01 -0000	1.1174.2.14
--- cp/decl.c	19 Mar 2004 07:10:09 -0000
*************** duplicate_decls (tree newdecl, tree oldd
*** 1592,1601 ****
--- 1592,1604 ----
  	  && DECL_INITIAL (DECL_TEMPLATE_RESULT (newdecl)) != NULL_TREE)
  	{
  	  DECL_SOURCE_LOCATION (olddecl) 
  	    = DECL_SOURCE_LOCATION (DECL_TEMPLATE_RESULT (olddecl))
  	    = DECL_SOURCE_LOCATION (newdecl);
+ 	  if (DECL_FUNCTION_TEMPLATE_P (newdecl))
+ 	    DECL_ARGUMENTS (DECL_TEMPLATE_RESULT (olddecl))
+ 	      = DECL_ARGUMENTS (DECL_TEMPLATE_RESULT (newdecl));
  	}
  
        if (DECL_FUNCTION_TEMPLATE_P (newdecl))
  	{
  	  DECL_INLINE (DECL_TEMPLATE_RESULT (olddecl)) 
Index: cp/name-lookup.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/name-lookup.c,v
retrieving revision 1.34.2.8
diff -c -5 -p -r1.34.2.8 name-lookup.c
*** cp/name-lookup.c	19 Mar 2004 01:18:33 -0000	1.34.2.8
--- cp/name-lookup.c	19 Mar 2004 07:10:09 -0000
*************** do_nonmember_using_decl (tree scope, tre
*** 2216,2228 ****
  	     this function to the using declarations for this
  	     scope.  */
  	  if (tmp1)
  	    continue;
  	    
  	  *newval = build_overload (OVL_CURRENT (tmp), *newval);
  	  if (TREE_CODE (*newval) != OVERLOAD)
! 	    *newval = ovl_cons (*newval, NULL_TREE);
  	  OVL_USED (*newval) = 1;
  	}
      }
    else 
      {
--- 2216,2240 ----
  	     this function to the using declarations for this
  	     scope.  */
  	  if (tmp1)
  	    continue;
  	    
+ 	  /* If we are adding to an existing OVERLOAD, then we no
+ 	     longer know the type of the set of functions.  */
+ 	  if (*newval && TREE_CODE (*newval) == OVERLOAD)
+ 	    TREE_TYPE (*newval) = unknown_type_node;
+ 	  /* Add this new function to the set.  */
  	  *newval = build_overload (OVL_CURRENT (tmp), *newval);
+ 	  /* If there is only one function, then we use its type.  (A
+ 	     using-declaration naming a single function can be used in
+ 	     contexts where overload resolution cannot be
+ 	     performed.)  */
  	  if (TREE_CODE (*newval) != OVERLOAD)
! 	    {
! 	      *newval = ovl_cons (*newval, NULL_TREE);
! 	      TREE_TYPE (*newval) = TREE_TYPE (OVL_CURRENT (tmp));
! 	    }
  	  OVL_USED (*newval) = 1;
  	}
      }
    else 
      {
Index: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.157.2.23
diff -c -5 -p -r1.157.2.23 parser.c
*** cp/parser.c	19 Mar 2004 01:18:33 -0000	1.157.2.23
--- cp/parser.c	19 Mar 2004 07:10:11 -0000
*************** cp_parser_postfix_expression (cp_parser 
*** 3553,3566 ****
  				    /*check_dependency_p=*/true,
  				    /*is_declaration=*/true);
  	/* If that didn't work, try an identifier.  */
  	if (!cp_parser_parse_definitely (parser))
  	  id = cp_parser_identifier (parser);
  	/* Create a TYPENAME_TYPE to represent the type to which the
  	   functional cast is being performed.  */
! 	type = make_typename_type (parser->scope, id, 
! 				   /*complain=*/1);
  
  	postfix_expression = cp_parser_functional_cast (parser, type);
        }
        break;
  
--- 3553,3572 ----
  				    /*check_dependency_p=*/true,
  				    /*is_declaration=*/true);
  	/* If that didn't work, try an identifier.  */
  	if (!cp_parser_parse_definitely (parser))
  	  id = cp_parser_identifier (parser);
+ 	/* If we look up a template-id in a non-dependent qualifying
+ 	   scope, there's no need to create a dependent type.  */
+ 	if (TREE_CODE (id) == TYPE_DECL
+ 	    && !dependent_type_p (parser->scope))
+ 	  type = TREE_TYPE (id);
  	/* Create a TYPENAME_TYPE to represent the type to which the
  	   functional cast is being performed.  */
! 	else
! 	  type = make_typename_type (parser->scope, id, 
! 				     /*complain=*/1);
  
  	postfix_expression = cp_parser_functional_cast (parser, type);
        }
        break;
  
*************** cp_parser_postfix_expression (cp_parser 
*** 3895,3904 ****
--- 3901,3913 ----
  		    name = build_nt (SCOPE_REF, parser->scope, name);
  		    parser->scope = NULL_TREE;
  		    parser->qualifying_scope = NULL_TREE;
  		    parser->object_scope = NULL_TREE;
  		  }
+ 		if (scope && name && BASELINK_P (name))
+ 		  adjust_result_of_qualified_name_lookup 
+ 		    (name, BINFO_TYPE (BASELINK_BINFO (name)), scope);
  		postfix_expression 
  		  = finish_class_member_access_expr (postfix_expression, name);
  	      }
  	    /* Otherwise, try the pseudo-destructor-name production.  */
  	    else
Index: cp/search.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/search.c,v
retrieving revision 1.284.4.1
diff -c -5 -p -r1.284.4.1 search.c
*** cp/search.c	14 Feb 2004 02:32:47 -0000	1.284.4.1
--- cp/search.c	19 Mar 2004 07:10:12 -0000
*************** lookup_base_r (tree binfo, tree base, ba
*** 230,250 ****
      }
    return found;
  }
  
  /* Returns true if type BASE is accessible in T.  (BASE is known to be
!    a base class of T.)  */
  
  bool
  accessible_base_p (tree t, tree base)
  {
    tree decl;
  
    /* [class.access.base]
  
       A base class is said to be accessible if an invented public
!      member of the base class is accessible.  */
    /* Rather than inventing a public member, we use the implicit
       public typedef created in the scope of every class.  */
    decl = TYPE_FIELDS (base);
    while (!DECL_SELF_REFERENCE_P (decl))
      decl = TREE_CHAIN (decl);
--- 230,255 ----
      }
    return found;
  }
  
  /* Returns true if type BASE is accessible in T.  (BASE is known to be
!    a (possibly non-proper) base class of T.)  */
  
  bool
  accessible_base_p (tree t, tree base)
  {
    tree decl;
  
    /* [class.access.base]
  
       A base class is said to be accessible if an invented public
!      member of the base class is accessible.  
! 
!      If BASE is a non-proper base, this condition is trivially
!      true.  */
!   if (same_type_p (t, base))
!     return true;
    /* Rather than inventing a public member, we use the implicit
       public typedef created in the scope of every class.  */
    decl = TYPE_FIELDS (base);
    while (!DECL_SELF_REFERENCE_P (decl))
      decl = TREE_CHAIN (decl);
Index: cp/semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/semantics.c,v
retrieving revision 1.381.4.9
diff -c -5 -p -r1.381.4.9 semantics.c
*** cp/semantics.c	16 Mar 2004 21:35:14 -0000	1.381.4.9
--- cp/semantics.c	19 Mar 2004 07:10:14 -0000
*************** finish_pseudo_destructor_expr (tree obje
*** 1801,1811 ****
  	{
  	  error ("invalid qualifying scope in pseudo-destructor name");
  	  return error_mark_node;
  	}
        
!       if (!same_type_p (TREE_TYPE (object), destructor))
  	{
  	  error ("`%E' is not of type `%T'", object, destructor);
  	  return error_mark_node;
  	}
      }
--- 1801,1825 ----
  	{
  	  error ("invalid qualifying scope in pseudo-destructor name");
  	  return error_mark_node;
  	}
        
!       /* [expr.pseudo] says both:
! 
!            The type designated by the pseudo-destructor-name shall be
! 	   the same as the object type.
! 
!          and:
! 
!            The cv-unqualified versions of the object type and of the
! 	   type designated by the pseudo-destructor-name shall be the
! 	   same type.
! 
!          We implement the more generous second sentence, since that is
!          what most other compilers do.  */
!       if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (object), 
! 						      destructor))
  	{
  	  error ("`%E' is not of type `%T'", object, destructor);
  	  return error_mark_node;
  	}
      }
Index: cp/tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/tree.c,v
retrieving revision 1.360.4.4
diff -c -5 -p -r1.360.4.4 tree.c
*** cp/tree.c	10 Mar 2004 21:04:14 -0000	1.360.4.4
--- cp/tree.c	19 Mar 2004 07:10:14 -0000
*************** build_zc_wrapper (struct z_candidate* pt
*** 1650,1661 ****
  
  tree
  lvalue_type (tree arg)
  {
    tree type = TREE_TYPE (arg);
-   if (TREE_CODE (arg) == OVERLOAD)
-     type = unknown_type_node;
    return type;
  }
  
  /* The type of ARG for printing error messages; denote lvalues with
     reference types.  */
--- 1650,1659 ----
Index: cp/typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.519.2.11
diff -c -5 -p -r1.519.2.11 typeck.c
*** cp/typeck.c	19 Mar 2004 01:18:34 -0000	1.519.2.11
--- cp/typeck.c	19 Mar 2004 07:10:15 -0000
*************** complete_type_or_diagnostic (tree type, 
*** 161,172 ****
  /* Return truthvalue of whether type of EXP is instantiated.  */
  
  int
  type_unknown_p (tree exp)
  {
!   return (TREE_CODE (exp) == OVERLOAD
!           || TREE_CODE (exp) == TREE_LIST
  	  || TREE_TYPE (exp) == unknown_type_node);
  }
  
  
  /* Return the common type of two parameter lists.
--- 161,171 ----
  /* Return truthvalue of whether type of EXP is instantiated.  */
  
  int
  type_unknown_p (tree exp)
  {
!   return (TREE_CODE (exp) == TREE_LIST
  	  || TREE_TYPE (exp) == unknown_type_node);
  }
  
  
  /* Return the common type of two parameter lists.
*************** build_unary_op (enum tree_code code, tre
*** 4021,4031 ****
  	case FIX_ROUND_EXPR:
  	case FIX_CEIL_EXPR:
  	  if (! lvalue_p (arg) && pedantic)
  	    pedwarn ("ISO C++ forbids taking the address of a cast to a non-lvalue expression");
  	  break;
! 	  
  	default:
  	  break;
  	}
  
        /* Allow the address of a constructor if all the elements
--- 4020,4034 ----
  	case FIX_ROUND_EXPR:
  	case FIX_CEIL_EXPR:
  	  if (! lvalue_p (arg) && pedantic)
  	    pedwarn ("ISO C++ forbids taking the address of a cast to a non-lvalue expression");
  	  break;
! 
! 	case OVERLOAD:
! 	  arg = OVL_CURRENT (arg);
! 	  break;
! 
  	default:
  	  break;
  	}
  
        /* Allow the address of a constructor if all the elements
Index: testsuite/g++.dg/expr/cond6.C
===================================================================
RCS file: testsuite/g++.dg/expr/cond6.C
diff -N testsuite/g++.dg/expr/cond6.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/expr/cond6.C	19 Mar 2004 07:10:19 -0000
***************
*** 0 ****
--- 1,24 ----
+ // { dg-do "run" }
+ 
+ extern "C" void abort ();
+ 
+ struct B {
+   B() {}
+   B(const B& b) { abort (); }
+ };
+ 
+ struct D : public B {
+   D() {}
+   D(const D& d) : B() {}
+ };
+ 
+ D d;
+ B b;
+ 
+ D f() {
+   return d;
+ }
+ 
+ int main () {
+   b = (true ? f() : b);
+ }
Index: testsuite/g++.dg/expr/dtor2.C
===================================================================
RCS file: testsuite/g++.dg/expr/dtor2.C
diff -N testsuite/g++.dg/expr/dtor2.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/expr/dtor2.C	19 Mar 2004 07:10:19 -0000
***************
*** 0 ****
--- 1,6 ----
+ typedef const int I;
+ int i;
+ 
+ void f() {
+   i.I::~I();
+ }
Index: testsuite/g++.dg/lookup/anon4.C
===================================================================
RCS file: testsuite/g++.dg/lookup/anon4.C
diff -N testsuite/g++.dg/lookup/anon4.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/lookup/anon4.C	19 Mar 2004 07:10:19 -0000
***************
*** 0 ****
--- 1,9 ----
+ static union {
+   int i;
+ };
+ 
+ int *ip;
+ 
+ void g() {
+   ip = &i;
+ }
Index: testsuite/g++.dg/overload/using1.C
===================================================================
RCS file: testsuite/g++.dg/overload/using1.C
diff -N testsuite/g++.dg/overload/using1.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/overload/using1.C	19 Mar 2004 07:10:19 -0000
***************
*** 0 ****
--- 1,11 ----
+ void f();
+ 
+ namespace N { 
+   using ::f;
+ }
+ 
+ bool b;
+ 
+ void g() {
+   b = N::f == ::f;
+ }
Index: testsuite/g++.dg/template/lookup7.C
===================================================================
RCS file: testsuite/g++.dg/template/lookup7.C
diff -N testsuite/g++.dg/template/lookup7.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/lookup7.C	19 Mar 2004 07:10:19 -0000
***************
*** 0 ****
--- 1,9 ----
+ class S;
+ 
+ template<class T>
+ int f(T, S);
+ 
+ class S {
+   template<class T>
+   friend int f(T t, S) { t; return 0; }
+ };
Index: testsuite/g++.dg/template/typename6.C
===================================================================
RCS file: testsuite/g++.dg/template/typename6.C
diff -N testsuite/g++.dg/template/typename6.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/typename6.C	19 Mar 2004 07:10:19 -0000
***************
*** 0 ****
--- 1,11 ----
+ struct O {
+   template <typename T>
+   struct I {
+     I (int);
+   };
+ };
+ 
+ template <typename T>
+ void f() {
+   typename ::O::I<int>(3);
+ }


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