diff options
author | Marek Polacek <polacek@redhat.com> | 2015-10-02 12:56:17 +0000 |
---|---|---|
committer | Marek Polacek <mpolacek@gcc.gnu.org> | 2015-10-02 12:56:17 +0000 |
commit | 3e3b8d63e54773e0f5add898ad55acf1be22d950 (patch) | |
tree | 2068f8ebdec3daf3c4cd446ea0c01a7dfe75c37d /gcc/c | |
parent | 0f6ca79c15711e28ea7a6330fc9ac017077fbaad (diff) | |
download | gcc-3e3b8d63e54773e0f5add898ad55acf1be22d950.zip gcc-3e3b8d63e54773e0f5add898ad55acf1be22d950.tar.gz gcc-3e3b8d63e54773e0f5add898ad55acf1be22d950.tar.bz2 |
re PR c/64249 (Missing warning for if (A) else if (A))
PR c/64249
* c-common.c (warn_duplicated_cond_add_or_warn): New function.
* c-common.h (warn_duplicated_cond_add_or_warn): Declare.
* c.opt (Wduplicated-cond): New option.
* c-parser.c (c_parser_statement_after_labels): Add CHAIN parameter
and pass it down to c_parser_if_statement.
(c_parser_else_body): Add CHAIN parameter and pass it down to
c_parser_statement_after_labels.
(c_parser_if_statement): Add CHAIN parameter. Add code to warn about
duplicated if-else-if conditions.
* parser.c (cp_parser_statement): Add CHAIN parameter and pass it
down to cp_parser_selection_statement.
(cp_parser_selection_statement): Add CHAIN parameter. Add code to
warn about duplicated if-else-if conditions.
(cp_parser_implicitly_scoped_statement): Add CHAIN parameter and pass
it down to cp_parser_statement.
* doc/invoke.texi: Document -Wduplicated-cond.
* Makefile.in (insn-latencytab.o): Use -Wno-duplicated-cond.
(insn-dfatab.o): Likewise.
* genemit.c (gen_exp): Rewrite condition to avoid -Wduplicated-cond
warning.
* c-c++-common/Wduplicated-cond-1.c: New test.
* c-c++-common/Wduplicated-cond-2.c: New test.
* c-c++-common/Wduplicated-cond-3.c: New test.
* c-c++-common/Wduplicated-cond-4.c: New test.
* c-c++-common/Wmisleading-indentation.c (fn_37): Avoid
-Wduplicated-cond warning.
From-SVN: r228388
Diffstat (limited to 'gcc/c')
-rw-r--r-- | gcc/c/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/c/c-parser.c | 60 |
2 files changed, 58 insertions, 12 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 577fdc0..7c0051f 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,13 @@ +2015-10-02 Marek Polacek <polacek@redhat.com> + + PR c/64249 + * c-parser.c (c_parser_statement_after_labels): Add CHAIN parameter + and pass it down to c_parser_if_statement. + (c_parser_else_body): Add CHAIN parameter and pass it down to + c_parser_statement_after_labels. + (c_parser_if_statement): Add CHAIN parameter. Add code to warn about + duplicated if-else-if conditions. + 2015-10-01 Marek Polacek <polacek@redhat.com> * c-typeck.c (convert_for_assignment): Improve commentary. diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 2fab3f0..00fa238 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -1198,8 +1198,8 @@ 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 *); -static void c_parser_if_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_switch_statement (c_parser *); static void c_parser_while_statement (c_parser *, bool); static void c_parser_do_statement (c_parser *, bool); @@ -4961,10 +4961,11 @@ c_parser_statement (c_parser *parser) c_parser_statement_after_labels (parser); } -/* Parse a statement, other than a labeled statement. */ +/* Parse a statement, other than a labeled statement. CHAIN is a vector + of if-else-if conditions. */ static void -c_parser_statement_after_labels (c_parser *parser) +c_parser_statement_after_labels (c_parser *parser, vec<tree> *chain) { location_t loc = c_parser_peek_token (parser)->location; tree stmt = NULL_TREE; @@ -4979,7 +4980,7 @@ c_parser_statement_after_labels (c_parser *parser) switch (c_parser_peek_token (parser)->keyword) { case RID_IF: - c_parser_if_statement (parser); + c_parser_if_statement (parser, chain); break; case RID_SWITCH: c_parser_switch_statement (parser); @@ -5230,10 +5231,12 @@ c_parser_if_body (c_parser *parser, bool *if_p, /* Parse the else body of an if statement. This is just parsing a statement but (a) it is a block in C99, (b) we handle an empty body - specially for the sake of -Wempty-body warnings. */ + specially for the sake of -Wempty-body warnings. CHAIN is a vector + of if-else-if conditions. */ static tree -c_parser_else_body (c_parser *parser, const token_indent_info &else_tinfo) +c_parser_else_body (c_parser *parser, const token_indent_info &else_tinfo, + vec<tree> *chain) { location_t body_loc = c_parser_peek_token (parser)->location; tree block = c_begin_compound_stmt (flag_isoc99); @@ -5251,7 +5254,7 @@ c_parser_else_body (c_parser *parser, const token_indent_info &else_tinfo) c_parser_consume_token (parser); } else - c_parser_statement_after_labels (parser); + c_parser_statement_after_labels (parser, chain); token_indent_info next_tinfo = get_token_indent_info (c_parser_peek_token (parser)); @@ -5265,10 +5268,11 @@ c_parser_else_body (c_parser *parser, const token_indent_info &else_tinfo) if-statement: if ( expression ) statement if ( expression ) statement else statement -*/ + + CHAIN is a vector of if-else-if conditions. */ static void -c_parser_if_statement (c_parser *parser) +c_parser_if_statement (c_parser *parser, vec<tree> *chain) { tree block; location_t loc; @@ -5294,15 +5298,47 @@ c_parser_if_statement (c_parser *parser) parser->in_if_block = true; first_body = c_parser_if_body (parser, &first_if, if_tinfo); parser->in_if_block = in_if_block; + + if (warn_duplicated_cond) + warn_duplicated_cond_add_or_warn (EXPR_LOCATION (cond), cond, &chain); + if (c_parser_next_token_is_keyword (parser, RID_ELSE)) { token_indent_info else_tinfo = get_token_indent_info (c_parser_peek_token (parser)); c_parser_consume_token (parser); - second_body = c_parser_else_body (parser, else_tinfo); + if (warn_duplicated_cond) + { + if (c_parser_next_token_is_keyword (parser, RID_IF) + && chain == NULL) + { + /* We've got "if (COND) else if (COND2)". Start the + condition chain and add COND as the first element. */ + chain = new vec<tree> (); + if (!CONSTANT_CLASS_P (cond) && !TREE_SIDE_EFFECTS (cond)) + chain->safe_push (cond); + } + else if (!c_parser_next_token_is_keyword (parser, RID_IF)) + { + /* This is if-else without subsequent if. Zap the condition + chain; we would have already warned at this point. */ + delete chain; + chain = NULL; + } + } + second_body = c_parser_else_body (parser, else_tinfo, chain); } else - second_body = NULL_TREE; + { + second_body = NULL_TREE; + if (warn_duplicated_cond) + { + /* This if statement does not have an else clause. We don't + need the condition chain anymore. */ + delete chain; + chain = NULL; + } + } c_finish_if_stmt (loc, cond, first_body, second_body, first_if); if_stmt = c_end_compound_stmt (loc, block, flag_isoc99); |