2011/11/5 K. Frank <[email protected]>:
> Hello Kai!
>
> On Sat, Nov 5, 2011 at 10:31 AM, Kai Tietz <[email protected]> wrote:
>> 2011/11/5 K. Frank <[email protected]>:
>>> Hi Kai!
>>>
>>> Thanks for your response.
>>>
>>> I don't follow what you are saying -- please see my comments at
>>> the bottom.
>>>
>>> On Sat, Nov 5, 2011 at 4:29 AM, Kai Tietz <[email protected]> wrote:
>>>> 2011/11/5 K. Frank <[email protected]>:
>>>>> Hello List (and Ruben)!
>>>>>
>>>>> I think I have come across a bug in Ruben's 64-bit 4.7.0 build, otherwise
>>>>> known as "The Mighty Ruben's Wacky Build" ("TMRWB") (TM).
>>>>> ...
>>>>> I can also explain why I think this is a real bug, and not incorrect code
>>>>> invoking "undefined behavior."
>>>
>>> A quick comment on this.  Kai raises the issue of signed / unsigned
>>> conversions (because std::streamsize is signed).  I've raised the issue
>>> of narrower (32-bit) / wider (64-bit) unsigned conversions.  As I explain
>>> below, I don't think std::streamsize enters into this, but even if it did, I
>>> still believe that the compiler is not behaving properly.
>>>
>>> As I read the standard, neither the signed / unsigned nor the narrower /
>>> wider conversions invoke undefined behavior.  Narrower / wider integral
>>> are, I believe, well specified by the standard.  I believe that signed /
>>> unsigned integral conversions can be implementation-defined (based
>>> on how the implementation / hardware represents negative integers,
>>> and how it implements sign extension), but not undefined.
>>>
>>> No matter how the conversions are implemented, as I look at the code,
>>> I think that the behavior should be well defined and the function should
>>> either enter an infinite loop or run correctly.  Exiting the loop apparently
>>> early (no matter what the conversions are) seems to me to be a compiler
>>> bug.
>>>
>>>>> ...
>>>>> Thanks for anyone's thoughts.
>>>>>
>>>>> K. Frank
>>>>
>>>> Hmm, this looks to me indeed as logical wrong code, but by different
>>>> reason as you are assuming.  The underlying issue here is that
>>>> streamsize is derived from ptrdiff_t, which is a signed type.  But you
>>>> are using here an 'unsigned'.
>>>> The expanding rule from unsigned to signed with higher precision
>>>> remains unsigned valued.  For 32-bit we have here for both types same
>>>> precision, and therefore indeed the sign check is done as intended.
>>>
>>> Here's what I don't understand about your comment:  In the code above,
>>> std::streamsize is used explicitly in two places:
>>>
>>>    virtual std::streamsize xsputn (const char *p, std::streamsize n) {
>>>
>>> as the return type of xsputn, and as the type of the argument n.  It is
>>> also used implicitly, if you will, in the return statement of xsputn:
>>>
>>>       return n;
>>>
>>> But n is never modified in the code, and is only used, as I understand it,
>>> in a fully legal pointer-arithmetic expression:
>>>
>>>   m_string.append (p, p + n);
>>>
>>> (p is a char*).
>>>
>>> So I just don't see any signed / unsigned mismatch between std::streamsize
>>> and any other integral type.
>>>
>>>> If you are using here instead of 'unsigned' a 'signed' n, everything
>>>> works as expected.
>>>
>>> I don't follow what the concrete change to the code would be.  I'm happy
>>> to make such a change and see if it fixes the problem, but I don't see
>>> what specific change you are proposing.
>>>
>>> If you mean changing the type of the argument n to be unsigned:
>>>
>>>    virtual std::streamsize xsputn (const char *p, unsigned n) {
>>>
>>> I don't think that I would be allowed to do that because the signature of
>>> xsputn is defined by the iostream library (and hence by the standard).
>>>
>>> (Of course, when I say I think there is an error in the compiler, I mean
>>> the whole compiler / library package.  The compiler could be okay, but
>>> there could be an error in the library code.  To clarify, I do believe that
>>> the compiler is generating incorrect code, but if a coding error in the
>>> library were invoking undefined behavior, the compiler would technically
>>> be within its rights to do so.)
>>>
>>>> Regards,
>>>> Kai
>>>
>>> Further thoughts would be greatly appreciated.
>>
>> See, if I have a 32-bit unsigned scalar integer and I convert it into
>> a 64-bit signed integer conversion, it is wrong believe that a
>> sign-conversion is done here.  The unsigned 32-bit integer scalar fits
>> into value-range of the 64-bit signed integer scalar.  So result of
>> widen cast remains unsigned.  As by rule, always for a comparison of
>> X == Y - where X has 32-bit width, and Y has 64-bit width - value gets
>> promoted to wider-scalar width for comparision, we get into your
>> described behavior.
>>
>> so the comparsion X == -1LL can be never true.  And this is what you
>> are actually try do here. As X gets promoted for value 0xfffffffff to
>> 0xffffffffLL and not as you trying to suggest to 0xffffffffffffffffLL.
>
> I agree with this analysis.  Yes, X == -1LL can never be true.
>
> But this is exactly where I see the compiler bug.  If X == -1LL is never
> true, then the code should enter an infinite loop.  It does not.  Instead,
> the function seems to exit (seemingly not through its return statement),
> executing the loop only once.
>
> Again, I agree that the code that triggers the compiler bug is logically
> incorrect (in that it does not do what it was intended to do).  But I still
> believe that there is a compiler bug, in that the compiler does not generate
> executable code that does what the standard says the well-defined (but
> logically incorrect) source code should do.
>
>> Regards,
>> Kai
>
> Thanks again.
>
>
> K. Frank

Hmm, I was distracted by one typedef I saw, but missed that C++ is a
mess and the really used type might be defined else-where ...

The issue here is definition of npos. It has type size_type, which is
indeed based on size_t.
So the following line in base_string

static const size_type     npos = static_cast<size_type>(-1);

leads to a definition of npos as 0xffffffff (due -1 is a 32-bit
scalar, which gets casted to unsigned with wider-scalar).

This might, or might not be a libstdc++ failure.  I am no C++ guru to
tell by spec. But at least it remains odd.

Cheers,
Kai

------------------------------------------------------------------------------
RSA(R) Conference 2012
Save $700 by Nov 18
Register now
http://p.sf.net/sfu/rsa-sfdev2dev1
_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to