// 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)); }