www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - LLVM talks 1: Clang for Chromium

reply bearophile <bearophileHUGS lycos.com> writes:
There are the videos of the 2011 LLVM Developer Meeting:
http://www.youtube.com/playlist?list=PL970A5BD02C11F80C

Slides too:
http://llvm.org/devmtg/2011-11/

As usual the LLVM talks are quite interesting. I have started to see the
videos/slides, it will require some time.

An interesting talk, "Using clang in the Chromium project":
http://www.youtube.com/watch?v=IvL3f8xY7Uw

Slides:
http://llvm.org/devmtg/2011-11/Weber_Wennborg_UsingClangInChromium.pdf

-----------------------------------

It shows some problems found by Clang.


a.cc:2:9: warning: using the result of an assignment as a condition without
parentheses [-Wparentheses]
  if (x |= y)
      ~~^~~~
a.cc:2:9: note: use '!=' to turn this compound assignment into an inequality
comparison
  if (x |= y)
        ^~
        !=

1 warning generated.



This code doesn't compile with DMD:
Error: assignment cannot be used as a condition, perhaps == was meant?

void main() {
    int x, y;
    if (x = y) {}
}


But this gives no errors:

void main() {
    int x, y;
    if (x |= y) {}
    if (x += y) {}
}


Do you know why DMD forbids assignments as conditions, but it accepts compound
assignments there? It looks like a incongruence that's better to remove.

-----------------------------------

10.25 in the video:

a.cc:2:16: warning: operator '?:' has lower precedence than '+'; '+' will be
evaluated first
  return x + b ? y : 0;
         ~~~~~ ^
a.cc:2:16: note: place parentheses around the '?:' expression to evaluate it
first
  return x + b ? y : 0;
               ^
            (         )

1 warning generated.

They say:

 It's a bug every time!
Given the frequence of bugs caused by the ?: operator, I think something like this will be good to have in D too. ----------------------------------- a.cc:8:23: warning: argument to ’sizeof’ in ’memset’ call is the same expression as the destination; did you mean to dereference it? memset(s, 0, sizeof(s)); ~ ^ 1 warning generated. ----------------------------------- At 14.45-16.39 there is an interesting part, about slide 22 of the PDF. It's about crashes/bugs caused by undefined order of evaluation of function arguments. This is a class of bugs that don't have to happen in D2 code. Bye, bearophile
Dec 16 2011
next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Friday, 16 December 2011 at 12:23:25 UTC, bearophile wrote:
 This code doesn't compile with DMD:
   if (x = y) {}
 But this gives no errors:
   if (x |= y) {}
 Do you know why DMD forbids assignments as conditions, but it 
 accepts compound assignments there? It looks like a 
 incongruence that's better to remove.
They aren't similar at all. Sometimes, if I'm coming from a couple days writing Visual Basic, I'll hit the wrong equal sign. If a = 10 Then ' correct VB blah End If if(a = 10) // wrong C/C++/D/etc blah That's a mistake that's pretty easy to make, especially if you switch languages. But I've never myself, nor seen anybody else, actually write += or |= when they meant == or !=. The keys aren't even close (on en-US anyway) so it's not a likely typo, and the concepts are nothing alike so a brain or language mixup isn't likely to cause it. If you write "if(a += 10)", you almost certainly meant to say "if(a += 10)". That's not the case with (a = 10) vs (a == 10).
 a.cc:2:16: warning: operator '?:' has lower precedence than 
 '+'; '+' will be evaluated first
 return x + b ? y : 0;

 They say:

 It's a bug every time!
They're wrong. I've done something similar for plurals where you only care about if it is equal to one or not, and that was intentional. That said, if I have to put any effort at all into thinking about a line of code, I usually rewrite it. (That's why in some of my code you'll see stuff like return a != 0 ? true : false; even though I could have just said return a != 0; Sometimes my brain gets mixed up with the double negative so I just write it out anyway.) In the case of the ternary, sometimes the precidence is easy to forget, so I put a lot of parenthesis around it. return ((a) ? (b) : (c)); Just because then each piece is obviously grouped in a certain way. That's just a personal style though. I don't think the language should enforce it since sometimes those parenthesis make it worse, not better, to read.
 At 14.45-16.39 there is an interesting part, about slide 22 of 
 the PDF. It's about crashes/bugs caused by undefined order of 
 evaluation of function arguments. This is a class of bugs that 
 don't have to happen in D2 code.
I believe the order of evaulation is defined in D.
Dec 16 2011
parent bearophile <bearophileHUGS lycos.com> writes:
Adam D. Ruppe:

 But I've never myself, nor seen anybody else, actually
 write += or |= when they meant == or !=. The keys aren't
 even close (on en-US anyway) so it's not a likely typo, and
 the concepts are nothing alike so a brain or language mixup
 isn't likely to cause it.
 
 If you write "if(a += 10)", you almost certainly meant to say
 "if(a += 10)".
 
 That's not the case with (a = 10) vs (a == 10).
OK.
 In the case of the ternary, sometimes the precidence
 is easy to forget, so I put a lot of parenthesis around
 it.
 
 
 return ((a) ?
            (b) :
            (c));
 
 
 Just because then each piece is obviously grouped in a certain
 way.
 
 
 That's just a personal style though. I don't think the language
 should enforce it since sometimes those parenthesis make it
 worse, not better, to read.
I see. But unlike the if(a|=x) case, I have seen many cases where expressions like x+b?y:0 have caused troubles (I am able to show you some examples). So I will think about this some more.
 I believe the order of evaulation is defined in D.
I don't know. Thank you for your answer, bearophile
Dec 16 2011
prev sibling next sibling parent =?windows-1252?Q?Alex_R=F8nne_Petersen?= <xtzgzorex gmail.com> writes:
On 16-12-2011 13:23, bearophile wrote:
 There are the videos of the 2011 LLVM Developer Meeting:
 http://www.youtube.com/playlist?list=PL970A5BD02C11F80C

 Slides too:
 http://llvm.org/devmtg/2011-11/

 As usual the LLVM talks are quite interesting. I have started to see the
videos/slides, it will require some time.

 An interesting talk, "Using clang in the Chromium project":
 http://www.youtube.com/watch?v=IvL3f8xY7Uw

 Slides:
 http://llvm.org/devmtg/2011-11/Weber_Wennborg_UsingClangInChromium.pdf

 -----------------------------------

 It shows some problems found by Clang.


 a.cc:2:9: warning: using the result of an assignment as a condition without
parentheses [-Wparentheses]
    if (x |= y)
        ~~^~~~
 a.cc:2:9: note: use '!=' to turn this compound assignment into an inequality
comparison
    if (x |= y)
          ^~
          !=

 1 warning generated.



 This code doesn't compile with DMD:
 Error: assignment cannot be used as a condition, perhaps == was meant?

 void main() {
      int x, y;
      if (x = y) {}
 }


 But this gives no errors:

 void main() {
      int x, y;
      if (x |= y) {}
      if (x += y) {}
 }


 Do you know why DMD forbids assignments as conditions, but it accepts compound
assignments there? It looks like a incongruence that's better to remove.

 -----------------------------------

 10.25 in the video:

 a.cc:2:16: warning: operator '?:' has lower precedence than '+'; '+' will be
evaluated first
    return x + b ? y : 0;
           ~~~~~ ^
 a.cc:2:16: note: place parentheses around the '?:' expression to evaluate it
first
    return x + b ? y : 0;
                 ^
              (         )

 1 warning generated.

 They say:

 It's a bug every time!
Given the frequence of bugs caused by the ?: operator, I think something like this will be good to have in D too. ----------------------------------- a.cc:8:23: warning: argument to ’sizeof’ in ’memset’ call is the same expression as the destination; did you mean to dereference it? memset(s, 0, sizeof(s)); ~ ^ 1 warning generated. ----------------------------------- At 14.45-16.39 there is an interesting part, about slide 22 of the PDF. It's about crashes/bugs caused by undefined order of evaluation of function arguments. This is a class of bugs that don't have to happen in D2 code. Bye, bearophile
I generally don't like that a compiler throws warnings at me for perfectly valid code. Yes, it *can* be error prone, but most often, I know what I'm doing and am actually utilizing a language feature. Personally, I'd make no warnings the default and add an option that looks for suspicious stuff like if (a = b). - Alex
Dec 16 2011
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 12/16/2011 4:23 AM, bearophile wrote:
 This code doesn't compile with DMD:
 Error: assignment cannot be used as a condition, perhaps == was meant?

 void main() {
      int x, y;
      if (x = y) {}
 }


 But this gives no errors:

 void main() {
      int x, y;
      if (x |= y) {}
      if (x += y) {}
 }


 Do you know why DMD forbids assignments as conditions, but it accepts compound
assignments there? It looks like a incongruence that's better to remove.
Because using = where == was meant is commonplace, but I've never seen the others in the wild.
 a.cc:2:16: warning: operator '?:' has lower precedence than '+'; '+' will be
evaluated first
    return x + b ? y : 0;
           ~~~~~ ^
 a.cc:2:16: note: place parentheses around the '?:' expression to evaluate it
first
    return x + b ? y : 0;
                 ^
              (         )

 1 warning generated.

 They say:

 It's a bug every time!
Given the frequence of bugs caused by the ?: operator, I think something like this will be good to have in D too.
I haven't seen the "bug every time" with this.
 a.cc:8:23: warning: argument to ’sizeof’ in ’memset’ call is the same
expression as the destination;
    did you mean to dereference it?
    memset(s, 0, sizeof(s));
           ~            ^

 1 warning generated.
Fixing bugs in C code is not in D's charter, which is why it also does not scan printf strings, etc.
 At 14.45-16.39 there is an interesting part, about slide 22 of the PDF. It's
about crashes/bugs caused by undefined order of evaluation of function
arguments. This is a class of bugs that don't have to happen in D2 code.
D2 intends to define the order of evaluation of function arguments as strictly left-to-right. There are some problems implementing this, but that's where we want to go with it.
Dec 16 2011
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 12/16/2011 06:50 PM, Walter Bright wrote:
 D2 intends to define the order of evaluation of function arguments as
 strictly left-to-right. There are some problems implementing this, but
 that's where we want to go with it.
What would be a case where this currently does not hold?
Dec 16 2011
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 12/16/2011 9:52 AM, Timon Gehr wrote:
 On 12/16/2011 06:50 PM, Walter Bright wrote:
 D2 intends to define the order of evaluation of function arguments as
 strictly left-to-right. There are some problems implementing this, but
 that's where we want to go with it.
What would be a case where this currently does not hold?
The back end will evaluate them in different orders, as it is more efficient to evaluate varargs functions from right-to-left, and others from left-to-right. It's not an insurmountable problem, it just needs to be worked on.
Dec 16 2011
parent reply "Kagamin" <spam here.lot> writes:
 The back end will evaluate them in different orders, as it is 
 more efficient to evaluate varargs functions from 
 right-to-left, and others from left-to-right. It's not an 
 insurmountable problem, it just needs to be worked on.
Are you taking about push vs mov? By default gcc preallocates space for arguments, evaluates them from left to right and `mov`es them to the stack. `push`es take more cycles, `mov`s take more space. Which of them is more efficient?
Dec 17 2011
parent Walter Bright <newshound2 digitalmars.com> writes:
On 12/17/2011 2:04 AM, Kagamin wrote:
 The back end will evaluate them in different orders, as it is more efficient
 to evaluate varargs functions from right-to-left, and others from
 left-to-right. It's not an insurmountable problem, it just needs to be worked
on.
Are you taking about push vs mov?
Yes.
 By default gcc preallocates space for
 arguments, evaluates them from left to right and `mov`es them to the stack.
 `push`es take more cycles, `mov`s take more space. Which of them is more
efficient?
Depends on the processor.
Dec 17 2011
prev sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Walter:

 Given the frequence of bugs caused by the ?: operator, I think something like
this will be good to have in D too.
I haven't seen the "bug every time" with this.
Surely it's not a bug every time (but maybe was often enough a bug in the Chromium project, that is several millions lines of code). But in articles about PVS-Studio, and elsewhere, I have seen several cases where code like x+b?y:0 was a bug in good and real code. But I don't yet know how common those problems are. I will study some more on this.
D2 intends to define the order of evaluation of function arguments as strictly
left-to-right. There are some problems implementing this, but that's where we
want to go with it.<
Good. There is also the problem of code like this, that will require one or more solutions for D2. Defining or refusing or this kind of code are the possibilities (or both of such solutions, in different situations): x = x++; Thank you for your answers, bearophile
Dec 16 2011
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 12/16/2011 10:16 AM, bearophile wrote:
 There is also the problem of code like this, that will require one or more
solutions for D2. Defining or refusing or this kind of code are the
possibilities (or both of such solutions, in different situations):
 x = x++;
Define order of evaluation as rvalue, then lvalue.
Dec 16 2011
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 12/16/2011 10:43 AM, Walter Bright wrote:
 x = x++;
Define order of evaluation as rvalue, then lvalue.
Which, I might add, is a tractable problem. Trying to nail down every case of OOE dependencies is flat out impossible.
Dec 16 2011
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 12/16/2011 07:45 PM, Walter Bright wrote:
 On 12/16/2011 10:43 AM, Walter Bright wrote:
 x = x++;
Define order of evaluation as rvalue, then lvalue.
Which, I might add, is a tractable problem. Trying to nail down every case of OOE dependencies is flat out impossible.
How can that work together with NRVO?
Dec 16 2011
parent Walter Bright <newshound2 digitalmars.com> writes:
On 12/16/2011 10:58 AM, Timon Gehr wrote:
 Which, I might add, is a tractable problem. Trying to nail down every
 case of OOE dependencies is flat out impossible.
How can that work together with NRVO?
These are orthogonal.
Dec 16 2011
prev sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Walter:

 x = x++;
Define order of evaluation as rvalue, then lvalue.
So I presume your desire is to define the semantics of all code like that, and statically refuse no cases like that. This is an acceptable solution. The advantage of this solution is that it gives no restrictions on the acceptable D code, and it avoids complexities caused by choosing what are the cases to refuse statically. Some of its disadvantages are that programmers are free to write very unreadable D code that essentially only the compiler is able to understand, and that is hard to port to C/C++. Bye, bearophile
Dec 17 2011
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 12/17/2011 2:54 AM, bearophile wrote:
 Walter:

 x = x++;
Define order of evaluation as rvalue, then lvalue.
So I presume your desire is to define the semantics of all code like that, and statically refuse no cases like that. This is an acceptable solution. The advantage of this solution is that it gives no restrictions on the acceptable D code, and it avoids complexities caused by choosing what are the cases to refuse statically.
I think you overlook the real advantage - how it works is guaranteed. Keep in mind that it is IMPOSSIBLE for any static analyzer to prove there are no order dependencies when the order is implementation defined. It's trivial to write code that'll pass the static analyzer but will rely on implementation defined behavior. You'll always be relying on faith-based programming with the C/C++ approach.
 Some of its disadvantages are that programmers
 are free to write very unreadable D code that essentially only the compiler
 is able to understand,
D's approach on this allows one to reason reliably about how the code works - this does NOT contribute to making code unreadable.
 and that is hard to port to C/C++.
D isn't designed to be ported to C/C++. D is full of features that are not reasonably portable to C/C++. It's a completely irrelevant point.
Dec 17 2011
parent bearophile <bearophileHUGS lycos.com> writes:
Walter:

Keep in mind that it is IMPOSSIBLE for any static analyzer to prove there are
no order dependencies when the order is implementation defined.<
I see.
D's approach on this allows one to reason reliably about how the code works -
this does NOT contribute to making code unreadable.<
Guido V. Rossum was not sure about adding the conditional expressions (X if P else Y) to Python because despite it's possible to reason reliably about them, they sometimes lead to less readable code, and readability is a very important point of Python design. C code usually doesn't contain many pre/post increments (or related things) in the middle of expressions because many C programmers know that C leaves the meaning of such code to the specific compiler/system. If the semantics of that code becomes well defined in D, I fear some programmers will feel free to use that kind of code more often (and that kind of code _is_ often not much readable). So programmers need to not misuse the tools a language gives them, but on the other hand the language designers must take care of not giving too much trust to the programmers, to help keep programs more tidy. It's a matter of balances and trade-offs.
D isn't designed to be ported to C/C++. D is full of features that are not
reasonably portable to C/C++. It's a completely irrelevant point.<
I understand. On the other hand I have spent a good amount of time porting/translating code between different languages, so I am sensitive to this issue. I have grown further dislike for: - Languages that have a particularly not explic syntax (example: sometimes Perl); - Original code without unittest. Unittests are good when you translate code in another language, because they help you trust that the translation is done correctly; - Not readable code in general, like C code with expressions that contain lot of pre/post increments (this is what we were discussing in this part of this thread). - Languages that seem to differ in some details from each other only because they seem to want to be different. How many different ways there are to do the same things? Sometimes I'd like a bit more syntactic standardization of small things/semantic bits that many languages share. Language don't need to look all the same, but there is no need to invent twenty different syntaxes to test if a number is bigger than another number. Languages are not used alone, most programmers live in a world of more than one language. Translating code between different languages seems a fact of a programmer's life. Bye, bearophile
Dec 18 2011