aboutsummaryrefslogtreecommitdiff
path: root/gcc/c
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2015-10-02 12:56:17 +0000
committerMarek Polacek <mpolacek@gcc.gnu.org>2015-10-02 12:56:17 +0000
commit3e3b8d63e54773e0f5add898ad55acf1be22d950 (patch)
tree2068f8ebdec3daf3c4cd446ea0c01a7dfe75c37d /gcc/c
parent0f6ca79c15711e28ea7a6330fc9ac017077fbaad (diff)
downloadgcc-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/ChangeLog10
-rw-r--r--gcc/c/c-parser.c60
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);