re PR c/64249 (Missing warning for if (A) else if (A))
authorMarek Polacek <polacek@redhat.com>
Fri, 2 Oct 2015 12:56:17 +0000 (12:56 +0000)
committerMarek Polacek <mpolacek@gcc.gnu.org>
Fri, 2 Oct 2015 12:56:17 +0000 (12:56 +0000)
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

18 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/c-family/c-common.h
gcc/c-family/c.opt
gcc/c/ChangeLog
gcc/c/c-parser.c
gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/doc/invoke.texi
gcc/genemit.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/Wduplicated-cond-1.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/Wduplicated-cond-2.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/Wduplicated-cond-3.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/Wduplicated-cond-4.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/Wmisleading-indentation.c

index 57a5a43ffb9aec555ba1cdd6b500920683e2c87d..ee1c217d083c2b5a1203333ee1a3a71868a1a164 100644 (file)
@@ -1,3 +1,12 @@
+2015-10-02  Marek Polacek  <polacek@redhat.com>
+
+       PR c/64249
+       * 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.
+
 2015-10-02  Oleg Endo  <olegendo@gcc.gnu.org>
 
        * config/sh/sh.md: Add new unnamed split pattern to handle movt-movt
index 009c745a0c864ac0cf97c197eb330a4006637e3a..b22b5aba0ca66c023c808d4de6db1df983c5b1e4 100644 (file)
@@ -217,6 +217,8 @@ libgcov-merge-tool.o-warn = -Wno-error
 gimple-match.o-warn = -Wno-unused
 generic-match.o-warn = -Wno-unused
 dfp.o-warn = -Wno-strict-aliasing
+insn-latencytab.o-warn = -Wno-duplicated-cond
+insn-dfatab.o-warn = -Wno-duplicated-cond
 
 # All warnings have to be shut off in stage1 if the compiler used then
 # isn't gcc; configure determines that.  WARN_CFLAGS will be either
index 3b33dc1191d4e6a808708cde4bc088e70d9c3247..8ab8964a8c535c5073a1dda44ce1c9f52ab8790f 100644 (file)
@@ -1,3 +1,10 @@
+2015-10-02  Marek Polacek  <polacek@redhat.com>
+
+       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.
+
 2015-10-01  Joseph Myers  <joseph@codesourcery.com>
 
        * c.opt (std=c11): Do not describe as experimental.
index e5395272ec30b0eb28a4eafc17f7398a3fafff8c..f38378d69dd1be998e32674891371caebe16a5d1 100644 (file)
@@ -12921,4 +12921,45 @@ reject_gcc_builtin (const_tree expr, location_t loc /* = UNKNOWN_LOCATION */)
   return false;
 }
 
+/* If we're creating an if-else-if condition chain, first see if we
+   already have this COND in the CHAIN.  If so, warn and don't add COND
+   into the vector, otherwise add the COND there.  LOC is the location
+   of COND.  */
+
+void
+warn_duplicated_cond_add_or_warn (location_t loc, tree cond, vec<tree> **chain)
+{
+  /* No chain has been created yet.  Do nothing.  */
+  if (*chain == NULL)
+    return;
+
+  if (TREE_SIDE_EFFECTS (cond))
+    {
+      /* Uh-oh!  This condition has a side-effect, thus invalidates
+        the whole chain.  */
+      delete *chain;
+      *chain = NULL;
+      return;
+    }
+
+  unsigned int ix;
+  tree t;
+  bool found = false;
+  FOR_EACH_VEC_ELT (**chain, ix, t)
+    if (operand_equal_p (cond, t, 0))
+      {
+       if (warning_at (loc, OPT_Wduplicated_cond,
+                       "duplicated %<if%> condition"))
+         inform (EXPR_LOCATION (t), "previously used here");
+       found = true;
+       break;
+      }
+
+  if (!found
+      && !CONSTANT_CLASS_P (cond)
+      /* Don't infinitely grow the chain.  */
+      && (*chain)->length () < 512)
+    (*chain)->safe_push (cond);
+}
+
 #include "gt-c-family-c-common.h"
index 0b4d993c3c9cbaac40c027a29df2cfb3776c1b0b..ff4530f630e8003675b3ba37e8478c0425eb8835 100644 (file)
@@ -1451,5 +1451,6 @@ extern tree cilk_for_number_of_iterations (tree);
 extern bool check_no_cilk (tree, const char *, const char *,
                           location_t loc = UNKNOWN_LOCATION);
 extern bool reject_gcc_builtin (const_tree, location_t = UNKNOWN_LOCATION);
+extern void warn_duplicated_cond_add_or_warn (location_t, tree, vec<tree> **);
 
 #endif /* ! GCC_C_COMMON_H */
index b79c1439713391d29ab4eeecfc3589bd2c4b5499..a79b9f1a39f90d4684db3061c87a4ca66f0714f3 100644 (file)
@@ -406,6 +406,10 @@ Wdiv-by-zero
 C ObjC C++ ObjC++ Var(warn_div_by_zero) Init(1) Warning
 Warn about compile-time integer division by zero
 
+Wduplicated-cond
+C ObjC C++ ObjC++ Var(warn_duplicated_cond) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn about duplicated conditions in an if-else-if chain
+
 Weffc++
 C++ ObjC++ Var(warn_ecpp) Warning
 Warn about violations of Effective C++ style rules
index 577fdc020bf0b3a2f460a71eab01ef8e85189664..7c0051f20f63294e40392c455e15120ed4e10ba6 100644 (file)
@@ -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.
index 2fab3f0ebe404f207f6d55b14a0d0d7dc110a2f4..00fa2386c46d58034954574c1e1fe12d181b6588 100644 (file)
@@ -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);
 
index 72c3bf93b09df01d61debb82dafe9833b3bf79fb..e6e2e0caf0d565afa294c877ab05c4b4394499de 100644 (file)
@@ -1,3 +1,13 @@
+2015-10-02  Marek Polacek  <polacek@redhat.com>
+
+       PR c/64249
+       * 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.
+
 2015-10-01  Ville Voutilainen  <ville.voutilainen@gmail.com>
 
        PR c++/54430
index 8aeca4063dbb8ec491d6841ccb850e8426ec013b..46aff88f61e5f455b7c4c4e7591b77d2e2256259 100644 (file)
@@ -2023,7 +2023,7 @@ static void cp_parser_lambda_body
 /* Statements [gram.stmt.stmt]  */
 
 static void cp_parser_statement
-  (cp_parser *, tree, bool, bool *);
+  (cp_parser *, tree, bool, bool *, vec<tree> * = NULL);
 static void cp_parser_label_for_labeled_statement
 (cp_parser *, tree);
 static tree cp_parser_expression_statement
@@ -2033,7 +2033,7 @@ static tree cp_parser_compound_statement
 static void cp_parser_statement_seq_opt
   (cp_parser *, tree);
 static tree cp_parser_selection_statement
-  (cp_parser *, bool *);
+  (cp_parser *, bool *, vec<tree> *);
 static tree cp_parser_condition
   (cp_parser *);
 static tree cp_parser_iteration_statement
@@ -2058,7 +2058,7 @@ static void cp_parser_declaration_statement
   (cp_parser *);
 
 static tree cp_parser_implicitly_scoped_statement
-  (cp_parser *, bool *, const token_indent_info &);
+  (cp_parser *, bool *, const token_indent_info &, vec<tree> * = NULL);
 static void cp_parser_already_scoped_statement
   (cp_parser *, const token_indent_info &);
 
@@ -9923,11 +9923,13 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr)
 
   If IF_P is not NULL, *IF_P is set to indicate whether the statement
   is a (possibly labeled) if statement which is not enclosed in braces
-  and has an else clause.  This is used to implement -Wparentheses.  */
+  and has an else clause.  This is used to implement -Wparentheses.
+
+  CHAIN is a vector of if-else-if conditions.  */
 
 static void
 cp_parser_statement (cp_parser* parser, tree in_statement_expr,
-                    bool in_compound, bool *if_p)
+                    bool in_compound, bool *if_p, vec<tree> *chain)
 {
   tree statement, std_attrs = NULL_TREE;
   cp_token *token;
@@ -9975,7 +9977,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
 
        case RID_IF:
        case RID_SWITCH:
-         statement = cp_parser_selection_statement (parser, if_p);
+         statement = cp_parser_selection_statement (parser, if_p, chain);
          break;
 
        case RID_WHILE:
@@ -10404,10 +10406,14 @@ cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr)
    If IF_P is not NULL, *IF_P is set to indicate whether the statement
    is a (possibly labeled) if statement which is not enclosed in
    braces and has an else clause.  This is used to implement
-   -Wparentheses.  */
+   -Wparentheses.
+
+   CHAIN is a vector of if-else-if conditions.  This is used to implement
+   -Wduplicated-cond.  */
 
 static tree
-cp_parser_selection_statement (cp_parser* parser, bool *if_p)
+cp_parser_selection_statement (cp_parser* parser, bool *if_p,
+                              vec<tree> *chain)
 {
   cp_token *token;
   enum rid keyword;
@@ -10458,6 +10464,10 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p)
            /* Add the condition.  */
            finish_if_stmt_cond (condition, statement);
 
+           if (warn_duplicated_cond)
+             warn_duplicated_cond_add_or_warn (token->location, condition,
+                                               &chain);
+
            /* Parse the then-clause.  */
            in_statement = parser->in_statement;
            parser->in_statement |= IN_IF_STMT;
@@ -10475,10 +10485,41 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p)
                  = get_token_indent_info (cp_lexer_peek_token (parser->lexer));
                /* Consume the `else' keyword.  */
                cp_lexer_consume_token (parser->lexer);
+               if (warn_duplicated_cond)
+                 {
+                   if (cp_lexer_next_token_is_keyword (parser->lexer,
+                                                       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 (condition)
+                           && !TREE_SIDE_EFFECTS (condition))
+                       {
+                         /* Wrap it in a NOP_EXPR so that we can set the
+                            location of the condition.  */
+                         tree e = build1 (NOP_EXPR, TREE_TYPE (condition),
+                                          condition);
+                         SET_EXPR_LOCATION (e, token->location);
+                         chain->safe_push (e);
+                       }
+                     }
+                   else if (!cp_lexer_next_token_is_keyword (parser->lexer,
+                                                             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;
+                     }
+                 }
                begin_else_clause (statement);
                /* Parse the else-clause.  */
                cp_parser_implicitly_scoped_statement (parser, NULL,
-                                                      guard_tinfo);
+                                                      guard_tinfo, chain);
 
                finish_else_clause (statement);
 
@@ -10500,6 +10541,12 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p)
                  warning_at (EXPR_LOCATION (statement), OPT_Wparentheses,
                              "suggest explicit braces to avoid ambiguous"
                              " %<else%>");
+               if (warn_duplicated_cond)
+                 {
+                   /* We don't need the condition chain anymore.  */
+                   delete chain;
+                   chain = NULL;
+                 }
              }
 
            /* Now we're all done with the if-statement.  */
@@ -11419,11 +11466,15 @@ cp_parser_declaration_statement (cp_parser* parser)
    braces and has an else clause.  This is used to implement
    -Wparentheses.
 
+   CHAIN is a vector of if-else-if conditions.  This is used to implement
+   -Wduplicated-cond.
+
    Returns the new statement.  */
 
 static tree
 cp_parser_implicitly_scoped_statement (cp_parser* parser, bool *if_p,
-                                      const token_indent_info &guard_tinfo)
+                                      const token_indent_info &guard_tinfo,
+                                      vec<tree> *chain)
 {
   tree statement;
   location_t body_loc = cp_lexer_peek_token (parser->lexer)->location;
@@ -11456,7 +11507,7 @@ cp_parser_implicitly_scoped_statement (cp_parser* parser, bool *if_p,
       /* Create a compound-statement.  */
       statement = begin_compound_stmt (0);
       /* Parse the dependent-statement.  */
-      cp_parser_statement (parser, NULL_TREE, false, if_p);
+      cp_parser_statement (parser, NULL_TREE, false, if_p, chain);
       /* Finish the dummy compound-statement.  */
       finish_compound_stmt (statement);
     }
index ebfaaa132fac044dbddc64ed789796eb7631b3f7..2a6c3978ed43e8a0e2d8340a6221c1d1e71b1cef 100644 (file)
@@ -242,7 +242,7 @@ Objective-C and Objective-C++ Dialects}.
 -pedantic-errors @gol
 -w  -Wextra  -Wall  -Waddress  -Waggregate-return  @gol
 -Waggressive-loop-optimizations -Warray-bounds -Warray-bounds=@var{n} @gol
--Wbool-compare -Wframe-address @gol
+-Wbool-compare -Wduplicated-cond -Wframe-address @gol
 -Wno-attributes -Wno-builtin-macro-redefined @gol
 -Wc90-c99-compat -Wc99-c11-compat @gol
 -Wc++-compat -Wc++11-compat -Wc++14-compat -Wcast-align  -Wcast-qual  @gol
@@ -3522,6 +3522,7 @@ Options} and @ref{Objective-C and Objective-C++ Dialect Options}.
 -Wimplicit-int @r{(C and Objective-C only)} @gol
 -Wimplicit-function-declaration @r{(C and Objective-C only)} @gol
 -Wbool-compare  @gol
+-Wduplicated-cond  @gol
 -Wcomment  @gol
 -Wformat   @gol
 -Wmain @r{(only for C/ObjC and unless} @option{-ffreestanding}@r{)}  @gol
@@ -4553,6 +4554,17 @@ if ((n > 1) == 2) @{ @dots{} @}
 @end smallexample
 This warning is enabled by @option{-Wall}.
 
+@item -Wduplicated-cond
+@opindex Wno-duplicated-cond
+@opindex Wduplicated-cond
+Warn about duplicated conditions in an if-else-if chain.  For instance,
+warn for the following code:
+@smallexample
+if (p->q != NULL) @{ @dots{} @}
+else if (p->q != NULL) @{ @dots{} @}
+@end smallexample
+This warning is enabled by @option{-Wall}.
+
 @item -Wframe-address
 @opindex Wno-frame-address
 @opindex Wframe-address
index a2c474dacd6101996d11df35e7c5af41800b69f9..13f911955bcfdbd96e45b4bcd2beac2648851c5a 100644 (file)
@@ -179,10 +179,10 @@ gen_exp (rtx x, enum rtx_code subroutine_type, char *used)
       else if (INTVAL (x) == -1)
        printf ("constm1_rtx");
       else if (-MAX_SAVED_CONST_INT <= INTVAL (x)
-         && INTVAL (x) <= MAX_SAVED_CONST_INT)
+              && INTVAL (x) <= MAX_SAVED_CONST_INT)
        printf ("const_int_rtx[MAX_SAVED_CONST_INT + (%d)]",
                (int) INTVAL (x));
-      else if (INTVAL (x) == STORE_FLAG_VALUE)
+      else if (STORE_FLAG_VALUE > 1 && INTVAL (x) == STORE_FLAG_VALUE)
        printf ("const_true_rtx");
       else
        {
index c95cda9e0d9b751225656c6cee611e70ebbd0676..ced7d33bfaf5eeee1cedfde1e5dcbbf21918aab4 100644 (file)
@@ -1,3 +1,13 @@
+2015-10-02  Marek Polacek  <polacek@redhat.com>
+
+       PR c/64249
+       * 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.
+
 2015-10-02  Renlin Li  <renlin.li@arm.com>
 
        * gcc.target/aarch64/csneg-1.c: Update.
diff --git a/gcc/testsuite/c-c++-common/Wduplicated-cond-1.c b/gcc/testsuite/c-c++-common/Wduplicated-cond-1.c
new file mode 100644 (file)
index 0000000..4763a84
--- /dev/null
@@ -0,0 +1,200 @@
+/* PR c/64249 */
+/* { dg-do compile } */
+/* { dg-options "-Wduplicated-cond" } */
+
+#ifndef __cplusplus
+# define bool _Bool
+# define true 1
+# define false 0
+#endif
+
+extern int foo (void);
+
+int
+fn1 (int n)
+{
+  if (n == 1) /* { dg-message "previously used here" } */
+    return -1;
+  else if (n == 2)
+    return 0;
+  else if (n == 1) /* { dg-warning "duplicated .if. condition" } */
+    return 1;
+  return 0;
+}
+
+int
+fn2 (void)
+{
+  if (4)
+    return 1;
+  else if (4)
+    return 2;
+
+#define N 10
+  if (N)
+    return 3;
+  else if (N)
+    return 4;
+}
+
+int
+fn3 (int n)
+{
+  if (n == 42)
+    return 1;
+  if (n == 42)
+    return 2;
+
+  if (n)
+    if (n)
+      if (n)
+       if (n)
+         return 42;
+
+  if (!n)
+    return 10;
+  else
+    return 11;
+}
+
+int
+fn4 (int n)
+{
+  if (n > 0)
+    {
+      if (n == 1) /* { dg-message "previously used here" } */
+       return 1;
+      else if (n == 1) /* { dg-warning "duplicated .if. condition" } */
+       return 2;
+    }
+  else if (n < 0)
+    {
+      if (n < -1)
+       return 6;
+      else if (n < -2)
+       {
+         if (n == -10) /* { dg-message "previously used here" } */
+           return 3;
+         else if (n == -10) /* { dg-warning "duplicated .if. condition" } */
+           return 4;
+       }
+    }
+  else
+    return 7;
+  return 0;
+}
+
+struct S { long p, q; };
+
+int
+fn5 (struct S *s)
+{
+  if (!s->p) /* { dg-message "previously used here" } */
+    return 12345;
+  else if (!s->p) /* { dg-warning "duplicated .if. condition" } */
+    return 1234;
+  return 0;
+}
+
+int
+fn6 (int n)
+{
+  if (n) /* { dg-message "previously used here" } */
+    return n;
+  else if (n) /* { dg-warning "duplicated .if. condition" } */
+    return n;
+  else if (n) /* { dg-warning "duplicated .if. condition" } */
+    return n;
+  else if (n) /* { dg-warning "duplicated .if. condition" } */
+    return n;
+  else if (n) /* { dg-warning "duplicated .if. condition" } */
+    return n;
+  else if (n) /* { dg-warning "duplicated .if. condition" } */
+    return n;
+  else if (n) /* { dg-warning "duplicated .if. condition" } */
+    return n;
+  else if (n) /* { dg-warning "duplicated .if. condition" } */
+    return n;
+  return 0;
+}
+
+int
+fn7 (int n)
+{
+  if (n == 0) /* { dg-message "previously used here" } */
+    return 10;
+  else if (n == 1) /* { dg-message "previously used here" } */
+    return 11;
+  else if (n == 2) /* { dg-message "previously used here" } */
+    return 12;
+  else if (n == 3) /* { dg-message "previously used here" } */
+    return 13;
+  else if (n == 4) /* { dg-message "previously used here" } */
+    return 14;
+  else if (n == 5) /* { dg-message "previously used here" } */
+    return 15;
+  else if (n == 6) /* { dg-message "previously used here" } */
+    return 16;
+  else if (n == 7) /* { dg-message "previously used here" } */
+    return 17;
+  else if (n == 0) /* { dg-warning "duplicated .if. condition" } */
+    return 100;
+  else if (n == 1) /* { dg-warning "duplicated .if. condition" } */
+    return 101;
+  else if (n == 2) /* { dg-warning "duplicated .if. condition" } */
+    return 102;
+  else if (n == 3) /* { dg-warning "duplicated .if. condition" } */
+    return 103;
+  else if (n == 4) /* { dg-warning "duplicated .if. condition" } */
+    return 104;
+  else if (n == 5) /* { dg-warning "duplicated .if. condition" } */
+    return 105;
+  else if (n == 6) /* { dg-warning "duplicated .if. condition" } */
+    return 106;
+  else if (n == 7) /* { dg-warning "duplicated .if. condition" } */
+    return 107;
+  return 0;
+}
+
+int
+fn8 (bool b)
+{
+  if (!b) /* { dg-message "previously used here" } */
+    return 16;
+  else if (!b) /* { dg-warning "duplicated .if. condition" } */
+    return 27;
+  else
+    return 64;
+}
+
+int
+fn9 (int i, int j, int k)
+{
+  if (i > 0 && j > 0 && k > 0) /* { dg-message "previously used here" } */
+    return -999;
+  else
+  if (i > 0 && j > 0 && k > 0) /* { dg-warning "duplicated .if. condition" } */
+    return 999;
+  else
+    return 0;
+}
+
+int
+fn10 (void)
+{
+  if (foo ())
+    return 1732984;
+  else if (foo ())
+    return 18409;
+  return 0;
+}
+
+int
+fn11 (int n)
+{
+  if (++n == 10)
+    return 666;
+  else if (++n == 10)
+    return 9;
+  return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/Wduplicated-cond-2.c b/gcc/testsuite/c-c++-common/Wduplicated-cond-2.c
new file mode 100644 (file)
index 0000000..90a8663
--- /dev/null
@@ -0,0 +1,200 @@
+/* PR c/64249 */
+/* { dg-do compile } */
+/* { dg-options "-Wall" } */
+
+#ifndef __cplusplus
+# define bool _Bool
+# define true 1
+# define false 0
+#endif
+
+extern int foo (void);
+
+int
+fn1 (int n)
+{
+  if (n == 1) /* { dg-message "previously used here" } */
+    return -1;
+  else if (n == 2)
+    return 0;
+  else if (n == 1) /* { dg-warning "duplicated .if. condition" } */
+    return 1;
+  return 0;
+}
+
+int
+fn2 (void)
+{
+  if (4)
+    return 1;
+  else if (4)
+    return 2;
+
+#define N 10
+  if (N)
+    return 3;
+  else if (N)
+    return 4;
+}
+
+int
+fn3 (int n)
+{
+  if (n == 42)
+    return 1;
+  if (n == 42)
+    return 2;
+
+  if (n)
+    if (n)
+      if (n)
+       if (n)
+         return 42;
+
+  if (!n)
+    return 10;
+  else
+    return 11;
+}
+
+int
+fn4 (int n)
+{
+  if (n > 0)
+    {
+      if (n == 1) /* { dg-message "previously used here" } */
+       return 1;
+      else if (n == 1) /* { dg-warning "duplicated .if. condition" } */
+       return 2;
+    }
+  else if (n < 0)
+    {
+      if (n < -1)
+       return 6;
+      else if (n < -2)
+       {
+         if (n == -10) /* { dg-message "previously used here" } */
+           return 3;
+         else if (n == -10) /* { dg-warning "duplicated .if. condition" } */
+           return 4;
+       }
+    }
+  else
+    return 7;
+  return 0;
+}
+
+struct S { long p, q; };
+
+int
+fn5 (struct S *s)
+{
+  if (!s->p) /* { dg-message "previously used here" } */
+    return 12345;
+  else if (!s->p) /* { dg-warning "duplicated .if. condition" } */
+    return 1234;
+  return 0;
+}
+
+int
+fn6 (int n)
+{
+  if (n) /* { dg-message "previously used here" } */
+    return n;
+  else if (n) /* { dg-warning "duplicated .if. condition" } */
+    return n;
+  else if (n) /* { dg-warning "duplicated .if. condition" } */
+    return n;
+  else if (n) /* { dg-warning "duplicated .if. condition" } */
+    return n;
+  else if (n) /* { dg-warning "duplicated .if. condition" } */
+    return n;
+  else if (n) /* { dg-warning "duplicated .if. condition" } */
+    return n;
+  else if (n) /* { dg-warning "duplicated .if. condition" } */
+    return n;
+  else if (n) /* { dg-warning "duplicated .if. condition" } */
+    return n;
+  return 0;
+}
+
+int
+fn7 (int n)
+{
+  if (n == 0) /* { dg-message "previously used here" } */
+    return 10;
+  else if (n == 1) /* { dg-message "previously used here" } */
+    return 11;
+  else if (n == 2) /* { dg-message "previously used here" } */
+    return 12;
+  else if (n == 3) /* { dg-message "previously used here" } */
+    return 13;
+  else if (n == 4) /* { dg-message "previously used here" } */
+    return 14;
+  else if (n == 5) /* { dg-message "previously used here" } */
+    return 15;
+  else if (n == 6) /* { dg-message "previously used here" } */
+    return 16;
+  else if (n == 7) /* { dg-message "previously used here" } */
+    return 17;
+  else if (n == 0) /* { dg-warning "duplicated .if. condition" } */
+    return 100;
+  else if (n == 1) /* { dg-warning "duplicated .if. condition" } */
+    return 101;
+  else if (n == 2) /* { dg-warning "duplicated .if. condition" } */
+    return 102;
+  else if (n == 3) /* { dg-warning "duplicated .if. condition" } */
+    return 103;
+  else if (n == 4) /* { dg-warning "duplicated .if. condition" } */
+    return 104;
+  else if (n == 5) /* { dg-warning "duplicated .if. condition" } */
+    return 105;
+  else if (n == 6) /* { dg-warning "duplicated .if. condition" } */
+    return 106;
+  else if (n == 7) /* { dg-warning "duplicated .if. condition" } */
+    return 107;
+  return 0;
+}
+
+int
+fn8 (bool b)
+{
+  if (!b) /* { dg-message "previously used here" } */
+    return 16;
+  else if (!b) /* { dg-warning "duplicated .if. condition" } */
+    return 27;
+  else
+    return 64;
+}
+
+int
+fn9 (int i, int j, int k)
+{
+  if (i > 0 && j > 0 && k > 0) /* { dg-message "previously used here" } */
+    return -999;
+  else
+  if (i > 0 && j > 0 && k > 0) /* { dg-warning "duplicated .if. condition" } */
+    return 999;
+  else
+    return 0;
+}
+
+int
+fn10 (void)
+{
+  if (foo ())
+    return 1732984;
+  else if (foo ())
+    return 18409;
+  return 0;
+}
+
+int
+fn11 (int n)
+{
+  if (++n == 10)
+    return 666;
+  else if (++n == 10)
+    return 9;
+  return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/Wduplicated-cond-3.c b/gcc/testsuite/c-c++-common/Wduplicated-cond-3.c
new file mode 100644 (file)
index 0000000..e3b5ac0
--- /dev/null
@@ -0,0 +1,204 @@
+/* PR c/64249 */
+/* { dg-do compile } */
+/* { dg-options "-Wall -Wno-duplicated-cond" } */
+
+#ifndef __cplusplus
+# define bool _Bool
+# define true 1
+# define false 0
+#endif
+
+extern int foo (void);
+
+int
+fn1 (int n)
+{
+  if (n == 1)
+    return -1;
+  else if (n == 2)
+    return 0;
+  else if (n == 1)
+    return 1;
+  return 0;
+}
+
+int
+fn2 (void)
+{
+  if (4)
+    return 1;
+  else if (4)
+    return 2;
+
+#define N 10
+  if (N)
+    return 3;
+  else if (N)
+    return 4;
+}
+
+int
+fn3 (int n)
+{
+  if (n == 42)
+    return 1;
+  if (n == 42)
+    return 2;
+
+  if (n)
+    if (n)
+      if (n)
+       if (n)
+         return 42;
+
+  if (!n)
+    return 10;
+  else
+    return 11;
+}
+
+int
+fn4 (int n)
+{
+  if (n > 0)
+    {
+      if (n == 1)
+       return 1;
+      else if (n == 1)
+       return 2;
+    }
+  else if (n < 0)
+    {
+      if (n < -1)
+       return 6;
+      else if (n < -2)
+       {
+         if (n == -10)
+           return 3;
+         else if (n == -10)
+           return 4;
+       }
+    }
+  else
+    return 7;
+  return 0;
+}
+
+struct S { long p, q; };
+
+int
+fn5 (struct S *s)
+{
+  if (!s->p)
+    return 12345;
+  else if (!s->p)
+    return 1234;
+  return 0;
+}
+
+int
+fn6 (int n)
+{
+  if (n)
+    return n;
+  else if (n)
+    return n;
+  else if (n)
+    return n;
+  else if (n)
+    return n;
+  else if (n)
+    return n;
+  else if (n)
+    return n;
+  else if (n)
+    return n;
+  else if (n)
+    return n;
+  return 0;
+}
+
+int
+fn7 (int n)
+{
+  if (n == 0)
+    return 10;
+  else if (n == 1)
+    return 11;
+  else if (n == 2)
+    return 12;
+  else if (n == 3)
+    return 13;
+  else if (n == 4)
+    return 14;
+  else if (n == 5)
+    return 15;
+  else if (n == 6)
+    return 16;
+  else if (n == 7)
+    return 17;
+  else if (n == 0)
+    return 100;
+  else if (n == 1)
+    return 101;
+  else if (n == 2)
+    return 102;
+  else if (n == 3)
+    return 103;
+  else if (n == 4)
+    return 104;
+  else if (n == 5)
+    return 105;
+  else if (n == 6)
+    return 106;
+  else if (n == 7)
+    return 107;
+  return 0;
+}
+
+int
+fn8 (bool b)
+{
+  if (!b)
+    return 16;
+  else if (!b)
+    return 27;
+  else
+    return 64;
+}
+
+int
+fn9 (int i, int j, int k)
+{
+  if ((i > 0 && j > 0 && k > 0)
+      && ((i > 11 && j == 76 && k < 10)
+         || (i < 0 && j == 99 && k > 103)))
+    return -999;
+  else
+  if ((i > 0 && j > 0 && k > 0)
+      && ((i > 11 && j == 76 && k < 10)
+         || (i < 0 && j == 99 && k > 103)))
+    return 999;
+  else
+    return 0;
+}
+
+int
+fn10 (void)
+{
+  if (foo ())
+    return 1732984;
+  else if (foo ())
+    return 18409;
+  return 0;
+}
+
+int
+fn11 (int n)
+{
+  if (++n == 10)
+    return 666;
+  else if (++n == 10)
+    return 9;
+  return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/Wduplicated-cond-4.c b/gcc/testsuite/c-c++-common/Wduplicated-cond-4.c
new file mode 100644 (file)
index 0000000..4fb7e17
--- /dev/null
@@ -0,0 +1,32 @@
+/* PR c/64249 */
+/* { dg-do compile } */
+/* { dg-options "-Wduplicated-cond" } */
+/* Test we don't warn if a condition in an if-else-if chain
+   has a side-effect.  E.g. __cxxabiv1::__cxa_end_catch ()
+   uses such a construction.  */
+
+extern int a, bar (void);
+
+int
+fn1 (void)
+{
+  if (a)
+    return 1;
+  else if (bar ())
+    return 2;
+  else if (a)
+    return 3;
+  return 0;
+}
+
+int
+fn2 (int c)
+{
+  if (c < 0)
+    return 1;
+  else if (--c == 0)
+    return 2;
+  else if (c < 0)
+    return 3;
+  return 0;
+}
index 00c0a505386fe318b3dff7ef3381f52a4473df05..a3f5acdd533e74389e376b059255878efec51a44 100644 (file)
@@ -708,7 +708,7 @@ fn_37 (void)
 
   if (flagA)
     ;
-  else if (flagA); /* { dg-message "8: ...this 'if' clause" } */
+  else if (flagB); /* { dg-message "8: ...this 'if' clause" } */
     foo (0); /* { dg-warning "statement is indented as if" } */
   while (flagA) /* { dg-message "3: ...this 'while' clause" } */
     /* blah */;
@@ -716,13 +716,13 @@ fn_37 (void)
 
   if (flagA)
     ;
-  else if (flagA) /* { dg-message "8: ...this 'if' clause" } */
+  else if (flagB) /* { dg-message "8: ...this 'if' clause" } */
     foo (1);
     foo (2); /* { dg-warning "statement is indented as if" } */
 
   if (flagA)
     foo (1);
-  else if (flagA) /* { dg-message "8: ...this 'if' clause" } */
+  else if (flagB) /* { dg-message "8: ...this 'if' clause" } */
     foo (2);
     foo (3); /* { dg-warning "statement is indented as if" } */