2011/11/5 Kai Tietz <[email protected]>
> 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.
>
I know for a fact that because of C type conversions, "-1", when converted
to an unsigned type, will result in the maximum representable value of that
unsigned type. That's what npos relies on here.
FYI, libc++ (and the FDIS of C++11 n3290) has this as definition of npos:
static const size_type npos = -1;
Would removing the static_cast have any effect at all? Isn't it implied
anyways?
Ruben
>
> 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
>
------------------------------------------------------------------------------
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