Hi. In current implementation we avoid giving "logical and/or of equal expressions" warning for literal constant operands. The attached patch fixes the check to make it treat const-qualified VAR_DECLs with constant initializers the same way.
Bootstrapped and regtested on x86_64-linux. OK for trunk? -- Regards, Mikhail Maltsev
gcc/c-family/ChangeLog: 2015-06-19 Mikhail Maltsev <malts...@gmail.com> PR c++/66572 * c-common.c (warn_logical_operator): Treat constant-initialized VAR_DECLs like literal constants. gcc/testsuite/ChangeLog: 2015-06-19 Mikhail Maltsev <malts...@gmail.com> PR c++/66572 * c-c++-common/Wlogical-op-2.c: New test. * g++.dg/warn/Wlogical-op-2.C: New test.
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index dc2bf00..38c7be9 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -1766,9 +1766,12 @@ warn_logical_operator (location_t location, enum tree_code code, tree type, return; } - /* We do not warn for constants because they are typical of macro - expansions that test for features. */ - if (CONSTANT_CLASS_P (op_left) || CONSTANT_CLASS_P (op_right)) + /* We do not warn for literal constants because they are typical of macro + expansions that test for features. Likewise, we do not warn for + const-qualified and constexpr variables which are initialized by constant + expressions, because they can come from e.g. <type_traits> or similar user + code. */ + if (TREE_CONSTANT (op_left) || TREE_CONSTANT (op_right)) return; /* This warning only makes sense with logical operands. */ diff --git a/gcc/testsuite/c-c++-common/Wlogical-op-2.c b/gcc/testsuite/c-c++-common/Wlogical-op-2.c new file mode 100644 index 0000000..47f5c28 --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wlogical-op-2.c @@ -0,0 +1,24 @@ +/* PR c++/66572 */ +/* { dg-do compile } */ +/* { dg-options "-Wlogical-op" } */ + +#ifndef __cplusplus +# define bool _Bool +# define true 1 +# define false 0 +#endif + +void +no_warn () +{ + const bool cst_a = true; + const bool cst_b = false; + + if (cst_a || cst_b) {} + if (cst_a && cst_b) {} + if (true && cst_a) {} + if (true || cst_a) {} + if (false && cst_a) {} + if (false || cst_a) {} +} + diff --git a/gcc/testsuite/g++.dg/warn/Wlogical-op-2.C b/gcc/testsuite/g++.dg/warn/Wlogical-op-2.C new file mode 100644 index 0000000..252592c6 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wlogical-op-2.C @@ -0,0 +1,59 @@ +// PR c++/66572 +// { dg-do compile } +// { dg-options "-Wlogical-op" } + +#if __cplusplus >= 201103L +# define CONSTEXPR constexpr +#else +# define CONSTEXPR const +#endif + +struct true_type +{ + static CONSTEXPR bool value = true; +}; + +struct false_type +{ + static CONSTEXPR bool value = true; +}; + +template<typename T> +struct is_unsigned : false_type { }; + +template<> +struct is_unsigned<unsigned int> : true_type { }; + +template<typename T1, typename T2> +bool both_are_unsigned () +{ + return is_unsigned <T1>::value && is_unsigned <T2>::value; +} + +template<typename T1, typename T2> +bool one_of_is_unsigned () +{ + return is_unsigned <T1>::value || is_unsigned <T2>::value; +} + +void +foo () +{ + both_are_unsigned <unsigned int, unsigned int> (); + both_are_unsigned <int, unsigned int> (); + both_are_unsigned <int, int> (); + one_of_is_unsigned <unsigned int, unsigned int> (); + one_of_is_unsigned <int, unsigned int> (); + one_of_is_unsigned <int, int> (); +} + +void +bar (const int parm_a) +{ + const bool a = parm_a; + if (a && a) {} /* { dg-warning "logical .and. of equal expressions" } */ + if (a || a) {} /* { dg-warning "logical .or. of equal expressions" } */ + if (parm_a && parm_a) {} /* { dg-warning "logical .and. of equal expressions" } */ + if (parm_a || parm_a) {} /* { dg-warning "logical .or. of equal expressions" } */ +} +