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 <pola...@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