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 15786


This patch fixes PR c++/15786, an error-message regression in the new
parser.  On this code:

  struct A {
    void foo(bar *p);
  };

instead of complaining about "bar" being undeclared we blathered on
about variables being declared with "void" type.

Fixed by teaching the parser that parenthesized initializers are not
valid for member declarators.  For non-member declarations we still
get a message about a field with "void" type -- but then we say that
"bar" was undeclared.  And, since "bar * p" could be an expression
involving a multiplication, I don't think that is as bad a situation.

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

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

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

	PR c++/15786
	* parser.c (cp_parser_declarator): Add member_p parameter. 
	(cp_parser_condition): Adjust calls to cp_parser_declarator.
	(cp_parser_explicit_instantiation): Likewise.
	(cp_parser_init_declarator): Likewise.
	(cp_parser_direct_declarator): Add member_p parameter.  Do not
	parse tentatively when parsing the parameters to a member.
	(cp_parser_type_id): Adjust calls to cp_parser_declarator.
	(cp_parser_parameter_declaration): Likewise.
	(cp_parser_member_declaration): Likewise.
	(cp_parser_exception_declaration): Likewise.

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

	PR c++/15876
	* g++.dg/parse/error22.C: New test.

Index: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.262
diff -c -5 -p -r1.262 parser.c
*** cp/parser.c	10 Oct 2004 05:02:53 -0000	1.262
--- cp/parser.c	12 Oct 2004 01:49:55 -0000
*************** static void cp_parser_linkage_specificat
*** 1541,1553 ****
  /* Declarators [gram.dcl.decl] */
  
  static tree cp_parser_init_declarator
    (cp_parser *, cp_decl_specifier_seq *, bool, bool, int, bool *);
  static cp_declarator *cp_parser_declarator
!   (cp_parser *, cp_parser_declarator_kind, int *, bool *);
  static cp_declarator *cp_parser_direct_declarator
!   (cp_parser *, cp_parser_declarator_kind, int *);
  static enum tree_code cp_parser_ptr_operator
    (cp_parser *, tree *, cp_cv_quals *);
  static cp_cv_quals cp_parser_cv_qualifier_seq_opt
    (cp_parser *);
  static tree cp_parser_declarator_id
--- 1541,1553 ----
  /* Declarators [gram.dcl.decl] */
  
  static tree cp_parser_init_declarator
    (cp_parser *, cp_decl_specifier_seq *, bool, bool, int, bool *);
  static cp_declarator *cp_parser_declarator
!   (cp_parser *, cp_parser_declarator_kind, int *, bool *, bool);
  static cp_declarator *cp_parser_direct_declarator
!   (cp_parser *, cp_parser_declarator_kind, int *, bool);
  static enum tree_code cp_parser_ptr_operator
    (cp_parser *, tree *, cp_cv_quals *);
  static cp_cv_quals cp_parser_cv_qualifier_seq_opt
    (cp_parser *);
  static tree cp_parser_declarator_id
*************** cp_parser_condition (cp_parser* parser)
*** 6273,6283 ****
        tree initializer = NULL_TREE;
  
        /* Parse the declarator.  */
        declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
  					 /*ctor_dtor_or_conv_p=*/NULL,
! 					 /*parenthesized_p=*/NULL);
        /* Parse the attributes.  */
        attributes = cp_parser_attributes_opt (parser);
        /* Parse the asm-specification.  */
        asm_specification = cp_parser_asm_specification_opt (parser);
        /* If the next token is not an `=', then we might still be
--- 6273,6284 ----
        tree initializer = NULL_TREE;
  
        /* Parse the declarator.  */
        declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
  					 /*ctor_dtor_or_conv_p=*/NULL,
! 					 /*parenthesized_p=*/NULL,
! 					 /*member_p=*/false);
        /* Parse the attributes.  */
        attributes = cp_parser_attributes_opt (parser);
        /* Parse the asm-specification.  */
        asm_specification = cp_parser_asm_specification_opt (parser);
        /* If the next token is not an `=', then we might still be
*************** cp_parser_explicit_instantiation (cp_par
*** 9070,9080 ****
  
        /* Parse the declarator.  */
        declarator
  	= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
  				/*ctor_dtor_or_conv_p=*/NULL,
! 				/*parenthesized_p=*/NULL);
        cp_parser_check_for_definition_in_return_type (declarator,
  						     declares_class_or_enum);
        if (declarator != cp_error_declarator)
  	{
  	  decl = grokdeclarator (declarator, &decl_specifiers,
--- 9071,9082 ----
  
        /* Parse the declarator.  */
        declarator
  	= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
  				/*ctor_dtor_or_conv_p=*/NULL,
! 				/*parenthesized_p=*/NULL,
! 				/*member_p=*/false);
        cp_parser_check_for_definition_in_return_type (declarator,
  						     declares_class_or_enum);
        if (declarator != cp_error_declarator)
  	{
  	  decl = grokdeclarator (declarator, &decl_specifiers,
*************** cp_parser_init_declarator (cp_parser* pa
*** 10487,10497 ****
  
    /* Parse the declarator.  */
    declarator
      = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
  			    &ctor_dtor_or_conv_p,
! 			    /*parenthesized_p=*/NULL);
    /* Gather up the deferred checks.  */
    stop_deferring_access_checks ();
  
    /* If the DECLARATOR was erroneous, there's no need to go
       further.  */
--- 10489,10500 ----
  
    /* Parse the declarator.  */
    declarator
      = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
  			    &ctor_dtor_or_conv_p,
! 			    /*parenthesized_p=*/NULL,
! 			    /*member_p=*/false);
    /* Gather up the deferred checks.  */
    stop_deferring_access_checks ();
  
    /* If the DECLARATOR was erroneous, there's no need to go
       further.  */
*************** cp_parser_init_declarator (cp_parser* pa
*** 10747,10763 ****
     to handle something like `f()'.  We want to notice that there are
     no decl-specifiers, and therefore realize that this is an
     expression, not a declaration.)
  
     If PARENTHESIZED_P is non-NULL, *PARENTHESIZED_P is set to true iff
!    the declarator is a direct-declarator of the form "(...)".  */
  
  static cp_declarator *
  cp_parser_declarator (cp_parser* parser,
                        cp_parser_declarator_kind dcl_kind,
                        int* ctor_dtor_or_conv_p,
! 		      bool* parenthesized_p)
  {
    cp_token *token;
    cp_declarator *declarator;
    enum tree_code code;
    cp_cv_quals cv_quals;
--- 10750,10769 ----
     to handle something like `f()'.  We want to notice that there are
     no decl-specifiers, and therefore realize that this is an
     expression, not a declaration.)
  
     If PARENTHESIZED_P is non-NULL, *PARENTHESIZED_P is set to true iff
!    the declarator is a direct-declarator of the form "(...)".  
! 
!    MEMBER_P is true iff this declarator is a member-declarator.  */
  
  static cp_declarator *
  cp_parser_declarator (cp_parser* parser,
                        cp_parser_declarator_kind dcl_kind,
                        int* ctor_dtor_or_conv_p,
! 		      bool* parenthesized_p,
! 		      bool member_p)
  {
    cp_token *token;
    cp_declarator *declarator;
    enum tree_code code;
    cp_cv_quals cv_quals;
*************** cp_parser_declarator (cp_parser* parser,
*** 10794,10804 ****
  	cp_parser_parse_tentatively (parser);
  
        /* Parse the dependent declarator.  */
        declarator = cp_parser_declarator (parser, dcl_kind,
  					 /*ctor_dtor_or_conv_p=*/NULL,
! 					 /*parenthesized_p=*/NULL);
  
        /* If we are parsing an abstract-declarator, we must handle the
  	 case where the dependent declarator is absent.  */
        if (dcl_kind != CP_PARSER_DECLARATOR_NAMED
  	  && !cp_parser_parse_definitely (parser))
--- 10800,10811 ----
  	cp_parser_parse_tentatively (parser);
  
        /* Parse the dependent declarator.  */
        declarator = cp_parser_declarator (parser, dcl_kind,
  					 /*ctor_dtor_or_conv_p=*/NULL,
! 					 /*parenthesized_p=*/NULL,
! 					 /*member_p=*/false);
  
        /* If we are parsing an abstract-declarator, we must handle the
  	 case where the dependent declarator is absent.  */
        if (dcl_kind != CP_PARSER_DECLARATOR_NAMED
  	  && !cp_parser_parse_definitely (parser))
*************** cp_parser_declarator (cp_parser* parser,
*** 10819,10829 ****
      {
        if (parenthesized_p)
  	*parenthesized_p = cp_lexer_next_token_is (parser->lexer,
  						   CPP_OPEN_PAREN);
        declarator = cp_parser_direct_declarator (parser, dcl_kind,
! 						ctor_dtor_or_conv_p);
      }
  
    if (attributes && declarator != cp_error_declarator)
      declarator->attributes = attributes;
  
--- 10826,10837 ----
      {
        if (parenthesized_p)
  	*parenthesized_p = cp_lexer_next_token_is (parser->lexer,
  						   CPP_OPEN_PAREN);
        declarator = cp_parser_direct_declarator (parser, dcl_kind,
! 						ctor_dtor_or_conv_p,
! 						member_p);
      }
  
    if (attributes && declarator != cp_error_declarator)
      declarator->attributes = attributes;
  
*************** cp_parser_declarator (cp_parser* parser,
*** 10852,10868 ****
     CP_PARSER_DECLARATOR_ABSTRACT, if we are parsing a
     direct-abstract-declarator.  It is CP_PARSER_DECLARATOR_NAMED, if
     we are parsing a direct-declarator.  It is
     CP_PARSER_DECLARATOR_EITHER, if we can accept either - in the case
     of ambiguity we prefer an abstract declarator, as per
!    [dcl.ambig.res].  CTOR_DTOR_OR_CONV_P is as for
     cp_parser_declarator.  */
  
  static cp_declarator *
  cp_parser_direct_declarator (cp_parser* parser,
                               cp_parser_declarator_kind dcl_kind,
!                              int* ctor_dtor_or_conv_p)
  {
    cp_token *token;
    cp_declarator *declarator = NULL;
    tree scope = NULL_TREE;
    bool saved_default_arg_ok_p = parser->default_arg_ok_p;
--- 10860,10877 ----
     CP_PARSER_DECLARATOR_ABSTRACT, if we are parsing a
     direct-abstract-declarator.  It is CP_PARSER_DECLARATOR_NAMED, if
     we are parsing a direct-declarator.  It is
     CP_PARSER_DECLARATOR_EITHER, if we can accept either - in the case
     of ambiguity we prefer an abstract declarator, as per
!    [dcl.ambig.res].  CTOR_DTOR_OR_CONV_P and MEMBER_P are as for
     cp_parser_declarator.  */
  
  static cp_declarator *
  cp_parser_direct_declarator (cp_parser* parser,
                               cp_parser_declarator_kind dcl_kind,
!                              int* ctor_dtor_or_conv_p,
! 			     bool member_p)
  {
    cp_token *token;
    cp_declarator *declarator = NULL;
    tree scope = NULL_TREE;
    bool saved_default_arg_ok_p = parser->default_arg_ok_p;
*************** cp_parser_direct_declarator (cp_parser* 
*** 10917,10927 ****
  	  if (!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED)
  	    {
  	      cp_parameter_declarator *params;
  	      unsigned saved_num_template_parameter_lists;
  
! 	      cp_parser_parse_tentatively (parser);
  
  	      /* Consume the `('.  */
  	      cp_lexer_consume_token (parser->lexer);
  	      if (first)
  		{
--- 10926,10943 ----
  	  if (!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED)
  	    {
  	      cp_parameter_declarator *params;
  	      unsigned saved_num_template_parameter_lists;
  
! 	      /* In a member-declarator, the only valid interpretation
! 		 of a parenthesis is the start of a
! 		 parameter-declaration-clause.  (It is invalid to
! 		 initialize a static data member with a parenthesized
! 		 initializer; only the "=" form of initialization is
! 		 permitted.)  */
! 	      if (!member_p)
! 		cp_parser_parse_tentatively (parser);
  
  	      /* Consume the `('.  */
  	      cp_lexer_consume_token (parser->lexer);
  	      if (first)
  		{
*************** cp_parser_direct_declarator (cp_parser* 
*** 10943,10953 ****
  	      parser->num_template_parameter_lists
  		= saved_num_template_parameter_lists;
  
  	      /* If all went well, parse the cv-qualifier-seq and the
  	     	 exception-specification.  */
! 	      if (cp_parser_parse_definitely (parser))
  		{
  		  cp_cv_quals cv_quals;
  		  tree exception_specification;
  
  		  if (ctor_dtor_or_conv_p)
--- 10959,10969 ----
  	      parser->num_template_parameter_lists
  		= saved_num_template_parameter_lists;
  
  	      /* If all went well, parse the cv-qualifier-seq and the
  	     	 exception-specification.  */
! 	      if (member_p || cp_parser_parse_definitely (parser))
  		{
  		  cp_cv_quals cv_quals;
  		  tree exception_specification;
  
  		  if (ctor_dtor_or_conv_p)
*************** cp_parser_direct_declarator (cp_parser* 
*** 10991,11001 ****
  	      /* Parse the nested declarator.  */
  	      saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p;
  	      parser->in_type_id_in_expr_p = true;
  	      declarator
  		= cp_parser_declarator (parser, dcl_kind, ctor_dtor_or_conv_p,
! 					/*parenthesized_p=*/NULL);
  	      parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
  	      first = false;
  	      /* Expect a `)'.  */
  	      if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
  		declarator = cp_error_declarator;
--- 11007,11018 ----
  	      /* Parse the nested declarator.  */
  	      saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p;
  	      parser->in_type_id_in_expr_p = true;
  	      declarator
  		= cp_parser_declarator (parser, dcl_kind, ctor_dtor_or_conv_p,
! 					/*parenthesized_p=*/NULL,
! 					member_p);
  	      parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
  	      first = false;
  	      /* Expect a `)'.  */
  	      if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
  		declarator = cp_error_declarator;
*************** cp_parser_type_id (cp_parser* parser)
*** 11418,11428 ****
    /* There might or might not be an abstract declarator.  */
    cp_parser_parse_tentatively (parser);
    /* Look for the declarator.  */
    abstract_declarator
      = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_ABSTRACT, NULL,
! 			    /*parenthesized_p=*/NULL);
    /* Check to see if there really was a declarator.  */
    if (!cp_parser_parse_definitely (parser))
      abstract_declarator = NULL;
  
    return groktypename (&type_specifier_seq, abstract_declarator);
--- 11435,11446 ----
    /* There might or might not be an abstract declarator.  */
    cp_parser_parse_tentatively (parser);
    /* Look for the declarator.  */
    abstract_declarator
      = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_ABSTRACT, NULL,
! 			    /*parenthesized_p=*/NULL,
! 			    /*member_p=*/false);
    /* Check to see if there really was a declarator.  */
    if (!cp_parser_parse_definitely (parser))
      abstract_declarator = NULL;
  
    return groktypename (&type_specifier_seq, abstract_declarator);
*************** cp_parser_parameter_declaration (cp_pars
*** 11772,11782 ****
  	cp_parser_commit_to_tentative_parse (parser);
        /* Parse the declarator.  */
        declarator = cp_parser_declarator (parser,
  					 CP_PARSER_DECLARATOR_EITHER,
  					 /*ctor_dtor_or_conv_p=*/NULL,
! 					 parenthesized_p);
        parser->default_arg_ok_p = saved_default_arg_ok_p;
        /* After the declarator, allow more attributes.  */
        decl_specifiers.attributes
  	= chainon (decl_specifiers.attributes,
  		   cp_parser_attributes_opt (parser));
--- 11790,11801 ----
  	cp_parser_commit_to_tentative_parse (parser);
        /* Parse the declarator.  */
        declarator = cp_parser_declarator (parser,
  					 CP_PARSER_DECLARATOR_EITHER,
  					 /*ctor_dtor_or_conv_p=*/NULL,
! 					 parenthesized_p,
! 					 /*member_p=*/false);
        parser->default_arg_ok_p = saved_default_arg_ok_p;
        /* After the declarator, allow more attributes.  */
        decl_specifiers.attributes
  	= chainon (decl_specifiers.attributes,
  		   cp_parser_attributes_opt (parser));
*************** cp_parser_member_declaration (cp_parser*
*** 13088,13098 ****
  
  	      /* Parse the declarator.  */
  	      declarator
  		= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
  					&ctor_dtor_or_conv_p,
! 					/*parenthesized_p=*/NULL);
  
  	      /* If something went wrong parsing the declarator, make sure
  		 that we at least consume some tokens.  */
  	      if (declarator == cp_error_declarator)
  		{
--- 13107,13118 ----
  
  	      /* Parse the declarator.  */
  	      declarator
  		= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
  					&ctor_dtor_or_conv_p,
! 					/*parenthesized_p=*/NULL,
! 					/*member_p=*/true);
  
  	      /* If something went wrong parsing the declarator, make sure
  		 that we at least consume some tokens.  */
  	      if (declarator == cp_error_declarator)
  		{
*************** cp_parser_exception_declaration (cp_pars
*** 13705,13715 ****
    if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
      declarator = NULL;
    else
      declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_EITHER,
  				       /*ctor_dtor_or_conv_p=*/NULL,
! 				       /*parenthesized_p=*/NULL);
  
    /* Restore the saved message.  */
    parser->type_definition_forbidden_message = saved_message;
  
    if (type_specifiers.any_specifiers_p)
--- 13725,13736 ----
    if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
      declarator = NULL;
    else
      declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_EITHER,
  				       /*ctor_dtor_or_conv_p=*/NULL,
! 				       /*parenthesized_p=*/NULL,
! 				       /*member_p=*/false);
  
    /* Restore the saved message.  */
    parser->type_definition_forbidden_message = saved_message;
  
    if (type_specifiers.any_specifiers_p)
Index: testsuite/g++.dg/parse/error22.C
===================================================================
RCS file: testsuite/g++.dg/parse/error22.C
diff -N testsuite/g++.dg/parse/error22.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/parse/error22.C	12 Oct 2004 01:50:05 -0000
***************
*** 0 ****
--- 1,5 ----
+ // PR c++/15786
+ 
+ struct A {
+   void foo(bar* p); /* { dg-error "declared" } */
+ };


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