+2017-01-20 Marek Polacek <polacek@redhat.com>
+
+ PR c/64279
+ * doc/invoke.texi: Document -Wduplicated-branches.
+ * fold-const.c (operand_equal_p): Handle MODIFY_EXPR, INIT_EXPR,
+ COMPOUND_EXPR, PREDECREMENT_EXPR, PREINCREMENT_EXPR,
+ POSTDECREMENT_EXPR, POSTINCREMENT_EXPR, CLEANUP_POINT_EXPR, EXPR_STMT,
+ STATEMENT_LIST, and RETURN_EXPR. For non-pure non-const functions
+ return 0 only when not OEP_LEXICOGRAPHIC.
+ (fold_build_cleanup_point_expr): Use the expression
+ location when building CLEANUP_POINT_EXPR.
+ * tree-core.h (enum operand_equal_flag): Add OEP_LEXICOGRAPHIC.
+ * tree.c (add_expr): Handle error_mark_node.
+
2017-01-20 Martin Liska <mliska@suse.cz>
PR lto/69188
+2017-01-20 Marek Polacek <polacek@redhat.com>
+
+ PR c/64279
+ * c-common.h (do_warn_duplicated_branches_r): Declare.
+ * c-gimplify.c (c_genericize): Walk the function tree calling
+ do_warn_duplicated_branches_r.
+ * c-warn.c (expr_from_macro_expansion_r): New.
+ (do_warn_duplicated_branches): New.
+ (do_warn_duplicated_branches_r): New.
+ * c.opt (Wduplicated-branches): New option.
+
2017-01-17 David Malcolm <dmalcolm@redhat.com>
PR c++/71497
extern bool maybe_warn_shift_overflow (location_t, tree, tree);
extern void warn_duplicated_cond_add_or_warn (location_t, tree, vec<tree> **);
extern bool diagnose_mismatched_attributes (tree, tree);
+extern tree do_warn_duplicated_branches_r (tree *, int *, void *);
/* In c-attribs.c. */
extern bool attribute_takes_identifier_p (const_tree);
&pset);
}
+ if (warn_duplicated_branches)
+ walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
+ do_warn_duplicated_branches_r, NULL);
+
/* Dump the C-specific tree IR. */
dump_orig = get_dump_info (TDI_original, &local_dump_flags);
if (dump_orig)
free (arg_positions);
}
+
+/* Callback function to determine whether an expression TP or one of its
+ subexpressions comes from macro expansion. Used to suppress bogus
+ warnings. */
+
+static tree
+expr_from_macro_expansion_r (tree *tp, int *, void *)
+{
+ if (CAN_HAVE_LOCATION_P (*tp)
+ && from_macro_expansion_at (EXPR_LOCATION (*tp)))
+ return integer_zero_node;
+
+ return NULL_TREE;
+}
+
+/* Possibly warn when an if-else has identical branches. */
+
+static void
+do_warn_duplicated_branches (tree expr)
+{
+ tree thenb = COND_EXPR_THEN (expr);
+ tree elseb = COND_EXPR_ELSE (expr);
+
+ /* Don't bother if there's no else branch. */
+ if (elseb == NULL_TREE)
+ return;
+
+ /* And don't warn for empty statements. */
+ if (TREE_CODE (thenb) == NOP_EXPR
+ && TREE_TYPE (thenb) == void_type_node
+ && TREE_OPERAND (thenb, 0) == size_zero_node)
+ return;
+
+ /* ... or empty branches. */
+ if (TREE_CODE (thenb) == STATEMENT_LIST
+ && STATEMENT_LIST_HEAD (thenb) == NULL)
+ return;
+
+ /* Compute the hash of the then branch. */
+ inchash::hash hstate0 (0);
+ inchash::add_expr (thenb, hstate0);
+ hashval_t h0 = hstate0.end ();
+
+ /* Compute the hash of the else branch. */
+ inchash::hash hstate1 (0);
+ inchash::add_expr (elseb, hstate1);
+ hashval_t h1 = hstate1.end ();
+
+ /* Compare the hashes. */
+ if (h0 == h1
+ && operand_equal_p (thenb, elseb, OEP_LEXICOGRAPHIC)
+ /* Don't warn if any of the branches or their subexpressions comes
+ from a macro. */
+ && !walk_tree_without_duplicates (&thenb, expr_from_macro_expansion_r,
+ NULL)
+ && !walk_tree_without_duplicates (&elseb, expr_from_macro_expansion_r,
+ NULL))
+ warning_at (EXPR_LOCATION (expr), OPT_Wduplicated_branches,
+ "this condition has identical branches");
+}
+
+/* Callback for c_genericize to implement -Wduplicated-branches. */
+
+tree
+do_warn_duplicated_branches_r (tree *tp, int *, void *)
+{
+ if (TREE_CODE (*tp) == COND_EXPR)
+ do_warn_duplicated_branches (*tp);
+ return NULL_TREE;
+}
C ObjC C++ ObjC++ Var(warn_div_by_zero) Init(1) Warning
Warn about compile-time integer division by zero.
+Wduplicated-branches
+C ObjC C++ ObjC++ Var(warn_duplicated_branches) Init(0) Warning
+Warn about duplicated branches in if-else statements.
+
Wduplicated-cond
C ObjC C++ ObjC++ Var(warn_duplicated_cond) Init(0) Warning
Warn about duplicated conditions in an if-else-if chain.
+2017-01-20 Marek Polacek <polacek@redhat.com>
+
+ PR c/64279
+ * c-typeck.c (build_conditional_expr): Warn about duplicated branches.
+
2017-01-13 Richard Biener <rguenther@suse.de>
* gimple-parser.c (c_parser_gimple_compound_statement): Handle
ret = build1 (EXCESS_PRECISION_EXPR, semantic_result_type, ret);
protected_set_expr_location (ret, colon_loc);
+
+ /* If the OP1 and OP2 are the same and don't have side-effects,
+ warn here, because the COND_EXPR will be turned into OP1. */
+ if (warn_duplicated_branches
+ && TREE_CODE (ret) == COND_EXPR
+ && (op1 == op2 || operand_equal_p (op1, op2, 0)))
+ warning_at (EXPR_LOCATION (ret), OPT_Wduplicated_branches,
+ "this condition has identical branches");
+
return ret;
}
\f
+2017-01-20 Marek Polacek <polacek@redhat.com>
+
+ PR c/64279
+ * call.c (build_conditional_expr_1): Warn about duplicated branches.
+ * semantics.c (finish_expr_stmt): Build statement using the proper
+ location.
+
2017-01-19 Jason Merrill <jason@redhat.com>
US 20 - forwarding references and class template argument deduction
valid_operands:
result = build3_loc (loc, COND_EXPR, result_type, arg1, arg2, arg3);
+ /* If the ARG2 and ARG3 are the same and don't have side-effects,
+ warn here, because the COND_EXPR will be turned into ARG2. */
+ if (warn_duplicated_branches
+ && (arg2 == arg3 || operand_equal_p (arg2, arg3, 0)))
+ warning_at (EXPR_LOCATION (result), OPT_Wduplicated_branches,
+ "this condition has identical branches");
+
/* We can't use result_type below, as fold might have returned a
throw_expr. */
finish_expr_stmt (tree expr)
{
tree r = NULL_TREE;
+ location_t loc = EXPR_LOCATION (expr);
if (expr != NULL_TREE)
{
if (TREE_CODE (expr) != CLEANUP_POINT_EXPR)
{
if (TREE_CODE (expr) != EXPR_STMT)
- expr = build_stmt (input_location, EXPR_STMT, expr);
+ expr = build_stmt (loc, EXPR_STMT, expr);
expr = maybe_cleanup_point_expr_void (expr);
}
-Warray-bounds=1 @r{(only with} @option{-O2}@r{)} @gol
-Wbool-compare @gol
-Wbool-operation @gol
--Wc++11-compat -Wc++14-compat@gol
+-Wc++11-compat -Wc++14-compat @gol
-Wchar-subscripts @gol
-Wcomment @gol
-Wduplicate-decl-specifier @r{(C and Objective-C only)} @gol
This warning is enabled by @option{-Wall}.
+@item -Wduplicated-branches
+@opindex Wno-duplicated-branches
+@opindex Wduplicated-branches
+Warn when an if-else has identical branches. This warning detects cases like
+@smallexample
+if (p != NULL)
+ return 0;
+else
+ return 0;
+@end smallexample
+It doesn't warn when both branches contain just a null statement. This warning
+also warn for conditional operators:
+@smallexample
+ int i = x ? *p : *p;
+@end smallexample
+
@item -Wduplicated-cond
@opindex Wno-duplicated-cond
@opindex Wduplicated-cond
If OEP_ADDRESS_OF is set, we are actually comparing addresses of objects,
not values of expressions.
+ If OEP_LEXICOGRAPHIC is set, then also handle expressions with side-effects
+ such as MODIFY_EXPR, RETURN_EXPR, as well as STATEMENT_LISTs.
+
Unless OEP_MATCH_SIDE_EFFECTS is set, the function returns false on
any operand with side effect. This is unnecesarily conservative in the
case we know that arg0 and arg1 are in disjoint code paths (such as in
case BIT_INSERT_EXPR:
return OP_SAME (0) && OP_SAME (1) && OP_SAME (2);
+ case MODIFY_EXPR:
+ case INIT_EXPR:
+ case COMPOUND_EXPR:
+ case PREDECREMENT_EXPR:
+ case PREINCREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ case POSTINCREMENT_EXPR:
+ if (flags & OEP_LEXICOGRAPHIC)
+ return OP_SAME (0) && OP_SAME (1);
+ return 0;
+
+ case CLEANUP_POINT_EXPR:
+ case EXPR_STMT:
+ if (flags & OEP_LEXICOGRAPHIC)
+ return OP_SAME (0);
+ return 0;
+
default:
return 0;
}
cef &= ECF_CONST | ECF_PURE;
else
cef &= ECF_CONST;
- if (!cef)
+ if (!cef && !(flags & OEP_LEXICOGRAPHIC))
return 0;
}
}
return 1;
}
+ else if (TREE_CODE (arg0) == STATEMENT_LIST
+ && (flags & OEP_LEXICOGRAPHIC))
+ {
+ /* Compare the STATEMENT_LISTs. */
+ tree_stmt_iterator tsi1, tsi2;
+ tree body1 = CONST_CAST_TREE (arg0);
+ tree body2 = CONST_CAST_TREE (arg1);
+ for (tsi1 = tsi_start (body1), tsi2 = tsi_start (body2); ;
+ tsi_next (&tsi1), tsi_next (&tsi2))
+ {
+ /* The lists don't have the same number of statements. */
+ if (tsi_end_p (tsi1) ^ tsi_end_p (tsi2))
+ return 0;
+ if (tsi_end_p (tsi1) && tsi_end_p (tsi2))
+ return 1;
+ if (!operand_equal_p (tsi_stmt (tsi1), tsi_stmt (tsi2),
+ OEP_LEXICOGRAPHIC))
+ return 0;
+ }
+ }
return 0;
+ case tcc_statement:
+ switch (TREE_CODE (arg0))
+ {
+ case RETURN_EXPR:
+ if (flags & OEP_LEXICOGRAPHIC)
+ return OP_SAME_WITH_NULL (0);
+ return 0;
+ default:
+ return 0;
+ }
+
default:
return 0;
}
return expr;
}
- return build1 (CLEANUP_POINT_EXPR, type, expr);
+ return build1_loc (EXPR_LOCATION (expr), CLEANUP_POINT_EXPR, type, expr);
}
/* Given a pointer value OP0 and a type TYPE, return a simplified version
+2017-01-20 Marek Polacek <polacek@redhat.com>
+
+ PR c/64279
+ * c-c++-common/Wduplicated-branches-1.c: New test.
+ * c-c++-common/Wduplicated-branches-10.c: New test.
+ * c-c++-common/Wduplicated-branches-11.c: New test.
+ * c-c++-common/Wduplicated-branches-12.c: New test.
+ * c-c++-common/Wduplicated-branches-2.c: New test.
+ * c-c++-common/Wduplicated-branches-3.c: New test.
+ * c-c++-common/Wduplicated-branches-4.c: New test.
+ * c-c++-common/Wduplicated-branches-5.c: New test.
+ * c-c++-common/Wduplicated-branches-6.c: New test.
+ * c-c++-common/Wduplicated-branches-7.c: New test.
+ * c-c++-common/Wduplicated-branches-8.c: New test.
+ * c-c++-common/Wduplicated-branches-9.c: New test.
+ * c-c++-common/Wimplicit-fallthrough-7.c: Coalesce dg-warning.
+ * g++.dg/cpp0x/lambda/lambda-switch.C: Move dg-warning.
+ * g++.dg/ext/builtin-object-size3.C: Likewise.
+ * g++.dg/gomp/loop-1.C: Likewise.
+ * g++.dg/warn/Wduplicated-branches1.C: New test.
+ * g++.dg/warn/Wduplicated-branches2.C: New test.
+
2017-01-20 Martin Liska <mliska@suse.cz>
PR lto/69188
--- /dev/null
+/* PR c/64279 */
+/* { dg-do compile } */
+/* { dg-options "-Wduplicated-branches -O2" } */
+
+extern void foo (int);
+extern int g;
+extern int a[10];
+
+int
+f (int i, int *p)
+{
+ const int j = 0;
+ if (j == 0)
+ {
+ if (i > 10) /* { dg-warning "this condition has identical branches" } */
+ /* Optimizers can figure out that this is 1. */
+ *p = j * 2 + 1;
+ else
+ *p = 1;
+ }
+
+ if (i)
+ ;
+ else
+ ;
+
+ if (i == 0) /* { dg-warning "this condition has identical branches" } */
+ return 0;
+ else
+ return 0;
+
+ if (i == 1) /* { dg-warning "this condition has identical branches" } */
+ {
+ g = 10;
+ }
+ else
+ {
+ g = 10;
+ }
+
+ const char *s;
+ if (i == 2) /* { dg-warning "this condition has identical branches" } */
+ s = "foo";
+ else
+ s = "foo";
+
+ if (i == 3) /* { dg-warning "this condition has identical branches" } */
+ g = a[i];
+ else
+ g = a[i];
+
+ if (i == 4) /* { dg-warning "this condition has identical branches" } */
+ return i ? 1 : g;
+ else
+ return i ? 1 : g;
+
+ if (i == 5) /* { dg-warning "this condition has identical branches" } */
+ {
+ {
+ {
+ {
+ g++;
+ }
+ }
+ }
+ }
+ else
+ {
+ {
+ {
+ {
+ g++;
+ }
+ }
+ }
+ }
+
+ if (i == 6) /* { dg-warning "this condition has identical branches" } */
+ g = i * 6;
+ else
+ g = i * 6;
+
+ /* Don't warn. */
+ if (i == 7)
+ g = i / 6;
+ else
+ g = 6 / i;
+
+ if (i == 8) /* { dg-warning "this condition has identical branches" } */
+ return i * 8 * i * 8;
+ else
+ return 8 * i * 8 * i;
+
+
+ if (i == 9) /* { dg-warning "this condition has identical branches" } */
+ {
+ p++;
+ return *p;
+ }
+ else
+ {
+ p++;
+ return *p;
+ }
+
+ /* Don't warn. */
+ if (i == 10)
+ return *++p;
+ else
+ return ++*p;
+
+ if (i == 11) /* { dg-warning "this condition has identical branches" } */
+ {
+ foo (6);
+ }
+ else
+ {
+ foo (6);
+ }
+
+ if (i == 12) /* { dg-warning "this condition has identical branches" } */
+ {
+ foo (6 + i), foo (2);
+ }
+ else
+ {
+ foo (6 + i), foo (2);
+ }
+
+ if (i == 13) /* { dg-warning "this condition has identical branches" } */
+ p += (g + 1);
+ else
+ p += (g + 1);
+
+ if (i == 14) /* { dg-warning "this condition has identical branches" } */
+ {
+ foo (7);
+ *p = 0;
+ foo (9);
+ }
+ else
+ {
+ foo (7);
+ *p = 0;
+ foo (9);
+ }
+
+ if (i == 15) /* { dg-warning "this condition has identical branches" } */
+ p += (g + (1 + 2));
+ else
+ p += (g + (1 + 1 + 1));
+
+ if (i == 16) /* { dg-warning "this condition has identical branches" } */
+ foo (10 + g);
+ else
+ foo (g + 10);
+
+ if (i == 17) /* { dg-warning "this condition has identical branches" } */
+ ({ foo (i); });
+ else
+ ({ foo (i); });
+
+ if (i == 18)
+ {
+ if (i == 19)
+ {
+ if (i == 20) /* { dg-warning "this condition has identical branches" } */
+ foo (++i);
+ else
+ foo (++i);
+ }
+ }
+
+ /* Don't warn. */
+ if (i == 21)
+ {
+ foo (1);
+ foo (2);
+ }
+ else
+ {
+ foo (2);
+ foo (1);
+ }
+
+ return 0;
+}
--- /dev/null
+/* PR c/64279 */
+/* { dg-do compile } */
+/* { dg-options "-Wduplicated-branches" } */
+
+#define DEBUG(msg) ;
+
+void
+f (int i)
+{
+ if (i > 9)
+ {
+ DEBUG ("foo");
+ }
+ else
+ {
+ DEBUG ("bar");
+ }
+}
--- /dev/null
+/* PR c/64279 */
+/* { dg-do compile } */
+/* { dg-options "-Wduplicated-branches" } */
+
+int
+f (int p)
+{
+ if (p == 0)
+ {
+ p += 1, ++p;
+ }
+ else
+ {
+ p -= 1, ++p;
+ }
+
+ if (p == 1)
+ {
+ }
+ else
+ p++;
+
+ if (p == 2)
+ p++;
+ else
+ {
+ }
+
+ if (p == 3)
+ {
+ }
+ else
+ {
+ }
+
+ if (p == 4)
+ {
+ ++p;
+ return p;
+ }
+ else
+ {
+ p++;
+ return p;
+ }
+
+ if (p == 5)
+ ++p;
+ else
+ p++;
+
+ if (p == 6)
+ {
+ ++p;
+ ++p;
+ return p;
+ }
+ else
+ {
+ ++p;
+ return p;
+ }
+
+ if (p == 7)
+ {
+ ++p;
+ return p;
+ }
+ else
+ {
+ ++p;
+ ++p;
+ return p;
+ }
+}
--- /dev/null
+/* PR c/64279 */
+/* { dg-do compile } */
+/* { dg-options "-Wduplicated-branches" } */
+
+void
+f (int i)
+{
+ if (i) /* { dg-warning "this condition has identical branches" } */
+ return 0;
+/* { dg-warning ".return. with a value" "" { target c } .-1 } */
+/* { dg-error "return-statement with a value" "" { target c++ } .-2 } */
+ else
+ return 0;
+/* { dg-warning ".return. with a value" "" { target c } .-1 } */
+/* { dg-error "return-statement with a value" "" { target c++ } .-2 } */
+}
--- /dev/null
+/* PR c/64279 */
+/* { dg-do compile } */
+/* { dg-options "-Wduplicated-branches -O2" } */
+
+void
+f (int *p)
+{
+ if (*p > 0)
+ {
+ if (x == 0) /* { dg-error "undeclared|not declared" } */
+ *p = 5;
+ else
+ *p = 6;
+ }
+}
+
+void
+f2 (int *p)
+{
+ if (*p > 0)
+ {
+ if (*p > 2)
+ *p = x; /* { dg-error "undeclared|not declared" } */
+ else
+ *p = 6;
+ }
+}
+
+void
+f3 (int *p)
+{
+ if (*p > 0)
+ {
+ if (*p > 2)
+ *p = 8;
+ else
+ *p = x; /* { dg-error "undeclared|not declared" } */
+ }
+}
+
+void
+f4 (int *p)
+{
+ if (*p > 0)
+ {
+ if (x == 0) /* { dg-error "undeclared|not declared" } */
+ *p = 5;
+ else
+ *p = 6;
+ }
+ else
+ {
+ if (x == 0) /* { dg-error "not declared" "" { target c++ } } */
+ *p = 7;
+ else
+ *p = 6;
+ }
+}
+
+void
+f5 (int *p)
+{
+ if (*p > 0)
+ {
+ if (*p > 2)
+ *p = x; /* { dg-error "undeclared|not declared" } */
+ else
+ *p = 6;
+ }
+ else
+ {
+ if (x == 0) /* { dg-error "not declared" "" { target c++ } } */
+ *p = 5;
+ else
+ *p = 6;
+ }
+}
+
+void
+f6 (int *p)
+{
+ if (*p > 0)
+ {
+ if (*p > 2)
+ *p = 8;
+ else
+ *p = x; /* { dg-error "undeclared|not declared" } */
+ }
+ else
+ {
+ if (x == 0) /* { dg-error "not declared" "" { target c++ } } */
+ *p = 5;
+ else
+ *p = 6;
+ }
+}
+
+void
+f7 (int i)
+{
+ if (i > 5)
+ ({ x++; }); /* { dg-error "undeclared|not declared" } */
+ else
+ ({ i++; });
+}
+
+void
+f8 (int i)
+{
+ if (i > 5)
+ ({ i++; });
+ else
+ ({ x++; }); /* { dg-error "undeclared|not declared" } */
+}
--- /dev/null
+/* PR c/64279 */
+/* { dg-do compile } */
+/* { dg-options "-Wduplicated-branches" } */
+
+extern int *g;
+
+void
+f (short int i)
+{
+ if (i == 0) /* { dg-warning "this condition has identical branches" } */
+ *g = (int) i;
+ else
+ *g = (int) i;
+
+ if (i == 1)
+ *g = (unsigned char) i;
+ else
+ *g = (signed char) i;
+}
--- /dev/null
+/* PR c/64279 */
+/* { dg-do compile } */
+/* { dg-options "-Wduplicated-branches" } */
+
+extern int *g;
+extern const int *q;
+
+void
+f (int i)
+{
+ int j;
+
+ if (i == 0)
+ for (j = 0; j < 10; j++)
+ ++*g;
+ else
+ for (j = 0; j < 10; j++)
+ ++*g;
+
+ if (i == 1)
+ {
+ int i = 10;
+ *g = i;
+ }
+ else
+ {
+ int i = 10;
+ *g = i;
+ }
+
+ if (i == 3)
+ q = (const int []){1};
+ else
+ q = (const int []){1};
+}
--- /dev/null
+/* PR c/64279 */
+/* { dg-do compile } */
+/* { dg-options "-Wduplicated-branches" } */
+
+extern int g;
+extern void foo ();
+#define A g = i
+#define B g = i
+#define DOIT() foo()
+#define DOIT2() foo()
+
+void
+f (int i)
+{
+ if (i == 0)
+ A;
+ else
+ B;
+
+ if (i == 1)
+ DOIT();
+ else
+ DOIT2();
+}
--- /dev/null
+/* PR c/64279 */
+/* { dg-do compile } */
+/* { dg-options "-Wduplicated-branches" } */
+
+void
+f (int i)
+{
+ if (i == 0)
+ ;
+ else if (i == 1)
+ ;
+}
--- /dev/null
+/* PR c/64279 */
+/* { dg-do compile } */
+/* { dg-options "-Wduplicated-branches" } */
+
+struct S
+{
+ int x;
+} s;
+int a[10];
+
+#define XMEM(R) ((R).x)
+#define XSTR(R) ((R).x)
+
+void
+f (int i)
+{
+ if (i)
+ XMEM(s) = 1;
+ else
+ XSTR(s) = 1;
+
+ if (i) /* { dg-warning "this condition has identical branches" } */
+ s.x = 1;
+ else
+ s.x = 1;
+
+ if (i)
+ XMEM(s) = 1;
+ else
+ s.x = 1;
+
+ if (i)
+ s.x = 1;
+ else
+ XMEM(s) = 1;
+}
--- /dev/null
+/* PR c/64279 */
+/* { dg-do compile } */
+/* { dg-options "-Wduplicated-branches" } */
+
+#define A 5
+#define B 5
+#define I i
+extern int a[10];
+extern int g;
+
+int
+f (int i)
+{
+ if (i == 1) /* { dg-warning "this condition has identical branches" } */
+ return a[5];
+ else
+ return a[5];
+
+ if (i == 2) /* { dg-bogus "this condition has identical branches" "" { xfail *-*-* } } */
+ return a[A];
+ else
+ return a[5];
+
+ if (i == 3) /* { dg-bogus "this condition has identical branches" "" { xfail *-*-* } } */
+ return a[5];
+ else
+ return a[A];
+
+ if (i == 4) /* { dg-warning "this condition has identical branches" } */
+ return a[A];
+ else
+ return a[A];
+
+ if (i == 5) /* { dg-warning "this condition has identical branches" } */
+ return a[i];
+ else
+ return a[i];
+
+ if (i == 6) /* { dg-bogus "this condition has identical branches" "" { xfail *-*-* } } */
+ return a[I];
+ else
+ return a[i];
+
+ if (i == 7) /* { dg-bogus "this condition has identical branches" "" { xfail *-*-* } } */
+ return a[i];
+ else
+ return a[I];
+
+ if (i == 8) /* { dg-warning "this condition has identical branches" } */
+ return a[I];
+ else
+ return a[I];
+
+ if (i == 10) /* { dg-bogus "this condition has identical branches" "" { xfail *-*-* } } */
+ g += A;
+ else
+ g += B;
+
+ if (i == 11) /* { dg-bogus "this condition has identical branches" "" { xfail *-*-* } } */
+ g += B;
+ else
+ g += A;
+
+ if (i == 12) /* { dg-bogus "this condition has identical branches" "" { xfail *-*-* } } */
+ g += A;
+ else
+ g += 5;
+
+ if (i == 12) /* { dg-bogus "this condition has identical branches" "" { xfail *-*-* } } */
+ g += 5;
+ else
+ g += A;
+}
--- /dev/null
+/* PR c/64279 */
+/* { dg-do compile } */
+/* { dg-options "-Wduplicated-branches" } */
+
+extern int *p, foo (void), a[10];
+#define N 5
+#define M 5
+#define I i
+
+void
+f (int i)
+{
+ *p += i ? 1 : 1; /* { dg-warning "this condition has identical branches" } */
+ *p += i ? N : M; /* { dg-bogus "this condition has identical branches" "" { xfail *-*-* } } */
+ *p += i ? M : N; /* { dg-bogus "this condition has identical branches" "" { xfail *-*-* } } */
+ *p += i ? i : i; /* { dg-warning "this condition has identical branches" } */
+ *p += i ? i++ : i++; /* { dg-warning "this condition has identical branches" } */
+ *p += i ? foo () : foo (); /* { dg-warning "this condition has identical branches" } */
+ *p += i ? ({ i++; }) : ({ i++; }); /* { dg-warning "this condition has identical branches" } */
+ *p += i ? a[i] : a[i]; /* { dg-warning "this condition has identical branches" } */
+ *p += i ? a[5] : a[5]; /* { dg-warning "this condition has identical branches" } */
+ *p += i ? a[N] : a[M]; /* { dg-bogus "this condition has identical branches" "" { xfail *-*-* } } */
+ *p += i ? a[5] : a[M]; /* { dg-bogus "this condition has identical branches" "" { xfail *-*-* } } */
+ *p += i ? a[M] : a[5]; /* { dg-bogus "this condition has identical branches" "" { xfail *-*-* } } */
+ *p += i ? a[I] : a[I]; /* { dg-warning "this condition has identical branches" } */
+ *p += i ? a[i] : a[I]; /* { dg-bogus "this condition has identical branches" "" { xfail *-*-* } } */
+ *p += i ? a[I] : a[i]; /* { dg-bogus "this condition has identical branches" "" { xfail *-*-* } } */
+
+ *p += i ?: 1;
+ *p += i ?: M;
+ *p += i ?: N;
+ *p += i ?: i; /* { dg-warning "this condition has identical branches" "" { target c++ } } */
+ *p += i ?: i++;
+ *p += i ?: foo ();
+ *p += i ?: ({ i++; });
+ *p += i ?: a[i];
+ *p += i ?: a[5];
+ *p += i ?: a[M];
+ *p += i ?: a[M];
+ *p += i ?: a[5];
+ *p += i ?: a[I];
+ *p += i ?: a[I];
+ *p += i ?: a[i];
+
+ *p += (i > 5 ? (i > 10 ? i : i) : i); /* { dg-warning "this condition has identical branches" } */
+}
switch (i)
{
case 1:
- do /* { dg-warning "statement may fall through" "" { target c++ } 42 } */
+ do
bar (2);
- while (--i); /* { dg-warning "statement may fall through" "" { target c } 44 } */
+ while (--i); /* { dg-warning "statement may fall through" } */
case 2:
bar (99);
}
break; // { dg-error "break" }
}
};
- l = []()
+ l = []() // { dg-warning "statement will never be executed" }
{
case 3: // { dg-error "case" }
break; // { dg-error "break" }
- }; // { dg-warning "statement will never be executed" }
+ };
}
}
}
void baz (int *, int *);
-#define MEMCPY(d,s,l) __builtin___memcpy_chk (d, s, l, __builtin_object_size (d, 0))
+#define MEMCPY(d,s,l) __builtin___memcpy_chk (d, s, l, __builtin_object_size (d, 0)) // { dg-warning "writing" }
int
foo ()
{
int *p = new int;
int *q = new int[4];
- MEMCPY (p, "abcdefghijklmnopqrstuvwxyz", sizeof (int) + 1); // { dg-warning "writing" }
- MEMCPY (q, "abcdefghijklmnopqrstuvwxyz", 4 * sizeof (int) + 1); // { dg-warning "writing" }
+ MEMCPY (p, "abcdefghijklmnopqrstuvwxyz", sizeof (int) + 1); // { dg-message "in expansion of macro" }
+ MEMCPY (q, "abcdefghijklmnopqrstuvwxyz", 4 * sizeof (int) + 1); // { dg-message "in expansion of macro" }
baz (p, q);
}
for (j = i + 3; j < 16; j += 2) /* { dg-error "initializer expression refers to iteration variable" } */
;
#pragma omp for collapse(2)
- for (i = 0; i < 16; i++) /* { dg-error "initializer expression refers to iteration variable" } */
- for (j = baz (&i); j < 16; j += 2)
+ for (i = 0; i < 16; i++)
+ for (j = baz (&i); j < 16; j += 2) /* { dg-error "initializer expression refers to iteration variable" } */
;
#pragma omp for collapse(2)
for (i = 0; i < 16; i++)
for (int j = i + 3; j < 16; j += 2) /* { dg-error "initializer expression refers to iteration variable" } */
;
#pragma omp for collapse(2)
- for (int i = 0; i < 16; i++) /* { dg-error "initializer expression refers to iteration variable" } */
- for (int j = baz (&i); j < 16; j += 2)
+ for (int i = 0; i < 16; i++)
+ for (int j = baz (&i); j < 16; j += 2) /* { dg-error "initializer expression refers to iteration variable" } */
;
#pragma omp for collapse(2)
for (int i = 0; i < 16; i++)
--- /dev/null
+// PR c/64279
+// { dg-do compile }
+// { dg-options "-Wduplicated-branches" }
+
+template <typename T>
+void
+f (char i, int *p)
+{
+ if (i)
+ *p = (signed short) i;
+ else
+ *p = (unsigned short) i;
+
+ if (i) // { dg-warning "this condition has identical branches" }
+ *p = (T) i;
+ else
+ *p = (unsigned short) i;
+}
+
+template void f<unsigned short>(char, int *); // { dg-message "required from here" }
+template void f<signed short>(char, int *);
--- /dev/null
+// PR c/6427
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wduplicated-branches" }
+
+template<typename _ITp>
+struct S {
+ static constexpr int i = sizeof(_ITp) > alignof(_ITp) ? sizeof(_ITp) : alignof(_ITp);
+};
/* Internal within operand_equal_p: */
OEP_NO_HASH_CHECK = 16,
/* Internal within inchash::add_expr: */
- OEP_HASH_CHECK = 32
+ OEP_HASH_CHECK = 32,
+ /* Makes operand_equal_p handle more expressions: */
+ OEP_LEXICOGRAPHIC = 64
};
/* Enum and arrays used for tree allocation stats.
enum tree_code code;
enum tree_code_class tclass;
- if (t == NULL_TREE)
+ if (t == NULL_TREE || t == error_mark_node)
{
hstate.merge_hash (0);
return;