[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [lmi] 0x0000000000000000 != 0x0000000000000000

From: Greg Chicares
Subject: Re: [lmi] 0x0000000000000000 != 0x0000000000000000
Date: Mon, 22 May 2017 01:19:59 +0000
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.8.0

On 2017-05-21 23:35, Vadim Zeitlin wrote:
> On Sun, 21 May 2017 22:56:05 +0000 Greg Chicares <address@hidden> wrote:
> GC> The patch below [0] seems to construct a 'double' that is bitwise
> GC> identical to zero, yet compares unequal to zero. How can this be?
>  No idea yet. I'll try to debug this later (i.e. not today I'm afraid)
> because I also don't see how can this be possible, so I'd like to look at
> the generated code and see what it does.
>  Just to avoid wasting time on something you might have already checked,
> does this happen only with -O2 or does the problem also exist with -O0?

Only with '-O2'.

With '-O0':

x86_64-w64-mingw32-g++ -MMD -MP -MT tn_range_test.o -MF tn_range_test.d  -c -I 
/opt/lmi/src/lmi -I /opt/lmi/src/lmi/tools/pete-2.1.1 -I 
/opt/lmi/third_party/include -I /opt/lmi/third_party/src -I 
/opt/lmi/local/include -I /opt/lmi/local/include/libxml2 -DLMI_WX_NEW_USE_SO  
-pedantic-errors -Werror -Wall -Wcast-align -Wconversion 
-Wdeprecated-declarations -Wdisabled-optimization -Wextra -Wimport -Wmultichar 
-Wpacked -Wpointer-arith -Wredundant-decls -Wsign-compare -Wundef 
-Wwrite-strings  -Wno-long-long -Wctor-dtor-privacy -Wdeprecated 
-Wnon-template-friend -Woverloaded-virtual -Wpmf-conversions -Wsynth  
-Wcast-qual  -Wno-conversion -Wno-deprecated-declarations -Wno-parentheses 
-Wno-unused-local-typedefs -Wno-unused-variable     -ggdb -O0    
/opt/lmi/src/lmi/tn_range_test.cpp -otn_range_test.o
                                                          ^^^ <-- yes, "oh zero"
x86_64-w64-mingw32-g++ -o tn_range_test.exe alert.o alert_cli.o fenv_lmi.o 
getopt.o license.o datum_base.o facets.o tn_range_test.o tn_range_test_aux.o -L 
. -L /opt/lmi/local-x86_64-w64/lib -L /opt/lmi/local-x86_64-w64/bin -L 
/opt/lmi/local/lib -L /opt/lmi/local/bin   -lexslt -lxslt -lxml2      

Running tn_range_test:
hex value of 0.0 is: 0000000000000000 / 0000000000000000
hex value of p1.minimum() is: 0000000000000000 / 0000000000000000

tiny 2.225074e-308
p1.minimum() 0.000000e+000

.... 325 tests succeeded

!!!! no errors detected

> GC> This outcome is seen only with 64-bit msw (not with 32-bit msw,
> GC> and not with 64-bit GNU/Linux).
>  I've decided to quickly check it nevertheless and discovered that I
> couldn't compile tn_range_test.cpp with gcc6 because of its new
> "bool-compare" error. I've applied the attached patch as a quick and
> minimal fix, but I didn't test it under MSW yet. At least under Linux it
> allows me to build and run the test without errors.

I'll have to study this further. In this part of the patch:

     T const minT = std::numeric_limits<T>::lowest();
     INVOKE_BOOST_TEST(!is_strictly_between_extrema(maxT), file, line);
-    if(1 < maxT)
+    if(T(1) < maxT)
         INVOKE_BOOST_TEST( is_strictly_between_extrema<T>(1), file, line);

we're comparing int(1) to std::numeric_limits<bool>::max(), apparently
just as a way of detecting type 'bool'; perhaps we should detect that
in some other way. But what is the complaint? The documentation says:

| Warn about boolean expression compared with an integer value different
| from true/false. For instance, the following comparison is always false:
| int n = 5;
| …
| if ((n > 1) == 2) { … }

I read "an integer value different from true/false" as meaning any int
other than zero or positive one. In the warning's documentation above,
a bool lvalue is compared to two, which it can never equal; I understand
that. However, the lmi example compares to unity:
-    if(1 < maxT)
+    if(T(1) < maxT)
which doesn't fit the definition in the warning: unity is an integer
value NOT different from true/false.

I do see that (1 < X) cannot be true for any bool X. But the change that
makes the warning go away:
+    if(T(1) < maxT)
just tests (true < X) instead, yet that condition can never be true either,
so I wonder why gcc doesn't complain about it.

That example may come down to gcc and me being pedantic in conflicting
ways, but I'm more concerned about
-        INVOKE_BOOST_TEST_EQUAL(-1, signum(T(-1)), file, line);
+        INVOKE_BOOST_TEST_EQUAL(T(-1), signum(T(-1)), file, line);
when T is bool, because I did intend the left-hand side of the comparison
to be strictly less than zero, and casting it to bool as T(-1) changes its
sign. Of course, that test is meaningless for bool, and it's guarded by
the condition
  if(minT < 0)
which is unchanged by the patch...why? If gcc won't allow
  if(1 < maxT)
above, why does it allow
  if(minT < 0)
here, given that neither can be true of type bool? Is this warning perhaps
implemented in a premature way, with insufficient rigor?

But the real question is: how do we suppress tests like this that are
inapplicable for a particular type T? Is that what constexpr-if is for?
Is there a clean way of doing this with C++11? If the answers to the
last two questions are "yes" and "no", then I guess we should have a
pragma to suppress the warning for now.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]