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: Fix dce1.C


This test case:

  void foo(void)
  {
    if (0)
      break;		/* { dg-error "" } */
    if (1)
      ;
    else
      continue;		/* { dg-error "" } */
  }

was not generating error messages because the AST->RTL converters
never saw the invalid break/continue statements.

Of course, the fact that the AST->RTL converters are responsible for
generating error messages on this code is a design bug.  (They should
never generate errors, period, but that's one of my well-known rants.)
These errors should be issued early, when the statements are first
seen.  Furthermore, we should try to avoid creating invalid tree
structure; that just gives us opportunities to crash later.

So, I put the checks into the parser where they belong.
(Unfortunately, I could not eliminate them from the AST->RTL
converters without changing the C parser, which I did not want to do.)

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

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

2003-11-12  Mark Mitchell  <mark@codesourcery.com>

	* decl.c (finish_case_label): Do not check that we are within a
	switch statement here.
	* parser.c (struct cp_parser): Add in_iteration_statement_p and
	in_switch_statement_p.
	(cp_parser_new): Initialize them.
	(cp_parser_labeled_statement): Check validity of case labels
	here.
	(cp_parser_selection_statement): Set in_switch_statement_p.
	(cp_parser_iteration_statement): Set in_iteration_statement_p.
	(cp_parser_jump_statement): Check validity of break/continue
	statements here.

Index: decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1152
diff -c -5 -p -r1.1152 decl.c
*** decl.c	12 Nov 2003 18:15:01 -0000	1.1152
--- decl.c	12 Nov 2003 19:55:26 -0000
*************** tree
*** 2431,2452 ****
  finish_case_label (tree low_value, tree high_value)
  {
    tree cond, r;
    register struct cp_binding_level *p;
  
-   if (! switch_stack)
-     {
-       if (high_value)
- 	error ("case label not within a switch statement");
-       else if (low_value)
- 	error ("case label `%E' not within a switch statement",
- 		  low_value);
-       else
- 	error ("`default' label not within a switch statement");
-       return NULL_TREE;
-     }
- 
    if (processing_template_decl)
      {
        tree label;
  
        /* For templates, just add the case label; we'll do semantic
--- 2431,2440 ----
Index: parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.119
diff -c -5 -p -r1.119 parser.c
*** parser.c	11 Nov 2003 22:27:31 -0000	1.119
--- parser.c	12 Nov 2003 19:55:27 -0000
*************** typedef struct cp_parser GTY(())
*** 1228,1237 ****
--- 1228,1245 ----
  
    /* TRUE if we are presently parsing a declarator, after the
       direct-declarator.  */
    bool in_declarator_p;
  
+   /* TRUE if we are presently parsing the body of an
+      iteration-statement.  */
+   bool in_iteration_statement_p;
+ 
+   /* TRUE if we are presently parsing the body of a switch
+      statement.  */
+   bool in_switch_statement_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)
*** 2116,2125 ****
--- 2124,2139 ----
    parser->in_unbraced_linkage_specification_p = false;
  
    /* We are not processing a declarator.  */
    parser->in_declarator_p = false;
  
+   /* We are not in an iteration statement.  */
+   parser->in_iteration_statement_p = false;
+ 
+   /* We are not in a switch statement.  */
+   parser->in_switch_statement_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_statement (cp_parser* parser, 
*** 5226,5236 ****
  
  static tree
  cp_parser_labeled_statement (cp_parser* parser, bool in_statement_expr_p)
  {
    cp_token *token;
!   tree statement = NULL_TREE;
  
    /* The next token should be an identifier.  */
    token = cp_lexer_peek_token (parser->lexer);
    if (token->type != CPP_NAME
        && token->type != CPP_KEYWORD)
--- 5240,5250 ----
  
  static tree
  cp_parser_labeled_statement (cp_parser* parser, bool in_statement_expr_p)
  {
    cp_token *token;
!   tree statement = error_mark_node;
  
    /* The next token should be an identifier.  */
    token = cp_lexer_peek_token (parser->lexer);
    if (token->type != CPP_NAME
        && token->type != CPP_KEYWORD)
*************** cp_parser_labeled_statement (cp_parser* 
*** 5249,5268 ****
  	cp_lexer_consume_token (parser->lexer);
  	/* Parse the constant-expression.  */
  	expr = cp_parser_constant_expression (parser, 
  					      /*allow_non_constant_p=*/false,
  					      NULL);
! 	/* Create the label.  */
! 	statement = finish_case_label (expr, NULL_TREE);
        }
        break;
  
      case RID_DEFAULT:
        /* Consume the `default' token.  */
        cp_lexer_consume_token (parser->lexer);
!       /* Create the label.  */
!       statement = finish_case_label (NULL_TREE, NULL_TREE);
        break;
  
      default:
        /* Anything else must be an ordinary label.  */
        statement = finish_label_stmt (cp_parser_identifier (parser));
--- 5263,5286 ----
  	cp_lexer_consume_token (parser->lexer);
  	/* Parse the constant-expression.  */
  	expr = cp_parser_constant_expression (parser, 
  					      /*allow_non_constant_p=*/false,
  					      NULL);
! 	if (!parser->in_switch_statement_p)
! 	  error ("case label `%E' not within a switch statement", expr);
! 	else
! 	  statement = finish_case_label (expr, NULL_TREE);
        }
        break;
  
      case RID_DEFAULT:
        /* Consume the `default' token.  */
        cp_lexer_consume_token (parser->lexer);
!       if (!parser->in_switch_statement_p)
! 	error ("case label not within a switch statement");
!       else
! 	statement = finish_case_label (NULL_TREE, NULL_TREE);
        break;
  
      default:
        /* Anything else must be an ordinary label.  */
        statement = finish_label_stmt (cp_parser_identifier (parser));
*************** cp_parser_selection_statement (cp_parser
*** 5441,5456 ****
--- 5459,5478 ----
  	    finish_if_stmt ();
  	  }
  	else
  	  {
  	    tree body;
+ 	    bool in_switch_statement_p;
  
  	    /* Add the condition.  */
  	    finish_switch_cond (condition, statement);
  
  	    /* Parse the body of the switch-statement.  */
+ 	    in_switch_statement_p = parser->in_switch_statement_p;
+ 	    parser->in_switch_statement_p = true;
  	    body = cp_parser_implicitly_scoped_statement (parser);
+ 	    parser->in_switch_statement_p = in_switch_statement_p;
  
  	    /* Now we're all done with the switch-statement.  */
  	    finish_switch_stmt (statement);
  	  }
  
*************** static tree
*** 5562,5577 ****
--- 5584,5605 ----
  cp_parser_iteration_statement (cp_parser* parser)
  {
    cp_token *token;
    enum rid keyword;
    tree statement;
+   bool in_iteration_statement_p;
+ 
  
    /* Peek at the next token.  */
    token = cp_parser_require (parser, CPP_KEYWORD, "iteration-statement");
    if (!token)
      return error_mark_node;
  
+   /* Remember whether or not we are already within an iteration
+      statement.  */ 
+   in_iteration_statement_p = parser->in_iteration_statement_p;
+ 
    /* See what kind of keyword it is.  */
    keyword = token->keyword;
    switch (keyword)
      {
      case RID_WHILE:
*************** cp_parser_iteration_statement (cp_parser
*** 5586,5596 ****
--- 5614,5626 ----
  	condition = cp_parser_condition (parser);
  	finish_while_stmt_cond (condition, statement);
  	/* Look for the `)'.  */
  	cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
  	/* Parse the dependent statement.  */
+ 	parser->in_iteration_statement_p = true;
  	cp_parser_already_scoped_statement (parser);
+ 	parser->in_iteration_statement_p = in_iteration_statement_p;
  	/* We're done with the while-statement.  */
  	finish_while_stmt (statement);
        }
        break;
  
*************** cp_parser_iteration_statement (cp_parser
*** 5599,5609 ****
--- 5629,5641 ----
  	tree expression;
  
  	/* Begin the do-statement.  */
  	statement = begin_do_stmt ();
  	/* Parse the body of the do-statement.  */
+ 	parser->in_iteration_statement_p = true;
  	cp_parser_implicitly_scoped_statement (parser);
+ 	parser->in_iteration_statement_p = in_iteration_statement_p;
  	finish_do_body (statement);
  	/* Look for the `while' keyword.  */
  	cp_parser_require_keyword (parser, RID_WHILE, "`while'");
  	/* Look for the `('.  */
  	cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
*************** cp_parser_iteration_statement (cp_parser
*** 5644,5654 ****
--- 5676,5688 ----
  	finish_for_expr (expression, statement);
  	/* Look for the `)'.  */
  	cp_parser_require (parser, CPP_CLOSE_PAREN, "`;'");
  
  	/* Parse the body of the for-statement.  */
+ 	parser->in_iteration_statement_p = true;
  	cp_parser_already_scoped_statement (parser);
+ 	parser->in_iteration_statement_p = in_iteration_statement_p;
  
  	/* We're done with the for-statement.  */
  	finish_for_stmt (statement);
        }
        break;
*************** cp_parser_jump_statement (cp_parser* par
*** 5725,5740 ****
    /* See what kind of keyword it is.  */
    keyword = token->keyword;
    switch (keyword)
      {
      case RID_BREAK:
!       statement = finish_break_stmt ();
        cp_parser_require (parser, CPP_SEMICOLON, "`;'");
        break;
  
      case RID_CONTINUE:
!       statement = finish_continue_stmt ();
        cp_parser_require (parser, CPP_SEMICOLON, "`;'");
        break;
  
      case RID_RETURN:
        {
--- 5759,5787 ----
    /* See what kind of keyword it is.  */
    keyword = token->keyword;
    switch (keyword)
      {
      case RID_BREAK:
!       if (!parser->in_switch_statement_p
! 	  && !parser->in_iteration_statement_p)
! 	{
! 	  error ("break statement not within loop or switch");
! 	  statement = error_mark_node;
! 	}
!       else
! 	statement = finish_break_stmt ();
        cp_parser_require (parser, CPP_SEMICOLON, "`;'");
        break;
  
      case RID_CONTINUE:
!       if (!parser->in_iteration_statement_p)
! 	{
! 	  error ("continue statement not within a loop");
! 	  statement = error_mark_node;
! 	}
!       else
! 	statement = finish_continue_stmt ();
        cp_parser_require (parser, CPP_SEMICOLON, "`;'");
        break;
  
      case RID_RETURN:
        {


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