This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: Implement -Wduplicated-branches (PR c/64279) (v3)
- From: Marek Polacek <polacek at redhat dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Cc: Jakub Jelinek <jakub at redhat dot com>, Jason Merrill <jason at redhat dot com>, Joseph Myers <joseph at codesourcery dot com>
- Date: Tue, 25 Oct 2016 15:59:20 +0200
- Subject: Re: Implement -Wduplicated-branches (PR c/64279) (v3)
- Authentication-results: sourceware.org; auth=none
- References: <20161019110707.GJ2576@redhat.com> <20161020102835.GM2576@redhat.com> <20161024141018.GD5939@redhat.com>
On Mon, Oct 24, 2016 at 04:10:21PM +0200, Marek Polacek wrote:
> On Thu, Oct 20, 2016 at 12:28:36PM +0200, Marek Polacek wrote:
> > I found a problem with this patch--we can't call do_warn_duplicated_branches in
> > build_conditional_expr, because that way the C++-specific codes might leak into
> > the hasher. Instead, I should use operand_equal_p, I think. Let me rework
> > that part of the patch.
>
> Thus:
And one more thing, let's not warn for if { } else { }, either.
Thanks Tobias for testing.
Bootstrapped/regtested on x86_64-linux, ok for trunk?
2016-10-25 Marek Polacek <polacek@redhat.com>
PR c/64279
* c-common.h (do_warn_duplicated_branches_r,
do_warn_duplicated_branches): 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.
* c-typeck.c (build_conditional_expr): Warn about duplicated branches.
* call.c (build_conditional_expr_1): Warn about duplicated branches.
* semantics.c (finish_expr_stmt): Build statement using the proper
location.
* doc/invoke.texi: Document -Wduplicated-branches.
* fold-const.c (fold_build_cleanup_point_expr): Use the expression
location when building CLEANUP_POINT_EXPR.
* tree.c (add_expr): Handle error_mark_node.
* c-c++-common/Wduplicated-branches-1.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/Wduplicated-branches-10.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 (bar): Likewise.
* g++.dg/gomp/loop-1.C: Likewise.
* g++.dg/warn/Wduplicated-branches1.C: New test.
* g++.dg/warn/Wduplicated-branches2.C: New test.
diff --git gcc/c-family/c-common.h gcc/c-family/c-common.h
index 547bab2..46e9d2e 100644
--- gcc/c-family/c-common.h
+++ gcc/c-family/c-common.h
@@ -1530,6 +1530,7 @@ extern void maybe_warn_bool_compare (location_t, enum tree_code, tree, tree);
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);
diff --git gcc/c-family/c-gimplify.c gcc/c-family/c-gimplify.c
index c18b057..3ed2da8 100644
--- gcc/c-family/c-gimplify.c
+++ gcc/c-family/c-gimplify.c
@@ -125,6 +125,10 @@ c_genericize (tree fndecl)
&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)
diff --git gcc/c-family/c-warn.c gcc/c-family/c-warn.c
index 904f6d3..433f5c3 100644
--- gcc/c-family/c-warn.c
+++ gcc/c-family/c-warn.c
@@ -2154,3 +2154,72 @@ maybe_warn_bool_compare (location_t loc, enum tree_code code, tree op0,
"with boolean expression is always false", cst);
}
}
+
+/* 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
+ /* 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;
+}
diff --git gcc/c-family/c.opt gcc/c-family/c.opt
index 458d453..035dc68 100644
--- gcc/c-family/c.opt
+++ gcc/c-family/c.opt
@@ -444,6 +444,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-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.
diff --git gcc/c/c-typeck.c gcc/c/c-typeck.c
index f0917ed..0056088 100644
--- gcc/c/c-typeck.c
+++ gcc/c/c-typeck.c
@@ -5162,6 +5162,15 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
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;
}
diff --git gcc/cp/call.c gcc/cp/call.c
index 4c19d2f..82db79f 100644
--- gcc/cp/call.c
+++ gcc/cp/call.c
@@ -5234,6 +5234,13 @@ build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3,
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. */
diff --git gcc/cp/semantics.c gcc/cp/semantics.c
index 1a7c478..19e7c07 100644
--- gcc/cp/semantics.c
+++ gcc/cp/semantics.c
@@ -670,6 +670,7 @@ tree
finish_expr_stmt (tree expr)
{
tree r = NULL_TREE;
+ location_t loc = EXPR_LOCATION (expr);
if (expr != NULL_TREE)
{
@@ -694,7 +695,7 @@ finish_expr_stmt (tree expr)
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);
}
diff --git gcc/doc/invoke.texi gcc/doc/invoke.texi
index 5ccd424..ec01256 100644
--- gcc/doc/invoke.texi
+++ gcc/doc/invoke.texi
@@ -266,8 +266,8 @@ Objective-C and Objective-C++ Dialects}.
-Wno-deprecated -Wno-deprecated-declarations -Wno-designated-init @gol
-Wdisabled-optimization @gol
-Wno-discarded-qualifiers -Wno-discarded-array-qualifiers @gol
--Wno-div-by-zero -Wdouble-promotion -Wduplicated-cond @gol
--Wempty-body -Wenum-compare -Wno-endif-labels @gol
+-Wno-div-by-zero -Wdouble-promotion -Wduplicated-branches @gol
+-Wduplicated-cond -Wempty-body -Wenum-compare -Wno-endif-labels @gol
-Werror -Werror=* -Wfatal-errors -Wfloat-equal -Wformat -Wformat=2 @gol
-Wno-format-contains-nul -Wno-format-extra-args -Wformat-length=@var{n} @gol
-Wformat-nonliteral @gol
@@ -3674,7 +3674,7 @@ Options} and @ref{Objective-C and Objective-C++ Dialect Options}.
-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
@@ -5088,6 +5088,22 @@ Incrementing a boolean is invalid in C++1z, and deprecated otherwise.)
This warning is enabled by @option{-Wall}.
+@item -Wduplicated-branches
+@opindex Wno-duplicated-branches
+@opindex Wduplicated-branches
+Warn when an if-else has indentical 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
diff --git gcc/fold-const.c gcc/fold-const.c
index 89ed89d..ec0c990 100644
--- gcc/fold-const.c
+++ gcc/fold-const.c
@@ -14014,7 +14014,7 @@ fold_build_cleanup_point_expr (tree type, tree expr)
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
diff --git gcc/testsuite/c-c++-common/Wduplicated-branches-1.c gcc/testsuite/c-c++-common/Wduplicated-branches-1.c
index e69de29..c0b93fc 100644
--- gcc/testsuite/c-c++-common/Wduplicated-branches-1.c
+++ gcc/testsuite/c-c++-common/Wduplicated-branches-1.c
@@ -0,0 +1,187 @@
+/* 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;
+}
diff --git gcc/testsuite/c-c++-common/Wduplicated-branches-10.c gcc/testsuite/c-c++-common/Wduplicated-branches-10.c
index e69de29..8d918ef 100644
--- gcc/testsuite/c-c++-common/Wduplicated-branches-10.c
+++ gcc/testsuite/c-c++-common/Wduplicated-branches-10.c
@@ -0,0 +1,18 @@
+/* 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");
+ }
+}
diff --git gcc/testsuite/c-c++-common/Wduplicated-branches-2.c gcc/testsuite/c-c++-common/Wduplicated-branches-2.c
index e69de29..8669dd6 100644
--- gcc/testsuite/c-c++-common/Wduplicated-branches-2.c
+++ gcc/testsuite/c-c++-common/Wduplicated-branches-2.c
@@ -0,0 +1,114 @@
+/* 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" } */
+}
diff --git gcc/testsuite/c-c++-common/Wduplicated-branches-3.c gcc/testsuite/c-c++-common/Wduplicated-branches-3.c
index e69de29..e188384 100644
--- gcc/testsuite/c-c++-common/Wduplicated-branches-3.c
+++ gcc/testsuite/c-c++-common/Wduplicated-branches-3.c
@@ -0,0 +1,19 @@
+/* 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;
+}
diff --git gcc/testsuite/c-c++-common/Wduplicated-branches-4.c gcc/testsuite/c-c++-common/Wduplicated-branches-4.c
index e69de29..79af549 100644
--- gcc/testsuite/c-c++-common/Wduplicated-branches-4.c
+++ gcc/testsuite/c-c++-common/Wduplicated-branches-4.c
@@ -0,0 +1,35 @@
+/* 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};
+}
diff --git gcc/testsuite/c-c++-common/Wduplicated-branches-5.c gcc/testsuite/c-c++-common/Wduplicated-branches-5.c
index e69de29..f2eb8ec 100644
--- gcc/testsuite/c-c++-common/Wduplicated-branches-5.c
+++ gcc/testsuite/c-c++-common/Wduplicated-branches-5.c
@@ -0,0 +1,24 @@
+/* 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();
+}
diff --git gcc/testsuite/c-c++-common/Wduplicated-branches-6.c gcc/testsuite/c-c++-common/Wduplicated-branches-6.c
index e69de29..0010693 100644
--- gcc/testsuite/c-c++-common/Wduplicated-branches-6.c
+++ gcc/testsuite/c-c++-common/Wduplicated-branches-6.c
@@ -0,0 +1,12 @@
+/* PR c/64279 */
+/* { dg-do compile } */
+/* { dg-options "-Wduplicated-branches" } */
+
+void
+f (int i)
+{
+ if (i == 0)
+ ;
+ else if (i == 1)
+ ;
+}
diff --git gcc/testsuite/c-c++-common/Wduplicated-branches-7.c gcc/testsuite/c-c++-common/Wduplicated-branches-7.c
index e69de29..03721dc 100644
--- gcc/testsuite/c-c++-common/Wduplicated-branches-7.c
+++ gcc/testsuite/c-c++-common/Wduplicated-branches-7.c
@@ -0,0 +1,36 @@
+/* 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;
+}
diff --git gcc/testsuite/c-c++-common/Wduplicated-branches-8.c gcc/testsuite/c-c++-common/Wduplicated-branches-8.c
index e69de29..c5e8ca0 100644
--- gcc/testsuite/c-c++-common/Wduplicated-branches-8.c
+++ gcc/testsuite/c-c++-common/Wduplicated-branches-8.c
@@ -0,0 +1,73 @@
+/* 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;
+}
diff --git gcc/testsuite/c-c++-common/Wduplicated-branches-9.c gcc/testsuite/c-c++-common/Wduplicated-branches-9.c
index e69de29..9b21776 100644
--- gcc/testsuite/c-c++-common/Wduplicated-branches-9.c
+++ gcc/testsuite/c-c++-common/Wduplicated-branches-9.c
@@ -0,0 +1,46 @@
+/* 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" } */
+}
diff --git gcc/testsuite/c-c++-common/Wimplicit-fallthrough-7.c gcc/testsuite/c-c++-common/Wimplicit-fallthrough-7.c
index 21a158c..898e5fa 100644
--- gcc/testsuite/c-c++-common/Wimplicit-fallthrough-7.c
+++ gcc/testsuite/c-c++-common/Wimplicit-fallthrough-7.c
@@ -39,9 +39,9 @@ f (int i)
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);
}
diff --git gcc/testsuite/g++.dg/cpp0x/lambda/lambda-switch.C gcc/testsuite/g++.dg/cpp0x/lambda/lambda-switch.C
index d71d3ad..ee87def 100644
--- gcc/testsuite/g++.dg/cpp0x/lambda/lambda-switch.C
+++ gcc/testsuite/g++.dg/cpp0x/lambda/lambda-switch.C
@@ -16,11 +16,11 @@ main ()
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" }
+ };
}
}
}
diff --git gcc/testsuite/g++.dg/ext/builtin-object-size3.C gcc/testsuite/g++.dg/ext/builtin-object-size3.C
index 09263e5..aec3b7ce 100644
--- gcc/testsuite/g++.dg/ext/builtin-object-size3.C
+++ gcc/testsuite/g++.dg/ext/builtin-object-size3.C
@@ -3,7 +3,7 @@
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 "will always overflow destination buffer" }
int
foo ()
@@ -20,7 +20,7 @@ bar ()
{
int *p = new int;
int *q = new int[4];
- MEMCPY (p, "abcdefghijklmnopqrstuvwxyz", sizeof (int) + 1); // { dg-warning "will always overflow destination buffer" }
- MEMCPY (q, "abcdefghijklmnopqrstuvwxyz", 4 * sizeof (int) + 1); // { dg-warning "will always overflow destination buffer" }
+ 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);
}
diff --git gcc/testsuite/g++.dg/gomp/loop-1.C gcc/testsuite/g++.dg/gomp/loop-1.C
index de08eb3..b3db0f4 100644
--- gcc/testsuite/g++.dg/gomp/loop-1.C
+++ gcc/testsuite/g++.dg/gomp/loop-1.C
@@ -82,8 +82,8 @@ f1 (int x)
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++)
@@ -215,8 +215,8 @@ f2 (int x)
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++)
diff --git gcc/testsuite/g++.dg/warn/Wduplicated-branches1.C gcc/testsuite/g++.dg/warn/Wduplicated-branches1.C
index e69de29..7ebd55e 100644
--- gcc/testsuite/g++.dg/warn/Wduplicated-branches1.C
+++ gcc/testsuite/g++.dg/warn/Wduplicated-branches1.C
@@ -0,0 +1,21 @@
+// 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 *);
diff --git gcc/testsuite/g++.dg/warn/Wduplicated-branches2.C gcc/testsuite/g++.dg/warn/Wduplicated-branches2.C
index e69de29..4da2d54 100644
--- gcc/testsuite/g++.dg/warn/Wduplicated-branches2.C
+++ gcc/testsuite/g++.dg/warn/Wduplicated-branches2.C
@@ -0,0 +1,8 @@
+// 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);
+};
diff --git gcc/tree.c gcc/tree.c
index 30d4373..2f586ff 100644
--- gcc/tree.c
+++ gcc/tree.c
@@ -7754,7 +7754,7 @@ add_expr (const_tree t, inchash::hash &hstate, unsigned int flags)
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;
Marek