<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><br><div><div>On Sep 22, 2010, at 9:08 AM, Abramo Bagnara wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div>Il 22/09/2010 17:55, Douglas Gregor ha scritto:<br><blockquote type="cite"><br></blockquote><blockquote type="cite">On Sep 22, 2010, at 8:13 AM, Abramo Bagnara wrote:<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">int g();<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">int main() {<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"> // enum { x = (g(), 0) };<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"> enum { x = (int)(int(*)[g()])0 };<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"> return 0;<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">}<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">Constant expression evaluator seems to (wrongly IMHO) believe that types<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">cannot have side effects.<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">Do you confirm we have a bug here?<br></blockquote></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">I don't think this was meant to be well-formed C99, although it seems like there is a gap in the C99 standard here. In particular, C99 6.7.5.2p2 says:<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"> An ordinary identifier (as defined in 6.2.3) that has a variably modified type shall have either block scope and no linkage or function prototype scope.<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">Now, we're in a type-name (C99 6.7.6), so there is no identifier... however, the general view of type-names is that they are declarators without the identifier, which implies that C99 6.7.5p2 applies in this case. C99 6.7.7p3 strengthens our case somewhat, even though it is about typedefs, because it says:<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"><span class="Apple-tab-span" style="white-space:pre"> </span>Any array size expressions associated with variable length array declarators are evaluated each time the declaration of the typedef name is reached in the order of execution.<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">There is no way to reach an enumerator constant in the order of execution, so it doesn't make sense to have a VLA there.<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">Oh, and EDG rejects this code in C99 mode.<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">Long story short: yes, there is a bug here, which is that Clang accepts this ill-formed program. It should reject the use of a variably-modified type in a cast.<br></blockquote><br>I believe this conclusion is far too strict:<br><br>int x = (int)(int(*)[g()])0;<br><br>I think this is perfectly ok and it has side effects that have to be<br>executed (and clang behave as expected).<br></div></blockquote><div><br></div><div>Yes, good point. This is well-formed; I maintain that the original example is still ill-formed.</div><div><br></div><blockquote type="cite"><div>The clang problem is *not* to accept VM types in cast, but it is to<br>ignore their inner side effects in constant evaluation.<br><br>I'm missing something?<br></div></blockquote><div><br></div><div>The import issue here is that the value of an enumeration-constant is a constant-expression, and an expression involving a VLA type is not a constant expression. That's why EDG rejects the original example but not your revised example, because the call to g() makes the enumerator's value non-constant. In particular, C99 6.6p6:</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre"> </span><span class="Apple-style-span" style="font-family: Times; font-size: 12px; ">Cast operators in an integer constant expression shall only convert arithmetic types to integer types, except as part of an operand to the </span><span class="Apple-style-span" style="font-family: Times; font-size: 12px; "><span style="font: 12.0px Courier"><b>sizeof </b></span></span><span class="Apple-style-span" style="font-family: Times; font-size: 12px; ">operator.</span></div><div><br></div><div>So it's a (different) accepts-valid bug in Clang than the one I was thinking of.</div><br></div><div><span class="Apple-tab-span" style="white-space:pre"> </span>- Doug</div><br></body></html>