[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
-DLIBXML_USE_DLL -DSTRICT -DBOOST_STRICT_CONFIG -std=c++11
-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
-Wl,-Map,tn_range_test.exe.map
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
1
.... 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:
https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#Warning-Options
| 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.