On Thu, Feb 2, 2012 at 10:40 AM, Matthieu Monrocq < [email protected]> wrote:
> Le 1 février 2012 23:34, Richard Smith <[email protected]> a écrit : > >> On Wed, Feb 1, 2012 at 12:14 PM, Matthieu Monrocq < >> [email protected]> wrote: >> >>> Le 31 janvier 2012 22:57, Richard Smith <[email protected]> a écrit >>> : >>> >>> On Tue, Jan 31, 2012 at 12:40 AM, Abramo Bagnara < >>>> [email protected]> wrote: >>>> >>>>> Il 31/01/2012 03:22, Eli Friedman ha scritto: >>>>> > On Mon, Jan 30, 2012 at 6:01 PM, Richard Smith < >>>>> [email protected]> wrote: >>>>> >> On Mon, Jan 30, 2012 at 4:29 PM, Eli Friedman < >>>>> [email protected]> >>>>> >> wrote: >>>>> >>> >>>>> >>> On Mon, Jan 30, 2012 at 2:27 PM, Richard Smith >>>>> >>> <[email protected]> wrote: >>>>> >>>> Author: rsmith >>>>> >>>> Date: Mon Jan 30 16:27:01 2012 >>>>> >>>> New Revision: 149286 >>>>> >>>> >>>>> >>>> URL: http://llvm.org/viewvc/llvm-project?rev=149286&view=rev >>>>> >>>> Log: >>>>> >>>> constexpr: disallow signed integer overflow in integral >>>>> conversions in >>>>> >>>> constant >>>>> >>>> expressions in C++11. >>>>> >>> >>>>> >>> Standard citation? As far as I can tell, the result of >>>>> >>> (int)0x80000000u is implementation-defined, but it's still a >>>>> constant >>>>> >>> expression given how we define it. >>>>> >> >>>>> >> >>>>> >> Oops, r149327. This was (incorrectly) factored out of another >>>>> change which >>>>> >> I'm still questioning... Consider: >>>>> >> >>>>> >> enum E { n = 2 }; >>>>> >> E e = (E)5; >>>>> >> >>>>> >> 5 is not in the range of values of the enumeration (which is 0..3 by >>>>> >> [dcl.enum]p7), but is clearly in the underlying type. Is this value >>>>> in the >>>>> >> range of representable values for its type (or is this undefined >>>>> behavior by >>>>> >> [expr]p4)? >>>>> > >>>>> > I think the relevant passage is actually [expr.static.cast]p10: >>>>> > >>>>> > A value of integral or enumeration type can be explicitly converted >>>>> to >>>>> > an enumeration type. The value is unchanged if the original value is >>>>> > within the range of the enumeration values (7.2). Otherwise, the >>>>> > resulting value is unspecified (and might not be in that range). >>>>> > >>>>> > >>>>> > That doesn't sound like undefined behavior to me. >>>>> >>>>> Yes, you're definitely right from a standard point of view, but using >>>>> the point of view of constant evaluator, does it make a difference? >>>>> >>>>> I.e., the conversion of an integer out of enum range specified by >>>>> [decl.enum]p7 to that enum type should be a known constant? >>>>> >>>>> I don't think so, but I'd like to hear your opinion. >>>> >>>> >>>> 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"). >>>> >>>> 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? >>>> >>>> To address the first question, [class.bit]p4 says: >>>> >>>> "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." >>>> >>>> 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. >>>> >>>> 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. >>>> >>>> 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. >>>> >>>> - Richard >>>> >>>> >>>> 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: >>> >>> Given Min the smallest enumerator value and Max the biggest enumerator >>> value of the enumeration: >>> >>> - 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. >>> - if both Min and Max are negative, then the bitfield should be *just* >>> enough to represent all values in [0, -Min] + a bit sign. >>> - if both Min and Max are positive, then the bitfield should be *just* >>> enough to represent all values in [0, Max] (no bit sign). >>> >>> 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. >>> >>> >>> Summary: >>> * Min = min { enumerators } >>> * Max = max { enumerators } >>> * K positive such that 2^(K-1) <= max(abs(Min), abs(Max)) < 2^K >>> >>> If Min < 0, then the representable range is [-2^K, 2^K-1], else it is >>> [0, 2^K-1]. >>> >>> 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. >>> >>> >>> 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. >>> >>> And if my reasoning is not totally skewed, then it means this *can* be >>> treated as a constant expression. >>> >> >> 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. >> >> - Richard >> > > Not at all :) I hope Clang keeps aiming at maximum standard conformance. > > I was reacting to this (from you): > > > > 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. > > 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]. > That's right. The "values of the enumeration" is a term of art, defined in the standard in [dcl.enum]p7 to what you are describing [ apart from an off-by-one error in your description for negative enumerators ;-) ]. It is not simply the range of values of the enumerators. Sorry for not making that clear :) > 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. > > Which here will affect which values are out-of-range and thus > non-constant, I think. > Yes, absolutely. As in my original example: enum E { n = 2 }; E e = (E)5; Here, I think that (E)5 is not a constant expression, but (E)3 is. Possibly we're in violent agreement about that? - Richard
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
