static tree c_parser_compound_statement (c_parser *);
static void c_parser_compound_statement_nostart (c_parser *);
static void c_parser_label (c_parser *);
-static void c_parser_statement (c_parser *);
-static void c_parser_statement_after_labels (c_parser *, vec<tree> * = NULL);
-static void c_parser_if_statement (c_parser *, vec<tree> *);
+static void c_parser_statement (c_parser *, bool *);
+static void c_parser_statement_after_labels (c_parser *, bool *,
+ vec<tree> * = NULL);
+static void c_parser_if_statement (c_parser *, bool *, vec<tree> *);
static void c_parser_switch_statement (c_parser *);
-static void c_parser_while_statement (c_parser *, bool);
+static void c_parser_while_statement (c_parser *, bool, bool *);
static void c_parser_do_statement (c_parser *, bool);
-static void c_parser_for_statement (c_parser *, bool);
+static void c_parser_for_statement (c_parser *, bool, bool *);
static tree c_parser_asm_statement (c_parser *);
static tree c_parser_asm_operands (c_parser *);
static tree c_parser_asm_goto_operands (c_parser *);
last_label = false;
last_stmt = true;
mark_valid_location_for_stdc_pragma (false);
- c_parser_statement_after_labels (parser);
+ c_parser_statement_after_labels (parser, NULL);
}
parser->error = false;
statement:
transaction-statement
transaction-cancel-statement
-*/
+
+ IF_P is used to track whether there's a (possibly labeled) if statement
+ which is not enclosed in braces and has an else clause. This is used to
+ implement -Wparentheses. */
static void
-c_parser_statement (c_parser *parser)
+c_parser_statement (c_parser *parser, bool *if_p)
{
c_parser_all_labels (parser);
- c_parser_statement_after_labels (parser);
+ c_parser_statement_after_labels (parser, if_p, NULL);
}
/* Parse a statement, other than a labeled statement. CHAIN is a vector
- of if-else-if conditions. */
+ of if-else-if conditions.
+
+ IF_P is used to track whether there's a (possibly labeled) if statement
+ which is not enclosed in braces and has an else clause. This is used to
+ implement -Wparentheses. */
static void
-c_parser_statement_after_labels (c_parser *parser, vec<tree> *chain)
+c_parser_statement_after_labels (c_parser *parser, bool *if_p,
+ vec<tree> *chain)
{
location_t loc = c_parser_peek_token (parser)->location;
tree stmt = NULL_TREE;
bool in_if_block = parser->in_if_block;
parser->in_if_block = false;
+ if (if_p != NULL)
+ *if_p = false;
switch (c_parser_peek_token (parser)->type)
{
case CPP_OPEN_BRACE:
switch (c_parser_peek_token (parser)->keyword)
{
case RID_IF:
- c_parser_if_statement (parser, chain);
+ c_parser_if_statement (parser, if_p, chain);
break;
case RID_SWITCH:
c_parser_switch_statement (parser);
break;
case RID_WHILE:
- c_parser_while_statement (parser, false);
+ c_parser_while_statement (parser, false, if_p);
break;
case RID_DO:
c_parser_do_statement (parser, false);
break;
case RID_FOR:
- c_parser_for_statement (parser, false);
+ c_parser_for_statement (parser, false, if_p);
break;
case RID_CILK_FOR:
if (!flag_cilkplus)
return cond;
}
-/* Parse a statement which is a block in C99. */
+/* Parse a statement which is a block in C99.
+
+ IF_P is used to track whether there's a (possibly labeled) if statement
+ which is not enclosed in braces and has an else clause. This is used to
+ implement -Wparentheses. */
static tree
-c_parser_c99_block_statement (c_parser *parser)
+c_parser_c99_block_statement (c_parser *parser, bool *if_p)
{
tree block = c_begin_compound_stmt (flag_isoc99);
location_t loc = c_parser_peek_token (parser)->location;
- c_parser_statement (parser);
+ c_parser_statement (parser, if_p);
return c_end_compound_stmt (loc, block, flag_isoc99);
}
we handle an empty body specially for the sake of -Wempty-body
warnings, and (d) we call parser_compound_statement directly
because c_parser_statement_after_labels resets
- parser->in_if_block. */
+ parser->in_if_block.
+
+ IF_P is used to track whether there's a (possibly labeled) if statement
+ which is not enclosed in braces and has an else clause. This is used to
+ implement -Wparentheses. */
static tree
c_parser_if_body (c_parser *parser, bool *if_p,
= get_token_indent_info (c_parser_peek_token (parser));
c_parser_all_labels (parser);
- *if_p = c_parser_next_token_is_keyword (parser, RID_IF);
if (c_parser_next_token_is (parser, CPP_SEMICOLON))
{
location_t loc = c_parser_peek_token (parser)->location;
else if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
add_stmt (c_parser_compound_statement (parser));
else
- c_parser_statement_after_labels (parser);
+ c_parser_statement_after_labels (parser, if_p);
token_indent_info next_tinfo
= get_token_indent_info (c_parser_peek_token (parser));
c_parser_consume_token (parser);
}
else
- c_parser_statement_after_labels (parser, chain);
+ c_parser_statement_after_labels (parser, NULL, chain);
token_indent_info next_tinfo
= get_token_indent_info (c_parser_peek_token (parser));
if ( expression ) statement
if ( expression ) statement else statement
- CHAIN is a vector of if-else-if conditions. */
+ CHAIN is a vector of if-else-if conditions.
+ IF_P is used to track whether there's a (possibly labeled) if statement
+ which is not enclosed in braces and has an else clause. This is used to
+ implement -Wparentheses. */
static void
-c_parser_if_statement (c_parser *parser, vec<tree> *chain)
+c_parser_if_statement (c_parser *parser, bool *if_p, vec<tree> *chain)
{
tree block;
location_t loc;
tree cond;
- bool first_if = false;
+ bool nested_if = false;
tree first_body, second_body;
bool in_if_block;
tree if_stmt;
}
in_if_block = parser->in_if_block;
parser->in_if_block = true;
- first_body = c_parser_if_body (parser, &first_if, if_tinfo);
+ first_body = c_parser_if_body (parser, &nested_if, if_tinfo);
parser->in_if_block = in_if_block;
if (warn_duplicated_cond)
}
}
second_body = c_parser_else_body (parser, else_tinfo, chain);
+ /* Set IF_P to true to indicate that this if statement has an
+ else clause. This may trigger the Wparentheses warning
+ below when we get back up to the parent if statement. */
+ if (if_p != NULL)
+ *if_p = true;
}
else
{
second_body = NULL_TREE;
+
+ /* Diagnose an ambiguous else if if-then-else is nested inside
+ if-then. */
+ if (nested_if)
+ warning_at (loc, OPT_Wparentheses,
+ "suggest explicit braces to avoid ambiguous %<else%>");
+
if (warn_duplicated_cond)
{
/* This if statement does not have an else clause. We don't
chain = NULL;
}
}
- c_finish_if_stmt (loc, cond, first_body, second_body, first_if);
+ c_finish_if_stmt (loc, cond, first_body, second_body);
if_stmt = c_end_compound_stmt (loc, block, flag_isoc99);
/* If the if statement contains array notations, then we expand them. */
c_start_case (switch_loc, switch_cond_loc, expr, explicit_cast_p);
save_break = c_break_label;
c_break_label = NULL_TREE;
- body = c_parser_c99_block_statement (parser);
+ body = c_parser_c99_block_statement (parser, NULL/*if??*/);
c_finish_case (body, ce.original_type);
if (c_break_label)
{
while-statement:
while (expression) statement
-*/
+
+ IF_P is used to track whether there's a (possibly labeled) if statement
+ which is not enclosed in braces and has an else clause. This is used to
+ implement -Wparentheses. */
static void
-c_parser_while_statement (c_parser *parser, bool ivdep)
+c_parser_while_statement (c_parser *parser, bool ivdep, bool *if_p)
{
tree block, cond, body, save_break, save_cont;
location_t loc;
token_indent_info body_tinfo
= get_token_indent_info (c_parser_peek_token (parser));
- body = c_parser_c99_block_statement (parser);
+ body = c_parser_c99_block_statement (parser, if_p);
c_finish_loop (loc, cond, NULL, body, c_break_label, c_cont_label, true);
add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
c_break_label = NULL_TREE;
save_cont = c_cont_label;
c_cont_label = NULL_TREE;
- body = c_parser_c99_block_statement (parser);
+ body = c_parser_c99_block_statement (parser, NULL);
c_parser_require_keyword (parser, RID_WHILE, "expected %<while%>");
new_break = c_break_label;
c_break_label = save_break;
like the beginning of the for-statement, and we can tell it is a
foreach-statement only because the initial declaration or
expression is terminated by 'in' instead of ';'.
-*/
+
+ IF_P is used to track whether there's a (possibly labeled) if statement
+ which is not enclosed in braces and has an else clause. This is used to
+ implement -Wparentheses. */
static void
-c_parser_for_statement (c_parser *parser, bool ivdep)
+c_parser_for_statement (c_parser *parser, bool ivdep, bool *if_p)
{
tree block, cond, incr, save_break, save_cont, body;
/* The following are only used when parsing an ObjC foreach statement. */
token_indent_info body_tinfo
= get_token_indent_info (c_parser_peek_token (parser));
- body = c_parser_c99_block_statement (parser);
+ body = c_parser_c99_block_statement (parser, if_p);
if (is_foreach_statement)
objc_finish_foreach_loop (loc, object_expression, collection_expression, body, c_break_label, c_cont_label);
return false;
}
if (c_parser_next_token_is_keyword (parser, RID_FOR))
- c_parser_for_statement (parser, true);
+ c_parser_for_statement (parser, true, NULL);
else if (c_parser_next_token_is_keyword (parser, RID_WHILE))
- c_parser_while_statement (parser, true);
+ c_parser_while_statement (parser, true, NULL);
else
c_parser_do_statement (parser, true);
return false;
c_parser_omp_structured_block (c_parser *parser)
{
tree stmt = push_stmt_list ();
- c_parser_statement (parser);
+ c_parser_statement (parser, NULL);
return pop_stmt_list (stmt);
}
add_stmt (c_end_compound_stmt (here, stmt, true));
}
else
- add_stmt (c_parser_c99_block_statement (parser));
+ add_stmt (c_parser_c99_block_statement (parser, NULL));
if (c_cont_label)
{
tree t = build1 (LABEL_EXPR, void_type_node, c_cont_label);
}
block = c_begin_omp_parallel ();
- c_parser_statement (parser);
+ c_parser_statement (parser, NULL);
stmt = c_finish_omp_parallel (loc, clauses, block);
return stmt;
"#pragma omp task");
block = c_begin_omp_task ();
- c_parser_statement (parser);
+ c_parser_statement (parser, NULL);
return c_finish_omp_task (loc, clauses, block);
}