<br><br><div class="gmail_quote">Le 1 février 2012 23:34, Richard Smith <span dir="ltr"><<a href="mailto:richard@metafoo.co.uk">richard@metafoo.co.uk</a>></span> a écrit :<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="gmail_quote">On Wed, Feb 1, 2012 at 12:14 PM, Matthieu Monrocq <span dir="ltr"><<a href="mailto:matthieu.monrocq@gmail.com" target="_blank">matthieu.monrocq@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<div class="gmail_quote">Le 31 janvier 2012 22:57, Richard Smith <span dir="ltr"><<a href="mailto:richard@metafoo.co.uk" target="_blank">richard@metafoo.co.uk</a>></span> a écrit :<div><div><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


<div class="gmail_quote">On Tue, Jan 31, 2012 at 12:40 AM, Abramo Bagnara <span dir="ltr"><<a href="mailto:abramo.bagnara@gmail.com" target="_blank">abramo.bagnara@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">



Il 31/01/2012 03:22, Eli Friedman ha scritto:<br>
<div><div>> On Mon, Jan 30, 2012 at 6:01 PM, Richard Smith <<a href="mailto:richard@metafoo.co.uk" target="_blank">richard@metafoo.co.uk</a>> wrote:<br>
>> On Mon, Jan 30, 2012 at 4:29 PM, Eli Friedman <<a href="mailto:eli.friedman@gmail.com" target="_blank">eli.friedman@gmail.com</a>><br>
>> wrote:<br>
>>><br>
>>> On Mon, Jan 30, 2012 at 2:27 PM, Richard Smith<br>
>>> <<a href="mailto:richard-llvm@metafoo.co.uk" target="_blank">richard-llvm@metafoo.co.uk</a>> wrote:<br>
>>>> Author: rsmith<br>
>>>> Date: Mon Jan 30 16:27:01 2012<br>
>>>> New Revision: 149286<br>
>>>><br>
>>>> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=149286&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=149286&view=rev</a><br>
>>>> Log:<br>
>>>> constexpr: disallow signed integer overflow in integral conversions in<br>
>>>> constant<br>
>>>> expressions in C++11.<br>
>>><br>
>>> Standard citation?  As far as I can tell, the result of<br>
>>> (int)0x80000000u is implementation-defined, but it's still a constant<br>
>>> expression given how we define it.<br>
>><br>
>><br>
>> Oops, r149327. This was (incorrectly) factored out of another change which<br>
>> I'm still questioning... Consider:<br>
>><br>
>>   enum E { n = 2 };<br>
>>   E e = (E)5;<br>
>><br>
>> 5 is not in the range of values of the enumeration (which is 0..3 by<br>
>> [dcl.enum]p7), but is clearly in the underlying type. Is this value in the<br>
>> range of representable values for its type (or is this undefined behavior by<br>
>> [expr]p4)?<br>
><br>
> I think the relevant passage is actually [expr.static.cast]p10:<br>
><br>
> A value of integral or enumeration type can be explicitly converted to<br>
> an enumeration type. The value is unchanged if the original value is<br>
> within the range of the enumeration values (7.2). Otherwise, the<br>
> resulting value is unspecified (and might not be in that range).<br>
><br>
><br>
> That doesn't sound like undefined behavior to me.<br>
<br>
</div></div>Yes, you're definitely right from a standard point of view, but using<br>
the point of view of constant evaluator, does it make a difference?<br>
<br>
I.e., the conversion of an integer out of enum range specified by<br>
[decl.enum]p7 to that enum type should be a known constant?<br>
<br>
I don't think so, but I'd like to hear your opinion.</blockquote><div> </div><div>In C++11, all conditional-expressions are core constant expressions, except those explicitly blacklisted in [expr.const]p2. The only relevant exemption there is "a result that is not mathematically defined or not in the range of representable values for its type;" (which DR1313 generalizes to "an operation that would have undefined behavior").</div>



<div><br></div><div>The standard does not make obvious what it means by "the range of representable values" for an enumeration type. Is it the range of values of the enumeration, or is it the range of representable values of the underlying type, or something else? And, when casting an out-of-range value to an enumeration, can the resulting unspecified value be out of the range of representable values for the type?</div>



<div><br></div><div><div>To address the first question, [class.bit]p4 says:</div><div><br></div><div>"If the value of an enumerator is stored into a bit-field of the same enumeration type and the number of bits in the bit-field is large enough to hold all the values of that enumeration type (7.2), the original enumerator value and the value of the bit-field shall compare equal."</div>



<div><br></div><div>From this, and the behavior of integral promotions on enumerations, I believe we can conclude that the range of representable values of an enumeration type is the range of values of the enumeration.</div>



</div><div><br></div><div>Eli's quotation states that casting an out-of-range value to an enumeration produces a value which need not be in the range of values of the enumeration. Therefore, if the unspecified value is not in that range (which by [expr.static.cast]p10 it might not be), then behavior is undefined, and the result of the cast is not a constant expression.</div>



<div><br></div><div>That said, such deductive reasoning applied to the (sadly, often imprecise and inconsistent) standard wording has led me to unintended conclusions several times before, so I'm still not certain whether such cases should be constant expressions.</div>


<span><font color="#888888">
<div><br></div><div>- Richard</div></font></span></div>
<br><br></blockquote></div></div><div>As far as the interpretation of "If the value of an enumerator is stored into a bit-field of the same 
enumeration type and the number of bits in the bit-field is large 
enough to hold all the values of that enumeration type (7.2), the 
original enumerator value and the value of the bit-field shall compare 
equal." I always understood:<br><br>Given Min the smallest enumerator value and Max the biggest enumerator value of the enumeration:<br><br>- if Min is negative and Max positive, then we deduce M = max(abs(Min), abs(Max)) and the bitfield should be *just* enough to represent all values in [0, M] + a bit sign.<br>


- if both Min and Max are negative, then the bitfield should be *just* enough to represent all values in [0, -Min] + a bit sign.<br>- if both Min and Max are positive, then the bitfield should be *just* enough to represent all values in [0, Max] (no bit sign).<br>


<br>So, you are looking for K such that 2^(K-1) <= max(abs(Min), abs(Max)) < 2^K and all values in [0, 2^K-1] are representable, as well as those in [-2^K, 0] if any enumerator was negative.<br><br><br>Summary:<br>

* Min = min { enumerators }<br>
* Max = max { enumerators }<br>* K positive such that 2^(K-1) <= max(abs(Min), abs(Max)) < 2^K<br><br>If Min < 0, then the representable range is [-2^K, 2^K-1], else it is [0, 2^K-1].<br><br>Any value outside this range cannot reliably represented, and it is unspecified what happens if one tries to assign such a value. The underlying type does not come into play, in the standard.<br>


<br><br>Now, as a compiler implementation, I think that Clang can make the additional guarantee (*) that as long as it fits into the underlying type, it's okay (it's probably what gcc does, so consistency is good) and that otherwise it just "wraps around" (not sure if it should for a signed underlying type...), this is the freedom that "unspecified behavior" gives us.<br>


<br>And if my reasoning is not totally skewed, then it means this *can* be treated as a constant expression.<br></div></div></blockquote><div><br></div><div>If I understand you correctly, you seem to be assuming that we can just decide for ourselves what is and is not a constant expression? We cannot; this is specified (though, in this case, not clearly) by the language semantics, and a non-conforming implementation (whether it treats too many, or too few, expressions as constant expressions) will reject valid code, accept invalid code, and give the wrong semantics to some code.</div>
<span class="HOEnZb"><font color="#888888">
<div><br></div><div>- Richard</div></font></span></div>
</blockquote></div><br>Not at all :) I hope Clang keeps aiming at maximum standard conformance.<br><br>I was reacting to this (from you):<br><br>> >From this, and the behavior of integral promotions on 
enumerations, I believe we can conclude that the range of representable 
values of an enumeration type is the range of values of the enumeration.


<div><br>I disagreed here on what is the range of representable values of an enumeration type and gave the formula to compute it: it is slightly broader than [Min...Max].<br><br></div><div>> Eli's quotation states that casting an 
out-of-range value to an enumeration produces a value which need not be 
in the range of values of the enumeration. Therefore, if the unspecified
 value is not in that range (which by [expr.static.cast]p10 it might not
 be), then behavior is undefined, and the result of the cast is not a 
constant expression.<br><br>Which here will affect which values are out-of-range and thus non-constant, I think.<br><br>Of course, I am no expert, so you might want to double check.<br><br>The unspecified behavior I was referencing, and which may have confused you, was more related to runtime. With hindsight I guess I had better not written about it as it muddled my message.<br>
<br>-- Matthieu<br></div>