On 23.06.2015 22:49, Marek Polacek wrote:
> On Sat, Jun 20, 2015 at 03:02:06AM +0300, Mikhail Maltsev wrote:
>> - /* 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;
>
> That looks wrong, because with TREE_CONSTANT we'd warn in C but not in C++
> for the following:
>
> const int a = 4;
> void
> f (void)
> {
> const int b = 4;
> static const int c = 5;
> if (a && a) {}
> if (b && b) {}
> if (c && c) {}
> }
>
Actually for this case the patch silences the warning both for C and
C++. It's interesting that Clang warns like this:
test.c:7:10: warning: use of logical '&&' with constant operand
[-Wconstant-logical-operand]
It does not warn for my testcase with templates. It also does not warn
about:
void
bar (const int parm_a)
{
const bool a = parm_a;
if (a && a) {}
if (a || a) {}
if (parm_a && parm_a) {}
if (parm_a || parm_a) {}
}
EDG does not give any warnings at all (in all 3 testcases).
> Note that const-qualified types are checked using TYPE_READONLY.
Yes, but I think we should warn about const-qualified types like in the
example above (and in your recent patch).
>
> But I'm not even sure that the warning in the original testcase in the PR
> is bogus; you won't get any warning when using e.g.
> foo<unsigned, signed>();
> in main().
Maybe my snippet does not express clearly enough what it was supposed to
express. I actually meant something like this:
template<class _U1, class _U2, class = typename
enable_if<__and_<is_convertible<_U1, _T1>,
is_convertible<_U2, _T2>>::value>::type>
constexpr pair(pair<_U1, _U2>&& __p)
: first(std::forward<_U1>(__p.first)),
second(std::forward<_U2>(__p.second)) { }
(it's std::pair move constructor)
It is perfectly possible that the user will construct an std::pair<T, T>
object from an std::pair<U, U>. In this case we get an "and" of two
identical is_convertible instantiations. The difference is that here
there is a clever __and_ template which helps to avoid warnings. Well,
at least I now know a good way to suppress them in my code :).
Though I still think that this warning is bogus. Probably the correct
(and the hard) way to check templates is to compare ASTs of the operands
before any substitutions.
But for now I could try to implement an idea, which I mentioned in the
bug report: add a new flag to enum tsubst_flags, and set it when we
check ASTs which depend on parameters of a template being instantiated
(we already have similar checks for macro expansions). What do you think
about such approach?
--
Regards,
Mikhail Maltsev