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]

statement-expression error recovery


This fixes a segv in gcc.c-torture/compile/990801-2.c when compiled 
with optimization.

The crash is because flow, in building the CFG, finds a label in no
basic block and dereferences NULL.  It turns out that the label never
made it into the initial rtl for the function.  This is because
expand_end_stmt_expr was never called, leaving an open sequence with
the label therein.  The sequence gets discarded at the beginning of
rest_of_compilation.

This does add a new shift-reduce error.  I believe the new error to be
inconsequential, but my yacc debugging skills are nothing to write home
about, so I may have found the wrong error.  It didn't help that the
list at the beginning of c-parse.in of expected errors hasn't been kept
up to date.


r~


	* c-parse.in (compstmt_primary_start): New, broken out of first
	part of compstmt handling in primary.
	(primary): Use it.  Add an error clause.
	(compstmt_nostart): Renamed from compstmt; remove all
	initial invocations of compstmt_start.
	(compstmt): New.

Index: c-parse.in
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/c-parse.in,v
retrieving revision 1.16.2.2
diff -c -p -d -r1.16.2.2 c-parse.in
*** c-parse.in	1999/08/25 23:30:20	1.16.2.2
--- c-parse.in	1999/08/28 22:04:14
*************** ifobjc
*** 31,60 ****
  %expect 66
  end ifobjc
  ifc
! %expect 51
! 
! /* These are the 23 conflicts you should get in parse.output;
!    the state numbers may vary if minor changes in the grammar are made.
! 
! State 42 contains 1 shift/reduce conflict.  (Two ways to parse ATTRIBUTE.)
! State 44 contains 1 shift/reduce conflict.  (Two ways to recover from error.)
! State 103 contains 1 shift/reduce conflict.  (Two ways to recover from error.)
! State 110 contains 1 shift/reduce conflict.  (Two ways to parse ATTRIBUTE.)
! State 111 contains 1 shift/reduce conflict.  (Two ways to recover from error.)
! State 115 contains 1 shift/reduce conflict.  (Two ways to recover from error.)
! State 132 contains 1 shift/reduce conflict.  (See comment at component_decl.)
! State 180 contains 1 shift/reduce conflict.  (Two ways to parse ATTRIBUTE.)
! State 194 contains 2 shift/reduce conflict.  (Four ways to parse this.)
! State 202 contains 1 shift/reduce conflict.  (Two ways to recover from error.)
! State 214 contains 1 shift/reduce conflict.  (Two ways to recover from error.)
! State 220 contains 1 shift/reduce conflict.  (Two ways to recover from error.)
! State 304 contains 2 shift/reduce conflicts.  (Four ways to parse this.)
! State 335 contains 2 shift/reduce conflicts.  (Four ways to parse this.)
! State 347 contains 1 shift/reduce conflict.  (Two ways to parse ATTRIBUTES.)
! State 352 contains 1 shift/reduce conflict.  (Two ways to parse ATTRIBUTES.)
! State 383 contains 2 shift/reduce conflicts.  (Four ways to parse this.)
! State 434 contains 2 shift/reduce conflicts.  (Four ways to parse this.)  */
! 
  end ifc
  
  %{
--- 31,37 ----
  %expect 66
  end ifobjc
  ifc
! %expect 52
  end ifc
  
  %{
*************** end ifc
*** 191,197 ****
  %type <ttype> maybe_attribute attributes attribute attribute_list attrib
  %type <ttype> any_word
  
! %type <ttype> compstmt
  
  %type <ttype> declarator
  %type <ttype> notype_declarator after_type_declarator
--- 168,174 ----
  %type <ttype> maybe_attribute attributes attribute attribute_list attrib
  %type <ttype> any_word
  
! %type <ttype> compstmt compstmt_nostart compstmt_primary_start
  
  %type <ttype> declarator
  %type <ttype> notype_declarator after_type_declarator
*************** end ifobjc
*** 806,848 ****
  		  $$ = $2; }
  	| '(' error ')'
  		{ $$ = error_mark_node; }
! 	| '('
! 		{ if (current_function_decl == 0)
! 		    {
! 		      error ("braced-group within expression allowed only inside a function");
! 		      YYERROR;
! 		    }
! 		  /* We must force a BLOCK for this level
! 		     so that, if it is not expanded later,
! 		     there is a way to turn off the entire subtree of blocks
! 		     that are contained in it.  */
! 		  keep_next_level ();
! 		  push_iterator_stack ();
! 		  push_label_level ();
! 		  $<ttype>$ = expand_start_stmt_expr (); }
! 	  compstmt ')'
  		{ tree rtl_exp;
  		  if (pedantic)
  		    pedwarn ("ANSI C forbids braced-groups within expressions");
  		  pop_iterator_stack ();
  		  pop_label_level ();
! 		  rtl_exp = expand_end_stmt_expr ($<ttype>2);
  		  /* The statements have side effects, so the group does.  */
  		  TREE_SIDE_EFFECTS (rtl_exp) = 1;
  
! 		  if (TREE_CODE ($3) == BLOCK)
  		    {
  		      /* Make a BIND_EXPR for the BLOCK already made.  */
  		      $$ = build (BIND_EXPR, TREE_TYPE (rtl_exp),
! 				  NULL_TREE, rtl_exp, $3);
  		      /* Remove the block from the tree at this point.
  			 It gets put back at the proper place
  			 when the BIND_EXPR is expanded.  */
! 		      delete_block ($3);
  		    }
  		  else
! 		    $$ = $3;
  		}
  	| primary '(' exprlist ')'   %prec '.'
  		{ $$ = build_function_call ($1, $3); }
  	| primary '[' expr ']'   %prec '.'
--- 783,820 ----
  		  $$ = $2; }
  	| '(' error ')'
  		{ $$ = error_mark_node; }
! 	| compstmt_primary_start compstmt_nostart ')'
  		{ tree rtl_exp;
  		  if (pedantic)
  		    pedwarn ("ANSI C forbids braced-groups within expressions");
  		  pop_iterator_stack ();
  		  pop_label_level ();
! 		  rtl_exp = expand_end_stmt_expr ($1);
  		  /* The statements have side effects, so the group does.  */
  		  TREE_SIDE_EFFECTS (rtl_exp) = 1;
  
! 		  if (TREE_CODE ($2) == BLOCK)
  		    {
  		      /* Make a BIND_EXPR for the BLOCK already made.  */
  		      $$ = build (BIND_EXPR, TREE_TYPE (rtl_exp),
! 				  NULL_TREE, rtl_exp, $2);
  		      /* Remove the block from the tree at this point.
  			 It gets put back at the proper place
  			 when the BIND_EXPR is expanded.  */
! 		      delete_block ($2);
  		    }
  		  else
! 		    $$ = $2;
  		}
+ 	| compstmt_primary_start error ')'
+ 		{
+ 		  /* Make sure we call expand_end_stmt_expr.  Otherwise
+ 		     we are likely to lose sequences and crash later.  */
+ 		  pop_iterator_stack ();
+ 		  pop_label_level ();
+ 		  expand_end_stmt_expr ($1);
+ 		  $$ = error_mark_node;
+ 		}
  	| primary '(' exprlist ')'   %prec '.'
  		{ $$ = build_function_call ($1, $3); }
  	| primary '[' expr ']'   %prec '.'
*************** compstmt_or_error:
*** 1795,1803 ****
  
  compstmt_start: '{' { compstmt_count++; }
  
! compstmt: compstmt_start '}'
  		{ $$ = convert (void_type_node, integer_zero_node); }
! 	| compstmt_start pushlevel maybe_label_decls decls xstmts '}'
  		{ emit_line_note (input_filename, lineno);
  		  expand_end_bindings (getdecls (), 1, 0);
  		  $$ = poplevel (1, 1, 0);
--- 1767,1775 ----
  
  compstmt_start: '{' { compstmt_count++; }
  
! compstmt_nostart: '}'
  		{ $$ = convert (void_type_node, integer_zero_node); }
! 	| pushlevel maybe_label_decls decls xstmts '}'
  		{ emit_line_note (input_filename, lineno);
  		  expand_end_bindings (getdecls (), 1, 0);
  		  $$ = poplevel (1, 1, 0);
*************** compstmt: compstmt_start '}'
*** 1805,1811 ****
  		    pop_momentary_nofree ();
  		  else
  		    pop_momentary (); }
! 	| compstmt_start pushlevel maybe_label_decls error '}'
  		{ emit_line_note (input_filename, lineno);
  		  expand_end_bindings (getdecls (), kept_level_p (), 0);
  		  $$ = poplevel (kept_level_p (), 0, 0);
--- 1777,1783 ----
  		    pop_momentary_nofree ();
  		  else
  		    pop_momentary (); }
! 	| pushlevel maybe_label_decls error '}'
  		{ emit_line_note (input_filename, lineno);
  		  expand_end_bindings (getdecls (), kept_level_p (), 0);
  		  $$ = poplevel (kept_level_p (), 0, 0);
*************** compstmt: compstmt_start '}'
*** 1813,1819 ****
  		    pop_momentary_nofree ();
  		  else
  		    pop_momentary (); }
! 	| compstmt_start pushlevel maybe_label_decls stmts '}'
  		{ emit_line_note (input_filename, lineno);
  		  expand_end_bindings (getdecls (), kept_level_p (), 0);
  		  $$ = poplevel (kept_level_p (), 0, 0);
--- 1785,1791 ----
  		    pop_momentary_nofree ();
  		  else
  		    pop_momentary (); }
! 	| pushlevel maybe_label_decls stmts '}'
  		{ emit_line_note (input_filename, lineno);
  		  expand_end_bindings (getdecls (), kept_level_p (), 0);
  		  $$ = poplevel (kept_level_p (), 0, 0);
*************** compstmt: compstmt_start '}'
*** 1821,1826 ****
--- 1793,1820 ----
  		    pop_momentary_nofree ();
  		  else
  		    pop_momentary (); }
+ 	;
+ 
+ compstmt_primary_start:
+ 	'(' '{'
+ 		{ if (current_function_decl == 0)
+ 		    {
+ 		      error ("braced-group within expression allowed only inside a function");
+ 		      YYERROR;
+ 		    }
+ 		  /* We must force a BLOCK for this level
+ 		     so that, if it is not expanded later,
+ 		     there is a way to turn off the entire subtree of blocks
+ 		     that are contained in it.  */
+ 		  keep_next_level ();
+ 		  push_iterator_stack ();
+ 		  push_label_level ();
+ 		  $$ = expand_start_stmt_expr ();
+ 		  compstmt_count++;
+ 		}
+ 
+ compstmt: compstmt_start compstmt_nostart
+ 		{ $$ = $2; }
  	;
  
  /* Value is number of statements counted as of the closeparen.  */


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