www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Undefined behaviors & Clang 3.3

reply "bearophile" <bearophileHUGS lycos.com> writes:
Another nice post about the Integer Undefined Behavior Detection 
of Clang 3.3:

http://blog.regehr.org/archives/963

Until these languages die, which isn’t going to happen anytime 
soon, our best defense against undefined behaviors is to write 
better checking tools.<

Some potential bugs it has found: http://article.gmane.org/gmane.comp.fonts.freetype.devel/8817 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57324 http://blog.regehr.org/extra_files/perl-test-output.txt Things like this in gcc: gcc/gcc/simplify-rtx.c:4004:16: runtime error: signed integer overflow: -1844674407370955161 + -9223372036854775808 cannot be represented in type 'long' gcc/gcc/stor-layout.c:2543:45: runtime error: signed integer overflow: -9223372036854775808 - 1 cannot be represented in type 'long' Is someone able to compile and run the dmd source code with Clang with "-fsanitize=undefined"? And is it possible to add -fsanitize=undefined to ldc2? Bye, bearophile
Jun 20 2013
next sibling parent "Paulo Pinto" <pjmlp progtools.org> writes:
On Thursday, 20 June 2013 at 14:28:42 UTC, bearophile wrote:
 Another nice post about the Integer Undefined Behavior 
 Detection of Clang 3.3:

 http://blog.regehr.org/archives/963

Until these languages die, which isn’t going to happen anytime 
soon, our best defense against undefined behaviors is to write 
better checking tools.<

Some potential bugs it has found: http://article.gmane.org/gmane.comp.fonts.freetype.devel/8817 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57324 http://blog.regehr.org/extra_files/perl-test-output.txt Things like this in gcc: gcc/gcc/simplify-rtx.c:4004:16: runtime error: signed integer overflow: -1844674407370955161 + -9223372036854775808 cannot be represented in type 'long' gcc/gcc/stor-layout.c:2543:45: runtime error: signed integer overflow: -9223372036854775808 - 1 cannot be represented in type 'long' Is someone able to compile and run the dmd source code with Clang with "-fsanitize=undefined"? And is it possible to add -fsanitize=undefined to ldc2? Bye, bearophile

I also advise those with Apple accounts to have a look at the WWDC 2013 videos, there are a few sessions about LLVM optimizations and auto-vectorization in Clang. Maybe those features could benefit LDC as well. -- Paulo
Jun 20 2013
prev sibling next sibling parent reply "qznc" <qznc web.de> writes:
On Thursday, 20 June 2013 at 14:28:42 UTC, bearophile wrote:
 Another nice post about the Integer Undefined Behavior 
 Detection of Clang 3.3:

 http://blog.regehr.org/archives/963

Until these languages die, which isn’t going to happen anytime 
soon, our best defense against undefined behaviors is to write 
better checking tools.<

Some potential bugs it has found: http://article.gmane.org/gmane.comp.fonts.freetype.devel/8817 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57324 http://blog.regehr.org/extra_files/perl-test-output.txt Things like this in gcc: gcc/gcc/simplify-rtx.c:4004:16: runtime error: signed integer overflow: -1844674407370955161 + -9223372036854775808 cannot be represented in type 'long' gcc/gcc/stor-layout.c:2543:45: runtime error: signed integer overflow: -9223372036854775808 - 1 cannot be represented in type 'long' Is someone able to compile and run the dmd source code with Clang with "-fsanitize=undefined"? And is it possible to add -fsanitize=undefined to ldc2? Bye, bearophile

In D an integer overflow is defined, so there is no need to detect anything about it. See Spec: "If both operands are of integral types and an overflow or underflow occurs in the computation, wrapping will happen. That is, uint.max + 1 == uint.min and uint.min - 1 == uint.max." http://dlang.org/expression.html
Jun 21 2013
next sibling parent Artur Skawina <art.08.09 gmail.com> writes:
On 06/21/13 15:48, eles wrote:
 On Friday, 21 June 2013 at 10:42:32 UTC, bearophile wrote:
 qznc:

 In D an integer overflow is defined, so there is no need to detect anything
about it.

A language should offer the programmer a way to specify when an integral overflow is acceptable. Otherwise the other cases are bugs. Clang 3.3 helps find some of those bugs.

I just wanted to say almost the same thing: that the original sentence should read: "In D an integer overflow is *badly or, at least, questionably and inflexibly* defined, so there is no *possibility* to detect anything *useful* about it." Well, that was the flame for today.

Actually, it's the other way around - mandating wrapping is what makes it possible for code to detect the overflow. Having overflow be undefined (C-like) means that the compiler as allowed to remove all code that checks for or relies on the overflow happening. Mandating /trapping/ on OF would be a bad idea for perf reasons, You can implement both trapping and saturating arithmetic on top of wrapping. As the people wanting these will either a) don't really care about bare metal performance or a) use h/w acceleration (simd etc) anyway, it isn't really a problem. artur
Jun 21 2013
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 6/21/2013 8:51 AM, qznc wrote:
 The D definition mirrors what modern PC architectures do and hence can be
 compiled efficiently there. C avoids coupling with any architecture hence
 "undefined".
 What architectures do not wrap around?

C is a very old language, and supported many architectures that no longer exist, such as ones-complement machines, machines with 10 bit bytes, weird floating point formats, EBCDIC, 16 bit CPUs, etc. A lot of C code tries to be "portable" to all these no-longer-existing machines, and a lot of effort is wasted. But D has the luxury of taking advantage of the fact that things have converged on 2s-complement, IEEE 754 floating point, 8 bit bytes, Unicode, etc. This means we can now nail down many implementation-defined and undefined behaviors.
Jun 21 2013
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
qznc:

 In D an integer overflow is defined, so there is no need to 
 detect anything about it.

A language should offer the programmer a way to specify when an integral overflow is acceptable. Otherwise the other cases are bugs. Clang 3.3 helps find some of those bugs. Bye, bearophile
Jun 21 2013
prev sibling next sibling parent Artur Skawina <art.08.09 gmail.com> writes:
On 06/21/13 10:20, qznc wrote:
 In D an integer overflow is defined, so there is no need to detect anything
about it. See Spec:
 
 "If both operands are of integral types and an overflow or underflow occurs in
the computation, wrapping will happen. That is, uint.max + 1 == uint.min and
uint.min - 1 == uint.max."
 http://dlang.org/expression.html

Keep in mind that this is not necessarily how real compilers treat it: void main() { auto a = int.max; if (a+1<a.max) assert(0); } will not assert when compiled with gdc; you'd have to explicitly disable that optimization. GCC statically evaluates this kind of checks, by assuming that signed overflow can't happen - because it's undefined. But that's not true for D, so, until the compiler is fixed, the '-fno-strict-overflow' compiler flag has to be used if "spec"-like behaviour is desired. Requiring wrapping arithmetic removes some opportunities for optimization, hence should, ideally, be complemented by more value range awareness in the language. D doesn't really have the latter, so right now, avoiding the UB in these cases has a cost. Still, GDC should just be fixed, as having a subtly different dialect is worse. Right now, incorrect (according to the "spec") code is silently generated, causing data corruption. artur
Jun 21 2013
prev sibling next sibling parent "eles" <eles eles.com> writes:
On Friday, 21 June 2013 at 10:42:32 UTC, bearophile wrote:
 qznc:

 In D an integer overflow is defined, so there is no need to 
 detect anything about it.

A language should offer the programmer a way to specify when an integral overflow is acceptable. Otherwise the other cases are bugs. Clang 3.3 helps find some of those bugs.

I just wanted to say almost the same thing: that the original sentence should read: "In D an integer overflow is *badly or, at least, questionably and inflexibly* defined, so there is no *possibility* to detect anything *useful* about it." Well, that was the flame for today.
Jun 21 2013
prev sibling next sibling parent "qznc" <qznc web.de> writes:
On Friday, 21 June 2013 at 13:48:19 UTC, eles wrote:
 On Friday, 21 June 2013 at 10:42:32 UTC, bearophile wrote:
 qznc:

 In D an integer overflow is defined, so there is no need to 
 detect anything about it.

A language should offer the programmer a way to specify when an integral overflow is acceptable. Otherwise the other cases are bugs. Clang 3.3 helps find some of those bugs.

I just wanted to say almost the same thing: that the original sentence should read: "In D an integer overflow is *badly or, at least, questionably and inflexibly* defined, so there is no *possibility* to detect anything *useful* about it." Well, that was the flame for today.

The D definition mirrors what modern PC architectures do and hence can be compiled efficiently there. C avoids coupling with any architecture hence "undefined". What architectures do not wrap around?
Jun 21 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Friday, 21 June 2013 at 15:51:55 UTC, qznc wrote:
 The D definition mirrors what modern PC architectures do and 
 hence can be compiled efficiently there. C avoids coupling with 
 any architecture hence "undefined".

 What architectures do not wrap around?

Some used to have +0 and -0 and so wrapping around do not work. But this didn't survived (or maybe in some exotic not heavily used chips). Similarly, some arch used to use different values than 0 for null. I don't know any modern one that does it.
Jun 21 2013
prev sibling next sibling parent "eles" <eles eles.com> writes:
On Friday, 21 June 2013 at 14:48:46 UTC, Artur Skawina wrote:
 On 06/21/13 15:48, eles wrote:
 On Friday, 21 June 2013 at 10:42:32 UTC, bearophile wrote:

what makes it possible for code to detect the overflow. Having overflow be

Very much aware of that. However, going from undefined to (badly) defined is not the best choice, as long as better is available.
Jun 21 2013
prev sibling next sibling parent "eles" <eles eles.com> writes:
On Friday, 21 June 2013 at 15:51:55 UTC, qznc wrote:
 On Friday, 21 June 2013 at 13:48:19 UTC, eles wrote:
 On Friday, 21 June 2013 at 10:42:32 UTC, bearophile wrote:

The D definition mirrors what modern PC architectures do and hence can be compiled efficiently there. C avoids coupling with any architecture hence "undefined".

First, it is not just about UNDEFINED behaviour, but also about DESIRED behaviur. C's arrays seen as pointers were efficient (and mirroring the architecture who kne nothing about arrays, just about addresses, that is pointers), still D abandoned them for a good reason. Efficiency vs better is a sensible trade-off. Secondly, is just enabling that overflow behavior if chasing a bug, explicitely, with a compiler flag. Use it only if you care. Although the best solution, in my eyes, is to have both wrapping and overfloing signed and unsigned integer types. Chose what you want.
 What architectures do not wrap around?

They wrap, but they carry. BTW, floats do not wrap, why integers should behave otherwise?
Jun 21 2013
prev sibling next sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Sat, 22 Jun 2013 02:14:18 +0200, eles <eles eles.com> wrote:

 BTW, floats do not wrap, why integers should behave otherwise?

Because that's how the hardware works. IEEE-754 floats have special values that do not behave like other numbers: infinity and nan. The ints the hardware supports have no such thing. Of course, one could write a complex wrapper around the int to get infinity in there, and even nan if one really wanted, but that'd be a lot less efficient, and contrary to how people expect things to work. -- Simen
Jun 22 2013
prev sibling next sibling parent "eles" <eles eles.com> writes:
On Saturday, 22 June 2013 at 07:59:05 UTC, Simen Kjaeraas wrote:
 On Sat, 22 Jun 2013 02:14:18 +0200, eles <eles eles.com> wrote:
 Of course, one could write a complex wrapper around the int to 
 get infinity
 in there, and even nan if one really wanted, but that'd be a 
 lot less
 efficient, and contrary to how people expect things to work.

They would never carry when wrapping up if that would have been the case.
Jun 24 2013
prev sibling parent "renoX" <renozyx gmail.com> writes:
On Friday, 21 June 2013 at 15:51:55 UTC, qznc wrote:
 What architectures do not wrap around?

The MIPS has instructions which trap on integer overflow (it has other which wrap too). Unfortunately, this is the only CPU I know where you can have a sane integer semantic "for free". renoX
Jun 25 2013