1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
|
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++20 -verify=expected,all %s
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++17 -verify=cxx17,all %s
// RUN: %clang_cc1 -std=c++20 -verify=ref,all %s
// RUN: %clang_cc1 -std=c++17 -verify=ref-cxx17,all %s
#define INT_MIN (~__INT_MAX__)
namespace shifts {
constexpr void test() { // ref-error {{constexpr function never produces a constant expression}} \
// ref-cxx17-error {{constexpr function never produces a constant expression}} \
// expected-error {{constexpr function never produces a constant expression}} \
// cxx17-error {{constexpr function never produces a constant expression}} \
char c; // cxx17-warning {{uninitialized variable}} \
// ref-cxx17-warning {{uninitialized variable}}
c = 0 << 0;
c = 0 << 1;
c = 1 << 0;
c = 1 << -0;
c = 1 >> -0;
c = 1 << -1; // expected-warning {{shift count is negative}} \
// expected-note {{negative shift count -1}} \
// cxx17-note {{negative shift count -1}} \
// cxx17-warning {{shift count is negative}} \
// ref-warning {{shift count is negative}} \
// ref-note {{negative shift count -1}} \
// ref-cxx17-warning {{shift count is negative}} \
// ref-cxx17-note {{negative shift count -1}}
c = 1 >> -1; // expected-warning {{shift count is negative}} \
// cxx17-warning {{shift count is negative}} \
// ref-warning {{shift count is negative}} \
// ref-cxx17-warning {{shift count is negative}}
c = 1 << (unsigned)-1; // expected-warning {{shift count >= width of type}} \
// expected-warning {{implicit conversion from 'int' to 'char' changes value from -2147483648 to 0}} \
// cxx17-warning {{shift count >= width of type}} \
// cxx17-warning {{implicit conversion from 'int' to 'char' changes value from -2147483648 to 0}} \
// ref-warning {{shift count >= width of type}} \
// ref-warning {{implicit conversion from 'int' to 'char' changes value from -2147483648 to 0}} \
// ref-cxx17-warning {{shift count >= width of type}} \
// ref-cxx17-warning {{implicit conversion from 'int' to 'char' changes value from -2147483648 to 0}}
c = 1 >> (unsigned)-1; // expected-warning {{shift count >= width of type}} \
// cxx17-warning {{shift count >= width of type}} \
// ref-warning {{shift count >= width of type}} \
// ref-cxx17-warning {{shift count >= width of type}}
c = 1 << c;
c <<= 0;
c >>= 0;
c <<= 1;
c >>= 1;
c <<= -1; // expected-warning {{shift count is negative}} \
// cxx17-warning {{shift count is negative}} \
// ref-warning {{shift count is negative}} \
// ref-cxx17-warning {{shift count is negative}}
c >>= -1; // expected-warning {{shift count is negative}} \
// cxx17-warning {{shift count is negative}} \
// ref-warning {{shift count is negative}} \
// ref-cxx17-warning {{shift count is negative}}
c <<= 999999; // expected-warning {{shift count >= width of type}} \
// cxx17-warning {{shift count >= width of type}} \
// ref-warning {{shift count >= width of type}} \
// ref-cxx17-warning {{shift count >= width of type}}
c >>= 999999; // expected-warning {{shift count >= width of type}} \
// cxx17-warning {{shift count >= width of type}} \
// ref-warning {{shift count >= width of type}} \
// ref-cxx17-warning {{shift count >= width of type}}
c <<= __CHAR_BIT__; // expected-warning {{shift count >= width of type}} \
// cxx17-warning {{shift count >= width of type}} \
// ref-warning {{shift count >= width of type}} \
// ref-cxx17-warning {{shift count >= width of type}}
c >>= __CHAR_BIT__; // expected-warning {{shift count >= width of type}} \
// cxx17-warning {{shift count >= width of type}} \
// ref-warning {{shift count >= width of type}} \
// ref-cxx17-warning {{shift count >= width of type}}
c <<= __CHAR_BIT__+1; // expected-warning {{shift count >= width of type}} \
// cxx17-warning {{shift count >= width of type}} \
// ref-warning {{shift count >= width of type}} \
// ref-cxx17-warning {{shift count >= width of type}}
c >>= __CHAR_BIT__+1; // expected-warning {{shift count >= width of type}} \
// cxx17-warning {{shift count >= width of type}} \
// ref-warning {{shift count >= width of type}} \
// ref-cxx17-warning {{shift count >= width of type}}
(void)((long)c << __CHAR_BIT__);
int i; // cxx17-warning {{uninitialized variable}} \
// ref-cxx17-warning {{uninitialized variable}}
i = 1 << (__INT_WIDTH__ - 2);
i = 2 << (__INT_WIDTH__ - 1); // cxx17-warning {{bits to represent, but 'int' only has}} \
// ref-cxx17-warning {{bits to represent, but 'int' only has}}
i = 1 << (__INT_WIDTH__ - 1); // cxx17-warning-not {{sets the sign bit of the shift expression}}
i = -1 << (__INT_WIDTH__ - 1); // cxx17-warning {{shifting a negative signed value is undefined}} \
// ref-cxx17-warning {{shifting a negative signed value is undefined}}
i = -1 << 0; // cxx17-warning {{shifting a negative signed value is undefined}} \
// ref-cxx17-warning {{shifting a negative signed value is undefined}}
i = 0 << (__INT_WIDTH__ - 1);
i = (char)1 << (__INT_WIDTH__ - 2);
unsigned u; // cxx17-warning {{uninitialized variable}} \
// ref-cxx17-warning {{uninitialized variable}}
u = 1U << (__INT_WIDTH__ - 1);
u = 5U << (__INT_WIDTH__ - 1);
long long int lli; // cxx17-warning {{uninitialized variable}} \
// ref-cxx17-warning {{uninitialized variable}}
lli = INT_MIN << 2; // cxx17-warning {{shifting a negative signed value is undefined}} \
// ref-cxx17-warning {{shifting a negative signed value is undefined}}
lli = 1LL << (sizeof(long long) * __CHAR_BIT__ - 2);
}
static_assert(1 << 4 == 16, "");
constexpr unsigned m = 2 >> 1;
static_assert(m == 1, "");
constexpr unsigned char c = 0 << 8;
static_assert(c == 0, "");
static_assert(true << 1, "");
static_assert(1 << (__INT_WIDTH__ +1) == 0, ""); // expected-error {{not an integral constant expression}} \
// expected-note {{>= width of type 'int'}} \
// cxx17-error {{not an integral constant expression}} \
// cxx17-note {{>= width of type 'int'}} \
// ref-error {{not an integral constant expression}} \
// ref-note {{>= width of type 'int'}} \
// ref-cxx17-error {{not an integral constant expression}} \
// ref-cxx17-note {{>= width of type 'int'}}
constexpr int i1 = 1 << -1; // expected-error {{must be initialized by a constant expression}} \
// expected-note {{negative shift count -1}} \
// cxx17-error {{must be initialized by a constant expression}} \
// cxx17-note {{negative shift count -1}} \
// ref-error {{must be initialized by a constant expression}} \
// ref-note {{negative shift count -1}} \
// ref-cxx17-error {{must be initialized by a constant expression}} \
// ref-cxx17-note {{negative shift count -1}}
constexpr int i2 = 1 << (__INT_WIDTH__ + 1); // expected-error {{must be initialized by a constant expression}} \
// expected-note {{>= width of type}} \
// cxx17-error {{must be initialized by a constant expression}} \
// cxx17-note {{>= width of type}} \
// ref-error {{must be initialized by a constant expression}} \
// ref-note {{>= width of type}} \
// ref-cxx17-error {{must be initialized by a constant expression}} \
// ref-cxx17-note {{>= width of type}}
constexpr char c2 = 1;
constexpr int i3 = c2 << (__CHAR_BIT__ + 1); // Not ill-formed
/// The purpose of these few lines is to test that we can shift more bits
/// than an unsigned *of the host* has. There was a bug where we casted
/// to host-unsigned. However, we cannot query what a host-unsigned even is
/// here, so only test this on platforms where `sizeof(long long) > sizeof(unsigned)`.
constexpr long long int L = 1;
constexpr signed int R = (sizeof(unsigned) * 8) + 1;
constexpr decltype(L) M = (R > 32 && R < 64) ? L << R : 0;
constexpr decltype(L) M2 = (R > 32 && R < 64) ? L >> R : 0;
constexpr int signedShift() { // cxx17-error {{never produces a constant expression}} \
// ref-cxx17-error {{never produces a constant expression}}
return 1024 << 31; // cxx17-warning {{signed shift result}} \
// ref-cxx17-warning {{signed shift result}} \
// cxx17-note {{signed left shift discards bits}} \
// ref-cxx17-note {{signed left shift discards bits}}
}
constexpr int negativeShift() { // cxx17-error {{never produces a constant expression}} \
// ref-cxx17-error {{never produces a constant expression}}
return -1 << 2; // cxx17-warning {{shifting a negative signed value is undefined}} \
// ref-cxx17-warning {{shifting a negative signed value is undefined}} \
// cxx17-note {{left shift of negative value -1}} \
// ref-cxx17-note {{left shift of negative value -1}}
}
constexpr int foo(int a) {
return -a << 2; // cxx17-note {{left shift of negative value -10}} \
// ref-cxx17-note {{left shift of negative value -10}} \
// cxx17-note {{left shift of negative value -2}} \
// ref-cxx17-note {{left shift of negative value -2}}
}
static_assert(foo(10)); // cxx17-error {{not an integral constant expression}} \
// cxx17-note {{in call to 'foo(10)'}} \
// ref-cxx17-error {{not an integral constant expression}} \
// ref-cxx17-note {{in call to 'foo(10)'}}
constexpr int a = -2;
static_assert(foo(a));
static_assert(foo(-a)); // cxx17-error {{not an integral constant expression}} \
// cxx17-note {{in call to 'foo(2)'}} \
// ref-cxx17-error {{not an integral constant expression}} \
// ref-cxx17-note {{in call to 'foo(2)'}}
};
namespace LongInt {
constexpr int f() {
int a = 1;
a <<= (long)0;
return 1;
}
static_assert(f() == 1, "");
};
enum shiftof {
X = (1<<-29), // all-error {{expression is not an integral constant expression}} \
// all-note {{negative shift count -29}}
X2 = (-1<<29), // cxx17-error {{expression is not an integral constant expression}} \
// cxx17-note {{left shift of negative value -1}} \
// ref-cxx17-error {{expression is not an integral constant expression}} \
// ref-cxx17-note {{left shift of negative value -1}}
X3 = (1<<32) // all-error {{expression is not an integral constant expression}} \
// all-note {{shift count 32 >= width of type 'int'}}
};
|