-select_or_iter_stmt:
- simple_if ELSE
- { c_expand_start_else ();
- $<itype>1 = stmt_count; }
- c99_block_lineno_labeled_stmt
- { c_finish_else ();
- c_expand_end_cond ();
- if (extra_warnings && stmt_count == $<itype>1)
- warning ("empty body in an else-statement"); }
- | simple_if %prec IF
- { c_expand_end_cond ();
- /* This warning is here instead of in simple_if, because we
- do not want a warning if an empty if is followed by an
- else statement. Increment stmt_count so we don't
- give a second error if this is a nested `if'. */
- if (extra_warnings && stmt_count++ == $<itype>1)
- warning_with_file_and_line (if_stmt_file, if_stmt_line,
- "empty body in an if-statement"); }
-/* Make sure c_expand_end_cond is run once
- for each call to c_expand_start_cond.
- Otherwise a crash is likely. */
- | simple_if ELSE error
- { c_expand_end_cond (); }
- /* We must build the WHILE_STMT node before parsing its
- condition so that STMT_LINENO refers to the line
- containing the "while", and not the line containing
- the close-parenthesis.
-
- c_begin_while_stmt returns the WHILE_STMT node, which
- we later pass to c_finish_while_stmt_cond to fill
- in the condition and other tidbits. */
- | WHILE
- { stmt_count++;
- $<ttype>$ = c_begin_while_stmt (); }
- '(' expr ')'
- { $4 = c_common_truthvalue_conversion ($4);
- c_finish_while_stmt_cond
- (c_common_truthvalue_conversion ($4), $<ttype>2);
- $<ttype>$ = add_stmt ($<ttype>2); }
- c99_block_lineno_labeled_stmt
- { RECHAIN_STMTS ($<ttype>6, WHILE_BODY ($<ttype>6)); }
- | do_stmt_start
- '(' expr ')' ';'
- { DO_COND ($1) = c_common_truthvalue_conversion ($3); }
- | do_stmt_start error
- { }
- | FOR
- { $<ttype>$ = build_stmt (FOR_STMT, NULL_TREE, NULL_TREE,
- NULL_TREE, NULL_TREE);
- add_stmt ($<ttype>$); }
- '(' for_init_stmt
- { stmt_count++;
- RECHAIN_STMTS ($<ttype>2, FOR_INIT_STMT ($<ttype>2)); }
- xexpr ';'
- { if ($6)
- FOR_COND ($<ttype>2)
- = c_common_truthvalue_conversion ($6); }
- xexpr ')'
- { FOR_EXPR ($<ttype>2) = $9; }
- c99_block_lineno_labeled_stmt
- { RECHAIN_STMTS ($<ttype>2, FOR_BODY ($<ttype>2)); }
- | SWITCH '(' expr ')'
- { stmt_count++;
- $<ttype>$ = c_start_case ($3); }
- c99_block_lineno_labeled_stmt
- { c_finish_case (); }
+condition: save_location expr
+ { $$ = lang_hooks.truthvalue_conversion ($2.value);
+ if (EXPR_P ($$))
+ SET_EXPR_LOCATION ($$, $1); }
+ ;
+
+/* Implement -Wparenthesis by special casing IF statement directly nested
+ within IF statement. This requires some amount of duplication of the
+ productions under c99_block_lineno_labeled_stmt in order to work out.
+ But it's still likely more maintainable than lots of state outside the
+ parser... */
+
+if_statement_1:
+ c99_block_start lineno_labels if_statement
+ { $$ = c_end_compound_stmt ($1, flag_isoc99); }
+ ;
+
+if_statement_2:
+ c99_block_start lineno_labels ';'
+ { if (extra_warnings)
+ add_stmt (build (NOP_EXPR, NULL_TREE, NULL_TREE));
+ $$ = c_end_compound_stmt ($1, flag_isoc99); }
+ | c99_block_lineno_labeled_stmt
+ ;
+
+if_statement:
+ IF c99_block_start save_location '(' condition ')'
+ if_statement_1 ELSE if_statement_2
+ { c_finish_if_stmt ($3, $5, $7, $9, true);
+ add_stmt (c_end_compound_stmt ($2, flag_isoc99)); }
+ | IF c99_block_start save_location '(' condition ')'
+ if_statement_2 ELSE if_statement_2
+ { c_finish_if_stmt ($3, $5, $7, $9, false);
+ add_stmt (c_end_compound_stmt ($2, flag_isoc99)); }
+ | IF c99_block_start save_location '(' condition ')'
+ if_statement_1 %prec IF
+ { c_finish_if_stmt ($3, $5, $7, NULL, true);
+ add_stmt (c_end_compound_stmt ($2, flag_isoc99)); }
+ | IF c99_block_start save_location '(' condition ')'
+ if_statement_2 %prec IF
+ { c_finish_if_stmt ($3, $5, $7, NULL, false);
+ add_stmt (c_end_compound_stmt ($2, flag_isoc99)); }
+ ;
+
+start_break: /* empty */
+ { $$ = c_break_label; c_break_label = NULL; }
+ ;
+
+start_continue: /* empty */
+ { $$ = c_cont_label; c_cont_label = NULL; }
+ ;
+
+while_statement:
+ WHILE c99_block_start save_location '(' condition ')'
+ start_break start_continue c99_block_lineno_labeled_stmt
+ { c_finish_loop ($3, $5, NULL, $9, c_break_label,
+ c_cont_label, true);
+ add_stmt (c_end_compound_stmt ($2, flag_isoc99));
+ c_break_label = $7; c_cont_label = $8; }
+ ;
+
+do_statement:
+ DO c99_block_start save_location start_break start_continue
+ c99_block_lineno_labeled_stmt WHILE
+ { $<ttype>$ = c_break_label; c_break_label = $4; }
+ { $<ttype>$ = c_cont_label; c_cont_label = $5; }
+ '(' condition ')' ';'
+ { c_finish_loop ($3, $11, NULL, $6, $<ttype>8,
+ $<ttype>9, false);
+ add_stmt (c_end_compound_stmt ($2, flag_isoc99)); }
+ ;
+
+xexpr:
+ /* empty */
+ { $$ = NULL_TREE; }
+ | expr
+ { $$ = $1.value; }