Bug 60049 - Right and left shift undefined behavior not an error in a constexpr
Summary: Right and left shift undefined behavior not an error in a constexpr
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.8.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks: constexpr
  Show dependency treegraph
 
Reported: 2014-02-04 04:19 UTC by Shafik Yaghmour
Modified: 2019-06-15 01:09 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work: 5.3.0, 6.1.0
Known to fail: 4.9.3
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Shafik Yaghmour 2014-02-04 04:19:35 UTC
I expected the following code involving constexpr to generate errors since all the shifts invoke undefined behavior:
 
  int main()
  {
    constexpr int x1 =  1 << 33 ;
    constexpr int x2 =  1 << -1 ;
    constexpr int x3 =  -1 << 1 ;
    constexpr int x4 =  1 >> 33 ;
    constexpr int x5 =  1 >> -1 ;
  }

but instead they generate warnings and all the variables are still considered constant expressions:

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

I built this using the following flags:

   -std=c++11 -Wall -Wextra -pedantic -fno-strict-aliasing -fwrapv

and you can see it live here:

   http://coliru.stacked-crooked.com/a/95685bb86b5b81e7

while clang 3.5 will generate errors for all these cases, see it live here:

   http://coliru.stacked-crooked.com/a/0638d424b28ecd87

I brought this up on StackOverflow, since it was not clear to me this was a bug:

   http://stackoverflow.com/questions/21502017/is-the-compiler-allowed-leeway-in-what-it-considers-undefined-behavior-in-a-cons

and although the consensus seems to be that this is strictly conforming standard behavior, a conversation I had offline suggests this behavior is surprising and probably not intended.

Note that in all the other cases I have tested of undefined behavior in a constexpr gcc does generate an error for example:

   constexpr int x = std::numeric_limits<int>::max() + 1 ;

generates the following error:

  main.cpp:6:61: error: overflow in constant expression [-fpermissive]
         constexpr int x = std::numeric_limits<int>::max() + 1 ;
                                                             ^
Comment 1 Martin Sebor 2016-05-13 20:57:10 UTC
GCC 4.9.3 still accepts the code, but GCC 5 and 6 reject it (see below).  Test added in r236225.  Resolving as Fixed.

$ gcc -S -std=c++11 -w xx.cpp
xx.cpp: In function ‘int main()’:
xx.cpp:3:27: error: right operand of shift expression ‘(1 << 33)’ is >= than the precision of the left operand [-fpermissive]
     constexpr int x1 =  1 << 33 ;
                         ~~^~~~~
xx.cpp:4:27: error: right operand of shift expression ‘(1 << -1)’ is negative [-fpermissive]
     constexpr int x2 =  1 << -1 ;
                         ~~^~~~~
xx.cpp:5:28: error: left operand of shift expression ‘(-1 << 1)’ is negative [-fpermissive]
     constexpr int x3 =  -1 << 1 ;
                         ~~~^~~~
xx.cpp:6:27: error: right operand of shift expression ‘(1 >> 33)’ is >= than the precision of the left operand [-fpermissive]
     constexpr int x4 =  1 >> 33 ;
                         ~~^~~~~
xx.cpp:7:27: error: right operand of shift expression ‘(1 >> -1)’ is negative [-fpermissive]
     constexpr int x5 =  1 >> -1 ;
                         ~~^~~~~