문제

We know that operations that would cause undefined behavior are not core constant expressions(section 5.19 paragraph 2 from the draft C++ standard)

In the tests I have done both clang and gcc treat undefined behavior in a constexpr as an error but they are inconsistent in the case of left an right shift. For example, in all of these cases which are considered undefined behavior according to section 5.8 Shift operators paragraph 1 to 3:

constexpr int x1 =  1 << 33 ; //Assuming 32-bit int
constexpr int x2 =  1 << -1 ;
constexpr int x3 =  -1 << 1 ;
constexpr int x4 =  1 >> 33 ; //Assuming 32-bit int
constexpr int x5 =  1 >> -1 ;

clang will produce an error (see it live):

error: constexpr variable 'x1' must be initialized by a constant expression
    constexpr int x1 =  1 << 33 ; //Assuming 32-bit int
                  ^     ~~~~~~~
note: shift count 33 >= width of type 'int' (32 bits)
    constexpr int x1 =  1 << 33 ; //Assuming 32-bit int
....

while gcc will produce a warning but it will still consider each variable to be constant expression (see it live):

warning: left shift count >= width of type [enabled by default]
 constexpr int x1 =  1 << 33 ; //Assuming 32-bit int
                          ^
warning: left shift count is negative [enabled by default]
 constexpr int x2 =  1 << -1 ;
...

This looks like a gcc bug but I know a compiler can make stronger guarantees for behavior the standard says is undefined and it does look like gcc gives some stronger guarantees for shifts. This may end up being a bug but it makes me wonder if the compiler allowed that same leeway in the context of a constexpr as well or does the compiler have to strictly adhere to what the standard says is undefined behavior here?

Update

As Alan mentions, it is indeed true that the diagnostic of an ill-formed program can be either an error or a warning but in this case gcc does not seem to consider the program ill-formed. Unlike other instances such as in the case of overflow, gcc does not complain about an invalid constexpr but warns about the shifts. So then it would seem that either it is a bug or gcc does not consider these cases to be undefined and hence my question.

도움이 되었습니까?

해결책

Since Johannes does not seem to want to convert his comment into an answer then I will self-answer. I had an offline conversation with Howard Hinnant and he confirmed the consensus in the comments that gccs behavior in this context is indeed conforming.

The relevant section from the draft standard would be section 1.4 Implementation compliance which says in paragraph 2:

Although this International Standard states only requirements on C++ implementations, those requirements are often easier to understand if they are phrased as requirements on programs, parts of programs, or execution of programs. Such requirements have the following meaning:

and has the following bullet (emphasis mine):

If a program contains a violation of any diagnosable rule or an occurrence of a construct described in this Standard as “conditionally-supported” when the implementation does not support that construct, a conforming implementation shall issue at least one diagnostic message.

A diagnostic can either be a warning or an error. So once gcc provides a warning about the undefined behavior it does not requires a subsequent warning about the constexpr itself.

Although this is conforming behavior generating an error for the constexpr and allowing SFINAE would seem to be more robust behavior. Considering that gcc issues errors in other instances of undefined behavior in a constexpr this does not seem like the intended behavior or if it was, at least inconsistent behavior, so I filed a bug report.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top