C++ PATCH: PR 17867, 17670, 17821, 17826

Mark Mitchell mark@codesourcery.com
Sun Oct 10 06:17:00 GMT 2004


These patches fix four more regressions.  

The only one that is non-obvious is 17821, which is a case where the
new parser gave inferior error messages about "x.y" where "x" was a
scalar type.  A better fix than the one I implemented would probably
be to have cp_parser_id_expression handle pseudo-destructor names as
well (if passed a flag saying that was permissible).  I judged that
too risky to implement at this stage, so I went with the simpler fix
below: if the pseudo-destructor parsing doesn't work out, try the
id-expression.

Tested on i686-pc-linux-gnu.  The 17821 and 17826 fixes were applied
on the mainline and on the 3.4 branch; the other two were applied only
on the mainline.

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

2004-10-09  Mark Mitchell  <mark@codesourcery.com>

	PR c++/17867
	* error.c (dump_expr): Correct handling of AGGR_INIT_EXPRs using a
	constructor.

	PR c++/17670
	* init.c (build_new): Correct comments.
	* parser.c (cp_parser_new_expression): Use NULL_TREE for nelts in
	the non-array case.

	PR c++/17821
	* parser.c (cp_parser_postfix_dot_deref_expression): If the
	pseduo-destructor-name production does not work, fall back to the
	ordinary production.

	PR c++/17826
	* tree.c (cp_tree_equal): Handle a BASELINK.

2004-10-09  Mark Mitchell  <mark@codesourcery.com>

	PR c++/17687
	* g++.dg/parse/error19.C: New test.

	PR c++/17670
	* g++.dg/init/new11.C: New test.

	PR c++/17821
	* g++.dg/parse/error20.C: New test.

	PR c++/17826
	* g++.dg/template/crash24.C: New test.

Index: cp/error.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/error.c,v
retrieving revision 1.266
diff -c -5 -p -r1.266 error.c
*** cp/error.c	8 Oct 2004 19:40:57 -0000	1.266
--- cp/error.c	10 Oct 2004 04:42:30 -0000
*************** dump_expr (tree t, int flags)
*** 1341,1351 ****
  	  fn = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
  
  	if (fn && TREE_CODE (fn) == FUNCTION_DECL)
  	  {
  	    if (DECL_CONSTRUCTOR_P (fn))
! 	      pp_cxx_tree_identifier (cxx_pp, TYPE_IDENTIFIER (TREE_TYPE (t)));
  	    else
  	      dump_decl (fn, 0);
  	  }
  	else
  	  dump_expr (TREE_OPERAND (t, 0), 0);
--- 1341,1351 ----
  	  fn = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
  
  	if (fn && TREE_CODE (fn) == FUNCTION_DECL)
  	  {
  	    if (DECL_CONSTRUCTOR_P (fn))
! 	      dump_type (DECL_CONTEXT (fn), flags);
  	    else
  	      dump_decl (fn, 0);
  	  }
  	else
  	  dump_expr (TREE_OPERAND (t, 0), 0);
Index: cp/init.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/init.c,v
retrieving revision 1.398
diff -c -5 -p -r1.398 init.c
*** cp/init.c	8 Oct 2004 09:33:54 -0000	1.398
--- cp/init.c	10 Oct 2004 04:42:30 -0000
*************** build_builtin_delete_call (tree addr)
*** 1604,1638 ****
  {
    mark_used (global_delete_fndecl);
    return build_call (global_delete_fndecl, build_tree_list (NULL_TREE, addr));
  }
  
! /* Generate a C++ "new" expression. DECL is either a TREE_LIST
!    (which needs to go through some sort of groktypename) or it
!    is the name of the class we are newing. INIT is an initialization value.
!    It is either an EXPRLIST, an EXPR_NO_COMMAS, or something in braces.
!    If INIT is void_type_node, it means do *not* call a constructor
!    for this instance.
! 
!    For types with constructors, the data returned is initialized
!    by the appropriate constructor.
! 
!    Whether the type has a constructor or not, if it has a pointer
!    to a virtual function table, then that pointer is set up
!    here.
! 
!    Unless I am mistaken, a call to new () will return initialized
!    data regardless of whether the constructor itself is private or
!    not.  NOPE; new fails if the constructor is private (jcm).
! 
!    Note that build_new does nothing to assure that any special
!    alignment requirements of the type are met.  Rather, it leaves
!    it up to malloc to do the right thing.  Otherwise, folding to
!    the right alignment cal cause problems if the user tries to later
!    free the memory returned by `new'.
! 
!    PLACEMENT is the `placement' list for user-defined operator new ().  */
  
  tree
  build_new (tree placement, tree type, tree nelts, tree init, 
  	   int use_global_new)
  {
--- 1604,1621 ----
  {
    mark_used (global_delete_fndecl);
    return build_call (global_delete_fndecl, build_tree_list (NULL_TREE, addr));
  }
  
! /* Generate a representation for a C++ "new" expression.  PLACEMENT is
!    a TREE_LIST of placement-new arguments (or NULL_TREE if none).  If
!    NELTS is NULL, TYPE is the type of the storage to be allocated.  If
!    NELTS is not NULL, then this is an array-new allocation; TYPE is
!    the type of the elements in the array and NELTS is the number of
!    elements in the array.  INIT, if non-NULL, is the initializer for
!    the new object.  If USE_GLOBAL_NEW is true, then the user
!    explicitly wrote "::new" rather than just "new".  */
  
  tree
  build_new (tree placement, tree type, tree nelts, tree init, 
  	   int use_global_new)
  {
Index: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.261
diff -c -5 -p -r1.261 parser.c
*** cp/parser.c	7 Oct 2004 13:48:22 -0000	1.261
--- cp/parser.c	10 Oct 2004 04:42:30 -0000
*************** cp_parser_postfix_dot_deref_expression (
*** 4272,4281 ****
--- 4272,4282 ----
  					bool for_offsetof, cp_id_kind *idk)
  {
    tree name;
    bool dependent_p;
    bool template_p;
+   bool pseudo_destructor_p;
    tree scope = NULL_TREE;
  
    /* If this is a `->' operator, dereference the pointer.  */
    if (token_type == CPP_DEREF)
      postfix_expression = build_x_arrow (postfix_expression);
*************** cp_parser_postfix_dot_deref_expression (
*** 4313,4327 ****
  	 messages.  */
        if (scope == error_mark_node)
  	postfix_expression = error_mark_node;
      }
  
!   /* If the SCOPE is not a scalar type, we are looking at an
!      ordinary class member access expression, rather than a
!      pseudo-destructor-name.  */
!   if (!scope || !SCALAR_TYPE_P (scope))
      {
        template_p = cp_parser_optional_template_keyword (parser);
        /* Parse the id-expression.  */
        name = cp_parser_id_expression (parser, template_p,
  				      /*check_dependency_p=*/true,
  				      /*template_p=*/NULL,
--- 4314,4351 ----
  	 messages.  */
        if (scope == error_mark_node)
  	postfix_expression = error_mark_node;
      }
  
!   /* Assume this expression is not a pseudo-destructor access.  */
!   pseudo_destructor_p = false;
! 
!   /* If the SCOPE is a scalar type, then, if this is a valid program,
!      we must be looking at a pseudo-destructor-name.  */
!   if (scope && SCALAR_TYPE_P (scope))
!     {
!       tree s;
!       tree type;
! 
!       cp_parser_parse_tentatively (parser);
!       /* Parse the pseudo-destructor-name.  */
!       s = NULL_TREE;
!       cp_parser_pseudo_destructor_name (parser, &s, &type);
!       if (cp_parser_parse_definitely (parser))
! 	{
! 	  pseudo_destructor_p = true;
! 	  postfix_expression
! 	    = finish_pseudo_destructor_expr (postfix_expression,
! 					     s, TREE_TYPE (type));
! 	}
!     }
! 
!   if (!pseudo_destructor_p)
      {
+       /* If the SCOPE is not a scalar type, we are looking at an
+ 	 ordinary class member access expression, rather than a
+ 	 pseudo-destructor-name.  */
        template_p = cp_parser_optional_template_keyword (parser);
        /* Parse the id-expression.  */
        name = cp_parser_id_expression (parser, template_p,
  				      /*check_dependency_p=*/true,
  				      /*template_p=*/NULL,
*************** cp_parser_postfix_dot_deref_expression (
*** 4352,4374 ****
  	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
-     {
-       tree s = NULL_TREE;
-       tree type;
- 
-       /* Parse the pseudo-destructor-name.  */
-       cp_parser_pseudo_destructor_name (parser, &s, &type);
-       /* Form the call.  */
-       postfix_expression
- 	= finish_pseudo_destructor_expr (postfix_expression,
- 					 s, TREE_TYPE (type));
-     }
  
    /* We no longer need to look up names in the scope of the object on
       the left-hand side of the `.' or `->' operator.  */
    parser->context->object_type = NULL_TREE;
  
--- 4376,4385 ----
*************** cp_parser_new_expression (cp_parser* par
*** 4860,4870 ****
  	{
  	  error ("array bound forbidden after parenthesized type-id");
  	  inform ("try removing the parentheses around the type-id");
  	  cp_parser_direct_new_declarator (parser);
  	}
!       nelts = integer_one_node;
      }
    /* Otherwise, there must be a new-type-id.  */
    else
      type = cp_parser_new_type_id (parser, &nelts);
  
--- 4871,4881 ----
  	{
  	  error ("array bound forbidden after parenthesized type-id");
  	  inform ("try removing the parentheses around the type-id");
  	  cp_parser_direct_new_declarator (parser);
  	}
!       nelts = NULL_TREE;
      }
    /* Otherwise, there must be a new-type-id.  */
    else
      type = cp_parser_new_type_id (parser, &nelts);
  
Index: cp/tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/tree.c,v
retrieving revision 1.413
diff -c -5 -p -r1.413 tree.c
*** cp/tree.c	28 Sep 2004 11:55:45 -0000	1.413
--- cp/tree.c	10 Oct 2004 04:42:38 -0000
*************** cp_tree_equal (tree t1, tree t2)
*** 1498,1507 ****
--- 1498,1513 ----
      case FUNCTION_DECL:
      case TEMPLATE_DECL:
      case IDENTIFIER_NODE:
        return false;
  
+     case BASELINK:
+       return (BASELINK_BINFO (t1) == BASELINK_BINFO (t2)
+ 	      && BASELINK_ACCESS_BINFO (t1) == BASELINK_ACCESS_BINFO (t2)
+ 	      && cp_tree_equal (BASELINK_FUNCTIONS (t1),
+ 				BASELINK_FUNCTIONS (t2)));
+ 
      case TEMPLATE_PARM_INDEX:
        return (TEMPLATE_PARM_IDX (t1) == TEMPLATE_PARM_IDX (t2)
  	      && TEMPLATE_PARM_LEVEL (t1) == TEMPLATE_PARM_LEVEL (t2)
  	      && same_type_p (TREE_TYPE (TEMPLATE_PARM_DECL (t1)),
  			      TREE_TYPE (TEMPLATE_PARM_DECL (t2))));
Index: testsuite/g++.dg/init/new11.C
===================================================================
RCS file: testsuite/g++.dg/init/new11.C
diff -N testsuite/g++.dg/init/new11.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/init/new11.C	10 Oct 2004 04:42:57 -0000
***************
*** 0 ****
--- 1,21 ----
+ // PR c++/17670
+ // { dg-do run }
+ 
+ #include <cstdlib>
+ #include <new>
+ 
+ bool abort_new;
+ void *operator new[](size_t bytes) throw (std::bad_alloc) { 
+   if (abort_new)
+     abort(); 
+   return operator new (bytes);
+ }
+ 
+ 
+ struct X {};  
+ int main () {
+   // Do not abort until main is running in case startup code uses
+   // operator new[].
+   abort_new = true;
+   new (X);
+ }
Index: testsuite/g++.dg/parse/error19.C
===================================================================
RCS file: testsuite/g++.dg/parse/error19.C
diff -N testsuite/g++.dg/parse/error19.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/parse/error19.C	10 Oct 2004 04:42:57 -0000
***************
*** 0 ****
--- 1,13 ----
+ // PR C++/17867
+ 
+ struct A
+ {  // { dg-error "candidate" }
+   A(int);
+ };
+ 
+ const A& foo();
+ 
+ void bar()
+ {
+   foo()=A(0); // { dg-error "A" }
+ }
Index: testsuite/g++.dg/parse/error20.C
===================================================================
RCS file: testsuite/g++.dg/parse/error20.C
diff -N testsuite/g++.dg/parse/error20.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/parse/error20.C	10 Oct 2004 04:42:57 -0000
***************
*** 0 ****
--- 1,17 ----
+ // PR c++/17821
+ 
+ struct A {
+   A(int i) {}
+ };
+ struct B {
+   int i;
+ };
+ struct C {
+   B* p;
+ };
+ int main() {
+   C c;
+   A(c.p.i); // { dg-error "member.*non-class" }
+   return 0;
+ }
+ 
Index: testsuite/g++.dg/template/crash24.C
===================================================================
RCS file: testsuite/g++.dg/template/crash24.C
diff -N testsuite/g++.dg/template/crash24.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/crash24.C	10 Oct 2004 04:52:22 -0000
***************
*** 0 ****
--- 1,14 ----
+ // PR c++/17826
+ 
+ struct A
+ {
+   template<typename> static int foo();
+ };
+ 
+ template<int> struct B {};
+ 
+ template<typename T> void bar()
+ {
+   B<sizeof A::foo<T>()> b1;
+   B<sizeof A::foo<T>()> b2;
+ }



More information about the Gcc-patches mailing list