| // PERMUTE_ARGS: -inline |
| /* |
| TEST_OUTPUT: |
| --- |
| compilable/interpret3.d(6350): Deprecation: identity comparison of static arrays implicitly coerces them to slices, which are compared by reference |
| --- |
| */ |
| |
| template compiles(int T) |
| { |
| bool compiles = true; |
| } |
| |
| alias TypeTuple(T...) = T; |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=3901 |
| // Arbitrary struct assignment, ref return |
| |
| struct ArrayRet |
| { |
| int x; |
| } |
| |
| int arrayRetTest(int z) |
| { |
| ArrayRet[6] w; |
| int q = (w[3].x = z); |
| return q; |
| } |
| static assert(arrayRetTest(51) == 51); |
| |
| // https://issues.dlang.org/show_bug.cgi?id=3842 -- must not segfault |
| int ice3842(int z) |
| { |
| ArrayRet w; |
| return arrayRetTest((*(&w)).x); |
| } |
| static assert(true || is(typeof(compiles!(ice3842(51))))); |
| |
| int arrayret2() |
| { |
| int[5] a; |
| int[3] b; |
| b[] = a[1 .. $-1] = 5; |
| return b[1]; |
| } |
| static assert(arrayret2() == 5); |
| |
| struct DotVarTest |
| { |
| ArrayRet z; |
| } |
| |
| struct DotVarTest2 |
| { |
| ArrayRet z; |
| DotVarTest p; |
| } |
| |
| int dotvar1() |
| { |
| DotVarTest w; |
| w.z.x = 3; |
| return w.z.x; |
| } |
| static assert(dotvar1() == 3); |
| |
| int dotvar2() |
| { |
| DotVarTest2[4] m; |
| m[2].z.x = 3; |
| m[1].p.z.x = 5; |
| return m[2].z.x + 7; |
| } |
| static assert(dotvar2() == 10); |
| |
| |
| struct RetRefStruct |
| { |
| int x; |
| char c; |
| } |
| |
| // Return value reference tests, for D2 only. |
| |
| ref RetRefStruct reffunc1(return ref RetRefStruct a) |
| { |
| int y = a.x; |
| return a; |
| } |
| |
| ref RetRefStruct reffunc2(return ref RetRefStruct a) |
| { |
| RetRefStruct z = a; |
| return reffunc1(a); |
| } |
| |
| ref int reffunc7(return ref RetRefStruct aa) |
| { |
| return reffunc1(aa).x; |
| } |
| |
| ref int reffunc3(return ref int a) |
| { |
| return a; |
| } |
| |
| struct RefTestStruct |
| { |
| RetRefStruct r; |
| |
| ref RefTestStruct reffunc4(ref RetRefStruct[3] a) return |
| { |
| return this; |
| } |
| |
| ref int reffunc6() return |
| { |
| return this.r.x; |
| } |
| } |
| |
| ref RetRefStruct reffunc5(return ref RetRefStruct[3] a) |
| { |
| int t = 1; |
| for (int i = 0; i < 10; ++i) |
| { |
| if (i == 7) |
| ++t; |
| } |
| return a[reffunc3(t)]; |
| } |
| |
| int retRefTest1() |
| { |
| RetRefStruct b = RetRefStruct(0, 'a'); |
| reffunc1(b).x = 3; |
| return b.x - 1; |
| } |
| |
| int retRefTest2() |
| { |
| RetRefStruct b = RetRefStruct(0, 'a'); |
| reffunc2(b).x = 3; |
| RetRefStruct[3] z; |
| RefTestStruct w; |
| w.reffunc4(z).reffunc4(z).r.x = 4; |
| assert(w.r.x == 4); |
| w.reffunc6() = 218; |
| assert(w.r.x == 218); |
| z[2].x = 3; |
| int q = 4; |
| int u = reffunc5(z).x + reffunc3(q); |
| assert(u == 7); |
| reffunc5(z).x += 7; |
| assert(z[2].x == 10); |
| RetRefStruct m = RetRefStruct(7, 'c'); |
| m.x = 6; |
| reffunc7(m) += 3; |
| assert(m.x == 9); |
| return b.x - 1; |
| } |
| |
| int retRefTest3() |
| { |
| RetRefStruct b = RetRefStruct(0, 'a'); |
| auto deleg = function (RetRefStruct a){ return a; }; |
| typeof(deleg)[3] z; |
| z[] = deleg; |
| auto y = deleg(b).x + 27; |
| b.x = 5; |
| assert(y == 27); |
| y = z[1](b).x + 22; |
| return y - 1; |
| } |
| |
| int retRefTest4() |
| { |
| RetRefStruct b = RetRefStruct(0, 'a'); |
| reffunc3(b.x) = 218; |
| assert(b.x == 218); |
| return b.x; |
| } |
| |
| static assert(retRefTest1() == 2); |
| static assert(retRefTest2() == 2); |
| static assert(retRefTest3() == 26); |
| static assert(retRefTest4() == 218); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7887 |
| // assign to returned reference |
| |
| bool test7887() |
| { |
| ref int f(ref int x) { return x; } |
| int a; |
| f(a) = 42; |
| return (a == 42); |
| } |
| static assert(test7887()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7473 |
| // struct non-ref |
| |
| struct S7473 |
| { |
| int i; |
| } |
| |
| static assert({ |
| S7473 s = S7473(1); |
| assert(s.i == 1); |
| bug7473(s); |
| assert(s.i == 1); |
| return true; |
| }()); |
| |
| void bug7473(S7473 s) |
| { |
| s.i = 2; |
| } |
| |
| struct S7473b |
| { |
| S7473 m; |
| } |
| |
| static assert({ |
| S7473b s = S7473b(S7473(7)); |
| assert(s.m.i == 7); |
| bug7473b(s); |
| assert(s.m.i == 7); |
| return true; |
| }()); |
| |
| void bug7473b(S7473b s) |
| { |
| s.m.i = 2; |
| } |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=4389 |
| |
| int bug4389() |
| { |
| string s; |
| dchar c = '\u2348'; |
| s ~= c; |
| assert(s.length == 3); |
| dchar d = 'D'; |
| s ~= d; |
| assert(s.length == 4); |
| s = ""; |
| s ~= c; |
| assert(s.length == 3); |
| s ~= d; |
| assert(s.length == 4); |
| string z; |
| wchar w = '\u0300'; |
| z ~= w; |
| assert(z.length == 2); |
| z = ""; |
| z ~= w; |
| assert(z.length == 2); |
| return 1; |
| } |
| |
| static assert(bug4389()); |
| |
| // ICE(constfold.c) |
| int ice4389() |
| { |
| string s; |
| dchar c = '\u2348'; |
| s ~= c; |
| s = s ~ "xxx"; |
| return 1; |
| } |
| |
| static assert(ice4389()); |
| |
| // ICE(expression.c) |
| string ice4390() |
| { |
| string s; |
| dchar c = '`'; |
| s ~= c; |
| s ~= c; |
| return s; |
| } |
| |
| static assert(mixin(ice4390()) == ``); |
| |
| // https://issues.dlang.org/show_bug.cgi?id=5248 |
| // (D1 + D2) |
| struct Leaf5248 |
| { |
| string Compile_not_ovloaded() |
| { |
| return "expression"; |
| } |
| } |
| struct Matrix5248 |
| { |
| Leaf5248 Right; |
| |
| string Compile() |
| { |
| return Right.Compile_not_ovloaded(); |
| } |
| }; |
| |
| static assert(Matrix5248().Compile()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=4837 |
| // >>>= |
| |
| bool bug4837() |
| { |
| ushort x = 0x89AB; |
| x >>>= 4; |
| assert(x == 0x89A); |
| byte y = 0x7C; |
| y >>>= 2; |
| assert(y == 0x1F); |
| return true; |
| } |
| |
| static assert(bug4837()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=10252 |
| // shift out of range |
| |
| int lshr10252(int shift) |
| { |
| int a = 5; |
| return a << shift; |
| } |
| |
| int rshr10252(int shift) |
| { |
| int a = 5; |
| return a >> shift; |
| } |
| |
| int ushr10252(int shift) |
| { |
| int a = 5; |
| return a >>> shift; |
| } |
| |
| static assert( is(typeof(compiles!(lshr10252( 4))))); |
| static assert(!is(typeof(compiles!(lshr10252(60))))); |
| static assert( is(typeof(compiles!(rshr10252( 4))))); |
| static assert(!is(typeof(compiles!(rshr10252(80))))); |
| static assert( is(typeof(compiles!(ushr10252( 2))))); |
| static assert(!is(typeof(compiles!(ushr10252(60))))); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=1982 |
| // CTFE null problems |
| |
| enum a1982 = [1, 2, 3]; |
| static assert(a1982 !is null); |
| |
| string foo1982() { return null; } |
| static assert(foo1982() is null); |
| static assert(!foo1982().length); |
| |
| static assert(null is null); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7988 |
| // CTFE return values should be allowed in compile-time expressions |
| |
| class X7988 { int y; this() { y = 2; } } |
| static assert((new X7988).y == 2); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=8253 |
| // ICE: calling of member function of non-CTFE class variable |
| |
| class Bug8253 |
| { |
| bool j() |
| { |
| return true; |
| } |
| } |
| Bug8253 m8253; |
| static assert(!is(typeof(compiles!(m8253.j())))); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=8285 |
| // Issue with slice returned from CTFE function |
| |
| string foo8285() |
| { |
| string s = "ab"; |
| return s[0 .. $]; |
| } |
| |
| template T8285b(string s) { } |
| |
| template T8285a() |
| { |
| enum s = foo8285(); |
| alias T8285b!(s) t2; |
| } |
| |
| int bar8285() |
| { |
| alias T8285a!() t1; |
| return 0; |
| } |
| |
| int baz8285(int x) |
| { |
| return 0; |
| } |
| |
| static assert(baz8285(bar8285()) == 0); |
| |
| // test case 2 |
| |
| string xbar8285() |
| { |
| string s = "ab"; |
| return s[0 .. $]; |
| } |
| |
| template xT8285a() |
| { |
| enum xT8285a = xbar8285()[0 .. $]; |
| } |
| |
| string xbaz8285() |
| { |
| return xT8285a!(); |
| } |
| |
| string xfoo8285(string s) |
| { |
| return s; |
| } |
| |
| static assert(xfoo8285(xbaz8285()) == "ab"); |
| |
| /************************************************** |
| 'this' parameter bug revealed during refactoring |
| **************************************************/ |
| |
| int thisbug1(int x) { return x; } |
| |
| struct ThisBug1 |
| { |
| int m = 1; |
| int wut() |
| { |
| return thisbug1(m); |
| } |
| } |
| |
| int thisbug2() |
| { |
| ThisBug1 spec; |
| return spec.wut(); |
| } |
| |
| static assert(thisbug2()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6972 |
| // ICE with cast()cast()assign |
| |
| int bug6972() |
| { |
| ubyte n = 6; |
| n /= 2u; |
| return n; |
| } |
| static assert(bug6972() == 3); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6164 |
| |
| size_t bug6164() |
| { |
| int[] ctfe2(int n) |
| { |
| int[] r = []; |
| if (n != 0) |
| r ~= [1] ~ ctfe2(n - 1); |
| return r; |
| } |
| return ctfe2(2).length; |
| } |
| static assert(bug6164() == 2); |
| |
| /************************************************** |
| Interpreter code coverage tests |
| **************************************************/ |
| |
| int cov1(int a) |
| { |
| a %= 15382; |
| a /= 5; |
| a = ~ a; |
| bool c = (a == 0); |
| bool b = true && c; |
| assert(b == 0); |
| b = false && c; |
| assert(b == 0); |
| b = false || c; |
| assert(b == 0); |
| a ^= 0x45349; |
| a = ~ a; |
| a &= 0xFF3F; |
| a >>>= 1; |
| a = a ^ 0x7393; |
| a = a >> 1; |
| a = a >>> 1; |
| a = a | 0x010101; |
| return a; |
| } |
| static assert(cov1(534564) == 71589); |
| |
| int cov2() |
| { |
| int i = 0; |
| do |
| { |
| goto DOLABEL; |
| DOLABEL: |
| if (i != 0) |
| { |
| goto IFLABEL; |
| IFLABEL: |
| switch(i) |
| { |
| case 3: |
| break; |
| case 6: |
| goto SWITCHLABEL; |
| SWITCHLABEL: |
| i = 27; |
| goto case 3; |
| default: |
| assert(0); |
| } |
| return i; |
| } |
| i = 6; |
| } while(true); |
| return 88; // unreachable |
| } |
| static assert(cov2() == 27); |
| |
| template CovTuple(T...) |
| { |
| alias T CovTuple; |
| } |
| |
| alias CovTuple!(int, long) TCov3; |
| |
| int cov3(TCov3 t) |
| { |
| TCov3 s; |
| s = t; |
| assert(s[0] == 1); |
| assert(s[1] == 2); |
| return 7; |
| } |
| static assert(cov3(1, 2) == 7); |
| |
| int badassert1(int z) |
| { |
| assert(z == 5, "xyz"); |
| return 1; |
| } |
| |
| size_t badslice1(int[] z) |
| { |
| return z[0 .. 3].length; |
| } |
| |
| size_t badslice2(int[] z) |
| { |
| return z[0 .. badassert1(1)].length; |
| } |
| |
| size_t badslice3(int[] z) |
| { |
| return z[badassert1(1) .. 2].length; |
| } |
| |
| static assert(!is(typeof(compiles!(badassert1(67))))); |
| static assert( is(typeof(compiles!(badassert1(5))))); |
| static assert(!is(typeof(compiles!(badslice1([1,2]))))); |
| static assert(!is(typeof(compiles!(badslice2([1,2]))))); |
| static assert(!is(typeof(compiles!(badslice3([1,2,3]))))); |
| |
| /*******************************************/ |
| |
| int bug7894() |
| { |
| for (int k = 0; k < 2; ++k) |
| { |
| goto Lagain; |
| Lagain: |
| ; |
| } |
| int m = 1; |
| do |
| { |
| ++m; |
| goto Ldo; |
| Ldo: ; |
| } while (m < 3); |
| assert(m == 3); |
| |
| return 1; |
| } |
| static assert(bug7894()); |
| |
| /*******************************************/ |
| |
| size_t bug5524(int x, int[] more...) |
| { |
| int[0] zz; |
| assert(zz.length == 0); |
| return 7 + more.length + x; |
| } |
| static assert(bug5524(3) == 10); |
| |
| |
| // https://issues.dlang.org/show_bug.cgi?id=5722 |
| |
| static assert(("" ~ "\©"[0]).length == 1); |
| const char[] null5722 = null; |
| static assert((null5722 ~ "\©"[0]).length == 1); |
| static assert(("\©"[0] ~ null5722).length == 1); |
| |
| /******************************************* |
| * Tests for CTFE Array support. |
| * https://issues.dlang.org/show_bug.cgi?id=1330 |
| * https://issues.dlang.org/show_bug.cgi?id=3801 |
| * https://issues.dlang.org/show_bug.cgi?id=3835 |
| * https://issues.dlang.org/show_bug.cgi?id=4050 |
| * https://issues.dlang.org/show_bug.cgi?id=4051 |
| * https://issues.dlang.org/show_bug.cgi?id=5147 |
| * and major functionality |
| *******************************************/ |
| |
| char[] bug1330StringIndex() |
| { |
| char[] blah = "foo".dup; |
| assert(blah == "foo"); |
| char[] s = blah[0 .. 2]; |
| blah[0] = 'h'; |
| assert(s == "ho"); |
| s[0] = 'm'; |
| return blah; |
| } |
| static assert(bug1330StringIndex() == "moo"); |
| static assert(bug1330StringIndex() == "moo"); // check we haven't clobbered any string literals |
| |
| int[] bug1330ArrayIndex() |
| { |
| int[] blah = [1,2,3]; |
| int[] s = blah; |
| s = blah[0 .. 2]; |
| int z = blah[0] = 6; |
| assert(z == 6); |
| assert(blah[0] == 6); |
| assert(s[0] == 6); |
| assert(s == [6, 2]); |
| s[1] = 4; |
| assert(z == 6); |
| return blah; |
| } |
| static assert(bug1330ArrayIndex() == [6, 4, 3]); |
| static assert(bug1330ArrayIndex() == [6, 4, 3]); // check we haven't clobbered any literals |
| |
| char[] bug1330StringSliceAssign() |
| { |
| char[] blah = "food".dup; |
| assert(blah == "food"); |
| char[] s = blah[1 .. 4]; |
| blah[0 .. 2] = "hc"; |
| assert(s == "cod"); |
| s[0 .. 2] = ['a', 'b']; // Mix string + array literal |
| assert(blah == "habd"); |
| s[0 .. 2] = "mq"; |
| return blah; |
| } |
| static assert(bug1330StringSliceAssign() == "hmqd"); |
| static assert(bug1330StringSliceAssign() == "hmqd"); |
| |
| int[] bug1330ArraySliceAssign() |
| { |
| int[] blah = [1, 2, 3, 4]; |
| int[] s = blah[1 .. 4]; |
| blah[0 .. 2] = [7, 9]; |
| assert(s == [9, 3, 4]); |
| s[0 .. 2] = [8, 15]; |
| return blah; |
| } |
| static assert(bug1330ArraySliceAssign() == [7, 8, 15, 4]); |
| |
| int[] bug1330ArrayBlockAssign() |
| { |
| int[] blah = [1, 2, 3, 4, 5]; |
| int[] s = blah[1 .. 4]; |
| blah[0 .. 2] = 17; |
| assert(s == [17, 3, 4]); |
| s[0 .. 2] = 9; |
| return blah; |
| } |
| static assert(bug1330ArrayBlockAssign() == [17, 9, 9, 4, 5]); |
| |
| char[] bug1330StringBlockAssign() |
| { |
| char[] blah = "abcde".dup; |
| char[] s = blah[1 .. 4]; |
| blah[0 .. 2] = 'x'; |
| assert(s == "xcd"); |
| s[0 .. 2] = 'y'; |
| return blah; |
| } |
| static assert(bug1330StringBlockAssign() == "xyyde"); |
| |
| int assignAA(int x) |
| { |
| int[int] aa; |
| int[int] cc = aa; |
| assert(cc.values.length == 0); |
| assert(cc.keys.length == 0); |
| aa[1] = 2; |
| aa[x] = 6; |
| int[int] bb = aa; |
| assert(bb.keys.length == 2); |
| assert(cc.keys.length == 0); // cc is not affected to aa, because it is null |
| aa[500] = 65; |
| assert(bb.keys.length == 3); // but bb is affected by changes to aa |
| return aa[1] + aa[x]; |
| } |
| static assert(assignAA(12) == 8); |
| |
| template Compileable(int z) { bool OK; } |
| |
| int arraybounds(int j, int k) |
| { |
| int[] xxx = [1, 2, 3, 4, 5]; |
| int[] s = xxx[1 .. $]; |
| s = s[j .. k]; // slice of slice |
| return s[$ - 1]; |
| } |
| static assert(!is(typeof(Compileable!(arraybounds(1, 14))))); |
| static assert(!is(typeof(Compileable!(arraybounds(15, 3))))); |
| static assert(arraybounds(2, 4) == 5); |
| |
| int arraybounds2(int j, int k) |
| { |
| int[] xxx = [1, 2, 3, 4, 5]; |
| int[] s = xxx[j .. k]; // direct slice |
| return 1; |
| } |
| static assert(!is(typeof(Compileable!(arraybounds2(1, 14))))); |
| static assert(!is(typeof(Compileable!(arraybounds2(15, 3))))); |
| static assert(arraybounds2(2, 4) == 1); |
| |
| int bug5147a() |
| { |
| int[1][2] a = 37; |
| return a[0][0]; |
| } |
| static assert(bug5147a() == 37); |
| |
| int bug5147b() |
| { |
| int[4][2][3][17] a = 37; |
| return a[0][0][0][0]; |
| } |
| static assert(bug5147b() == 37); |
| |
| int setlen() |
| { |
| int[][] zzz; |
| zzz.length = 2; |
| zzz[0].length = 10; |
| assert(zzz.length == 2); |
| assert(zzz[0].length == 10); |
| assert(zzz[1].length == 0); |
| return 2; |
| } |
| static assert(setlen() == 2); |
| |
| int[1][1] bug5147() |
| { |
| int[1][1] a = 1; |
| return a; |
| } |
| static assert(bug5147() == [[1]]); |
| |
| enum int[1][1] enum5147 = bug5147(); |
| static assert(enum5147 == [[1]]); |
| |
| immutable int[1][1] bug5147imm = bug5147(); |
| |
| // Index referencing |
| int[2][2] indexref1() |
| { |
| int[2][2] a = 2; |
| a[0] = 7; |
| |
| int[][] b = [null, null]; |
| b[0 .. $] = a[0][0 .. 2]; |
| assert(b[0][0] == 7); |
| assert(b[0][1] == 7); |
| int[] w; |
| w = a[0]; |
| assert(w[0] == 7); |
| w[0 .. $] = 5; |
| assert(a[0] != [7, 7]); |
| assert(a[0] == [5, 5]); |
| assert(b[0] == [5, 5]); |
| return a; |
| } |
| int[2][2] indexref2() |
| { |
| int[2][2] a = 2; |
| a[0] = 7; |
| |
| int[][2] b = null; |
| b[0 .. $] = a[0]; |
| assert(b[0][0] == 7); |
| assert(b[0][1] == 7); |
| assert(b == [[7, 7], [7, 7]]); |
| int[] w; |
| w = a[0]; |
| assert(w[0] == 7); |
| w[0 .. $] = 5; |
| assert(a[0] != [7, 7]); |
| assert(a[0] == [5, 5]); |
| assert(b[0] == [5, 5]); |
| return a; |
| } |
| int[2][2] indexref3() |
| { |
| int[2][2] a = 2; |
| a[0]=7; |
| |
| int[][2] b = [null, null]; |
| b[0 .. $] = a[0]; |
| assert(b[0][0] == 7); |
| assert(b[0][1] == 7); |
| int[] w; |
| w = a[0]; |
| assert(w[0] == 7); |
| w[0 .. $] = 5; |
| assert(a[0] != [7, 7]); |
| assert(a[0] == [5, 5]); |
| assert(b[0] == [5, 5]); |
| return a; |
| } |
| int[2][2] indexref4() |
| { |
| int[2][2] a = 2; |
| a[0] = 7; |
| |
| int[][2] b =[[1, 2, 3], [1, 2, 3]]; // wrong code |
| b[0] = a[0]; |
| assert(b[0][0] == 7); |
| assert(b[0][1] == 7); |
| int[] w; |
| w = a[0]; //[0 .. $]; |
| assert(w[0] == 7); |
| w[0 .. $] = 5; |
| assert(a[0] != [7, 7]); |
| assert(a[0] == [5, 5]); |
| assert(b[0] == [5, 5]); |
| return a; |
| } |
| static assert(indexref1() == [[5, 5], [2, 2]]); |
| static assert(indexref2() == [[5, 5], [2, 2]]); |
| static assert(indexref3() == [[5, 5], [2, 2]]); |
| static assert(indexref4() == [[5, 5], [2, 2]]); |
| |
| int staticdynamic() |
| { |
| int[2][1] a = 2; |
| assert(a == [[2, 2]]); |
| |
| int[][1] b = a[0][0 .. 1]; |
| assert(b[0] == [2]); |
| auto k = b[0]; |
| auto m = a[0][0 .. 1]; |
| assert(k == [2]); |
| assert(m == k); |
| return 0; |
| } |
| static assert(staticdynamic() == 0); |
| |
| int chainassign() |
| { |
| int[4] x = 6; |
| int[] y = new int[4]; |
| auto k = (y[] = (x[] = 2)); |
| return k[0]; |
| } |
| static assert(chainassign() == 2); |
| |
| // index assignment |
| struct S3801 |
| { |
| char c; |
| int[3] arr; |
| |
| this(int x, int y) |
| { |
| c = 'x'; |
| arr[0] = x; |
| arr[1] = y; |
| } |
| } |
| |
| int bug3801() |
| { |
| S3801 xxx = S3801(17, 67); |
| int[] w = xxx.arr; |
| xxx.arr[1] = 89; |
| assert(xxx.arr[0] == 17); |
| assert(w[1] == 89); |
| assert(w == [17, 89, 0]); |
| return xxx.arr[1]; |
| } |
| |
| enum : S3801 { bug3801e = S3801(17, 18) } |
| static assert(bug3801e.arr == [17, 18, 0]); |
| |
| immutable S3801 bug3801u = S3801(17, 18); |
| static assert(bug3801u.arr == [17, 18, 0]); |
| static assert(bug3801() == 89); |
| |
| int bug3835() |
| { |
| int[4] arr; |
| arr[] = 19; |
| arr[0] = 4; |
| int kk; |
| foreach (ref el; arr) |
| { |
| el += 10; |
| kk = el; |
| } |
| assert(arr[2] == 29); |
| arr[0] += 3; |
| return arr[0]; |
| } |
| static assert(bug3835() == 17); |
| |
| auto bug5852(const(string) s) |
| { |
| string[] r; |
| r ~= s; |
| assert(r.length == 1); |
| return r[0].length; |
| } |
| static assert(bug5852("abc") == 3); |
| |
| // https://issues.dlang.org/show_bug.cgi?id=7217 |
| |
| struct S7217 { int[] arr; } |
| |
| bool f7217() |
| { |
| auto s = S7217(); |
| auto t = s.arr; |
| return true; |
| } |
| static assert(f7217()); |
| |
| /******************************************* |
| Set array length |
| *******************************************/ |
| |
| static assert( |
| { |
| struct W { int[] z; } |
| W w; |
| w.z.length = 2; |
| assert(w.z.length == 2); |
| w.z.length = 6; |
| assert(w.z.length == 6); |
| return true; |
| }()); |
| |
| // https://issues.dlang.org/show_bug.cgi?id=7185 |
| // char[].length = n |
| |
| bool bug7185() |
| { |
| auto arr = new char[2]; |
| auto arr2 = new char[2]; |
| arr2[] = "ab"; |
| arr.length = 1; |
| arr2.length = 7; |
| assert(arr.length == 1); |
| assert(arr2.length == 7); |
| assert(arr2[0 .. 2] == "ab"); |
| return true; |
| } |
| static assert(bug7185()); |
| |
| bool bug9908() |
| { |
| static const int[3] sa = 1; |
| return sa == [1, 1, 1]; |
| } |
| static assert(bug9908()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6934 |
| |
| struct Struct6934 |
| { |
| int[] x = [1, 2]; |
| } |
| |
| void bar6934(ref int[] p) |
| { |
| p[0] = 12; |
| assert(p[0] == 12); |
| p[0 .. 1] = 17; |
| assert(p[0] == 17); |
| p = p[1 .. $]; |
| } |
| |
| int bug6934() |
| { |
| Struct6934 q; |
| bar6934(q.x); |
| int[][] y = [[2, 5], [3, 6, 8]]; |
| bar6934(y[0]); |
| return 1; |
| } |
| static assert(bug6934()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=5671 |
| |
| static assert(['a', 'b'] ~ "c" == "abc"); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=8624 |
| |
| int evil8624() |
| { |
| long m = 0x1_0000_0000L; |
| assert(m != 0); |
| long[] a = [0x1_0000_0000L]; |
| long[] b = [0x4_0000_0000L]; |
| assert(a[] != b[]); |
| return 1; |
| } |
| static assert(evil8624()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=8644 |
| // array literal >,< |
| |
| int bug8644() |
| { |
| auto m = "a"; |
| auto z = ['b']; |
| auto c = "b7"; |
| auto d = ['b', '6']; |
| assert(m < z); |
| assert(z > m); |
| assert(z <= c); |
| assert(c > z); |
| assert(c > d); |
| assert(d >= d); |
| return true; |
| } |
| static assert(bug8644()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6159 |
| |
| struct A6159 {} |
| |
| static assert({ return A6159.init is A6159.init; }()); |
| static assert({ return [1] is [1]; }()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=5685 |
| |
| string bug5685() |
| { |
| return "xxx"; |
| } |
| struct Bug5865 |
| { |
| void test1() |
| { |
| enum file2 = (bug5685())[0 .. $]; |
| } |
| } |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6235 |
| // Regression ICE on $ in template |
| |
| struct Bug6235(R) |
| { |
| enum XXX = is(typeof(R.init[0 .. $]) : const ubyte[]); |
| } |
| |
| Bug6235!(ubyte[]) bug6235; |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=8673 |
| // ICE |
| |
| enum dollar8673 = [0][(() => $ - 1)()]; |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=5840 |
| |
| struct Bug5840 |
| { |
| string g; |
| int w; |
| } |
| |
| int bug5840(int u) |
| { |
| // check for clobbering |
| Bug5840 x = void; |
| x.w = 4; |
| x.g = "3gs"; |
| if (u == 1) |
| bug5840(2); |
| if (u == 2) |
| { |
| x.g = "abc"; |
| x.w = 3465; |
| } |
| else |
| { |
| assert(x.g == "3gs"); |
| assert(x.w == 4); |
| } |
| return 56; |
| } |
| static assert(bug5840(1) == 56); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7810 |
| |
| int bug7810() |
| { |
| int[1][3] x = void; |
| x[0] = [2]; |
| x[1] = [7]; |
| assert(x[0][0] == 2); |
| |
| char[1][3] y = void; |
| y[0] = "a"; |
| y[1] = "b"; |
| assert(y[0][0] == 'a'); |
| |
| return 1; |
| } |
| static assert(bug7810()); |
| |
| struct Bug7810 |
| { |
| int w; |
| } |
| int bug7810b(T)(T[] items...) |
| { |
| assert(items[0] == Bug7810(20)); |
| return 42; |
| } |
| static assert(bug7810b(Bug7810(20), Bug7810(10)) == 42); |
| |
| /******************************************* |
| std.datetime ICE (30 April 2011) |
| *******************************************/ |
| |
| struct TimeOfDayZ |
| { |
| public: |
| this(int hour) { } |
| invariant() { } |
| } |
| const testTODsThrownZ = TimeOfDayZ(0); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=5954 |
| |
| struct Bug5954 |
| { |
| int x; |
| this(int xx) |
| { |
| this.x = xx; |
| } |
| } |
| void bug5954() |
| { |
| enum f = Bug5954(10); |
| static assert(f.x == 10); |
| } |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=5972 |
| |
| int bug5972() |
| { |
| char[] z = "abc".dup; |
| char[][] a = [null, null]; |
| a[0] = z[0 .. 2]; |
| char[] b = a[0]; |
| assert(b == "ab"); |
| a[0][1] = 'q'; |
| assert(a[0] == "aq"); |
| assert(b == "aq"); |
| assert(b[1] == 'q'); |
| //a[0][0 .. $ - 1][0 .. $] = a[0][0 .. $ - 1][0 .. $]; // overlap |
| return 56; |
| } |
| static assert(bug5972() == 56); |
| |
| /******************************************* |
| 2.053beta [CTFE]ICE 'global errors' |
| *******************************************/ |
| |
| int wconcat(wstring replace) |
| { |
| wstring value; |
| value = "A"w; |
| value = value ~ replace; |
| return 1; |
| } |
| static assert(wconcat("X"w)); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=10397 |
| // string concat |
| |
| static assert(!is(typeof(compiles!("abc" ~ undefined)))); |
| static assert(!is(typeof(compiles!(otherundefined ~ "abc")))); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=9634 |
| // struct concat |
| |
| struct Bug9634 |
| { |
| int raw; |
| } |
| |
| bool bug9634() |
| { |
| Bug9634[] jr = [Bug9634(42)]; |
| |
| Bug9634[] ir = null ~ jr; |
| Bug9634[] kr = jr ~ null; |
| Bug9634[] mr = jr ~ jr; |
| |
| jr[0].raw = 6; |
| assert(ir[0].raw == 42); |
| assert(kr[0].raw == 42); |
| assert(jr[0].raw == 6); |
| assert(&mr[0] != &mr[1]); |
| return true; |
| } |
| |
| static assert(bug9634()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=4001: A Space Oddity |
| |
| int space() { return 4001; } |
| |
| void oddity4001(int q) |
| { |
| const int bowie = space(); |
| static assert(space() == 4001); |
| static assert(bowie == 4001); |
| } |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=3779 |
| |
| static const bug3779 = ["123"][0][$ - 1]; |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=8893 |
| // ICE with bad struct literal |
| |
| struct Foo8893 |
| { |
| char[3] data; |
| } |
| int bar8893(Foo8893 f) |
| { |
| return f.data[0]; |
| } |
| static assert(!is(typeof(compiles!(bar8893(Foo8893(['a','b'])))))); |
| |
| /******************************************* |
| non-Cow struct literals |
| *******************************************/ |
| |
| struct Zadok |
| { |
| int[3] z; |
| char[4] s = void; |
| ref int[] fog(return ref int[] q) { return q; } |
| int bfg() |
| { |
| z[0] = 56; |
| auto zs = z[]; |
| fog(zs) = [56, 6, 8]; |
| |
| assert(z[0] == 56); |
| assert(z[1] == 61); |
| assert(z[2] == 61); |
| |
| assert(zs[0] == 56); |
| assert(zs[1] == 6); |
| return zs[2]; |
| } |
| } |
| |
| struct Vug |
| { |
| Zadok p; |
| int[] other; |
| } |
| |
| int quop() |
| { |
| int[] heap = new int[5]; |
| heap[] = 738; |
| Zadok pong; |
| pong.z = 3; |
| int[] w = pong.z; |
| assert(w[0] == 3); |
| Zadok phong; |
| phong.z = 61; |
| pong = phong; |
| assert(w[0] == 61); |
| Vug b = Vug(Zadok(17, "abcd")); |
| b = Vug(Zadok(17, "abcd"), heap); |
| b.other[2] = 78; |
| assert(heap[2] == 78); |
| char[] y = b.p.s; |
| assert(y[2] == 'c'); |
| phong.s = ['z','x','f', 'g']; |
| w = b.p.z; |
| assert(y[2] == 'c'); |
| assert(w[0] == 17); |
| b.p = phong; |
| assert(y[2] == 'f'); |
| |
| Zadok wok = Zadok(6, "xyzw"); |
| b.p = wok; |
| assert(y[2] == 'z'); |
| b.p = phong; |
| assert(w[0] == 61); |
| Vug q; |
| q.p = pong; |
| return pong.bfg(); |
| } |
| |
| static assert(quop() == 8); |
| static assert(quop() == 8); // check for clobbering |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=5676 |
| // tuple assign of struct that has void opAssign |
| |
| struct S5676 |
| { |
| int x; |
| void opAssign(S5676 rhs) { x = rhs.x; } |
| } |
| |
| struct Tup5676(E...) |
| { |
| E g; |
| void foo(E values) { g = values; } |
| } |
| |
| bool ice5676() |
| { |
| Tup5676!(S5676) q; |
| q.foo(S5676(3)); |
| assert(q.g[0].x == 3); |
| return true; |
| } |
| |
| static assert(ice5676()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=5682 |
| // Wrong CTFE with operator overloading |
| |
| struct A |
| { |
| int n; |
| auto opBinary(string op : "*")(A rhs) |
| { |
| return A(n * rhs.n); |
| } |
| } |
| |
| A foo(A[] lhs, A[] rhs) |
| { |
| A current; |
| for (size_t k = 0; k < rhs.length; ++k) |
| { |
| current = lhs[k] * rhs[k]; |
| } |
| return current; |
| } |
| |
| auto test() |
| { |
| return foo([A(1), A(2)], [A(3), A(4)]); |
| } |
| |
| static assert(test().n == 8); |
| |
| /************************************************** |
| Attempt to modify a read-only string literal |
| **************************************************/ |
| struct Xarg |
| { |
| char[] s; |
| } |
| |
| int zfs(int n) |
| { |
| char[] m = "exy".dup; |
| if (n == 1) |
| { |
| // it's OK to cast to const, then cast back |
| string ss = cast(string)m; |
| m = cast(char[])ss; |
| m[2]='q'; |
| return 56; |
| } |
| auto q = Xarg(cast(char[])"abc"); |
| assert(q.s[1] == 'b'); |
| if (n == 2) |
| q.s[1] = 'p'; |
| else if (n == 3) |
| q.s[0 .. $] = 'p'; |
| char* w = &q.s[2]; |
| if (n == 4) |
| *w = 'z'; |
| return 76; |
| } |
| |
| static assert(!is(typeof(compiles!(zfs(2))))); |
| static assert(!is(typeof(compiles!(zfs(3))))); |
| static assert(!is(typeof(compiles!(zfs(4))))); |
| static assert( is(typeof(compiles!(zfs(1))))); |
| static assert( is(typeof(compiles!(zfs(5))))); |
| |
| /************************************************** |
| .dup must protect string literals |
| **************************************************/ |
| |
| string mutateTheImmutable(immutable string _s) |
| { |
| char[] s = _s.dup; |
| foreach (ref c; s) |
| c = 'x'; |
| return s.idup; |
| } |
| |
| string doharm(immutable string _name) |
| { |
| return mutateTheImmutable(_name[2 .. $].idup); |
| } |
| |
| enum victimLiteral = "CL_INVALID_CONTEXT"; |
| |
| enum thug = doharm(victimLiteral); |
| static assert(victimLiteral == "CL_INVALID_CONTEXT"); |
| |
| /************************************************** |
| Use $ in a slice of a dotvar slice |
| **************************************************/ |
| |
| int sliceDollar() |
| { |
| Xarg z; |
| z.s = new char[20]; |
| z.s[] = 'b'; |
| z.s = z.s[2 .. $ - 2]; |
| z.s[$ - 2] = 'c'; |
| return z.s[$ - 2]; |
| } |
| static assert(sliceDollar() == 'c'); |
| |
| /************************************************** |
| Variation of 5972 which caused segfault |
| **************************************************/ |
| |
| int bug5972crash() |
| { |
| char[] z = "abc".dup; |
| char[][] a = [null, null]; |
| a[0] = z[0 .. 2]; |
| a[0][1] = 'q'; |
| return 56; |
| } |
| static assert(bug5972crash() == 56); |
| |
| /************************************************** |
| String slice assignment through ref parameter |
| **************************************************/ |
| |
| void popft(A)(ref A a) |
| { |
| a = a[1 .. $]; |
| } |
| |
| int sdfgasf() |
| { |
| auto scp = "abc".dup; |
| popft(scp); |
| return 1; |
| } |
| static assert(sdfgasf() == 1); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=8830 |
| // slice of slice.ptr |
| |
| string bug8830(string s) |
| { |
| auto ss = s[1 .. $]; |
| return ss.ptr[0 .. 2]; |
| } |
| static assert(bug8830("hello") == "el"); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=8608 |
| // ICE |
| |
| void bug8608(ref int m) {} |
| void test8608() |
| { |
| int z; |
| int foo(bool b) |
| { |
| if (b) |
| bug8608(z); |
| return 1; |
| } |
| static assert( is(typeof(compiles!(foo(false))))); |
| static assert(!is(typeof(compiles!(foo(true) )))); |
| } |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7770 |
| |
| immutable char[] foo7770 = "abcde"; |
| |
| int bug7770a(string a) |
| { |
| return 1; |
| } |
| |
| bool bug7770b(char c) |
| { |
| return true; |
| } |
| |
| static assert(bug7770a(foo7770[0 .. $])); |
| static assert(bug7770b(foo7770[$ - 2])); |
| |
| void baz7770() |
| { |
| static assert(bug7770a(foo7770[0 .. $])); |
| static assert(bug7770b(foo7770[$ - 2])); |
| } |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=8601 |
| // ICE |
| |
| dchar bug8601(dstring s) |
| { |
| dstring w = s[1 .. $]; |
| return w[0]; |
| } |
| |
| enum dstring e8601 = [cast(dchar)'o', 'n']; |
| static assert(bug8601(e8601) == 'n'); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6015 |
| |
| struct Foo6015 |
| { |
| string field; |
| } |
| |
| bool func6015(string input) |
| { |
| Foo6015 foo; |
| foo.field = input[0 .. $]; |
| assert(foo.field == "test"); |
| foo.field = "test2"; |
| assert(foo.field != "test"); |
| assert(foo.field == "test2"); |
| return true; |
| } |
| |
| static assert(func6015("test")); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6001 |
| |
| void bug6001e(ref int[] s) |
| { |
| int[] r = s; |
| s ~= 0; |
| } |
| bool bug6001f() |
| { |
| int[] s; |
| bug6001e(s); |
| return true; |
| } |
| static assert(bug6001f()); |
| |
| // Assignment to AAs |
| |
| void blah(int[char] as) |
| { |
| auto k = [6: as]; |
| as = k[6]; |
| } |
| int blaz() |
| { |
| int[char] q; |
| blah(q); |
| return 67; |
| } |
| static assert(blaz() == 67); |
| |
| void bug6001g(ref int[] w) |
| { |
| w = [88]; |
| bug6001e(w); |
| w[0] = 23; |
| } |
| |
| bool bug6001h() |
| { |
| int[] s; |
| bug6001g(s); |
| assert(s.length == 2); |
| assert(s[1] == 0); |
| assert(s[0] == 23); |
| return true; |
| } |
| static assert(bug6001h()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=10243 |
| // wrong code *&arr as ref parameter |
| // https://issues.dlang.org/show_bug.cgi?id=10551 |
| // wrong code (&arr)[0] as ref parameter |
| |
| void bug10243(ref int n) |
| { |
| n = 3; |
| } |
| |
| void bug10551(int* p) |
| { |
| bug10243(p[0]); |
| } |
| |
| bool test10243() |
| { |
| int[1] arr; |
| bug10243(*arr.ptr); |
| assert(arr[0] == 3); |
| int[1] arr2; |
| bug10551(arr2.ptr); |
| assert(arr2[0] == 3); |
| int v; |
| bug10551(&v); |
| assert(v == 3); |
| return true; |
| } |
| |
| static assert(test10243()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=4910 |
| |
| int bug4910(int a) |
| { |
| return a; |
| } |
| |
| static int var4910; |
| static assert(!is(typeof(Compiles!(bug4910(var4910))))); |
| |
| static assert(bug4910(123)); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=5845 |
| // Regression(2.041) |
| |
| void test5845(ulong cols) {} |
| |
| uint solve(bool niv, ref ulong cols) |
| { |
| if (niv) |
| solve(false, cols); |
| else |
| test5845(cols); |
| return 65; |
| } |
| |
| ulong nqueen(int n) |
| { |
| ulong cols = 0; |
| return solve(true, cols); |
| } |
| |
| static assert(nqueen(2) == 65); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=5258 |
| |
| struct Foo5258 { int x; } |
| void bar5258(int n, ref Foo5258 fong) |
| { |
| if (n) |
| bar5258(n - 1, fong); |
| else |
| fong.x++; |
| } |
| int bug5258() |
| { |
| Foo5258 foo5258 = Foo5258(); |
| bar5258(1, foo5258); |
| return 45; |
| } |
| static assert(bug5258() == 45); |
| |
| struct Foo5258b { int[2] r; } |
| void baqopY(int n, ref int[2] fongo) |
| { |
| if (n) |
| baqopY(n - 1, fongo); |
| else |
| fongo[0]++; |
| } |
| int bug5258b() |
| { |
| Foo5258b qq; |
| baqopY(1, qq.r); |
| return 618; |
| } |
| static assert(bug5258b() == 618); |
| |
| // Notice that this case involving reassigning the dynamic array |
| struct Foo5258c { int[] r; } |
| void baqop(int n, ref int[] fongo) |
| { |
| if (n) |
| baqop(n - 1, fongo); |
| else |
| { |
| fongo = new int[20]; |
| fongo[0]++; |
| } |
| } |
| size_t bug5258c() |
| { |
| Foo5258c qq; |
| qq.r = new int[30]; |
| baqop(1, qq.r); |
| return qq.r.length; |
| } |
| static assert(bug5258c() == 20); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6049 |
| |
| struct Bug6049 |
| { |
| int m; |
| this(int x) { m = x; } |
| invariant() { } |
| } |
| |
| const Bug6049[] foo6049 = [Bug6049(6), Bug6049(17)]; |
| |
| static assert(foo6049[0].m == 6); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6052 |
| |
| struct Bug6052 |
| { |
| int a; |
| } |
| |
| bool bug6052() |
| { |
| Bug6052[2] arr; |
| for (int i = 0; i < 2; ++ i) |
| { |
| Bug6052 el = {i}; |
| Bug6052 ek = el; |
| arr[i] = el; |
| el.a = i + 2; |
| assert(ek.a == i); // ok |
| assert(arr[i].a == i); // fail |
| } |
| assert(arr[1].a == 1); // ok |
| assert(arr[0].a == 0); // fail |
| return true; |
| } |
| |
| static assert(bug6052()); |
| |
| bool bug6052b() |
| { |
| int[][1] arr; |
| int[1] z = [7]; |
| arr[0] = z; |
| assert(arr[0][0] == 7); |
| arr[0] = z; |
| z[0] = 3; |
| assert(arr[0][0] == 3); |
| return true; |
| } |
| |
| static assert(bug6052b()); |
| |
| struct Bug6052c |
| { |
| int x; |
| this(int a) { x = a; } |
| } |
| |
| int bug6052c() |
| { |
| Bug6052c[] pieces = []; |
| for (int c = 0; c < 2; ++ c) |
| pieces ~= Bug6052c(c); |
| assert(pieces[1].x == 1); |
| assert(pieces[0].x == 0); |
| return 1; |
| } |
| static assert(bug6052c() == 1); |
| static assert(bug6052c() == 1); |
| |
| |
| static assert({ |
| Bug6052c[] pieces = []; |
| pieces.length = 2; |
| int c = 0; |
| pieces[0] = Bug6052c(c); |
| ++c; |
| pieces[1] = Bug6052c(c); |
| assert(pieces[0].x == 0); |
| return true; |
| }()); |
| |
| static assert({ |
| int[1][] pieces = []; |
| pieces.length = 2; |
| for (int c = 0; c < 2; ++ c) |
| pieces[c][0] = c; |
| assert(pieces[1][0] == 1); |
| assert(pieces[0][0] == 0); |
| return true; |
| }()); |
| |
| static assert({ |
| Bug6052c[] pieces = []; |
| for (int c = 0; c < 2; ++ c) |
| pieces ~= Bug6052c(c); |
| assert(pieces[1].x == 1); |
| assert(pieces[0].x == 0); |
| return true; |
| }()); |
| |
| static assert({ |
| int[1] z = 7; |
| int[1][] pieces = [z,z]; |
| pieces[1][0]=3; |
| assert(pieces[0][0] == 7); |
| pieces = pieces ~ [z,z]; |
| pieces[3][0] = 16; |
| assert(pieces[2][0] == 7); |
| pieces = [z,z] ~ pieces; |
| pieces[5][0] = 16; |
| assert(pieces[4][0] == 7); |
| return true; |
| }()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6749 |
| |
| struct CtState |
| { |
| string code; |
| } |
| |
| CtState bug6749() |
| { |
| CtState[] pieces; |
| CtState r = CtState("correct"); |
| pieces ~= r; |
| r = CtState("clobbered"); |
| return pieces[0]; |
| } |
| static assert(bug6749().code == "correct"); |
| |
| /************************************************** |
| Index + slice assign to function returns |
| **************************************************/ |
| |
| int[] funcRetArr(int[] a) |
| { |
| return a; |
| } |
| |
| int testFuncRetAssign() |
| { |
| int[] x = new int[20]; |
| funcRetArr(x)[2] = 4; |
| assert(x[2] == 4); |
| funcRetArr(x)[] = 27; |
| assert(x[15] == 27); |
| return 5; |
| } |
| static assert(testFuncRetAssign() == 5); |
| |
| int keyAssign() |
| { |
| int[int] pieces; |
| pieces[3] = 1; |
| pieces.keys[0] = 4; |
| pieces.values[0] = 27; |
| assert(pieces[3] == 1); |
| return 5; |
| } |
| static assert(keyAssign() == 5); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6054 |
| // AA literals |
| |
| enum x6054 = { |
| auto p = { |
| int[string] pieces; |
| pieces[['a'].idup] = 1; |
| return pieces; |
| }(); |
| return p; |
| }(); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6077 |
| |
| enum bug6077 = { |
| string s; |
| string t; |
| return s ~ t; |
| }(); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6078 |
| // Pass null array by ref |
| |
| struct Foo6078 |
| { |
| int[] bar; |
| } |
| |
| static assert({ |
| Foo6078 f; |
| int i; |
| foreach (ref e; f.bar) |
| { |
| i += e; |
| } |
| return i; |
| }() == 0); |
| |
| int bug6078(ref int[] z) |
| { |
| int[] q = z; |
| return 2; |
| } |
| |
| static assert({ |
| Foo6078 f; |
| return bug6078(f.bar); |
| }() == 2); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6079 |
| // Array bounds checking |
| |
| static assert(!is(typeof(compiles!({ |
| int[] x = [1, 2, 3, 4]; |
| x[4] = 1; |
| return true; |
| }() |
| )))); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6100 |
| |
| struct S6100 |
| { |
| int a; |
| } |
| |
| S6100 init6100(int x) |
| { |
| S6100 s = S6100(x); |
| return s; |
| } |
| |
| static const S6100[2] s6100a = [init6100(1), init6100(2)]; |
| static assert(s6100a[0].a == 1); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=4825 |
| // failed with -inline |
| |
| int a4825() |
| { |
| int r; |
| return r; |
| } |
| |
| int b4825() |
| { |
| return a4825(); |
| } |
| |
| void c4825() |
| { |
| void d() |
| { |
| auto e = b4825(); |
| } |
| static const int f = b4825(); |
| } |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=5708 |
| // failed with -inline |
| |
| string b5708(string s) { return s; } |
| string a5708(string s) { return b5708(s); } |
| |
| void bug5708() |
| { |
| void m() { a5708("lit"); } |
| static assert(a5708("foo") == "foo"); |
| static assert(a5708("bar") == "bar"); |
| } |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6120 |
| // failed with -inline |
| |
| struct Bug6120(T) |
| { |
| this(int x) { } |
| } |
| static assert({ |
| auto s = Bug6120!int(0); |
| return true; |
| }()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6123 |
| // failed with -inline |
| |
| struct Bug6123(T) |
| { |
| void f() {} |
| // can also trigger if the struct is normal but f is template |
| } |
| static assert({ |
| auto piece = Bug6123!int(); |
| piece.f(); |
| return true; |
| }()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6053 |
| // ICE involving pointers |
| |
| static assert({ |
| int* a = null; |
| assert(a is null); |
| assert(a == null); |
| return true; |
| }()); |
| |
| static assert({ |
| int b; |
| int* a = &b; |
| assert(a !is null); |
| *a = 7; |
| assert(b == 7); |
| assert(*a == 7); |
| return true; |
| }()); |
| |
| int dontbreak6053() |
| { |
| auto q = &dontbreak6053; |
| void caz() {} |
| auto tr = &caz; |
| return 5; |
| } |
| static assert(dontbreak6053()); |
| |
| static assert({ |
| int a; |
| *(&a) = 15; |
| assert(a == 15); |
| assert(*(&a) == 15); |
| return true; |
| }()); |
| |
| static assert({ |
| int a = 5, b = 6, c = 2; |
| assert(*(c ? &a : &b) == 5); |
| assert(*(!c ? &a : &b) == 6); |
| return true; |
| }()); |
| |
| static assert({ |
| int a, b, c; |
| (c ? a : b) = 1; |
| return true; |
| }()); |
| |
| static assert({ |
| int a, b, c = 1; |
| int* p = &a; |
| (c ? *p : b) = 51; |
| assert(a == 51); |
| return true; |
| }()); |
| |
| /************************************************** |
| Pointer arithmetic, dereference, and comparison |
| **************************************************/ |
| |
| // dereference null pointer |
| static assert(!is(typeof(compiles!({ |
| int a, b, c = 1; |
| int* p; |
| (c ? *p : b) = 51; |
| return 6; |
| }() |
| )))); |
| static assert(!is(typeof(compiles!({ |
| int* a = null; |
| assert(*a != 6); |
| return 72; |
| }() |
| )))); |
| |
| // cannot <, > compare pointers to different arrays |
| static assert(!is(typeof(compiles!({ |
| int[5] a, b; |
| bool c = (&a[0] > &b[0]); |
| return 72; |
| }() |
| )))); |
| |
| // can ==, is, !is, != compare pointers for different arrays |
| static assert({ |
| int[5] a; |
| int[5] b; |
| assert(!(&a[0] == &b[0])); |
| assert(&a[0] != &b[0]); |
| assert(!(&a[0] is &b[0])); |
| assert(&a[0] !is &b[0]); |
| return 72; |
| }()); |
| |
| static assert({ |
| int[5] a; |
| a[0] = 25; |
| a[1] = 5; |
| int* b = &a[1]; |
| assert(*b == 5); |
| *b = 34; |
| int c = *b; |
| *b += 6; |
| assert(b == &a[1]); |
| assert(b != &a[0]); |
| assert(&a[0] < &a[1]); |
| assert(&a[0] <= &a[1]); |
| assert(!(&a[0] >= &a[1])); |
| assert(&a[4] > &a[0]); |
| assert(c == 34); |
| assert(*b == 40); |
| assert(a[1] == 40); |
| return true; |
| }()); |
| |
| static assert({ |
| int[12] x; |
| int* p = &x[10]; |
| int* q = &x[4]; |
| return p - q; |
| }() == 6); |
| |
| static assert({ |
| int[12] x; |
| int* p = &x[10]; |
| int* q = &x[4]; |
| q = p; |
| assert(p == q); |
| q = &x[4]; |
| assert(p != q); |
| q = q + 6; |
| assert(q is p); |
| return 6; |
| }() == 6); |
| |
| static assert({ |
| int[12] x; |
| int[] y = x[2 .. 8]; |
| int* p = &y[4]; |
| int* q = &x[6]; |
| assert(p == q); |
| p = &y[5]; |
| assert(p > q); |
| p = p + 5; // OK, as long as we don't dereference |
| assert(p > q); |
| return 6; |
| }() == 6); |
| |
| static assert({ |
| char[12] x; |
| const(char)* p = "abcdef"; |
| const (char)* q = p; |
| q = q + 2; |
| assert(*q == 'c'); |
| assert(q > p); |
| assert(q - p == 2); |
| assert(p - q == -2); |
| q = &x[7]; |
| p = &x[1]; |
| assert(q>p); |
| return 6; |
| }() == 6); |
| |
| // Relations involving null pointers |
| bool nullptrcmp() |
| { |
| // null tests |
| void* null1 = null, null2 = null; |
| int x = 2; |
| void* p = &x; |
| assert(null1 == null2); |
| assert(null1 is null2); |
| assert(null1 <= null2); |
| assert(null1 >= null2); |
| assert(!(null1 > null2)); |
| assert(!(null2 > null1)); |
| assert(null1 != p); |
| assert(null1 !is p); |
| assert(p != null1); |
| assert(p !is null1); |
| assert(null1 <= p); |
| assert(p >= null2); |
| assert(p > null1); |
| assert(!(null1 > p)); |
| return true; |
| } |
| static assert(nullptrcmp()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=10840 |
| // null pointer in dotvar |
| |
| struct Data10840 |
| { |
| bool xxx; |
| } |
| |
| struct Bug10840 |
| { |
| Data10840* _data; |
| } |
| |
| bool bug10840(int n) |
| { |
| Bug10840 stack; |
| if (n == 1) |
| { |
| // detect deref through null pointer |
| return stack._data.xxx; |
| } |
| // Wrong-code for ?: |
| return stack._data ? false : true; |
| } |
| |
| static assert(bug10840(0)); |
| static assert(!is(typeof(Compileable!(bug10840(1))))); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=8216 |
| // ptr inside a pointer range |
| |
| // Four-pointer relations. Return true if [p1 .. p2] points inside [q1 .. q2] |
| // (where the end points don't coincide). |
| bool ptr4cmp(void* p1, void* p2, void* q1, void* q2) |
| { |
| // Each compare can be written with <, <=, >, or >=. |
| // Either && or || can be used, giving 32 permutations. |
| // Additionally each compare can be negated with !, yielding 128 in total. |
| bool b1 = (p1 > q1 && p2 <= q2); |
| bool b2 = (p1 > q1 && p2 < q2); |
| bool b3 = (p1 >= q1 && p2 <= q2); |
| bool b4 = (p1 >= q1 && p2 < q2); |
| |
| bool b5 = (q1 <= p1 && q2 > p2); |
| bool b6 = (q1 <= p1 && q2 >= p2); |
| bool b7 = (p2 <= q2 && p1 > q1); |
| bool b8 = (!(p1 <= q1) && p2 <= q2); |
| bool b9 = (!(p1 <= q1) && !(p2 > q2)); |
| bool b10 = (!!!(p1 <= q1) && !(p2 > q2)); |
| |
| assert(b1 == b2 && b1 == b3 && b1 == b4 && b1 == b5 && b1 == b6); |
| assert(b1 == b7 && b1 == b8 && b1 == b9 && b1 == b10); |
| |
| bool c1 = (p1 <= q1 || p2 > q2); |
| assert(c1 == !b1); |
| bool c2 = (p1 < q1 || p2 >= q2); |
| bool c3 = (!(q1 <= p1) || !(q2 >= p2)); |
| assert(c1 == c2 && c1 == c3); |
| return b1; |
| } |
| |
| bool bug8216() |
| { |
| int[4] a; |
| int[13] b; |
| int v; |
| int* p = &v; |
| assert(!ptr4cmp(&a[0], &a[3], p, p)); |
| assert(!ptr4cmp(&b[2], &b[9], &a[1], &a[2])); |
| assert(!ptr4cmp(&b[1], &b[9], &b[2], &b[8])); |
| assert( ptr4cmp(&b[2], &b[8], &b[1], &b[9])); |
| return 1; |
| } |
| static assert(bug8216()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6517 |
| // ptr++, ptr-- |
| |
| int bug6517() |
| { |
| int[] arr = [1, 2, 3]; |
| auto startp = arr.ptr; |
| auto endp = arr.ptr + arr.length; |
| |
| for (; startp < endp; startp++) {} |
| startp = arr.ptr; |
| assert(startp++ == arr.ptr); |
| assert(startp != arr.ptr); |
| assert(startp-- != arr.ptr); |
| assert(startp == arr.ptr); |
| |
| return 84; |
| } |
| static assert(bug6517() == 84); |
| |
| /************************************************** |
| Out-of-bounds pointer assignment and deference |
| **************************************************/ |
| |
| int ptrDeref(int ofs, bool wantDeref) |
| { |
| int[5] a; |
| int* b = &a[0]; |
| b = b + ofs; // OK |
| if (wantDeref) |
| return *b; // out of bounds |
| return 72; |
| } |
| |
| static assert(!is(typeof(compiles!(ptrDeref(-1, true))))); |
| static assert( is(typeof(compiles!(ptrDeref(4, true))))); |
| static assert( is(typeof(compiles!(ptrDeref(5, false))))); |
| static assert(!is(typeof(compiles!(ptrDeref(5, true))))); |
| static assert(!is(typeof(compiles!(ptrDeref(6, false))))); |
| static assert(!is(typeof(compiles!(ptrDeref(6, true))))); |
| |
| /************************************************** |
| Pointer += |
| **************************************************/ |
| static assert({ |
| int[12] x; |
| int zzz; |
| assert(&zzz); |
| int* p = &x[10]; |
| int* q = &x[4]; |
| q = p; |
| assert(p == q); |
| q = &x[4]; |
| assert(p != q); |
| q += 4; |
| assert(q == &x[8]); |
| q = q - 2; |
| q = q + 4; |
| assert(q is p); |
| return 6; |
| }() == 6); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=5615 |
| |
| const(char)[] passthrough(const(char)[] x) |
| { |
| return x; |
| } |
| |
| ptrdiff_t checkPass(Char1)(const(Char1)[] s) |
| { |
| const(Char1)[] balance = s[1 .. $]; |
| return passthrough(balance).ptr - s.ptr; |
| } |
| static assert(checkPass("foobar") == 1); |
| |
| /************************************************** |
| Pointers must not escape from CTFE |
| **************************************************/ |
| |
| struct Toq |
| { |
| char* m; |
| } |
| |
| Toq ptrRet(bool b) |
| { |
| char[] x = "abc".dup; |
| return Toq(b ? x[0 .. 1].ptr : null); |
| } |
| |
| static assert(is(typeof(compiles!({ |
| enum Toq boz = ptrRet(false); // OK - ptr is null |
| Toq z = ptrRet(true); // OK -- ptr doesn't escape |
| return 4; |
| }() |
| )))); |
| |
| static assert(!is(typeof(compiles!({ |
| enum Toq boz = ptrRet(true); // fail - ptr escapes |
| return 4; |
| }() |
| )))); |
| |
| /************************************************** |
| Pointers to struct members |
| **************************************************/ |
| |
| struct Qoz |
| { |
| int w; |
| int[3] yof; |
| } |
| |
| static assert({ |
| int[3] gaz; |
| gaz[2] = 3156; |
| Toq z = ptrRet(true); |
| auto p = z.m; |
| assert(*z.m == 'a'); |
| assert(*p == 'a'); |
| auto q = &z.m; |
| assert(*q == p); |
| assert(**q == 'a'); |
| Qoz g = Qoz(2, [5, 6, 7]); |
| auto r = &g.w; |
| assert(*r == 2); |
| r = &g.yof[1]; |
| assert(*r == 6); |
| g.yof[0] = 15; |
| ++r; |
| assert(*r == 7); |
| r -= 2; |
| assert(*r == 15); |
| r = &gaz[0]; |
| r += 2; |
| assert(*r == 3156); |
| return *p; |
| }() == 'a'); |
| |
| struct AList |
| { |
| AList* next; |
| int value; |
| static AList* newList() |
| { |
| AList[] z = new AList[1]; |
| return &z[0]; |
| } |
| static AList* make(int i, int j) |
| { |
| auto r = newList(); |
| r.next = (new AList[1]).ptr; |
| r.value = 1; |
| AList* z = r.next; |
| (*z).value = 2; |
| r.next.value = j; |
| assert(r.value == 1); |
| assert(r.next.value == 2); |
| r.next.next = &(new AList[1])[0]; |
| assert(r.next.next != null); |
| assert(r.next.next); |
| r.next.next.value = 3; |
| assert(r.next.next.value == 3); |
| r.next.next = newList(); |
| r.next.next.value = 9; |
| return r; |
| } |
| static int checkList() |
| { |
| auto r = make(1,2); |
| assert(r.value == 1); |
| assert(r.next.value == 2); |
| assert(r.next.next.value == 9); |
| return 2; |
| } |
| } |
| |
| static assert(AList.checkList() == 2); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7194 |
| // pointers as struct members |
| |
| struct S7194 { int* p, p2; } |
| |
| int f7194() |
| { |
| assert(S7194().p == null); |
| assert(!S7194().p); |
| assert(S7194().p == S7194().p2); |
| S7194 s = S7194(); |
| assert(!s.p); |
| assert(s.p == null); |
| assert(s.p == s.p2); |
| int x; |
| s.p = &x; |
| s.p2 = s.p; |
| assert(s.p == &x); |
| return 0; |
| } |
| |
| int g7194() |
| { |
| auto s = S7194(); |
| assert(s.p); // should fail |
| return 0; |
| } |
| |
| static assert(f7194() == 0); |
| static assert(!is(typeof(compiles!(g7194())))); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7248 |
| // recursive struct pointers in array |
| |
| struct S7248 { S7248* ptr; } |
| |
| bool bug7248() |
| { |
| S7248[2] sarr; |
| sarr[0].ptr = &sarr[1]; |
| sarr[0].ptr = null; |
| S7248* t = sarr[0].ptr; |
| return true; |
| } |
| static assert(bug7248()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7216 |
| // calling a struct pointer member |
| |
| struct S7216 |
| { |
| S7216* p; |
| int t; |
| |
| void f() { } |
| void g() { ++t; } |
| } |
| |
| bool bug7216() |
| { |
| S7216 s0, s1; |
| s1.t = 6; |
| s0.p = &s1; |
| s0.p.f(); |
| s0.p.g(); |
| assert(s1.t == 7); |
| return true; |
| } |
| |
| static assert(bug7216()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=10858 |
| // Wrong code with array of pointers |
| |
| bool bug10858() |
| { |
| int*[4] x; |
| x[0] = null; |
| assert(x[0] == null); |
| return true; |
| } |
| static assert(bug10858()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=12528 |
| // painting inout type for value type literals |
| |
| inout(T)[] dup12528(T)(inout(T)[] a) |
| { |
| inout(T)[] res; |
| foreach (ref e; a) |
| res ~= e; |
| return res; |
| } |
| |
| enum arr12528V1 = dup12528([0]); |
| enum arr12528V2 = dup12528([0, 1]); |
| static assert(arr12528V1 == [0]); |
| static assert(arr12528V2 == [0, 1]); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=9745 |
| // Allow pointers to static variables |
| |
| shared int x9745; |
| shared int[5] y9745; |
| |
| shared(int)* bug9745(int m) |
| { |
| auto k = &x9745; |
| auto j = &x9745; |
| auto p = &y9745[0]; |
| auto q = &y9745[3]; |
| assert(j - k == 0); |
| assert(j == k); |
| assert(q - p == 3); |
| --q; |
| int a = 0; |
| assert(p + 2 == q); |
| if (m == 7) |
| { |
| auto z1 = y9745[0 .. 2]; // slice global pointer |
| } |
| if (m == 8) |
| p[1] = 7; // modify through a pointer |
| if (m == 9) |
| a = p[1]; // read from a pointer |
| if (m == 0) |
| return &x9745; |
| return &y9745[1]; |
| } |
| |
| int test9745(int m) |
| { |
| bug9745(m); |
| // type painting |
| shared int* w = bug9745(0); |
| return 1; |
| } |
| |
| shared int* w9745a = bug9745(0); |
| shared int* w9745b = bug9745(1); |
| static assert( is(typeof(compiles!(test9745(6))))); |
| static assert(!is(typeof(compiles!(test9745(7))))); |
| static assert(!is(typeof(compiles!(test9745(8))))); |
| static assert(!is(typeof(compiles!(test9745(9))))); |
| |
| // pointers cast from an absolute address |
| // (mostly applies to fake pointers, eg Windows HANDLES) |
| bool test9745b() |
| { |
| void* b6 = cast(void*)0xFEFEFEFE; |
| void* b7 = cast(void*)0xFEFEFEFF; |
| assert(b6 is b6); |
| assert(b7 != b6); |
| return true; |
| } |
| static assert(test9745b()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=9364 |
| // ICE with pointer to local struct |
| |
| struct S9364 |
| { |
| int i; |
| } |
| |
| bool bug9364() |
| { |
| S9364 s; |
| auto k = (&s).i; |
| return 1; |
| } |
| |
| static assert(bug9364()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=10251 |
| // Pointers to const globals |
| |
| static const int glob10251 = 7; |
| |
| const(int)* bug10251() |
| { |
| return &glob10251; |
| } |
| |
| static a10251 = &glob10251; // OK |
| static b10251 = bug10251(); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=4065 |
| // [CTFE] AA "in" operator doesn't work |
| |
| bool bug4065(string s) |
| { |
| enum int[string] aa = ["aa":14, "bb":2]; |
| int* p = s in aa; |
| if (s == "aa") |
| assert(*p == 14); |
| else if (s == "bb") |
| assert(*p == 2); |
| else |
| assert(!p); |
| int[string] zz; |
| assert(!("xx" in zz)); |
| bool c = !p; |
| return cast(bool)(s in aa); |
| } |
| |
| static assert(!bug4065("xx")); |
| static assert( bug4065("aa")); |
| static assert( bug4065("bb")); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=12689 |
| // assigning via pointer from 'in' expression |
| |
| int g12689() |
| { |
| int[int] aa; |
| aa[1] = 13; |
| assert(*(1 in aa) == 13); |
| *(1 in aa) = 42; |
| return aa[1]; |
| } |
| static assert(g12689() == 42); |
| |
| /************************************************** |
| Pointers in ? : |
| **************************************************/ |
| |
| static assert({ |
| int[2] x; |
| int* p = &x[1]; |
| return p ? true: false; |
| }()); |
| |
| /************************************************** |
| Pointer slicing |
| **************************************************/ |
| |
| int ptrSlice() |
| { |
| auto arr = new int[5]; |
| int* x = &arr[0]; |
| int[] y = x[0 .. 5]; |
| x[1 .. 3] = 6; |
| ++x; |
| x[1 .. 3] = 14; |
| assert(arr[1] == 6); |
| assert(arr[2] == 14); |
| //x[-1 .. 4] = 5; // problematic because negative lower boundary will throw RangeError in runtime |
| (x - 1)[0 .. 3] = 5; |
| int[] z = arr[1 .. 2]; |
| z.length = 4; |
| z[$ - 1] = 17; |
| assert(arr.length == 5); |
| return 2; |
| } |
| static assert(ptrSlice() == 2); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6344 |
| // create empty slice from null pointer |
| |
| static assert({ |
| char* c = null; |
| auto m = c[0 .. 0]; |
| return true; |
| }()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=8365 |
| // block assignment of enum arrays |
| |
| enum E8365 { first = 7, second, third, fourth } |
| static assert({ E8365[2] x; return x[0]; }() == E8365.first); |
| static assert({ E8365[2][2] x; return x[0][0]; }() == E8365.first); |
| static assert({ E8365[2][2][2] x; return x[0][0][0]; }() == E8365.first); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=4448 |
| // labelled break + continue |
| |
| int bug4448() |
| { |
| int n = 2; |
| L1: |
| do |
| { |
| switch(n) |
| { |
| case 5: |
| return 7; |
| default: |
| n = 5; |
| break L1; |
| } |
| int w = 7; |
| } while (0); |
| return 3; |
| } |
| static assert(bug4448() == 3); |
| |
| int bug4448b() |
| { |
| int n = 2; |
| L1: |
| for (n = 2; n < 5; ++n) |
| { |
| for (int m = 1; m < 6; ++m) |
| { |
| if (n < 3) |
| { |
| assert(m == 1); |
| continue L1; |
| } |
| } |
| break; |
| } |
| return 3; |
| } |
| static assert(bug4448b() == 3); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6985 |
| // Formerly, non-constant case, but switch cases with mutable cases now error |
| // Currently: run-time constant variable case |
| |
| int bug6985(int z) |
| { |
| const int q = z * 2 - 6; |
| switch(z) |
| { |
| case q: |
| return 87; |
| default: |
| } |
| return q; |
| } |
| static assert(bug6985(6) == 87); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6281 |
| // [CTFE] A null pointer '!is null' returns 'true' |
| |
| static assert(!{ |
| auto p = null; |
| return p !is null; |
| }()); |
| |
| static assert(!{ |
| auto p = null; |
| return p != null; |
| }()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6331 |
| // evaluate SliceExp on if condition |
| |
| bool bug6331(string s) |
| { |
| if (s[0 .. 1]) |
| return true; |
| return false; |
| } |
| static assert(bug6331("str")); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6283 |
| // assign to AA with slice as index |
| |
| static assert({ |
| immutable p = "pp"; |
| int[string] pieces = [p: 0]; |
| pieces["qq"] = 1; |
| return true; |
| }()); |
| |
| static assert({ |
| immutable renames = [0: "pp"]; |
| int[string] pieces; |
| pieces[true ? renames[0] : "qq"] = 1; |
| pieces["anything"] = 1; |
| return true; |
| }()); |
| |
| static assert({ |
| immutable qq = "qq"; |
| string q = qq; |
| int[string] pieces = ["a":1]; |
| pieces[q] = 0; |
| string w = "ab"; |
| int z = pieces[w[0 .. 1]]; |
| assert(z == 1); |
| return true; |
| }()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6282 |
| // dereference 'in' of an AA |
| |
| static assert({ |
| int[] w = new int[4]; |
| w[2] = 6; |
| auto c = [5: w]; |
| auto kk = (*(5 in c))[2]; |
| (*(5 in c))[2] = 8; |
| (*(5 in c))[1 .. $ - 2] = 4; |
| auto a = [4:"1"]; |
| auto n = *(4 in a); |
| return n; |
| }() == "1"); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6337 |
| // member function call on struct literal |
| |
| struct Bug6337 |
| { |
| int k; |
| void six() |
| { |
| k = 6; |
| } |
| int ctfe() |
| { |
| six(); |
| return k; |
| } |
| } |
| static assert(Bug6337().ctfe() == 6); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6603 |
| // call manifest function pointer |
| |
| int f6603(int a) { return a + 5; } |
| enum bug6603 = &f6603; |
| static assert(bug6603(6) == 11); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6375 |
| |
| struct D6375 |
| { |
| int[] arr; |
| } |
| A6375 a6375(int[] array) |
| { |
| return A6375(array); |
| } |
| struct A6375 |
| { |
| D6375* _data; |
| this(int[] arr) |
| { |
| _data = new D6375; |
| _data.arr = arr; |
| } |
| int[] data() |
| { |
| return _data.arr; |
| } |
| } |
| static assert({ |
| int[] a = [1, 2]; |
| auto app2 = a6375(a); |
| auto data = app2.data(); |
| return true; |
| }()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6280 |
| // Converting pointers to bool |
| |
| static assert({ |
| if ((0 in [0:0])) {} |
| if ((0 in [0:0]) && (0 in [0:0])) {} |
| return true; |
| }()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6276 |
| // ~= |
| |
| struct Bug6276 |
| { |
| int[] i; |
| } |
| static assert({ |
| Bug6276 foo; |
| foo.i ~= 1; |
| foo.i ~= 2; |
| return true; |
| }()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6374 |
| // ptr[n] = x, x = ptr[n] |
| |
| static assert({ |
| int[] arr = [1]; |
| arr.ptr[0] = 2; |
| auto k = arr.ptr[0]; |
| assert(k == 2); |
| return arr[0]; |
| }() == 2); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6306 |
| // recursion and local variables |
| |
| void recurse6306() |
| { |
| bug6306(false); |
| } |
| |
| bool bug6306(bool b) |
| { |
| int x = 0; |
| if (b) |
| recurse6306(); |
| assert(x == 0); |
| x = 1; |
| return true; |
| } |
| static assert( |