| // PERMUTE_ARGS: -O -inline |
| |
| // Test value-range propagation. |
| // https://issues.dlang.org/show_bug.cgi?id=3147 |
| // https://issues.dlang.org/show_bug.cgi?id=6000 |
| // https://issues.dlang.org/show_bug.cgi?id=5225 |
| |
| void add() |
| { |
| byte x, y; |
| short a = x + y; |
| } |
| |
| void leftShift() |
| { |
| byte x, y; |
| short z = x << 1; |
| } |
| |
| void leftShiftFail() |
| { |
| { |
| ubyte x, y; |
| ushort z; |
| static assert(!__traits(compiles, z = x << y)); |
| // 1 << 31 surely overflows the range of 'ushort'. |
| } |
| { |
| ulong a, b; |
| int res; |
| static assert(!__traits(compiles, res = a << (b % 65U))); |
| } |
| } |
| |
| void rightShiftFail() |
| { |
| { |
| short x; |
| byte y, z; |
| static assert(!__traits(compiles, z = x >> y)); |
| // [this passes in 2.053.] |
| } |
| { |
| ulong a, b; |
| int res; |
| static assert(!__traits(compiles, res = a >> (b % 65U))); |
| } |
| } |
| |
| void rightShift() |
| { |
| ushort x; |
| ubyte y = x >> 16; |
| } |
| |
| void unsignedRightShiftFail() |
| { |
| int x; |
| ubyte y; |
| static assert(!__traits(compiles, y = x >>> 2)); |
| // [this passes in 2.053.] |
| } |
| |
| void subtract() |
| { |
| ubyte x, y; |
| short z = x - y; |
| } |
| |
| void multiply() |
| { |
| byte x, y; |
| short z = x * y; |
| } |
| |
| void subMulFail() |
| { |
| ubyte x, y; |
| ubyte z; |
| static assert(!__traits(compiles, z = x - y)); |
| static assert(!__traits(compiles, z = x * y)); |
| // [these pass in 2.053.] |
| } |
| |
| void multiplyNeg1() |
| { |
| byte b; |
| b = -1 + (b * -1); |
| static assert(!__traits(compiles, b = -1 + b * ulong.max)); |
| } |
| |
| void divide() |
| { |
| short w; |
| byte y = w / 300; |
| } |
| |
| void divideFail() |
| { |
| short w; |
| byte y; |
| static assert(!__traits(compiles, y = w / -1)); |
| } |
| |
| void plus1Fail() |
| { |
| byte u, v; |
| static assert(!__traits(compiles, v = u + 1)); |
| // [these pass in 2.053.] |
| } |
| |
| void modulus() |
| { |
| int x; |
| byte u = x % 128; |
| } |
| |
| void modulus_bug6000a() |
| { |
| ulong t; |
| uint u = t % 16; |
| } |
| |
| void modulus_bug6000b() |
| { |
| long n = 10520; |
| ubyte b; |
| static assert(!__traits(compiles, b = n % 10)); |
| } |
| |
| void modulus2() |
| { |
| short s; |
| byte b = byte.max; |
| byte c = s % b; |
| } |
| |
| void modulus3() |
| { |
| int i; |
| short s = short.max; |
| short t = i % s; |
| } |
| |
| void modulus4() |
| { |
| uint i; |
| ushort s; |
| short t; |
| static assert(!__traits(compiles, t = i % s)); |
| } |
| |
| void modulus5() |
| { |
| short a; |
| byte foo = (a - short.max - 1) % 127; |
| } |
| |
| void modulusFail() |
| { |
| int i; |
| short s; |
| byte b; |
| static assert(!__traits(compiles, b = i % s)); |
| static assert(!__traits(compiles, b = i % 257)); |
| // [these pass in 2.053.] |
| } |
| |
| void bitwise() |
| { |
| ubyte a, b, c; |
| uint d; |
| c = a & b; |
| c = a | b; |
| c = a ^ b; |
| c = d & 0xff; |
| // [these pass in 2.053.] |
| } |
| |
| void bitAnd() |
| { |
| byte c; |
| int d; |
| c = (0x3ff_ffffU << (0&c)) & (0x4000_0000U << (0&c)); |
| // the result of the above is always 0 :). |
| } |
| |
| void bitAndTest() |
| { |
| { |
| ushort a, b; |
| byte res = ((a % 7) - 6) & ((b % 7) - 6); |
| } |
| { |
| // rhs[-128..127] outside range of lhs[0..255] |
| // -> calls byte.implicitConvTo(ubyte) => MATCH.convert |
| byte a, b; |
| ubyte res; |
| |
| res = cast(byte)(a + 5) & b; |
| res = cast(byte)(a - 5) & b; |
| res = cast(byte)(a / 5) & b; |
| res = cast(byte)(a * 5) & b; |
| res = cast(byte)(a % 5) & b; |
| } |
| } |
| |
| void bitOrFail() |
| { |
| { |
| ubyte c; |
| static assert(!__traits(compiles, c = c | 0x100)); |
| // [this passes in 2.053.] |
| } |
| { |
| byte a, b; |
| ubyte res; |
| |
| static assert(!__traits(compiles, res = (a + 5) | b)); // [-128..255] |
| static assert(!__traits(compiles, res = (a - 5) | b)); // [-133..127] |
| static assert(!__traits(compiles, res = (a / 5) | b)); // [-128..127] |
| static assert(!__traits(compiles, res = (a * 5) | b)); // [-640..639] |
| static assert(!__traits(compiles, res = (a % 5) | b)); // [-128..127] |
| } |
| } |
| |
| void bitAndOr() |
| { |
| ubyte c; |
| c = (c | 0x1000) & ~0x1000; |
| } |
| |
| void bitOrTest() |
| { |
| { |
| // Tests condition for different signs between min & max |
| // ((imin.negative ^ imax.negative) == 1 && (rhs.imin.negative ^ rhs.imax.negative) == 1 |
| ushort a, b; |
| byte res = ((a % 127) - 126) | ((b % 6) - 5); |
| } |
| { |
| // rhs[-128..127] outside range of lhs[0..255] |
| // -> calls byte.implicitConvTo(ubyte) => MATCH.convert |
| byte a, b, c; |
| ubyte res; |
| |
| res = cast(byte)(a + 5) | b; |
| res = cast(byte)(a - 5) | b; |
| res = cast(byte)(a / 5) | b; |
| res = cast(byte)(a * 5) | b; |
| res = cast(byte)(a % 5) | b; |
| } |
| } |
| |
| void bitAndFail() |
| { |
| { |
| int d; |
| short s; |
| byte c; |
| static assert(!__traits(compiles, c = d & s)); |
| static assert(!__traits(compiles, c = d & 256)); |
| // [these pass in 2.053.] |
| } |
| { |
| byte a, b; |
| ubyte res; |
| |
| static assert(!__traits(compiles, res = (a + 5) & b)); // [-128..132] |
| static assert(!__traits(compiles, res = (a - 5) & b)); // [-256..127] |
| static assert(!__traits(compiles, res = (a / 5) & b)); // [-128..127] |
| static assert(!__traits(compiles, res = (a * 5) & b)); // [-640..635] |
| static assert(!__traits(compiles, res = (a % 5) & b)); // [-128..127] |
| } |
| } |
| |
| void bitXor() |
| { |
| { |
| ushort s; |
| ubyte c; |
| c = (0xffff << (s & 0)) ^ 0xff00; |
| } |
| { |
| // rhs[-128..127] outside range of lhs[0..255] |
| // -> calls byte.implicitConvTo(ubyte) => MATCH.convert |
| byte a, b, c; |
| ubyte res; |
| |
| res = cast(byte)(a + 5) ^ b; |
| res = cast(byte)(a - 5) ^ b; |
| res = cast(byte)(a / 5) ^ b; |
| res = cast(byte)(a * 5) ^ b; |
| res = cast(byte)(a % 5) ^ b; |
| } |
| } |
| |
| void bitXorFail() |
| { |
| { |
| byte a, b; |
| ubyte res; |
| |
| static assert(!__traits(compiles, res = (a + 5) ^ b)); // [-256..255] |
| static assert(!__traits(compiles, res = (a - 5) ^ b)); // [-256..255] |
| static assert(!__traits(compiles, res = (a / 5) ^ b)); // [-128..127] |
| static assert(!__traits(compiles, res = (a * 5) ^ b)); // [-640..1023] |
| static assert(!__traits(compiles, res = (a % 5) ^ b)); // [-128..127] |
| } |
| } |
| |
| void bitComplement() |
| { |
| int i; |
| ubyte b = ~(i | ~0xff); |
| } |
| |
| void bitComplementFail() |
| { |
| ubyte b; |
| static assert(!__traits(compiles, b = ~(b | 1))); |
| // [this passes in 2.053.] |
| } |
| |
| void negation() |
| { |
| int x; |
| byte b = -(x & 0x7); |
| } |
| |
| void negationFail() |
| { |
| int x; |
| byte b; |
| static assert(!__traits(compiles, b = -(x & 255))); |
| // [this passes in 2.053.] |
| } |
| |
| short bug5225(short a) { |
| return a>>1; |
| } |
| |
| short bug1977_comment5(byte i) { |
| byte t = 1; |
| short o = t - i; |
| return o; |
| } |
| |
| void testDchar() |
| { |
| dchar d; |
| uint i; |
| /+ |
| static assert(!__traits(compiles, d = i)); |
| static assert(!__traits(compiles, d = i & 0x1fffff)); |
| +/ |
| d = i % 0x110000; |
| } |
| |
| void bug1977_comment11() |
| { |
| uint a; |
| byte b = a & 1; |
| // [this passes in 2.053.] |
| } |
| |
| void bug1977_comment20() |
| { |
| long a; |
| int b = a % 1000; |
| } |
| |
| /******************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=9617 |
| |
| void test9617() |
| { |
| void f1(int) {} |
| void f2(short) {} |
| void f3(byte) {} |
| |
| // Why these calls are accepted? |
| static assert(!__traits(compiles, f1(ulong.max))); |
| static assert(!__traits(compiles, f2(ulong.max))); |
| static assert(!__traits(compiles, f3(ulong.max))); |
| |
| // But, if argument is not constant value, compilation fails. |
| ulong x; |
| static assert(!__traits(compiles, f1(x))); // is not callable using argument types (ulong) |
| static assert(!__traits(compiles, f2(x))); // is not callable using argument types (ulong) |
| static assert(!__traits(compiles, f3(x))); // is not callable using argument types (ulong) |
| |
| void f4(uint) {} |
| void f5(ushort) {} |
| void f6(ubyte) {} |
| |
| // If parameter type is unsigned, it is collectly rejected |
| static assert(!__traits(compiles, f4(ulong.max))); // is not callable using argument types (ulong) |
| static assert(!__traits(compiles, f5(ulong.max))); // is not callable using argument types (ulong) |
| static assert(!__traits(compiles, f6(ulong.max))); // is not callable using argument types (ulong) |
| } |
| |
| //import std.typetuple; |
| template TypeTuple(T...) { alias TypeTuple = T; } |
| template staticIota(size_t end) |
| { |
| static if (0 < end) |
| alias staticIota = TypeTuple!(staticIota!(end - 1), end - 1); |
| else |
| alias staticIota = TypeTuple!(); |
| } |
| void test9617a() |
| { |
| alias Repr = TypeTuple!( |
| byte, "127", // T and literal representation of T.max |
| ubyte, "255", |
| short, "32767", |
| ushort, "65535", |
| int, "2147483647", |
| uint, "4294967295", |
| long, "9223372036854775807", |
| ulong, "18446744073709551615" // "" or "L" -> "signed integral overflow" |
| ); |
| alias Indices = staticIota!(Repr.length / 2); |
| |
| foreach (t; Indices) |
| { |
| alias T = Repr[t * 2]; |
| void func(T)(T) {} |
| alias func!T f; |
| |
| foreach (r; Indices) |
| { |
| alias S = Repr[r * 2]; |
| S src = S.max; |
| |
| enum x = Repr[r * 2 + 1]; |
| foreach (repr; TypeTuple!(S.stringof~".max", x~"", x~"U", x~"L", x~"LU")) |
| { |
| static if (S.sizeof != T.sizeof) |
| static if (is(typeof(mixin(repr)) R)) |
| { |
| // "Compilable" test should be equal, even if |
| // the given argument is either constant or runtime variable. |
| enum ct = __traits(compiles, f( mixin(repr) )); |
| enum rt = __traits(compiles, f( src )); |
| |
| static assert(ct == rt); |
| //import std.string; |
| //enum msg = format("%6s.max to %-6s variable/constant = %d/%d, constant_repr = (%s) %s", |
| // S.stringof, T.stringof, rt, ct, R.stringof, repr); |
| //static if (ct != rt) pragma(msg, msg); |
| } |
| } |
| } |
| } |
| } |
| |
| void test10018(ubyte value) |
| { |
| const int c = value; |
| ubyte b = c; |
| static assert(!__traits(compiles, b = c - 1)); |
| static assert(!__traits(compiles, b = c + 1)); |
| immutable int i = value; |
| b = i; |
| static assert(!__traits(compiles, b = i - 1)); |
| static assert(!__traits(compiles, b = i + 1)); |
| } |
| |
| void test13001(bool unknown) |
| { |
| foreach (const i; 0..unknown?2:3) |
| { |
| ubyte b = i; |
| static assert(!__traits(compiles, b = i - 1)); |
| b = i + 253; |
| static assert(!__traits(compiles, b = i + 254)); |
| } |
| } |
| |
| void test10310() |
| { |
| int y; |
| ubyte x = ((y & 252) ^ 2) + 1; |
| } |
| |
| // https://issues.dlang.org/show_bug.cgi?id=15289 |
| void test15289a() |
| { |
| int [] arr = [1, 2, 3, 4]; |
| uint foo = 50 / arr.length; |
| } |
| |
| void test15289b() |
| { |
| int [] arr = [1, 2, 3, 4]; |
| uint foo = 50 % arr.length; |
| } |
| |
| void testShiftRightOnNegative() |
| { |
| int neg = -1; |
| uint[] arr = [1, 2, 3]; |
| ubyte b; |
| // Shift with negative value returns value in range [0, ulong.max] |
| static assert(!__traits(compiles, b = arr.length >> neg)); |
| static assert(!__traits(compiles, b = arr.length << neg)); |
| } |