C++ PATCH: PR 11551, 11919, 10762

Mark Mitchell mark@codesourcery.com
Thu Aug 21 17:47:00 GMT 2003


This patch fixes a few more C++ PRs.

PR 11551 is a regression where the new parser was allowing
typedef-names in the declarator-id for a destructor.

PR 11919 is a bug in overload resolution that has probably been there
forever; we were using pointer equality to determine type equality.

PR 10762 (where we were accepting template-ids in using-declarations)
is another case where we can leverage the new parser; by moving
syntax-checking into the parser, the code gets simpler and more
robust.

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

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

2003-08-21  Mark Mitchell  <mark@codesourcery.com>

	PR c++/11551
	* parser.c (cp_parser_id_expression): Add declarator_p parameter.
	(cp_parser_primary_expression): Adjust call to
	cp_parser_id_expression.
	(cp_parser_unqualified_id): Complain about the use of
	typedef-names in a destructor declarator.
	(cp_parser_postfix_expression): Adjust call to
	cp_parser_id_expression.
	(cp_parser_type_parameter): Likewise.
	(cp_parser_template_argument): Likewise.
	(cp_parser_declarator_id): Likewise.

	PR c++/11919
	* call.c (standard_conversion): Use same_type_p, not pointer
	equality, to compare types.

	PR c++/10762
	* parser.c (cp_parser_using_declaration): Check for invalid uses
	of template-ids here...
	* decl2.c (do_class_using_decl): ... rather than here.

2003-08-21  Mark Mitchell  <mark@codesourcery.com>

	PR c++/11919
	* g++.dg/overload/prom1.C: New test.

	PR c++/11551
	* g++.dg/parse/dtor2.C: New test.

	PR c++/10762
	* g++.dg/parse/using2.C: New test.

Index: cp/call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.421
diff -c -5 -p -r1.421 call.c
*** cp/call.c	12 Aug 2003 22:26:20 -0000	1.421
--- cp/call.c	21 Aug 2003 17:40:10 -0000
*************** standard_conversion (tree to, tree from,
*** 793,803 ****
        if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE))
  	return 0;
        conv = build_conv (STD_CONV, to, conv);
  
        /* Give this a better rank if it's a promotion.  */
!       if (to == type_promotes_to (from)
  	  && ICS_STD_RANK (TREE_OPERAND (conv, 0)) <= PROMO_RANK)
  	ICS_STD_RANK (conv) = PROMO_RANK;
      }
    else if (fcode == VECTOR_TYPE && tcode == VECTOR_TYPE
        && ((*targetm.vector_opaque_p) (from)
--- 793,803 ----
        if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE))
  	return 0;
        conv = build_conv (STD_CONV, to, conv);
  
        /* Give this a better rank if it's a promotion.  */
!       if (same_type_p (to, type_promotes_to (from))
  	  && ICS_STD_RANK (TREE_OPERAND (conv, 0)) <= PROMO_RANK)
  	ICS_STD_RANK (conv) = PROMO_RANK;
      }
    else if (fcode == VECTOR_TYPE && tcode == VECTOR_TYPE
        && ((*targetm.vector_opaque_p) (from)
Index: cp/decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.662
diff -c -5 -p -r1.662 decl2.c
*** cp/decl2.c	20 Aug 2003 07:06:41 -0000	1.662
--- cp/decl2.c	21 Aug 2003 17:40:12 -0000
*************** do_class_using_decl (tree decl)
*** 4089,4119 ****
    if (TREE_CODE (name) == BIT_NOT_EXPR)
      {
        error ("using-declaration cannot name destructor");
        return NULL_TREE;
      }
-   else if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
-     {
-     template_id_error:;
-       
-       error ("a using-declaration cannot specify a template-id");
-       return NULL_TREE;
-     }
    if (TREE_CODE (name) == TYPE_DECL)
!     {
!       if (CLASSTYPE_USE_TEMPLATE (TREE_TYPE (name)))
! 	goto template_id_error;
!       name = DECL_NAME (name);
!     }
    else if (TREE_CODE (name) == TEMPLATE_DECL)
       name = DECL_NAME (name);
    else if (BASELINK_P (name))
      {
        tree fns = BASELINK_FUNCTIONS (name);
-       
-       if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
- 	goto template_id_error;
        name = DECL_NAME (get_first_fn (fns));
      }
  
    my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 980716);
  
--- 4089,4105 ----
    if (TREE_CODE (name) == BIT_NOT_EXPR)
      {
        error ("using-declaration cannot name destructor");
        return NULL_TREE;
      }
    if (TREE_CODE (name) == TYPE_DECL)
!     name = DECL_NAME (name);
    else if (TREE_CODE (name) == TEMPLATE_DECL)
       name = DECL_NAME (name);
    else if (BASELINK_P (name))
      {
        tree fns = BASELINK_FUNCTIONS (name);
        name = DECL_NAME (get_first_fn (fns));
      }
  
    my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 980716);
  
Index: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.102
diff -c -5 -p -r1.102 parser.c
*** cp/parser.c	20 Aug 2003 07:06:42 -0000	1.102
--- cp/parser.c	21 Aug 2003 17:40:17 -0000
*************** static bool cp_parser_translation_unit
*** 1294,1306 ****
  /* Expressions [gram.expr]  */
  
  static tree cp_parser_primary_expression
    (cp_parser *, cp_id_kind *, tree *);
  static tree cp_parser_id_expression
!   (cp_parser *, bool, bool, bool *);
  static tree cp_parser_unqualified_id
!   (cp_parser *, bool, bool);
  static tree cp_parser_nested_name_specifier_opt
    (cp_parser *, bool, bool, bool);
  static tree cp_parser_nested_name_specifier
    (cp_parser *, bool, bool, bool);
  static tree cp_parser_class_or_namespace_name
--- 1294,1306 ----
  /* Expressions [gram.expr]  */
  
  static tree cp_parser_primary_expression
    (cp_parser *, cp_id_kind *, tree *);
  static tree cp_parser_id_expression
!   (cp_parser *, bool, bool, bool *, bool);
  static tree cp_parser_unqualified_id
!   (cp_parser *, bool, bool, bool);
  static tree cp_parser_nested_name_specifier_opt
    (cp_parser *, bool, bool, bool);
  static tree cp_parser_nested_name_specifier
    (cp_parser *, bool, bool, bool);
  static tree cp_parser_class_or_namespace_name
*************** cp_parser_primary_expression (cp_parser 
*** 2396,2406 ****
  	/* Parse the id-expression.  */
  	id_expression 
  	  = cp_parser_id_expression (parser, 
  				     /*template_keyword_p=*/false,
  				     /*check_dependency_p=*/true,
! 				     /*template_p=*/NULL);
  	if (id_expression == error_mark_node)
  	  return error_mark_node;
  	/* If we have a template-id, then no further lookup is
  	   required.  If the template-id was for a template-class, we
  	   will sometimes have a TYPE_DECL at this point.  */
--- 2396,2407 ----
  	/* Parse the id-expression.  */
  	id_expression 
  	  = cp_parser_id_expression (parser, 
  				     /*template_keyword_p=*/false,
  				     /*check_dependency_p=*/true,
! 				     /*template_p=*/NULL,
! 				     /*declarator_p=*/false);
  	if (id_expression == error_mark_node)
  	  return error_mark_node;
  	/* If we have a template-id, then no further lookup is
  	   required.  If the template-id was for a template-class, we
  	   will sometimes have a TYPE_DECL at this point.  */
*************** cp_parser_primary_expression (cp_parser 
*** 2493,2509 ****
     If CHECK_DEPENDENCY_P is false, then names are looked up inside
     uninstantiated templates.  
  
     If *TEMPLATE_P is non-NULL, it is set to true iff the
     `template' keyword is used to explicitly indicate that the entity
!    named is a template.  */
  
  static tree
  cp_parser_id_expression (cp_parser *parser,
  			 bool template_keyword_p,
  			 bool check_dependency_p,
! 			 bool *template_p)
  {
    bool global_scope_p;
    bool nested_name_specifier_p;
  
    /* Assume the `template' keyword was not used.  */
--- 2494,2514 ----
     If CHECK_DEPENDENCY_P is false, then names are looked up inside
     uninstantiated templates.  
  
     If *TEMPLATE_P is non-NULL, it is set to true iff the
     `template' keyword is used to explicitly indicate that the entity
!    named is a template.  
! 
!    If DECLARATOR_P is true, the id-expression is appearing as part of
!    a declarator, rather than as part of an exprsesion.  */
  
  static tree
  cp_parser_id_expression (cp_parser *parser,
  			 bool template_keyword_p,
  			 bool check_dependency_p,
! 			 bool *template_p,
! 			 bool declarator_p)
  {
    bool global_scope_p;
    bool nested_name_specifier_p;
  
    /* Assume the `template' keyword was not used.  */
*************** cp_parser_id_expression (cp_parser *pars
*** 2540,2550 ****
        saved_scope = parser->scope;
        saved_object_scope = parser->object_scope;
        saved_qualifying_scope = parser->qualifying_scope;
        /* Process the final unqualified-id.  */
        unqualified_id = cp_parser_unqualified_id (parser, *template_p,
! 						 check_dependency_p);
        /* Restore the SAVED_SCOPE for our caller.  */
        parser->scope = saved_scope;
        parser->object_scope = saved_object_scope;
        parser->qualifying_scope = saved_qualifying_scope;
  
--- 2545,2556 ----
        saved_scope = parser->scope;
        saved_object_scope = parser->object_scope;
        saved_qualifying_scope = parser->qualifying_scope;
        /* Process the final unqualified-id.  */
        unqualified_id = cp_parser_unqualified_id (parser, *template_p,
! 						 check_dependency_p,
! 						 declarator_p);
        /* Restore the SAVED_SCOPE for our caller.  */
        parser->scope = saved_scope;
        parser->object_scope = saved_object_scope;
        parser->qualifying_scope = saved_qualifying_scope;
  
*************** cp_parser_id_expression (cp_parser *pars
*** 2595,2605 ****
  	  return error_mark_node;
  	}
      }
    else
      return cp_parser_unqualified_id (parser, template_keyword_p,
! 				     /*check_dependency_p=*/true);
  }
  
  /* Parse an unqualified-id.
  
     unqualified-id:
--- 2601,2612 ----
  	  return error_mark_node;
  	}
      }
    else
      return cp_parser_unqualified_id (parser, template_keyword_p,
! 				     /*check_dependency_p=*/true,
! 				     declarator_p);
  }
  
  /* Parse an unqualified-id.
  
     unqualified-id:
*************** cp_parser_id_expression (cp_parser *pars
*** 2616,2631 ****
     production, an IDENTIFIER_NODE is returned.  For the `~ class-name'
     production a BIT_NOT_EXPR is returned; the operand of the
     BIT_NOT_EXPR is an IDENTIFIER_NODE for the class-name.  For the
     other productions, see the documentation accompanying the
     corresponding parsing functions.  If CHECK_DEPENDENCY_P is false,
!    names are looked up in uninstantiated templates.  */
  
  static tree
  cp_parser_unqualified_id (cp_parser* parser, 
                            bool template_keyword_p,
! 			  bool check_dependency_p)
  {
    cp_token *token;
  
    /* Peek at the next token.  */
    token = cp_lexer_peek_token (parser->lexer);
--- 2623,2641 ----
     production, an IDENTIFIER_NODE is returned.  For the `~ class-name'
     production a BIT_NOT_EXPR is returned; the operand of the
     BIT_NOT_EXPR is an IDENTIFIER_NODE for the class-name.  For the
     other productions, see the documentation accompanying the
     corresponding parsing functions.  If CHECK_DEPENDENCY_P is false,
!    names are looked up in uninstantiated templates.  If DECLARATOR_P
!    is true, the unqualified-id is appearing as part of a declarator,
!    rather than as part of an expression.  */
  
  static tree
  cp_parser_unqualified_id (cp_parser* parser, 
                            bool template_keyword_p,
! 			  bool check_dependency_p,
! 			  bool declarator_p)
  {
    cp_token *token;
  
    /* Peek at the next token.  */
    token = cp_lexer_peek_token (parser->lexer);
*************** cp_parser_unqualified_id (cp_parser* par
*** 2779,2788 ****
--- 2789,2808 ----
  	if (type_decl == error_mark_node && scope && TYPE_P (scope))
  	  return build_nt (BIT_NOT_EXPR, scope);
  	else if (type_decl == error_mark_node)
  	  return error_mark_node;
  
+ 	/* [class.dtor]
+ 
+ 	   A typedef-name that names a class shall not be used as the
+ 	   identifier in the declarator for a destructor declaration.  */
+ 	if (declarator_p 
+ 	    && !DECL_IMPLICIT_TYPEDEF_P (type_decl)
+ 	    && !DECL_SELF_REFERENCE_P (type_decl))
+ 	  error ("typedef-name `%D' used as destructor declarator",
+ 		 type_decl);
+ 
  	return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
        }
  
      case CPP_KEYWORD:
        if (token->keyword == RID_OPERATOR)
*************** cp_parser_postfix_expression (cp_parser 
*** 3623,3633 ****
  		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);
  		/* In general, build a SCOPE_REF if the member name is
  		   qualified.  However, if the name was not dependent
  		   and has already been resolved; there is no need to
  		   build the SCOPE_REF.  For example;
  
--- 3643,3654 ----
  		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,
! 						/*declarator_p=*/false);
  		/* In general, build a SCOPE_REF if the member name is
  		   qualified.  However, if the name was not dependent
  		   and has already been resolved; there is no need to
  		   build the SCOPE_REF.  For example;
  
*************** cp_parser_type_parameter (cp_parser* par
*** 7384,7394 ****
  	    /* Parse the id-expression.  */
  	    default_argument 
  	      = cp_parser_id_expression (parser,
  					 /*template_keyword_p=*/false,
  					 /*check_dependency_p=*/true,
! 					 /*template_p=*/NULL);
  	    /* Look up the name.  */
  	    default_argument 
  	      = cp_parser_lookup_name_simple (parser, default_argument);
  	    /* See if the default argument is valid.  */
  	    default_argument
--- 7405,7416 ----
  	    /* Parse the id-expression.  */
  	    default_argument 
  	      = cp_parser_id_expression (parser,
  					 /*template_keyword_p=*/false,
  					 /*check_dependency_p=*/true,
! 					 /*template_p=*/NULL,
! 					 /*declarator_p=*/false);
  	    /* Look up the name.  */
  	    default_argument 
  	      = cp_parser_lookup_name_simple (parser, default_argument);
  	    /* See if the default argument is valid.  */
  	    default_argument
*************** cp_parser_template_argument (cp_parser* 
*** 7803,7813 ****
    cp_parser_parse_tentatively (parser);
    /* Try a template.  */
    argument = cp_parser_id_expression (parser, 
  				      /*template_keyword_p=*/false,
  				      /*check_dependency_p=*/true,
! 				      &template_p);
    /* If the next token isn't a `,' or a `>', then this argument wasn't
       really finished.  */
    if (!cp_parser_next_token_ends_template_argument_p (parser))
      cp_parser_error (parser, "expected template-argument");
    if (!cp_parser_error_occurred (parser))
--- 7825,7836 ----
    cp_parser_parse_tentatively (parser);
    /* Try a template.  */
    argument = cp_parser_id_expression (parser, 
  				      /*template_keyword_p=*/false,
  				      /*check_dependency_p=*/true,
! 				      &template_p,
! 				      /*declarator_p=*/false);
    /* If the next token isn't a `,' or a `>', then this argument wasn't
       really finished.  */
    if (!cp_parser_next_token_ends_template_argument_p (parser))
      cp_parser_error (parser, "expected template-argument");
    if (!cp_parser_error_occurred (parser))
*************** cp_parser_using_declaration (cp_parser* 
*** 8990,9028 ****
  					 /*type_p=*/false);
  
    /* Parse the unqualified-id.  */
    identifier = cp_parser_unqualified_id (parser, 
  					 /*template_keyword_p=*/false,
! 					 /*check_dependency_p=*/true);
  
    /* The function we call to handle a using-declaration is different
       depending on what scope we are in.  */
!   scope = current_scope ();
!   if (scope && TYPE_P (scope))
!     {
!       /* Create the USING_DECL.  */
!       decl = do_class_using_decl (build_nt (SCOPE_REF,
! 					    parser->scope,
! 					    identifier));
!       /* Add it to the list of members in this class.  */
!       finish_member_declaration (decl);
!     }
    else
      {
!       decl = cp_parser_lookup_name_simple (parser, identifier);
!       if (decl == error_mark_node)
  	{
! 	  if (parser->scope && parser->scope != global_namespace)
! 	    error ("`%D::%D' has not been declared", 
! 		   parser->scope, identifier);
! 	  else
! 	    error ("`::%D' has not been declared", identifier);
  	}
-       else if (scope)
- 	do_local_using_decl (decl);
        else
! 	do_toplevel_using_decl (decl);
      }
  
    /* Look for the final `;'.  */
    cp_parser_require (parser, CPP_SEMICOLON, "`;'");
  }
--- 9013,9063 ----
  					 /*type_p=*/false);
  
    /* Parse the unqualified-id.  */
    identifier = cp_parser_unqualified_id (parser, 
  					 /*template_keyword_p=*/false,
! 					 /*check_dependency_p=*/true,
! 					 /*declarator_p=*/true);
  
    /* The function we call to handle a using-declaration is different
       depending on what scope we are in.  */
!   if (identifier == error_mark_node)
!     ;
!   else if (TREE_CODE (identifier) != IDENTIFIER_NODE
! 	   && TREE_CODE (identifier) != BIT_NOT_EXPR)
!     /* [namespace.udecl]
! 
!        A using declaration shall not name a template-id.  */
!     error ("a template-id may not appear in a using-declaration");
    else
      {
!       scope = current_scope ();
!       if (scope && TYPE_P (scope))
  	{
! 	  /* Create the USING_DECL.  */
! 	  decl = do_class_using_decl (build_nt (SCOPE_REF,
! 						parser->scope,
! 						identifier));
! 	  /* Add it to the list of members in this class.  */
! 	  finish_member_declaration (decl);
  	}
        else
! 	{
! 	  decl = cp_parser_lookup_name_simple (parser, identifier);
! 	  if (decl == error_mark_node)
! 	    {
! 	      if (parser->scope && parser->scope != global_namespace)
! 		error ("`%D::%D' has not been declared", 
! 		       parser->scope, identifier);
! 	      else
! 		error ("`::%D' has not been declared", identifier);
! 	    }
! 	  else if (scope)
! 	    do_local_using_decl (decl);
! 	  else
! 	    do_toplevel_using_decl (decl);
! 	}
      }
  
    /* Look for the final `;'.  */
    cp_parser_require (parser, CPP_SEMICOLON, "`;'");
  }
*************** cp_parser_declarator_id (cp_parser* pars
*** 10117,10127 ****
  
       will work, too.  */
    id_expression = cp_parser_id_expression (parser,
  					   /*template_keyword_p=*/false,
  					   /*check_dependency_p=*/false,
! 					   /*template_p=*/NULL);
    /* If the name was qualified, create a SCOPE_REF to represent 
       that.  */
    if (parser->scope)
      {
        id_expression = build_nt (SCOPE_REF, parser->scope, id_expression);
--- 10152,10163 ----
  
       will work, too.  */
    id_expression = cp_parser_id_expression (parser,
  					   /*template_keyword_p=*/false,
  					   /*check_dependency_p=*/false,
! 					   /*template_p=*/NULL,
! 					   /*declarator_p=*/true);
    /* If the name was qualified, create a SCOPE_REF to represent 
       that.  */
    if (parser->scope)
      {
        id_expression = build_nt (SCOPE_REF, parser->scope, id_expression);
Index: testsuite/g++.dg/overload/prom1.C
===================================================================
RCS file: testsuite/g++.dg/overload/prom1.C
diff -N testsuite/g++.dg/overload/prom1.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/overload/prom1.C	21 Aug 2003 17:40:24 -0000
***************
*** 0 ****
--- 1,9 ----
+ void foo(signed char) {}
+ typedef int bar;
+ void foo(bar) {}
+ 
+ int main (int, char **) {
+   char c;
+   foo(c);
+   return 0;
+ }
Index: testsuite/g++.dg/parse/dtor2.C
===================================================================
RCS file: testsuite/g++.dg/parse/dtor2.C
diff -N testsuite/g++.dg/parse/dtor2.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/parse/dtor2.C	21 Aug 2003 17:40:24 -0000
***************
*** 0 ****
--- 1,4 ----
+ struct A {
+   typedef A A2;
+   ~A2(); // { dg-error "" }
+ };
Index: testsuite/g++.dg/parse/using2.C
===================================================================
RCS file: testsuite/g++.dg/parse/using2.C
diff -N testsuite/g++.dg/parse/using2.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/parse/using2.C	21 Aug 2003 17:40:24 -0000
***************
*** 0 ****
--- 1,8 ----
+ namespace N {
+   template <typename T>
+   struct foo {};
+ }
+ 
+ int main() {
+   using N::foo<double>; // { dg-error "" }
+ }



More information about the Gcc-patches mailing list