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 c++/13536


Some of my recent patches to improve parser diagnostics by committing
earlier to tentative parses were incorrect.

This patch avoids committing early in situations where that is not
correct.

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

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

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

	PR c++/13536
	* parser.c (cp_parser): Add in_type_id_in_expr_p.
	(cp_parser_new): Initialize it.
	(cp_parser_postfix_expression): Set it.
	(cp_parser_sizeof_operand): Likewise.
	(cp_parser_parameteR_declaration): Do not commit early to tenative
	parsers when in_type_id_in_expr_p is set.

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

	PR c++/13536
	* g++.dg/parse/cast1.C: New test.

Index: gcc/cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.143
diff -c -5 -p -r1.143 parser.c
*** gcc/cp/parser.c	3 Jan 2004 08:25:38 -0000	1.143
--- gcc/cp/parser.c	4 Jan 2004 22:27:57 -0000
*************** typedef struct cp_parser GTY(())
*** 1255,1264 ****
--- 1255,1269 ----
  
    /* TRUE if we are presently parsing the body of a switch
       statement.  */
    bool in_switch_statement_p;
  
+   /* TRUE if we are parsing a type-id in an expression context.  In
+      such a situation, both "type (expr)" and "type (type)" are valid
+      alternatives.  */
+   bool in_type_id_in_expr_p;
+ 
    /* If non-NULL, then we are parsing a construct where new type
       definitions are not permitted.  The string stored here will be
       issued as an error message if a type is defined.  */
    const char *type_definition_forbidden_message;
  
*************** cp_parser_new (void)
*** 2252,2261 ****
--- 2257,2269 ----
    parser->in_iteration_statement_p = false;
  
    /* We are not in a switch statement.  */
    parser->in_switch_statement_p = false;
  
+   /* We are not parsing a type-id inside an expression.  */
+   parser->in_type_id_in_expr_p = false;
+ 
    /* The unparsed function queue is empty.  */
    parser->unparsed_functions_queues = build_tree_list (NULL_TREE, NULL_TREE);
  
    /* There are no classes being defined.  */
    parser->num_classes_being_defined = 0;
*************** cp_parser_postfix_expression (cp_parser 
*** 3466,3475 ****
--- 3474,3484 ----
  
      case RID_TYPEID:
        {
  	tree type;
  	const char *saved_message;
+ 	bool saved_in_type_id_in_expr_p;
  
  	/* Consume the `typeid' token.  */
  	cp_lexer_consume_token (parser->lexer);
  	/* Look for the `(' token.  */
  	cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
*************** cp_parser_postfix_expression (cp_parser 
*** 3479,3489 ****
--- 3488,3501 ----
  	  = "types may not be defined in a `typeid\' expression";
  	/* We can't be sure yet whether we're looking at a type-id or an
  	   expression.  */
  	cp_parser_parse_tentatively (parser);
  	/* Try a type-id first.  */
+ 	saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p;
+ 	parser->in_type_id_in_expr_p = true;
  	type = cp_parser_type_id (parser);
+ 	parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
  	/* Look for the `)' token.  Otherwise, we can't be sure that
  	   we're not looking at an expression: consider `typeid (int
  	   (3))', for example.  */
  	cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
  	/* If all went well, simply lookup the type-id.  */
*************** cp_parser_postfix_expression (cp_parser 
*** 3570,3585 ****
--- 3582,3601 ----
  	   compound-literal.  */
  	if (cp_parser_allow_gnu_extensions_p (parser)
  	    && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
  	  {
  	    tree initializer_list = NULL_TREE;
+ 	    bool saved_in_type_id_in_expr_p;
  
  	    cp_parser_parse_tentatively (parser);
  	    /* Consume the `('.  */
  	    cp_lexer_consume_token (parser->lexer);
  	    /* Parse the type.  */
+ 	    saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p;
+ 	    parser->in_type_id_in_expr_p = true;
  	    type = cp_parser_type_id (parser);
+ 	    parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
  	    /* Look for the `)'.  */
  	    cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
  	    /* Look for the `{'.  */
  	    cp_parser_require (parser, CPP_OPEN_BRACE, "`{'");
  	    /* If things aren't going well, there's no need to
*************** cp_parser_cast_expression (cp_parser *pa
*** 4711,4724 ****
--- 4727,4743 ----
  	 fail.  */
        if (compound_literal_p)
  	cp_parser_simulate_error (parser);
        else
  	{
+ 	  bool saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p;
+ 	  parser->in_type_id_in_expr_p = true;
  	  /* Look for the type-id.  */
  	  type = cp_parser_type_id (parser);
  	  /* Look for the closing `)'.  */
  	  cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ 	  parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
  	}
  
        /* Restore the saved message.  */
        parser->type_definition_forbidden_message = saved_message;
  
*************** cp_parser_parameter_declaration (cp_pars
*** 10953,10965 ****
        bool saved_default_arg_ok_p = parser->default_arg_ok_p;
        parser->default_arg_ok_p = false;
    
        /* After seeing a decl-specifier-seq, if the next token is not a
  	 "(", there is no possibility that the code is a valid
! 	 expression initializer.  Therefore, if parsing tentatively,
! 	 we commit at this point.  */
        if (!parser->in_template_argument_list_p
  	  && cp_parser_parsing_tentatively (parser)
  	  && !cp_parser_committed_to_tentative_parse (parser)
  	  && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN))
  	cp_parser_commit_to_tentative_parse (parser);
        /* Parse the declarator.  */
--- 10972,10991 ----
        bool saved_default_arg_ok_p = parser->default_arg_ok_p;
        parser->default_arg_ok_p = false;
    
        /* After seeing a decl-specifier-seq, if the next token is not a
  	 "(", there is no possibility that the code is a valid
! 	 expression.  Therefore, if parsing tentatively, we commit at
! 	 this point.  */
        if (!parser->in_template_argument_list_p
+ 	  /* Having seen:
+ 
+ 	       (int((char *)...
+ 
+ 	     we cannot be sure whether we are looking at a
+ 	     function-type (taking a */
+ 	  && !parser->in_type_id_in_expr_p
  	  && cp_parser_parsing_tentatively (parser)
  	  && !cp_parser_committed_to_tentative_parse (parser)
  	  && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN))
  	cp_parser_commit_to_tentative_parse (parser);
        /* Parse the declarator.  */
*************** cp_parser_sizeof_operand (cp_parser* par
*** 14471,14488 ****
--- 14497,14518 ----
    /* If it's a `(', then we might be looking at the type-id
       construction.  */
    if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
      {
        tree type;
+       bool saved_in_type_id_in_expr_p;
  
        /* We can't be sure yet whether we're looking at a type-id or an
  	 expression.  */
        cp_parser_parse_tentatively (parser);
        /* Consume the `('.  */
        cp_lexer_consume_token (parser->lexer);
        /* Parse the type-id.  */
+       saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p;
+       parser->in_type_id_in_expr_p = true;
        type = cp_parser_type_id (parser);
+       parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
        /* Now, look for the trailing `)'.  */
        cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
        /* If all went well, then we're done.  */
        if (cp_parser_parse_definitely (parser))
  	{
Index: gcc/testsuite//g++.dg/parse/cast1.C
===================================================================
RCS file: gcc/testsuite//g++.dg/parse/cast1.C
diff -N gcc/testsuite//g++.dg/parse/cast1.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- gcc/testsuite//g++.dg/parse/cast1.C	4 Jan 2004 22:27:57 -0000
***************
*** 0 ****
--- 1,10 ----
+ // PR c++/13536
+ // { dg-options "-w" }
+ 
+ #include <typeinfo>
+ 
+ void f() {
+   (int((char*)0));
+   sizeof ((int((char*)0)));
+   typeid ((int((char*)0)));
+ }


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