| // 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(bug6306(true)); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6386 |
| // ICE on unsafe pointer cast |
| |
| static assert(!is(typeof(compiles!({ |
| int x = 123; |
| int* p = &x; |
| float z; |
| float* q = cast(float*)p; |
| return true; |
| }() |
| )))); |
| |
| static assert({ |
| int[] x = [123, 456]; |
| int* p = &x[0]; |
| auto m = cast(const(int)*)p; |
| auto q = p; |
| return *q; |
| }()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6420 |
| // ICE on dereference of invalid pointer |
| |
| static assert({ |
| // Should compile, but pointer can't be dereferenced |
| int x = 123; |
| int* p = cast(int*)x; |
| auto q = cast(char*)x; |
| auto r = cast(char*)323; |
| // Valid const-changing cast |
| const float *m = cast(immutable float*)[1.2f,2.4f,3f]; |
| return true; |
| }() |
| ); |
| |
| static assert(!is(typeof(compiles!({ |
| int x = 123; |
| int* p = cast(int*)x; |
| int a = *p; |
| return true; |
| }() |
| )))); |
| |
| static assert(!is(typeof(compiles!({ |
| int* p = cast(int*)123; |
| int a = *p; |
| return true; |
| }() |
| )))); |
| |
| static assert(!is(typeof(compiles!({ |
| auto k = cast(int*)45; |
| *k = 1; |
| return true; |
| }() |
| )))); |
| |
| static assert(!is(typeof(compiles!({ |
| *cast(float*)"a" = 4.0; |
| return true; |
| }() |
| )))); |
| |
| static assert(!is(typeof(compiles!({ |
| float f = 2.8; |
| long *p = &f; |
| return true; |
| }() |
| )))); |
| |
| static assert(!is(typeof(compiles!({ |
| long *p = cast(long*)[1.2f, 2.4f, 3f]; |
| return true; |
| }() |
| )))); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6250 |
| // deref pointers to array |
| |
| int[]* simple6250(int[]* x) { return x; } |
| |
| void swap6250(int[]* lhs, int[]* rhs) |
| { |
| int[] kk = *lhs; |
| assert(simple6250(lhs) == lhs); |
| lhs = simple6250(lhs); |
| assert(kk[0] == 18); |
| assert((*lhs)[0] == 18); |
| assert((*rhs)[0] == 19); |
| *lhs = *rhs; |
| assert((*lhs)[0] == 19); |
| *rhs = kk; |
| assert(*rhs == kk); |
| assert(kk[0] == 18); |
| assert((*rhs)[0] == 18); |
| } |
| |
| int ctfeSort6250() |
| { |
| int[][2] x; |
| int[3] a = [17, 18, 19]; |
| x[0] = a[1 .. 2]; |
| x[1] = a[2 .. $]; |
| assert(x[0][0] == 18); |
| assert(x[0][1] == 19); |
| swap6250(&x[0], &x[1]); |
| assert(x[0][0] == 19); |
| assert(x[1][0] == 18); |
| a[1] = 57; |
| assert(x[0][0] == 19); |
| return x[1][0]; |
| } |
| |
| static assert(ctfeSort6250() == 57); |
| |
| /**************************************************/ |
| |
| long[]* simple6250b(long[]* x) { return x; } |
| |
| void swap6250b(long[]* lhs, long[]* rhs) |
| { |
| long[] kk = *lhs; |
| assert(simple6250b(lhs) == lhs); |
| lhs = simple6250b(lhs); |
| assert(kk[0] == 18); |
| assert((*lhs)[0] == 18); |
| assert((*rhs)[0] == 19); |
| *lhs = *rhs; |
| assert((*lhs)[0] == 19); |
| *rhs = kk; |
| assert(*rhs == kk); |
| assert(kk[0] == 18); |
| assert((*rhs)[0] == 18); |
| } |
| |
| long ctfeSort6250b() |
| { |
| long[][2] x; |
| long[3] a = [17, 18, 19]; |
| x[0] = a[1 .. 2]; |
| x[1] = a[2 .. $]; |
| assert(x[0][0] == 18); |
| assert(x[0][1] == 19); |
| swap6250b(&x[0], &x[1]); |
| assert(x[0][0] == 19); |
| assert(x[1][0] == 18); |
| a[1] = 57; |
| assert(x[0][0] == 19); |
| return x[1][0]; |
| } |
| |
| static assert(ctfeSort6250b() == 57); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6672 |
| // circular references in array |
| |
| void bug6672(ref string lhs, ref string rhs) |
| { |
| auto tmp = lhs; |
| lhs = rhs; |
| rhs = tmp; |
| } |
| |
| static assert({ |
| auto kw = ["a"]; |
| bug6672(kw[0], kw[0]); |
| return true; |
| }()); |
| |
| void slice6672(ref string[2] agg, ref string lhs) |
| { |
| agg[0 .. $] = lhs; |
| } |
| |
| static assert({ |
| string[2] kw = ["a", "b"]; |
| slice6672(kw, kw[0]); |
| assert(kw[0] == "a"); |
| assert(kw[1] == "a"); |
| return true; |
| }()); |
| |
| // an unrelated rejects-valid bug |
| static assert({ |
| string[2] kw = ["a", "b"]; |
| kw[0 .. 2] = "x"; |
| return true; |
| }()); |
| |
| void bug6672b(ref string lhs, ref string rhs) |
| { |
| auto tmp = lhs; |
| assert(tmp == "a"); |
| lhs = rhs; |
| assert(tmp == "a"); |
| rhs = tmp; |
| } |
| |
| static assert({ |
| auto kw=["a", "b"]; |
| bug6672b(kw[0], kw[1]); |
| assert(kw[0] == "b"); |
| assert(kw[1] == "a"); |
| return true; |
| }()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6399 |
| // (*p).length = n |
| |
| struct A6399 |
| { |
| int[] arr; |
| int subLen() |
| { |
| arr = [1, 2, 3, 4, 5]; |
| arr.length -= 1; |
| return cast(int)arr.length; |
| } |
| } |
| |
| static assert({ |
| A6399 a; |
| return a.subLen(); |
| }() == 4); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7789 |
| // (*p).length++ where *p is null |
| |
| struct S7789 |
| { |
| size_t foo() |
| { |
| _ary.length += 1; |
| return _ary.length; |
| } |
| |
| int[] _ary; |
| } |
| |
| static assert(S7789().foo()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6418 |
| // member named 'length' |
| |
| struct Bug6418 |
| { |
| size_t length() { return 189; } |
| } |
| static assert(Bug6418.init.length == 189); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=4021 |
| // rehash |
| |
| bool bug4021() |
| { |
| int[int] aa = [1: 1]; |
| aa.rehash; |
| return true; |
| } |
| static assert(bug4021()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=11629 |
| // crash on AA.rehash |
| |
| struct Base11629 |
| { |
| alias T = ubyte, Char = char; |
| alias String = immutable(Char)[]; |
| |
| const Char[T] toChar; |
| |
| this(int _dummy) |
| { |
| Char[T] toCharTmp = [0:'A']; |
| |
| toChar = toCharTmp.rehash; |
| } |
| } |
| enum ct11629 = Base11629(4); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=3512 |
| // foreach (dchar; string) |
| // https://issues.dlang.org/show_bug.cgi?id=6558 |
| // foreach (int, dchar; string) |
| |
| bool test3512() |
| { |
| string s = "öhai"; |
| int q = 0; |
| |
| foreach (wchar c; s) |
| { |
| if (q == 2) |
| assert(c == 'a'); |
| ++q; |
| } |
| assert(q == 4); |
| |
| // _aApplycd1 |
| foreach (dchar c; s) |
| { |
| ++q; |
| if (c == 'h') |
| break; |
| } |
| assert(q == 6); |
| |
| // _aApplycw2 |
| foreach (ptrdiff_t i, wchar c; s) |
| { |
| assert(i >= 0 && i < s.length); |
| } |
| |
| // _aApplycd2 |
| foreach (ptrdiff_t i, dchar c; s) |
| { |
| assert(i >= 0 && i < s.length); |
| } |
| |
| wstring w = "xüm"; |
| |
| // _aApplywc1 |
| foreach (char c; w) |
| { |
| ++q; |
| } |
| assert(q == 10); |
| |
| // _aApplywd1 |
| foreach (dchar c; w) |
| { |
| ++q; |
| } |
| assert(q == 13); |
| |
| // _aApplywc2 |
| foreach (ptrdiff_t i, char c; w) |
| { |
| assert(i >= 0 && i < w.length); |
| } |
| |
| // _aApplywd2 |
| foreach (ptrdiff_t i, dchar c; w) |
| { |
| assert(i >= 0 && i < w.length); |
| } |
| |
| dstring d = "yäq"; |
| |
| // _aApplydc1 |
| q = 0; |
| foreach (char c; d) |
| { |
| ++q; |
| } |
| assert(q == 4); |
| |
| // _aApplydw1 |
| q = 0; |
| foreach (wchar c; d) |
| { |
| ++q; |
| } |
| assert(q == 3); |
| |
| // _aApplydc2 |
| foreach (ptrdiff_t i, char c; d) |
| { |
| assert(i >= 0 && i < d.length); |
| } |
| // _aApplydw2 |
| foreach (ptrdiff_t i, wchar c; d) |
| { |
| assert(i >= 0 && i < d.length); |
| } |
| |
| dchar[] dr = "squop"d.dup; |
| |
| foreach (ptrdiff_t n, char c; dr) |
| { |
| if (n == 2) |
| break; |
| assert(c != 'o'); |
| } |
| |
| // _aApplyRdc1 |
| foreach_reverse (char c; dr) |
| {} |
| |
| // _aApplyRdw1 |
| foreach_reverse (wchar c; dr) |
| {} |
| |
| // _aApplyRdc2 |
| foreach_reverse (ptrdiff_t n, char c; dr) |
| { |
| if (n == 4) |
| break; |
| assert(c != 'o'); |
| } |
| |
| // _aApplyRdw2 |
| foreach_reverse (ptrdiff_t i, wchar c; dr) |
| { |
| assert(i >= 0 && i < dr.length); |
| } |
| |
| q = 0; |
| wstring w2 = ['x', 'ü', 'm']; // foreach over array literals |
| foreach_reverse (ptrdiff_t n, char c; w2) |
| { |
| ++q; |
| if (c == 'm') assert(n == 2 && q == 1); |
| if (c == 'x') assert(n == 0 && q == 4); |
| } |
| return true; |
| } |
| static assert(test3512()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6510 |
| // ICE only with -inline |
| |
| struct Stack6510 |
| { |
| struct Proxy |
| { |
| void shrink() {} |
| } |
| Proxy stack; |
| void pop() |
| { |
| stack.shrink(); |
| } |
| } |
| |
| int bug6510() |
| { |
| static int used() |
| { |
| Stack6510 junk; |
| junk.pop(); |
| return 3; |
| } |
| return used(); |
| } |
| |
| void test6510() |
| { |
| static assert(bug6510() == 3); |
| } |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6511 |
| // arr[] shouldn't make a copy |
| |
| T bug6511(T)() |
| { |
| T[1] a = [1]; |
| a[] += a[]; |
| return a[0]; |
| } |
| static assert(bug6511!ulong() == 2); |
| static assert(bug6511!long() == 2); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6512 |
| // new T[][] |
| |
| bool bug6512(int m) |
| { |
| auto x = new int[2][][](m, 5); |
| assert(x.length == m); |
| assert(x[0].length == 5); |
| assert(x[0][0].length == 2); |
| foreach (i; 0.. m) |
| foreach (j; 0 .. 5) |
| foreach (k; 0 .. 2) |
| x[i][j][k] = k + j*10 + i*100; |
| foreach (i; 0.. m) |
| foreach (j; 0 .. 5) |
| foreach (k; 0 .. 2) |
| assert(x[i][j][k] == k + j*10 + i*100); |
| return true; |
| } |
| static assert(bug6512(3)); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6516 |
| // ICE(constfold.c) |
| |
| dstring bug6516() |
| { |
| return cast(dstring)new dchar[](0); |
| } |
| |
| static assert(bug6516() == ""d); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6727 |
| // ICE(interpret.c) |
| |
| const(char)* ice6727(const(char)* z) { return z; } |
| static assert({ |
| auto q = ice6727("a".dup.ptr); |
| return true; |
| }()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6721 |
| // Cannot get pointer to start of char[] |
| |
| static assert({ |
| char[] c1 = "".dup; |
| auto p = c1.ptr; |
| string c2 = ""; |
| auto p2 = c2.ptr; |
| return 6; |
| }() == 6); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6693 |
| // Assign to null AA |
| |
| struct S6693 |
| { |
| int[int] m; |
| } |
| |
| static assert({ |
| int[int][int] aaa; |
| aaa[3][1] = 4; |
| int[int][3] aab; |
| aab[2][1] = 4; |
| S6693 s; |
| s.m[2] = 4; |
| return 6693; |
| }() == 6693); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7602 |
| // Segfault AA.keys on null AA |
| |
| string[] test7602() |
| { |
| int[string] array; |
| return array.keys; |
| } |
| |
| enum bug7602 = test7602(); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6739 |
| // Nested AA assignment |
| |
| static assert({ |
| int[int][int][int] aaa; |
| aaa[3][1][6] = 14; |
| return aaa[3][1][6]; |
| }() == 14); |
| |
| static assert({ |
| int[int][int] aaa; |
| aaa[3][1] = 4; |
| aaa[3][3] = 3; |
| aaa[1][5] = 9; |
| auto kk = aaa[1][5]; |
| return kk; |
| }() == 9); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6751 |
| // ref AA assignment |
| |
| void bug6751(ref int[int] aa) |
| { |
| aa[1] = 2; |
| } |
| |
| static assert({ |
| int[int] aa; |
| bug6751(aa); |
| assert(aa[1] == 2); |
| return true; |
| }()); |
| |
| void bug6751b(ref int[int][int] aa) |
| { |
| aa[1][17] = 2; |
| } |
| |
| struct S6751 |
| { |
| int[int][int] aa; |
| int[int] bb; |
| } |
| |
| static assert({ |
| S6751 s; |
| bug6751b(s.aa); |
| assert(s.aa[1][17] == 2); |
| return true; |
| }()); |
| |
| static assert({ |
| S6751 s; |
| s.aa[7][56] = 57; |
| bug6751b(s.aa); |
| assert(s.aa[1][17] == 2); |
| assert(s.aa[7][56] == 57); |
| bug6751c(s.aa); |
| assert(s.aa.keys.length == 1); |
| assert(s.aa.values.length == 1); |
| return true; |
| }()); |
| |
| static assert({ |
| S6751 s; |
| s.bb[19] = 97; |
| bug6751(s.bb); |
| assert(s.bb[1] == 2); |
| assert(s.bb[19] == 97); |
| return true; |
| }()); |
| |
| void bug6751c(ref int[int][int] aa) |
| { |
| aa = [38: [56 : 77]]; |
| } |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7790 |
| // AA foreach ref |
| |
| struct S7790 |
| { |
| size_t id; |
| } |
| |
| size_t bug7790(S7790[string] tree) |
| { |
| foreach (k, ref v; tree) |
| v.id = 1; |
| return tree["a"].id; |
| } |
| |
| static assert(bug7790(["a":S7790(0)]) == 1); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6765 |
| // null AA.length |
| |
| static assert({ |
| int[int] w; |
| return w.length; |
| }() == 0); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6769 |
| // AA.keys, AA.values with -inline |
| |
| static assert({ |
| double[char[3]] w = ["abc" : 2.3]; |
| double[] z = w.values; |
| return w.keys.length; |
| }() == 1); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=4022 |
| // AA.get |
| |
| static assert({ |
| int[int] aa = [58: 13]; |
| int r = aa.get(58, 1000); |
| assert(r == 13); |
| r = aa.get(59, 1000); |
| return r; |
| }() == 1000); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6775 |
| // AA.opApply |
| |
| static assert({ |
| int[int] aa = [58: 17, 45:6]; |
| int valsum = 0; |
| int keysum = 0; |
| foreach (m; aa) // aaApply |
| { |
| valsum += m; |
| } |
| assert(valsum == 17 + 6); |
| valsum = 0; |
| foreach (n, m; aa) // aaApply2 |
| { |
| valsum += m; |
| keysum += n; |
| } |
| assert(valsum == 17 + 6); |
| assert(keysum == 58 + 45); |
| // Check empty AA |
| valsum = 0; |
| int[int] bb; |
| foreach (m; bb) |
| { |
| ++valsum; |
| } |
| assert(valsum == 0); |
| return true; |
| }()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7890 |
| // segfault struct with AA field |
| |
| struct S7890 |
| { |
| int[int] tab; |
| } |
| |
| S7890 bug7890() |
| { |
| S7890 foo; |
| foo.tab[0] = 0; |
| return foo; |
| } |
| |
| enum e7890 = bug7890(); |
| |
| /************************************************** |
| AA.remove |
| **************************************************/ |
| |
| static assert({ |
| int[int] aa = [58: 17, 45:6]; |
| aa.remove(45); |
| assert(aa.length == 1); |
| aa.remove(7); |
| assert(aa.length == 1); |
| aa.remove(58); |
| assert(aa.length == 0); |
| return true; |
| }()); |
| |
| /************************************************** |
| try, finally |
| **************************************************/ |
| |
| static assert({ |
| int n = 0; |
| |
| try |
| { |
| n = 1; |
| } |
| catch (Exception e) |
| {} |
| assert(n == 1); |
| |
| try |
| { |
| n = 2; |
| } |
| catch (Exception e) |
| {} |
| finally |
| { |
| assert(n == 2); |
| n = 3; |
| } |
| assert(n == 3); |
| return true; |
| }()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6800 |
| // bad pointer casts |
| |
| bool badpointer(int k) |
| { |
| int m = 6; |
| int* w = &m; |
| assert(*w == 6); |
| int[3] a = [17, 2, 21]; |
| int* w2 = &a[2]; |
| assert(*w2 == 21); |
| |
| // cast int* to uint* is OK |
| uint* u1 = cast(uint*)w; |
| assert(*u1 == 6); |
| uint* u2 = cast(uint*)w2; |
| assert(*u2 == 21); |
| uint* u3 = cast(uint*)&m; |
| assert(*u3 == 6); |
| // cast int* to void* is OK |
| void* v1 = cast(void*)w; |
| void* v3 = &m; |
| void* v4 = &a[0]; |
| // cast from void* back to int* is OK |
| int* t3 = cast(int*)v3; |
| assert(*t3 == 6); |
| int* t4 = cast(int*)v4; |
| assert(*t4 == 17); |
| // cast from void* to uint* is OK |
| uint* t1 = cast(uint*)v1; |
| assert(*t1 == 6); |
| // and check that they're real pointers |
| m = 18; |
| assert(*t1 == 18); |
| assert(*u3 == 18); |
| |
| int** p = &w; |
| |
| if (k == 1) // bad reinterpret |
| double *d1 = cast(double*)w; |
| if (k == 3) // bad reinterpret |
| char* d3 = cast(char*)w2; |
| if (k == 4) { |
| void* q1 = cast(void*)p; // OK-void is int* |
| void* *q = cast(void**)p; // OK-void is int |
| } |
| if (k == 5) |
| void*** q = cast(void***)p; // bad: too many * |
| if (k == 6) // bad reinterpret through void* |
| double* d1 = cast(double*)v1; |
| if (k == 7) |
| double* d7 = cast(double*)v4; |
| if (k == 8) |
| ++v4; // can't do pointer arithmetic on void* |
| return true; |
| } |
| static assert(badpointer(4)); |
| static assert(!is(typeof(compiles!(badpointer(1))))); |
| static assert( is(typeof(compiles!(badpointer(2))))); |
| static assert(!is(typeof(compiles!(badpointer(3))))); |
| static assert( is(typeof(compiles!(badpointer(4))))); |
| static assert(!is(typeof(compiles!(badpointer(5))))); |
| static assert(!is(typeof(compiles!(badpointer(6))))); |
| static assert(!is(typeof(compiles!(badpointer(7))))); |
| static assert(!is(typeof(compiles!(badpointer(8))))); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=10211 |
| // Allow casts S**->D**, when S*->D* is OK |
| |
| int bug10211() |
| { |
| int m = 7; |
| int* x = &m; |
| int** y = &x; |
| assert(**y == 7); |
| uint* p = cast(uint*)x; |
| uint** q = cast(uint**)y; |
| return 1; |
| } |
| |
| static assert(bug10211()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=10568 |
| // CTFE rejects function pointer safety casts |
| |
| @safe void safetyDance() {} |
| |
| int isItSafeToDance() |
| { |
| void function() @trusted yourfriends = &safetyDance; |
| void function() @safe nofriendsOfMine = yourfriends; |
| return 1; |
| } |
| |
| static assert(isItSafeToDance()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=12296 |
| // CTFE rejects const compatible AA pointer cast |
| |
| int test12296() |
| { |
| immutable x = [5 : 4]; |
| auto aa = &x; |
| const(int[int])* y = aa; |
| return 1; |
| } |
| static assert(test12296()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=9170 |
| // Allow reinterpret casts float<->int |
| |
| int f9170(float x) |
| { |
| return *(cast(int*)&x); |
| } |
| |
| float i9170(int x) |
| { |
| return *(cast(float*)&x); |
| } |
| |
| float u9170(uint x) |
| { |
| return *(cast(float*)&x); |
| } |
| |
| int f9170arr(float[] x) |
| { |
| return *(cast(int*)&(x[1])); |
| } |
| |
| long d9170(double x) |
| { |
| return *(cast(long*)&x); |
| } |
| |
| int fref9170(ref float x) |
| { |
| return *(cast(int*)&x); |
| } |
| |
| long dref9170(ref double x) |
| { |
| return *(cast(long*)&x); |
| } |
| |
| bool bug9170() |
| { |
| float f = 1.25; |
| double d = 1.25; |
| assert(f9170(f) == 0x3FA0_0000); |
| assert(fref9170(f) == 0x3FA0_0000); |
| assert(d9170(d) == 0x3FF4_0000_0000_0000L); |
| assert(dref9170(d) == 0x3FF4_0000_0000_0000L); |
| float [3] farr = [0, 1.25, 0]; |
| assert(f9170arr(farr) == 0x3FA0_0000); |
| int i = 0x3FA0_0000; |
| assert(i9170(i) == 1.25); |
| uint u = 0x3FA0_0000; |
| assert(u9170(u) == 1.25); |
| return true; |
| } |
| |
| static assert(bug9170()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6792 |
| // ICE with pointer cast of indexed array |
| |
| struct S6792 |
| { |
| int i; |
| } |
| |
| static assert({ |
| { |
| void* p; |
| p = [S6792(1)].ptr; |
| S6792 s = *(cast(S6792*)p); |
| assert(s.i == 1); |
| } |
| { |
| void*[] ary; |
| ary ~= [S6792(2)].ptr; |
| S6792 s = *(cast(S6792*)ary[0]); |
| assert(s.i == 2); |
| } |
| { |
| void*[7] ary; |
| ary[6]= [S6792(2)].ptr; |
| S6792 s = *(cast(S6792*)ary[6]); |
| assert(s.i == 2); |
| } |
| { |
| void* p; |
| p = [S6792(1)].ptr; |
| void*[7] ary; |
| ary[5]= p; |
| S6792 s = *(cast(S6792*)ary[5]); |
| assert(s.i == 1); |
| } |
| { |
| S6792*[string] aa; |
| aa["key"] = [S6792(3)].ptr; |
| const(S6792) s = *(cast(const(S6792)*)aa["key"]); |
| assert(s.i == 3); |
| } |
| { |
| S6792[string] blah; |
| blah["abc"] = S6792(6); |
| S6792*[string] aa; |
| aa["kuy"] = &blah["abc"]; |
| const(S6792) s = *(cast(const(S6792)*)aa["kuy"]); |
| assert(s.i == 6); |
| |
| void*[7] ary; |
| ary[5]= &blah["abc"]; |
| S6792 t = *(cast(S6792*)ary[5]); |
| assert(t.i == 6); |
| |
| int q = 6; |
| ary[3]= &q; |
| int gg = *(cast(int*)(ary[3])); |
| } |
| return true; |
| }()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7780 |
| // array cast |
| |
| int bug7780(int testnum) |
| { |
| int[] y = new int[2]; |
| y[0] = 2000000; |
| if (testnum == 1) |
| { |
| void[] x = y; |
| return (cast(byte[])x)[1]; |
| } |
| if (testnum == 2) |
| { |
| int[] x = y[0 .. 1]; |
| return (cast(byte[])x)[1]; |
| } |
| return 1; |
| } |
| |
| static assert( is(typeof(compiles!(bug7780(0))))); |
| static assert(!is(typeof(compiles!(bug7780(1))))); |
| static assert(!is(typeof(compiles!(bug7780(2))))); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=14028 |
| // static array pointer that refers existing array elements. |
| |
| int test14028a(size_t ofs)(bool ct) |
| { |
| int[4] a; |
| int[2]* p; |
| int num = ofs; |
| |
| if (ct) |
| p = cast(int[2]*)&a[ofs]; // SymOffExp |
| else |
| p = cast(int[2]*)&a[num]; // CastExp + AddrExp |
| |
| // pointers comparison |
| assert(cast(void*)a.ptr <= cast(void*)p); |
| assert(cast(void*)a.ptr <= cast(void*)&(*p)[0]); |
| assert(cast(void*)&a[0] <= cast(void*)p); |
| |
| return 1; |
| } |
| static assert(test14028a!0(true)); |
| static assert(test14028a!0(false)); |
| static assert(test14028a!3(true)); |
| static assert(test14028a!3(false)); |
| static assert(!is(typeof(compiles!(test14028a!4(true))))); |
| static assert(!is(typeof(compiles!(test14028a!4(false))))); |
| |
| int test14028b(int num) |
| { |
| int[4] a; |
| int[2]* p; |
| |
| if (num == 1) |
| { |
| p = cast(int[2]*)&a[0]; // &a[0..2]; |
| (*p)[0] = 1; // a[0] = 1 |
| (*p)[1] = 2; // a[1] = 2 |
| assert(a == [1,2,0,0]); |
| p = p + 1; // &a[0] -> &a[2] |
| (*p)[0] = 3; // a[2] = 3 |
| (*p)[1] = 4; // a[3] = 4 |
| assert(a == [1,2,3,4]); |
| } |
| if (num == 2) |
| { |
| p = cast(int[2]*)&a[1]; // &a[1..3]; |
| (*p)[0] = 1; // a[1] = 1 |
| p = p + 1; // &a[1..3] -> &a[3..5] |
| (*p)[0] = 2; // a[3] = 2 |
| assert(a == [0,1,0,2]); |
| } |
| if (num == 3) |
| { |
| p = cast(int[2]*)&a[1]; // &a[1..3]; |
| (*p)[0] = 1; // a[1] = 1 |
| p = p + 1; // &a[1..3] -> &a[3..5] |
| (*p)[0] = 2; // a[3] = 2 |
| (*p)[1] = 3; // a[4] = 3 (CTFE error) |
| } |
| if (num == 4) |
| { |
| p = cast(int[2]*)&a[0]; // &a[0..2]; |
| p = p + 1; // &a[0..2] -> &a[2..4] |
| p = p + 1; // &a[2..4] -> &a[4..6] (ok) |
| } |
| if (num == 5) |
| { |
| p = cast(int[2]*)&a[1]; // &a[1..3]; |
| p = p + 2; // &a[1..3] -> &a[5..7] (CTFE error) |
| } |
| return 1; |
| } |
| static assert(test14028b(1)); |
| static assert(test14028b(2)); |
| static assert(!is(typeof(compiles!(test14028b(3))))); |
| static assert(test14028b(4)); |
| static assert(!is(typeof(compiles!(test14028b(5))))); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=10275 |
| // cast struct literals to immutable |
| |
| struct Bug10275 |
| { |
| uint[] ivals; |
| } |
| |
| Bug10275 bug10275() |
| { |
| return Bug10275([1, 2, 3]); |
| } |
| |
| int test10275() |
| { |
| immutable(Bug10275) xxx = cast(immutable(Bug10275))bug10275(); |
| return 1; |
| } |
| |
| static assert(test10275()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6851 |
| // passing pointer by argument |
| |
| void set6851(int* pn) |
| { |
| *pn = 20; |
| } |
| void bug6851() |
| { |
| int n = 0; |
| auto pn = &n; |
| *pn = 10; |
| assert(n == 10); |
| set6851(&n); |
| } |
| static assert({ bug6851(); return true; }()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7876 |
| |
| int* bug7876(int n) @system |
| { |
| int x; |
| auto ptr = &x; |
| if (n == 2) |
| ptr = null; |
| return ptr; |
| } |
| |
| struct S7876 |
| { |
| int* p; |
| } |
| |
| S7876 bug7876b(int n) @system |
| { |
| int x; |
| S7876 s; |
| s.p = &x; |
| if (n == 11) |
| s.p = null; |
| return s; |
| } |
| |
| int test7876(int n) |
| { |
| if (n >= 10) |
| { |
| S7876 m = bug7876b(n); |
| return 1; |
| } |
| int* p = bug7876(n); |
| return 1; |
| } |
| |
| static assert( is(typeof(compiles!(test7876(2))))); |
| static assert(!is(typeof(compiles!(test7876(0))))); |
| static assert( is(typeof(compiles!(test7876(11))))); |
| static assert(!is(typeof(compiles!(test7876(10))))); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=11824 |
| |
| int f11824(T)() |
| { |
| T[] arr = new T[](1); |
| T* getAddr(ref T a) |
| { |
| return &a; |
| } |
| getAddr(arr[0]); |
| return 1; |
| } |
| static assert(f11824!int()); // OK |
| static assert(f11824!(int[])()); // OK <- NG |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6817 |
| // if converted to &&, only with -inline |
| |
| static assert({ |
| void toggle() |
| { |
| bool b; |
| if (b) |
| b = false; |
| } |
| toggle(); |
| return true; |
| }()); |
| |
| /************************************************** |
| cast to void |
| **************************************************/ |
| |
| static assert({ |
| cast(void)(71); |
| return true; |
| }()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6816 |
| // nested function can't access this |
| |
| struct S6816 |
| { |
| size_t foo() |
| { |
| return (){ return value +1 ; }(); |
| } |
| size_t value; |
| } |
| |
| enum s6816 = S6816().foo(); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7277 |
| // ICE nestedstruct.init.tupleof |
| |
| struct Foo7277 |
| { |
| int a; |
| int func() |
| { |
| int b; |
| void nested() |
| { |
| b = 7; |
| a = 10; |
| } |
| nested(); |
| return a+b; |
| } |
| } |
| |
| static assert(Foo7277().func() == 17); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=10217 |
| // ICE. CTFE version of 9315 |
| |
| bool bug10217() |
| { |
| struct S |
| { |
| int i; |
| void bar() {} |
| } |
| auto yyy = S.init.tupleof[$ - 1]; |
| assert(!yyy); |
| return 1; |
| } |
| |
| static assert(bug10217()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=8276 |
| // ICE |
| |
| void bug8676(int n) |
| { |
| const int X1 = 4 + n; |
| const int X2 = 4; |
| int X3 = 4; |
| int bar1() { return X1; } |
| int bar2() { return X2; } |
| int bar3() { return X3; } |
| static assert(!is(typeof(compiles!(bar1())))); |
| static assert( is(typeof(compiles!(bar2())))); |
| static assert(!is(typeof(compiles!(bar3())))); |
| } |
| |
| /************************************************** |
| classes and interfaces |
| **************************************************/ |
| |
| interface SomeInterface |
| { |
| int daz(); |
| float bar(char); |
| int baz(); |
| } |
| |
| interface SomeOtherInterface |
| { |
| int xxx(); |
| } |
| |
| class TheBase : SomeInterface, SomeOtherInterface |
| { |
| int q = 88; |
| int rad = 61; |
| int a = 14; |
| int somebaseclassfunc() { return 28; } |
| int daz() { return 0; } |
| int baz() { return 0; } |
| int xxx() { return 762; } |
| int foo() { return q; } |
| float bar(char c) { return 3.6; } |
| } |
| |
| class SomeClass : TheBase, SomeInterface |
| { |
| int gab = 9; |
| int fab; |
| int a = 17; |
| int b = 23; |
| override int foo() { return gab + a; } |
| override float bar(char c) { return 2.6; } |
| int something() { return 0; } |
| override int daz() { return 0; } |
| override int baz() { return 0; } |
| } |
| |
| class Unrelated : TheBase |
| { |
| this(int x) { a = x; } |
| } |
| |
| auto classtest1(int n) |
| { |
| SomeClass c = new SomeClass; |
| assert(c.a == 17); |
| assert(c.q == 88); |
| TheBase d = c; |
| assert(d.a == 14); |
| assert(d.q == 88); |
| if (n == 7) |
| { |
| // bad cast -- should fail |
| Unrelated u = cast(Unrelated)d; |
| assert(u is null); |
| } |
| SomeClass e = cast(SomeClass)d; |
| d.q = 35; |
| assert(c.q == 35); |
| assert(c.foo() == 9 + 17); |
| ++c.a; |
| assert(c.foo() == 9 + 18); |
| assert(d.foo() == 9 + 18); |
| d = new TheBase; |
| SomeInterface fc = c; |
| SomeOtherInterface ot = c; |
| assert(fc.bar('x') == 2.6); |
| assert(ot.xxx() == 762); |
| fc = d; |
| ot = d; |
| assert(fc.bar('x') == 3.6); |
| assert(ot.xxx() == 762); |
| |
| Unrelated u2 = new Unrelated(7); |
| assert(u2.a == 7); |
| return 6; |
| } |
| static assert(classtest1(1)); |
| static assert(classtest1(2)); |
| static assert(classtest1(7)); // https://issues.dlang.org/show_bug.cgi?id=7154 |
| |
| // can't initialize enum with not null class |
| SomeClass classtest2(int n) |
| { |
| return n == 5 ? (new SomeClass) : null; |
| } |
| static assert( is(typeof((){ enum const(SomeClass) xx = classtest2(2);}()))); |
| static assert(!is(typeof((){ enum const(SomeClass) xx = classtest2(5);}()))); |
| |
| class RecursiveClass |
| { |
| int x; |
| this(int n) { x = n; } |
| RecursiveClass b; |
| void doit() { b = new RecursiveClass(7); b.x = 2;} |
| } |
| |
| int classtest3() |
| { |
| RecursiveClass x = new RecursiveClass(17); |
| x.doit(); |
| RecursiveClass y = x.b; |
| assert(y.x == 2); |
| assert(x.x == 17); |
| return 1; |
| } |
| |
| static assert(classtest3()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=12016 |
| // class cast and qualifier reinterpret |
| |
| class B12016 { } |
| |
| class C12016 : B12016 { } |
| |
| bool f12016(immutable B12016 b) |
| { |
| assert(b); |
| return true; |
| } |
| |
| static assert(f12016(new immutable C12016)); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=10610 |
| // ice immutable implicit conversion |
| |
| class Bug10610(T) |
| { |
| int baz() immutable |
| { |
| return 1; |
| } |
| static immutable(Bug10610!T) min = new Bug10610!T(); |
| } |
| |
| void ice10610() |
| { |
| alias T10610 = Bug10610!(int); |
| static assert (T10610.min.baz()); |
| } |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=13141 |
| // regression fix caused by 10610 |
| |
| struct MapResult13141(alias pred) |
| { |
| int[] range; |
| @property empty() { return range.length == 0; } |
| @property front() { return pred(range[0]); } |
| void popFront() { range = range[1 .. $]; } |
| } |
| |
| string[] array13141(R)(R r) |
| { |
| typeof(return) result; |
| foreach (e; r) |
| result ~= e; |
| return result; |
| } |
| |
| //immutable string[] splitterNames = [4].map!(e => "4").array(); |
| immutable string[] splitterNames13141 = MapResult13141!(e => "4")([4]).array13141(); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=11587 |
| // AA compare |
| |
| static assert([1:2, 3:4] == [3:4, 1:2]); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=14325 |
| // more AA comparisons |
| |
| static assert([1:1] != [1:2, 2:1]); // OK |
| static assert([1:1] != [1:2]); // OK |
| static assert([1:1] != [2:1]); // OK <- Error |
| static assert([1:1, 2:2] != [3:3, 4:4]); // OK <- Error |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7147 |
| // typeid() |
| |
| static assert({ |
| TypeInfo xxx = typeid(Object); |
| TypeInfo yyy = typeid(new Error("xxx")); |
| return true; |
| }()); |
| |
| int bug7147(int n) |
| { |
| Error err = n ? new Error("xxx") : null; |
| TypeInfo qqq = typeid(err); |
| return 1; |
| } |
| |
| // Must not segfault if class is null |
| static assert(!is(typeof(compiles!(bug7147(0))))); |
| static assert( is(typeof(compiles!(bug7147(1))))); |
| |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=14123 |
| // identity TypeInfo objects |
| |
| static assert({ |
| bool eq(TypeInfo t1, TypeInfo t2) |
| { |
| return t1 is t2; |
| } |
| |
| class C {} |
| struct S {} |
| |
| assert( eq(typeid(C), typeid(C))); |
| assert(!eq(typeid(C), typeid(Object))); |
| assert( eq(typeid(S), typeid(S))); |
| assert(!eq(typeid(S), typeid(int))); |
| assert( eq(typeid(int), typeid(int))); |
| assert(!eq(typeid(int), typeid(long))); |
| |
| Object o = new Object; |
| Object c = new C; |
| assert( eq(typeid(o), typeid(o))); |
| assert(!eq(typeid(c), typeid(o))); |
| assert(!eq(typeid(o), typeid(S))); |
| |
| return 1; |
| }()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6885 |
| // wrong code with new array |
| |
| struct S6885 |
| { |
| int p; |
| } |
| |
| int bug6885() |
| { |
| auto array = new double[1][2]; |
| array[1][0] = 6; |
| array[0][0] = 1; |
| assert(array[1][0] == 6); |
| |
| auto barray = new S6885[2]; |
| barray[1].p = 5; |
| barray[0].p = 2; |
| assert(barray[1].p == 5); |
| return 1; |
| } |
| |
| static assert(bug6885()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6886 |
| // ICE with new array of dynamic arrays |
| |
| int bug6886() |
| { |
| auto carray = new int[][2]; |
| carray[1] = [6]; |
| carray[0] = [4]; |
| assert(carray[1][0] == 6); |
| return 1; |
| } |
| |
| static assert(bug6886()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=10198 |
| // Multidimensional struct block initializer |
| |
| struct Block10198 |
| { |
| int[4][3] val; |
| } |
| |
| int bug10198() |
| { |
| Block10198 pp = Block10198(67); |
| assert(pp.val[2][3] == 67); |
| assert(pp.val[1][3] == 67); |
| return 1; |
| } |
| static assert(bug10198()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=14440 |
| // Multidimensional block initialization should create distinct arrays for each elements |
| |
| struct Matrix14440(E, size_t row, size_t col) |
| { |
| E[col][row] array2D; |
| |
| @safe pure nothrow |
| this(E[row * col] numbers...) |
| { |
| foreach (r; 0 .. row) |
| { |
| foreach (c; 0 .. col) |
| { |
| array2D[r][c] = numbers[r * col + c]; |
| } |
| } |
| } |
| } |
| |
| void test14440() |
| { |
| // Replace 'enum' with 'auto' here and it will work fine. |
| enum matrix = Matrix14440!(int, 3, 3)( |
| 1, 2, 3, |
| 4, 5, 6, |
| 7, 8, 9 |
| ); |
| |
| static assert(matrix.array2D[0][0] == 1); |
| static assert(matrix.array2D[0][1] == 2); |
| static assert(matrix.array2D[0][2] == 3); |
| static assert(matrix.array2D[1][0] == 4); |
| static assert(matrix.array2D[1][1] == 5); |
| static assert(matrix.array2D[1][2] == 6); |
| static assert(matrix.array2D[2][0] == 7); |
| static assert(matrix.array2D[2][1] == 8); |
| static assert(matrix.array2D[2][2] == 9); |
| } |
| |
| /**************************************************** |
| * Exception chaining tests from xtest46.d |
| ****************************************************/ |
| |
| class A75 |
| { |
| pure static void raise(string s) |
| { |
| throw new Exception(s); |
| } |
| } |
| |
| int test75() |
| { |
| int x = 0; |
| try |
| { |
| A75.raise("a"); |
| } |
| catch (Exception e) |
| { |
| x = 1; |
| } |
| assert(x == 1); |
| return 1; |
| } |
| static assert(test75()); |
| |
| /**************************************************** |
| * Exception chaining tests from test4.d |
| ****************************************************/ |
| |
| int test4_test54() |
| { |
| int status = 0; |
| |
| try |
| { |
| try |
| { |
| status++; |
| assert(status == 1); |
| throw new Exception("first"); |
| } |
| finally |
| { |
| status++; |
| assert(status == 2); |
| status++; |
| throw new Exception("second"); |
| } |
| } |
| catch (Exception e) |
| { |
| assert(e.msg == "first"); |
| assert(e.next.msg == "second"); |
| } |
| return true; |
| } |
| |
| static assert(test4_test54()); |
| |
| void foo55() |
| { |
| try |
| { |
| Exception x = new Exception("second"); |
| throw x; |
| } |
| catch (Exception e) |
| { |
| assert(e.msg == "second"); |
| } |
| } |
| |
| int test4_test55() |
| { |
| int status = 0; |
| try |
| { |
| try |
| { |
| status++; |
| assert(status == 1); |
| Exception x = new Exception("first"); |
| throw x; |
| } |
| finally |
| { |
| status++; |
| assert(status == 2); |
| status++; |
| foo55(); |
| } |
| } |
| catch (Exception e) |
| { |
| assert(e.msg == "first"); |
| assert(status == 3); |
| } |
| return 1; |
| } |
| |
| static assert(test4_test55()); |
| |
| /**************************************************** |
| * Exception chaining tests from eh.d |
| ****************************************************/ |
| |
| void bug1513outer() |
| { |
| int result1513; |
| |
| void bug1513a() |
| { |
| throw new Exception("d"); |
| } |
| |
| void bug1513b() |
| { |
| try |
| { |
| try |
| { |
| bug1513a(); |
| } |
| finally |
| { |
| result1513 |= 4; |
| throw new Exception("f"); |
| } |
| } |
| catch (Exception e) |
| { |
| assert(e.msg == "d"); |
| assert(e.next.msg == "f"); |
| assert(!e.next.next); |
| } |
| } |
| |
| void bug1513c() |
| { |
| try |
| { |
| try |
| { |
| throw new Exception("a"); |
| } |
| finally |
| { |
| result1513 |= 1; |
| throw new Exception("b"); |
| } |
| } |
| finally |
| { |
| bug1513b(); |
| result1513 |= 2; |
| throw new Exception("c"); |
| } |
| } |
| |
| void bug1513() |
| { |
| result1513 = 0; |
| try |
| { |
| bug1513c(); |
| } |
| catch (Exception e) |
| { |
| assert(result1513 == 7); |
| assert(e.msg == "a"); |
| assert(e.next.msg == "b"); |
| assert(e.next.next.msg == "c"); |
| } |
| } |
| |
| bug1513(); |
| } |
| |
| void collideone() |
| { |
| try |
| { |
| throw new Exception("x"); |
| } |
| finally |
| { |
| throw new Exception("y"); |
| } |
| } |
| |
| void doublecollide() |
| { |
| try |
| { |
| try |
| { |
| try |
| { |
| throw new Exception("p"); |
| } |
| finally |
| { |
| throw new Exception("q"); |
| } |
| } |
| finally |
| { |
| collideone(); |
| } |
| } |
| catch (Exception e) |
| { |
| assert(e.msg == "p"); |
| assert(e.next.msg == "q"); |
| assert(e.next.next.msg == "x"); |
| assert(e.next.next.next.msg == "y"); |
| assert(!e.next.next.next.next); |
| } |
| } |
| |
| void collidetwo() |
| { |
| try |
| { |
| try |
| { |
| throw new Exception("p2"); |
| } |
| finally |
| { |
| throw new Exception("q2"); |
| } |
| } |
| finally |
| { |
| collideone(); |
| } |
| } |
| |
| void collideMixed() |
| { |
| int works = 6; |
| try |
| { |
| try |
| { |
| try |
| { |
| throw new Exception("e"); |
| } |
| finally |
| { |
| throw new Error("t"); |
| } |
| } |
| catch (Exception f) |
| { |
| // Doesn't catch, because Error is chained to it. |
| works += 2; |
| } |
| } |
| catch (Error z) |
| { |
| works += 4; |
| assert(z.msg == "t"); // Error comes first |
| assert(z.next is null); |
| assert(z.bypassedException.msg == "e"); |
| } |
| assert(works == 10); |
| } |
| |
| class AnotherException : Exception |
| { |
| this(string s) |
| { |
| super(s); |
| } |
| } |
| |
| void multicollide() |
| { |
| try |
| { |
| try |
| { |
| try |
| { |
| try |
| { |
| throw new Exception("m2"); |
| } |
| finally |
| { |
| throw new AnotherException("n2"); |
| } |
| } |
| catch (AnotherException s) |
| { |
| // Not caught -- we needed to catch the root cause "m2", not |
| // just the collateral "n2" (which would leave m2 uncaught). |
| assert(0); |
| } |
| } |
| finally |
| { |
| collidetwo(); |
| } |
| } |
| catch (Exception f) |
| { |
| assert(f.msg == "m2"); |
| assert(f.next.msg == "n2"); |
| Throwable e = f.next.next; |
| assert(e.msg == "p2"); |
| assert(e.next.msg == "q2"); |
| assert(e.next.next.msg == "x"); |
| assert(e.next.next.next.msg == "y"); |
| assert(!e.next.next.next.next); |
| } |
| } |
| |
| int testsFromEH() |
| { |
| bug1513outer(); |
| doublecollide(); |
| collideMixed(); |
| multicollide(); |
| return 1; |
| } |
| static assert(testsFromEH()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6901 |
| // With + synchronized statements |
| |
| struct With1 |
| { |
| int a; |
| int b; |
| } |
| |
| class Foo6 |
| { |
| } |
| |
| class Foo32 |
| { |
| struct Bar |
| { |
| int x; |
| } |
| } |
| |
| class Base56 |
| { |
| private string myfoo; |
| private string mybar; |
| |
| // Get/set properties that will be overridden. |
| void foo(string s) { myfoo = s; } |
| string foo() { return myfoo; } |
| |
| // Get/set properties that will not be overridden. |
| void bar(string s) { mybar = s; } |
| string bar() { return mybar; } |
| } |
| |
| class Derived56 : Base56 |
| { |
| alias Base56.foo foo; // Bring in Base56's foo getter. |
| override void foo(string s) { super.foo = s; } // Override foo setter. |
| } |
| |
| int testwith() |
| { |
| With1 x = With1(7); |
| with (x) |
| { |
| a = 2; |
| } |
| assert(x.a == 2); |
| |
| // from test11.d |
| Foo6 foo6 = new Foo6(); |
| |
| with (foo6) |
| { |
| int xx; |
| xx = 4; |
| } |
| with (new Foo32) |
| { |
| Bar z; |
| z.x = 5; |
| } |
| Derived56 d = new Derived56; |
| with (d) |
| { |
| foo = "hi"; |
| d.foo = "hi"; |
| bar = "hi"; |
| assert(foo == "hi"); |
| assert(d.foo == "hi"); |
| assert(bar == "hi"); |
| } |
| int w = 7; |
| synchronized |
| { |
| ++w; |
| } |
| assert(w == 8); |
| return 1; |
| } |
| |
| static assert(testwith()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=9236 |
| // ICE switch with(EnumType) |
| |
| enum Command9236 |
| { |
| Char, |
| Any, |
| }; |
| |
| bool bug9236(Command9236 cmd) |
| { |
| int n = 0; |
| with (Command9236) switch (cmd) |
| { |
| case Any: |
| n = 1; |
| break; |
| default: |
| n = 2; |
| } |
| assert(n == 1); |
| |
| switch (cmd) with (Command9236) |
| { |
| case Any: |
| return true; |
| default: |
| return false; |
| } |
| } |
| |
| static assert(bug9236(Command9236.Any)); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6416 |
| // static struct declaration |
| |
| static assert({ |
| static struct S { int y = 7; } |
| S a; |
| a.y += 6; |
| assert(a.y == 13); |
| return true; |
| }()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=10499 |
| // static template struct declaration |
| |
| static assert({ |
| static struct Result() {} |
| return true; |
| }()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=13757 |
| // extern(C) alias declaration |
| |
| static assert({ |
| alias FP1 = extern(C) int function(); |
| alias extern(C) int function() FP2; |
| return true; |
| }()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6522 |
| // opAssign + foreach ref |
| |
| struct Foo6522 |
| { |
| bool b = false; |
| void opAssign(int x) |
| { |
| this.b = true; |
| } |
| } |
| |
| bool foo6522() |
| { |
| Foo6522[1] array; |
| foreach (ref item; array) |
| item = 1; |
| return true; |
| } |
| |
| static assert(foo6522()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7245 |
| // pointers + foreach ref |
| |
| int bug7245(int testnum) |
| { |
| int[3] arr; |
| arr[0] = 4; |
| arr[1] = 6; |
| arr[2] = 8; |
| int* ptr; |
| |
| foreach (i, ref p; arr) |
| { |
| if (i == 1) |
| ptr = &p; |
| if (testnum == 1) |
| p = 5; |
| } |
| |
| return *ptr; |
| } |
| |
| static assert(bug7245(0) == 6); |
| static assert(bug7245(1) == 5); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=8498 |
| // modifying foreach |
| // https://issues.dlang.org/show_bug.cgi?id=7658 |
| // foreach ref |
| // https://issues.dlang.org/show_bug.cgi?id=8539 |
| // nested funcs, ref param, -inline |
| |
| int bug8498() |
| { |
| foreach (ref i; 0 .. 5) |
| { |
| assert(i == 0); |
| i = 100; |
| } |
| return 1; |
| } |
| static assert(bug8498()); |
| |
| string bug7658() |
| { |
| string[] children = ["0"]; |
| foreach (ref child; children) |
| child = "1"; |
| return children[0]; |
| } |
| |
| static assert(bug7658() == "1"); |
| |
| int bug8539() |
| { |
| static void one(ref int x) |
| { |
| x = 1; |
| } |
| static void go() |
| { |
| int y; |
| one(y); |
| assert(y == 1); // fails with -inline |
| } |
| go(); |
| return 1; |
| } |
| |
| static assert(bug8539()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7874 |
| // https://issues.dlang.org/show_bug.cgi?id=13297 |
| // https://issues.dlang.org/show_bug.cgi?id=13740 |
| // better lvalue handling |
| |
| int bug7874(int x){ return ++x = 1; } |
| static assert(bug7874(0) == 1); |
| |
| // ---- |
| |
| struct S13297 |
| { |
| int* p; |
| } |
| void f13297(ref int* p) |
| { |
| p = cast(int*) 1; |
| assert(p); // passes |
| } |
| static assert( |
| { |
| S13297 s; |
| f13297(s.p); |
| return s.p != null; // false |
| }()); |
| |
| // ---- |
| |
| class R13740 |
| { |
| int e; |
| bool empty = false; |
| @property ref front() { return e; } |
| void popFront() { empty = true; } |
| } |
| static assert({ |
| auto r = new R13740(); |
| foreach (ref e; r) |
| e = 42; |
| assert(r.e == 42); /* fails in CTFE */ |
| |
| return true; |
| }()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6919 |
| |
| void bug6919(int* val) |
| { |
| *val = 1; |
| } |
| void test6919() |
| { |
| int n; |
| bug6919(&n); |
| assert(n == 1); |
| } |
| static assert({ test6919(); return true; }()); |
| |
| void bug6919b(string* val) |
| { |
| *val = "1"; |
| } |
| |
| void test6919b() |
| { |
| string val; |
| bug6919b(&val); |
| assert(val == "1"); |
| } |
| static assert({ test6919b(); return true; }()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6995 |
| |
| struct Foo6995 |
| { |
| static size_t index(size_t v)() |
| { |
| return v; |
| } |
| } |
| |
| static assert(Foo6995.index!(27)() == 27); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7043 |
| // ref with -inline |
| |
| int bug7043(S)(ref int x) |
| { |
| return x; |
| } |
| |
| static assert({ |
| int i = 416; |
| return bug7043!(char)(i); |
| }() == 416); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6037 |
| // recursive ref |
| |
| void bug6037(ref int x, bool b) |
| { |
| int w = 3; |
| if (b) |
| { |
| bug6037(w, false); |
| assert(w == 6); |
| } |
| else |
| { |
| x = 6; |
| assert(w == 3); // fails |
| } |
| } |
| |
| int bug6037outer() |
| { |
| int q; |
| bug6037(q, true); |
| return 401; |
| } |
| |
| static assert(bug6037outer() == 401); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=14299 |
| // [REG2.067a], more than one depth of recursive call with ref |
| |
| string gen14299(int max, int idx, ref string name) |
| { |
| string ret; |
| name = [cast(char)(idx + '0')]; |
| ret ~= name; |
| if (idx < max) |
| { |
| string subname; |
| ret ~= gen14299(max, idx + 1, subname); |
| } |
| ret ~= name; |
| return ret; |
| } |
| string test14299(int max) |
| { |
| string n; |
| return gen14299(max, 0, n); |
| } |
| static assert(test14299(1) == "0110"); // OK <- fail |
| static assert(test14299(2) == "012210"); // OK <- ICE |
| static assert(test14299(3) == "01233210"); |
| static assert(test14299(4) == "0123443210"); |
| static assert(test14299(5) == "012345543210"); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7940 |
| // wrong code for complicated assign |
| |
| struct Bug7940 |
| { |
| int m; |
| } |
| |
| struct App7940 |
| { |
| Bug7940[] x; |
| } |
| |
| int bug7940() |
| { |
| Bug7940[2] y; |
| App7940 app; |
| app.x = y[0 .. 1]; |
| app.x[0].m = 12; |
| assert(y[0].m == 12); |
| assert(app.x[0].m == 12); |
| return 1; |
| } |
| |
| static assert(bug7940()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=10298 |
| // wrong code for struct array literal init |
| |
| struct Bug10298 |
| { |
| int m; |
| } |
| |
| int bug10298() |
| { |
| Bug10298[1] y = [Bug10298(78)]; |
| y[0].m = 6; |
| assert(y[0].m == 6); |
| |
| // Root cause |
| Bug10298[1] x; |
| x[] = [cast(const Bug10298)(Bug10298(78))]; |
| assert(x[0].m == 78); |
| return 1; |
| } |
| |
| static assert(bug10298()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7266 |
| // dotvar ref parameters |
| |
| struct S7266 { int a; } |
| |
| bool bug7266() |
| { |
| S7266 s; |
| s.a = 4; |
| bar7266(s.a); |
| assert(s.a == 5); |
| out7266(s.a); |
| assert(s.a == 7); |
| return true; |
| } |
| |
| void bar7266(ref int b) |
| { |
| b = 5; |
| assert(b == 5); |
| } |
| |
| void out7266(out int b) |
| { |
| b = 7; |
| assert(b == 7); |
| } |
| |
| static assert(bug7266()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=9982 |
| // dotvar assign through pointer |
| |
| struct Bug9982 |
| { |
| int a; |
| } |
| |
| int test9982() |
| { |
| Bug9982 x; |
| int*q = &x.a; |
| *q = 99; |
| assert(x.a == 99); |
| return 1; |
| } |
| |
| static assert(test9982()); |
| |
| // https://issues.dlang.org/show_bug.cgi?id=9982 |
| // rejects-valid case |
| |
| struct SS9982 |
| { |
| Bug9982 s2; |
| this(Bug9982 s1) |
| { |
| s2.a = 6; |
| emplace9982(&s2, s1); |
| assert(s2.a == 3); |
| } |
| } |
| |
| void emplace9982(Bug9982* chunk, Bug9982 arg) |
| { |
| *chunk = arg; |
| } |
| |
| enum s9982 = Bug9982(3); |
| enum p9982 = SS9982(s9982); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=11618 |
| // dotvar assign through casted pointer |
| |
| struct Tuple11618(T...) |
| { |
| T field; |
| alias field this; |
| } |
| |
| static assert({ |
| Tuple11618!(immutable dchar) result = void; |
| auto addr = cast(dchar*)&result[0]; |
| *addr = dchar.init; |
| return (result[0] == dchar.init); |
| }()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7143 |
| // 'is' for classes |
| |
| class C7143 |
| { |
| int x; |
| } |
| |
| int bug7143(int test) |
| { |
| C7143 c = new C7143; |
| C7143 d = new C7143; |
| if (test == 1) |
| { |
| if (c) |
| return c.x + 8; |
| return -1; |
| } |
| if (test == 2) |
| { |
| if (c is null) |
| return -1; |
| return c.x + 45; |
| } |
| if (test == 3) |
| { |
| if (c is c) |
| return 58; |
| } |
| if (test == 4) |
| { |
| if (c !is c) |
| return -1; |
| else |
| return 48; |
| } |
| if (test == 6) |
| d = c; |
| if (test == 5 || test == 6) |
| { |
| if (c is d) |
| return 188; |
| else |
| return 48; |
| } |
| return -1; |
| } |
| |
| static assert(bug7143(1) == 8); |
| static assert(bug7143(2) == 45); |
| static assert(bug7143(3) == 58); |
| static assert(bug7143(4) == 48); |
| static assert(bug7143(5) == 48); |
| static assert(bug7143(6) == 188); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7147 |
| // virtual function calls from base class |
| |
| class A7147 |
| { |
| int foo() { return 0; } |
| |
| int callfoo() |
| { |
| return foo(); |
| } |
| } |
| |
| class B7147 : A7147 |
| { |
| override int foo() { return 1; } |
| } |
| |
| int test7147() |
| { |
| A7147 a = new B7147; |
| return a.callfoo(); |
| } |
| |
| static assert(test7147() == 1); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7158 |
| |
| class C7158 |
| { |
| bool b() { return true; } |
| } |
| struct S7158 |
| { |
| C7158 c; |
| } |
| |
| bool test7158() |
| { |
| S7158 s = S7158(new C7158); |
| return s.c.b; |
| } |
| static assert(test7158()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=8484 |
| |
| class C8484 |
| { |
| int n; |
| int b() { return n + 3; } |
| } |
| |
| struct S |
| { |
| C8484 c; |
| } |
| |
| int t8484(ref C8484 c) |
| { |
| return c.b(); |
| } |
| |
| int test8484() |
| { |
| auto s = S(new C8484); |
| s.c.n = 4; |
| return t8484(s.c); |
| } |
| static assert(test8484() == 7); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7419 |
| |
| struct X7419 |
| { |
| double x; |
| this(double x) |
| { |
| this.x = x; |
| } |
| } |
| |
| void bug7419() |
| { |
| enum x = { |
| auto p = X7419(3); |
| return p.x; |
| }(); |
| static assert(x == 3); |
| } |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=9445 |
| // ice |
| |
| template c9445(T...) { } |
| |
| void ice9445(void delegate() expr, void function() f2) |
| { |
| static assert(!is(typeof(c9445!(f2())))); |
| static assert(!is(typeof(c9445!(expr())))); |
| } |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=10452 |
| // delegate == |
| |
| struct S10452 |
| { |
| bool func() { return true; } |
| } |
| |
| struct Outer10452 |
| { |
| S10452 inner; |
| } |
| |
| class C10452 |
| { |
| bool func() { return true; } |
| } |
| |
| bool delegate() ref10452(return ref S10452 s) |
| { |
| return &s.func; |
| } |
| |
| bool test10452() |
| { |
| bool delegate() bar = () { return true; }; |
| |
| assert(bar !is null); |
| assert(bar is bar); |
| |
| S10452 bag; |
| S10452[6] bad; |
| Outer10452 outer; |
| C10452 tag = new C10452; |
| |
| auto rat = &outer.inner.func; |
| assert(rat == rat); |
| auto tat = &tag.func; |
| assert(tat == tat); |
| |
| auto bat = &outer.inner.func; |
| auto mat = &bad[2].func; |
| assert(mat is mat); |
| assert(rat == bat); |
| |
| auto zat = &bag.func; |
| auto cat = &bag.func; |
| assert(zat == zat); |
| assert(zat == cat); |
| |
| auto drat = ref10452(bag); |
| assert(cat == drat); |
| assert(drat == drat); |
| drat = ref10452(bad[2]); |
| assert( drat == mat); |
| assert(tat != rat); |
| assert(zat != rat); |
| assert(rat != cat); |
| assert(zat != bar); |
| assert(tat != cat); |
| cat = bar; |
| assert(cat == bar); |
| return true; |
| } |
| static assert(test10452()); |
| |
| /**************************************************/ |
| //https://issues.dlang.org/show_bug.cgi?id=7162 |
| // https://issues.dlang.org/show_bug.cgi?id=4711 |
| |
| void f7162() { } |
| |
| bool ice7162() |
| { |
| false && f7162(); |
| false || f7162(); |
| false && f7162(); // https://issues.dlang.org/show_bug.cgi?id=4711 |
| true && f7162(); |
| return true; |
| } |
| |
| static assert(ice7162()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=8857 |
| // only with -inline (creates an &&) |
| |
| struct Result8857 { char[] next; } |
| |
| void bug8857()() |
| { |
| Result8857 r; |
| r.next = null; |
| if (true) |
| { |
| auto next = r.next; |
| } |
| } |
| static assert({ |
| bug8857(); |
| return true; |
| }()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7527 |
| |
| struct Bug7527 |
| { |
| char[] data; |
| } |
| |
| int bug7527() |
| { |
| auto app = Bug7527(); |
| |
| app.data.ptr[0 .. 1] = "x"; |
| return 1; |
| } |
| |
| static assert(!is(typeof(compiles!(bug7527())))); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7527 |
| |
| int bug7380; |
| |
| static assert(!is(typeof( compiles!( |
| (){ |
| return &bug7380; |
| }() |
| )))); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7165 |
| |
| struct S7165 |
| { |
| int* ptr; |
| bool f() const { return !!ptr; } |
| } |
| |
| static assert(!S7165().f()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7187 |
| |
| int[] f7187() { return [0]; } |
| int[] f7187b(int n) { return [0]; } |
| |
| int g7187(int[] r) |
| { |
| auto t = r[0 .. 0]; |
| return 1; |
| } |
| |
| static assert(g7187(f7187())); |
| static assert(g7187(f7187b(7))); |
| |
| struct S7187 { const(int)[] field; } |
| |
| const(int)[] f7187c() |
| { |
| auto s = S7187([0]); |
| return s.field; |
| } |
| |
| bool g7187c(const(int)[] r) |
| { |
| auto t = r[0 .. 0]; |
| return true; |
| } |
| |
| static assert(g7187c(f7187c())); |
| |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6933 |
| // struct destructors |
| |
| struct Bug6933 |
| { |
| int x = 3; |
| ~this() { } |
| } |
| |
| int test6933() |
| { |
| Bug6933 q; |
| assert(q.x == 3); |
| return 3; |
| } |
| |
| static assert(test6933()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7197 |
| |
| int foo7197(int[] x...) |
| { |
| return 1; |
| } |
| template bar7197(y...) |
| { |
| enum int bar7197 = foo7197(y); |
| } |
| enum int bug7197 = 7; |
| static assert(bar7197!(bug7197)); |
| |
| /************************************************** |
| Enum string compare |
| **************************************************/ |
| |
| enum EScmp : string { a = "aaa" } |
| |
| bool testEScmp() |
| { |
| EScmp x = EScmp.a; |
| assert(x < "abc"); |
| return true; |
| } |
| |
| static assert(testEScmp()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7667 |
| |
| bool baz7667(int[] vars...) |
| { |
| return true; |
| } |
| |
| struct S7667 |
| { |
| static void his(int n) |
| { |
| static assert(baz7667(2)); |
| } |
| } |
| |
| bool bug7667() |
| { |
| S7667 unused; |
| unused.his(7); |
| return true; |
| } |
| enum e7667 = bug7667(); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7536 |
| |
| bool bug7536(string expr) |
| { |
| return true; |
| } |
| |
| void vop() |
| { |
| const string x7536 = "x"; |
| static assert(bug7536(x7536)); |
| } |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6681 |
| // unions |
| |
| struct S6681 |
| { |
| this(int a, int b) { this.a = b; this.b = a; } |
| union |
| { |
| ulong g; |
| struct { int a, b; }; |
| } |
| } |
| |
| static immutable S6681 s6681 = S6681(0, 1); |
| |
| bool bug6681(int test) |
| { |
| S6681 x = S6681(0, 1); |
| x.g = 5; |
| auto u = &x.g; |
| auto v = &x.a; |
| long w = *u; |
| int z; |
| assert(w == 5); |
| if (test == 4) |
| z = *v; // error |
| x.a = 2; // invalidate g, and hence u. |
| if (test == 1) |
| w = *u; // error |
| z = *v; |
| assert(z == 2); |
| x.g = 6; |
| w = *u; |
| assert(w == 6); |
| if (test == 3) |
| z = *v; |
| return true; |
| } |
| static assert(bug6681(2)); |
| static assert(!is(typeof(compiles!(bug6681(1))))); |
| static assert(!is(typeof(compiles!(bug6681(3))))); |
| static assert(!is(typeof(compiles!(bug6681(4))))); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=9113 |
| // ICE with struct in union |
| |
| union U9113 |
| { |
| struct M |
| { |
| int y; |
| } |
| int xx; |
| } |
| |
| int bug9113(T)() |
| { |
| U9113 x; |
| x.M.y = 10; // error, need 'this' |
| return 1; |
| } |
| |
| static assert(!is(typeof(compiles!(bug9113!(int)())))); |
| |
| /************************************************** |
| Creation of unions |
| **************************************************/ |
| |
| union UnionTest1 |
| { |
| int x; |
| float y; |
| } |
| |
| int uniontest1() |
| { |
| UnionTest1 u = UnionTest1(1); |
| return 1; |
| } |
| |
| static assert(uniontest1()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=6438 |
| // void |
| |
| struct S6438 |
| { |
| int a; |
| int b = void; |
| } |
| |
| void fill6438(int[] arr, int testnum) |
| { |
| if (testnum == 2) |
| { |
| auto u = arr[0]; |
| } |
| foreach (ref x; arr) |
| x = 7; |
| auto r = arr[0]; |
| S6438[2] s; |
| auto p = &s[0].b; |
| if (testnum == 3) |
| { |
| auto v = *p; |
| } |
| } |
| |
| bool bug6438(int testnum) |
| { |
| int[4] stackSpace = void; |
| fill6438(stackSpace[], testnum); |
| assert(stackSpace == [7, 7, 7, 7]); |
| return true; |
| } |
| |
| static assert( is(typeof(compiles!(bug6438(1))))); |
| static assert(!is(typeof(compiles!(bug6438(2))))); |
| static assert(!is(typeof(compiles!(bug6438(3))))); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=10994 |
| // void static array members |
| |
| struct Bug10994 |
| { |
| ubyte[2] buf = void; |
| } |
| |
| static bug10994 = Bug10994.init; |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=10937 |
| // struct inside union |
| |
| struct S10937 |
| { |
| union |
| { |
| ubyte[1] a; |
| struct |
| { |
| ubyte b; |
| } |
| } |
| |
| this(ubyte B) |
| { |
| if (B > 6) |
| this.b = B; |
| else |
| this.a[0] = B; |
| } |
| } |
| |
| enum test10937 = S10937(7); |
| enum west10937 = S10937(2); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=13831 |
| |
| struct Vector13831() |
| { |
| } |
| |
| struct Coord13831 |
| { |
| union |
| { |
| struct { short x; } |
| Vector13831!() vector; |
| } |
| } |
| |
| struct Chunk13831 |
| { |
| this(Coord13831) |
| { |
| coord = coord; |
| } |
| |
| Coord13831 coord; |
| |
| static const Chunk13831* unknownChunk = new Chunk13831(Coord13831()); |
| } |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7732 |
| |
| struct AssociativeArray |
| { |
| int* impl; |
| int f() |
| { |
| if (impl !is null) |
| auto x = *impl; |
| return 1; |
| } |
| } |
| |
| int test7732() |
| { |
| AssociativeArray aa; |
| return aa.f; |
| } |
| |
| static assert(test7732()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7784 |
| struct Foo7784 |
| { |
| void bug() |
| { |
| tab["A"] = Bar7784(&this); |
| auto pbar = "A" in tab; |
| auto bar = *pbar; |
| } |
| |
| Bar7784[string] tab; |
| } |
| |
| struct Bar7784 |
| { |
| Foo7784* foo; |
| int val; |
| } |
| |
| bool ctfe7784() |
| { |
| auto foo = Foo7784(); |
| foo.bug(); |
| return true; |
| } |
| |
| static assert(ctfe7784()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7781 |
| |
| static assert(({ return true; }())); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7785 |
| |
| bool bug7785(int n) |
| { |
| int val = 7; |
| auto p = &val; |
| if (n == 2) |
| { |
| auto ary = p[0 .. 1]; |
| } |
| auto x = p[0]; |
| val = 6; |
| assert(x == 7); |
| if (n == 3) |
| p[0 .. 1] = 1; |
| return true; |
| } |
| |
| static assert(bug7785(1)); |
| static assert(!is(typeof(compiles!(bug7785(2))))); |
| static assert(!is(typeof(compiles!(bug7785(3))))); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7987 |
| |
| class C7987 |
| { |
| int m; |
| } |
| |
| struct S7987 |
| { |
| int* p; |
| C7987 c; |
| } |
| |
| bool bug7987() |
| { |
| int[7] q; |
| int[][2] b = q[0 .. 5]; |
| assert(b == b); |
| assert(b is b); |
| C7987 c1 = new C7987; |
| C7987 c2 = new C7987; |
| S7987 s, t; |
| s.p = &q[0]; |
| t.p = &q[1]; |
| assert(s != t); |
| s.p = &q[1]; |
| /*assert(s == t);*/ assert(s.p == t.p); |
| s.c = c1; |
| t.c = c2; |
| /*assert(s != t);*/ assert(s.c !is t.c); |
| assert(s !is t); |
| s.c = c2; |
| /*assert(s == t);*/ assert(s.p == t.p && s.c is t.c); |
| assert(s is t); |
| return true; |
| } |
| |
| static assert(bug7987()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=10579 |
| // typeinfo.func() must not segfault |
| |
| static assert(!is(typeof(compiles!(typeid(int).toString.length)))); |
| |
| class Bug10579 |
| { |
| int foo() { return 1; } |
| } |
| Bug10579 uninitialized10579; |
| |
| static assert(!is(typeof(compiles!(uninitialized10579.foo())))); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=10804 |
| // mixin ArrayLiteralExp typed string |
| |
| void test10804() |
| { |
| String identity(String)(String a) { return a; } |
| |
| string cfun() |
| { |
| char[] s; |
| s.length = 8 + 2 + (2) + 1 + 2; |
| s[] = "identity(`Ω`c)"c[]; |
| return cast(string)s; // Return ArrayLiteralExp as the CTFE result |
| } |
| { |
| enum a1 = "identity(`Ω`c)"c; |
| enum a2 = cfun(); |
| static assert(cast(ubyte[])mixin(a1) == [0xCE, 0xA9]); |
| static assert(cast(ubyte[])mixin(a2) == [0xCE, 0xA9]); // should pass |
| } |
| |
| wstring wfun() |
| { |
| wchar[] s; |
| s.length = 8 + 2 + (2) + 1 + 2; |
| s[] = "identity(`\U0002083A`w)"w[]; |
| return cast(wstring)s; // Return ArrayLiteralExp as the CTFE result |
| } |
| { |
| enum a1 = "identity(`\U0002083A`w)"w; |
| enum a2 = wfun(); |
| static assert(cast(ushort[])mixin(a1) == [0xD842, 0xDC3A]); |
| static assert(cast(ushort[])mixin(a2) == [0xD842, 0xDC3A]); |
| } |
| |
| dstring dfun() |
| { |
| dchar[] s; |
| s.length = 8 + 2 + (1) + 1 + 2; |
| s[] = "identity(`\U00101000`d)"d[]; |
| return cast(dstring)s; // Return ArrayLiteralExp as the CTFE result |
| } |
| { |
| enum a1 = "identity(`\U00101000`d)"d; |
| enum a2 = dfun(); |
| static assert(cast(uint[])mixin(a1) == [0x00101000]); |
| static assert(cast(uint[])mixin(a2) == [0x00101000]); |
| } |
| } |
| |
| /******************************************************/ |
| |
| struct B73 {} |
| struct C73 { B73 b; } |
| C73 func73() { C73 b = void; b.b = B73(); return b; } |
| C73 test73 = func73(); |
| |
| /******************************************************/ |
| |
| struct S74 |
| { |
| int[1] n; |
| static S74 test(){ S74 ret = void; ret.n[0] = 0; return ret; } |
| } |
| |
| enum Test74 = S74.test(); |
| |
| /******************************************************/ |
| |
| static bool bug8865() |
| in |
| { |
| int x = 0; |
| label: |
| foreach (i; (++x) .. 3) |
| { |
| if (i == 1) |
| continue label; // doesn't work. |
| else |
| break label; // doesn't work. |
| } |
| } |
| out |
| { |
| int x = 0; |
| label: |
| foreach (i; (++x) .. 3) |
| { |
| if (i == 1) |
| continue label; // doesn't work. |
| else |
| break label; // doesn't work. |
| } |
| } |
| do |
| { |
| int x = 0; |
| label: |
| foreach (i; (++x) .. 3) |
| { |
| if (i == 1) |
| continue label; // works. |
| else |
| break label; // works. |
| } |
| |
| return true; |
| } |
| static assert(bug8865()); |
| |
| /******************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=15450 |
| // labeled foreach + continue/break |
| |
| static assert({ |
| L1: |
| foreach (l; [0]) |
| continue L1; |
| |
| L2: |
| foreach (l; [0]) |
| break L2; |
| |
| return true; |
| }()); |
| |
| struct Test75 |
| { |
| this(int) pure {} |
| } |
| |
| /******************************************************/ |
| |
| static assert( __traits(compiles, { static shared(Test75*) t75 = new shared(Test75)(0); return t75; })); |
| static assert( __traits(compiles, { static shared(Test75)* t75 = new shared(Test75)(0); return t75; })); |
| static assert( __traits(compiles, { static __gshared Test75* t75 = new Test75(0); return t75; })); |
| static assert( __traits(compiles, { static const(Test75*) t75 = new const(Test75)(0); return t75; })); |
| static assert( __traits(compiles, { static immutable Test75* t75 = new immutable(Test75)(0); return t75; })); |
| static assert(!__traits(compiles, { static Test75* t75 = new Test75(0); return t75; })); |
| /+ |
| static assert(!__traits(compiles, { enum t75 = new shared(Test75)(0); return t75; })); |
| static assert(!__traits(compiles, { enum t75 = new Test75(0); return t75; })); |
| static assert(!__traits(compiles, { enum shared(Test75)* t75 = new shared(Test75)(0); return t75; })); |
| static assert(!__traits(compiles, { enum Test75* t75 = new Test75(0); return t75; })); |
| |
| static assert( __traits(compiles, { enum t75 = new const(Test75)(0); return t75;})); |
| static assert( __traits(compiles, { enum t75 = new immutable(Test75)(0); return t75;})); |
| static assert( __traits(compiles, { enum const(Test75)* t75 = new const(Test75)(0); return t75;})); |
| static assert( __traits(compiles, { enum immutable(Test75)* t75 = new immutable(Test75)(0); return t75;})); |
| +/ |
| /******************************************************/ |
| |
| class Test76 |
| { |
| this(int) pure {} |
| } |
| /+ |
| static assert(!__traits(compiles, { enum t76 = new shared(Test76)(0); return t76;})); |
| static assert(!__traits(compiles, { enum t76 = new Test76(0); return t76;})); |
| static assert(!__traits(compiles, { enum shared(Test76) t76 = new shared(Test76)(0); return t76;})); |
| static assert(!__traits(compiles, { enum Test76 t76 = new Test76(0); return t76;})); |
| |
| static assert( __traits(compiles, { enum t76 = new const(Test76)(0); return t76;})); |
| static assert( __traits(compiles, { enum t76 = new immutable(Test76)(0); return t76;})); |
| static assert( __traits(compiles, { enum const(Test76) t76 = new const(Test76)(0); return t76;})); |
| static assert( __traits(compiles, { enum immutable(Test76) t76 = new immutable(Test76)(0); return t76;})); |
| +/ |
| /******************************************************/ |
| |
| static assert( __traits(compiles, { static shared Test76 t76 = new shared(Test76)(0); return t76; })); |
| static assert( __traits(compiles, { static shared(Test76) t76 = new shared(Test76)(0); return t76; })); |
| static assert( __traits(compiles, { static __gshared Test76 t76 = new Test76(0); return t76; })); |
| static assert( __traits(compiles, { static const Test76 t76 = new const(Test76)(0); return t76; })); |
| static assert( __traits(compiles, { static immutable Test76 t76 = new immutable Test76(0); return t76; })); |
| static assert(!__traits(compiles, { static Test76 t76 = new Test76(0); return t76; })); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=5678 |
| |
| struct Bug5678 |
| { |
| this(int) {} |
| } |
| |
| static assert(!__traits(compiles, { enum const(Bug5678)* b5678 = new const(Bug5678)(0); return b5678; })); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=10782 |
| // run semantic2 for class field |
| |
| enum e10782 = 0; |
| class C10782 { int x = e10782; } |
| string f10782() |
| { |
| auto c = new C10782(); |
| return ""; |
| } |
| mixin(f10782()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=10929 |
| // NRVO support in CTFE |
| |
| struct S10929 |
| { |
| this(this) |
| { |
| postblitCount++; |
| } |
| ~this() |
| { |
| dtorCount++; |
| } |
| int payload; |
| int dtorCount; |
| int postblitCount; |
| } |
| |
| auto makeS10929() |
| { |
| auto s = S10929(42, 0, 0); |
| return s; |
| } |
| |
| bool test10929() |
| { |
| auto s = makeS10929(); |
| assert(s.postblitCount == 0); |
| assert(s.dtorCount == 0); |
| return true; |
| }; |
| static assert(test10929()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=9245 |
| // support postblit call on array assignments |
| |
| bool test9245() |
| { |
| int postblits = 0; |
| struct S |
| { |
| this(this) |
| { |
| ++postblits; |
| } |
| } |
| |
| S s; |
| S[2] a; |
| assert(postblits == 0); |
| |
| { |
| S[2] arr = s; |
| assert(postblits == 2); |
| arr[] = s; |
| assert(postblits == 4); |
| postblits = 0; |
| |
| S[2] arr2 = arr; |
| assert(postblits == 2); |
| arr2 = arr; |
| assert(postblits == 4); |
| postblits = 0; |
| |
| const S[2] constArr = s; |
| assert(postblits == 2); |
| postblits = 0; |
| |
| const S[2] constArr2 = arr; |
| assert(postblits == 2); |
| postblits = 0; |
| } |
| { |
| S[2][2] arr = s; |
| assert(postblits == 4); |
| arr[] = a; |
| assert(postblits == 8); |
| postblits = 0; |
| |
| S[2][2] arr2 = arr; |
| assert(postblits == 4); |
| arr2 = arr; |
| assert(postblits == 8); |
| postblits = 0; |
| |
| const S[2][2] constArr = s; |
| assert(postblits == 4); |
| postblits = 0; |
| |
| const S[2][2] constArr2 = arr; |
| assert(postblits == 4); |
| postblits = 0; |
| } |
| |
| return true; |
| } |
| static assert(test9245()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=12906 |
| // don't call postblit on blit initializing |
| |
| struct S12906 { this(this) { assert(0); } } |
| |
| static assert({ |
| S12906[1] arr; |
| return true; |
| }()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=11510 |
| // support overlapped field access in CTFE |
| |
| struct S11510 |
| { |
| union |
| { |
| size_t x; |
| int* y; // pointer field |
| } |
| } |
| bool test11510() |
| { |
| S11510 s; |
| |
| s.y = [1,2,3].ptr; // writing overlapped pointer field is OK |
| assert(s.y[0 .. 3] == [1,2,3]); // reading valid field is OK |
| |
| s.x = 10; |
| assert(s.x == 10); |
| |
| // There's no reinterpretation between S.x and S.y |
| return true; |
| } |
| static assert(test11510()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=11534 |
| // subtitude inout |
| |
| struct MultiArray11534 |
| { |
| void set(size_t[] sizes...) |
| { |
| storage = new size_t[5]; |
| } |
| |
| @property auto raw_ptr() inout |
| { |
| return storage.ptr + 1; |
| } |
| size_t[] storage; |
| } |
| |
| enum test11534 = () { |
| auto m = MultiArray11534(); |
| m.set(3,2,1); |
| auto start = m.raw_ptr; //this trigger the bug |
| //auto start = m.storage.ptr + 1; //this obviously works |
| return 0; |
| }(); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=11941 |
| // Regression of 11534 fix |
| |
| void takeConst11941(const string[]) {} |
| string[] identity11941(string[] x) { return x; } |
| |
| bool test11941a() |
| { |
| struct S { string[] a; } |
| S s; |
| |
| takeConst11941(identity11941(s.a)); |
| s.a ~= []; |
| |
| return true; |
| } |
| static assert(test11941a()); |
| |
| bool test11941b() |
| { |
| struct S { string[] a; } |
| S s; |
| |
| takeConst11941(identity11941(s.a)); |
| s.a ~= "foo"; /* Error refers to this line (15), */ |
| string[] b = s.a[]; /* but only when this is here. */ |
| |
| return true; |
| } |
| static assert(test11941b()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=11535 |
| // element-wise assignment from string to ubyte array literal |
| |
| struct Hash11535 |
| { |
| ubyte[6] _buffer; |
| |
| void put(scope const(ubyte)[] data...) |
| { |
| uint i = 0, index = 0; |
| auto inputLen = data.length; |
| |
| (&_buffer[index])[0 .. inputLen - i] = (&data[i])[0 .. inputLen - i]; |
| } |
| } |
| |
| auto md5_digest11535(T...)(scope const T data) |
| { |
| Hash11535 hash; |
| hash.put(cast(const(ubyte[]))data[0]); |
| return hash._buffer; |
| } |
| |
| static assert(md5_digest11535(`TEST`) == [84, 69, 83, 84, 0, 0]); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=11540 |
| // goto label + try-catch-finally / with statement |
| |
| static assert(() |
| { |
| // jump inside TryCatchStatement.body |
| { |
| bool c = false; |
| try |
| { |
| if (c) // need to bypass front-end optimization |
| throw new Exception(""); |
| else |
| goto L2; |
| L2: |
| ; |
| } |
| catch (Exception e) {} |
| } |
| |
| // exit from TryCatchStatement.body |
| { |
| bool c = false; |
| try |
| { |
| if (c) // need to bypass front-end optimization |
| throw new Exception(""); |
| else |
| goto L3; |
| } |
| catch (Exception e) {} |
| |
| c = true; |
| L3: |
| assert(!c); |
| } |
| |
| return 1; |
| }()); |
| |
| static assert(() |
| { |
| // enter to TryCatchStatement.catches which has no exception variable |
| { |
| bool c = false; |
| goto L1; |
| try |
| { |
| c = true; |
| } |
| catch (Exception/* e*/) |
| { |
| L1: |
| ; |
| } |
| assert(c == false); |
| } |
| |
| // jump inside TryCatchStatement.catches |
| { |
| bool c = false; |
| try |
| { |
| throw new Exception(""); |
| } |
| catch (Exception e) |
| { |
| goto L2; |
| c = true; |
| L2: |
| ; |
| } |
| assert(c == false); |
| } |
| |
| // exit from TryCatchStatement.catches |
| { |
| bool c = false; |
| try |
| { |
| throw new Exception(""); |
| } |
| catch (Exception e) |
| { |
| goto L3; |
| c = true; |
| } |
| L3: |
| assert(c == false); |
| } |
| |
| return 1; |
| }()); |
| |
| static assert(() |
| { |
| // jump inside TryFinallyStatement.body |
| { |
| try |
| { |
| goto L2; |
| L2: ; |
| } |
| finally {} |
| } |
| |
| // exit from TryFinallyStatement.body |
| { |
| bool c = false; |
| try |
| { |
| goto L3; |
| } |
| finally {} |
| |
| c = true; |
| L3: |
| assert(!c); |
| } |
| |
| // enter in / exit out from finally block is rejected in semantic analysis |
| |
| // jump inside TryFinallyStatement.finalbody |
| { |
| bool c = false; |
| try |
| { |
| } |
| finally |
| { |
| goto L4; |
| c = true; |
| L4: |
| assert(c == false); |
| } |
| } |
| |
| return 1; |
| }()); |
| |
| static assert(() |
| { |
| { |
| bool c = false; |
| with (Object.init) |
| { |
| goto L2; |
| c = true; |
| L2: |
| ; |
| } |
| assert(c == false); |
| } |
| |
| { |
| bool c = false; |
| with (Object.init) |
| { |
| goto L3; |
| c = true; |
| } |
| L3: |
| assert(c == false); |
| } |
| |
| return 1; |
| }()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=11627 |
| //cast dchar to char at compile time on AA assignment |
| |
| bool test11627() |
| { |
| char[ubyte] toCharTmp; |
| dchar letter = 'A'; |
| |
| //char c = cast(char)letter; // OK |
| toCharTmp[0] = cast(char)letter; // NG |
| |
| return true; |
| } |
| static assert(test11627()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=11664 |
| // ignore function local static variables |
| |
| bool test11664() |
| { |
| static int x; |
| static int y = 1; |
| return true; |
| } |
| static assert(test11664()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=12110 |
| // operand of dereferencing does not need to be an lvalue |
| |
| struct SliceOverIndexed12110 |
| { |
| Uint24Array12110* arr; |
| |
| @property front(uint val) |
| { |
| arr.dupThisReference(); |
| } |
| } |
| |
| struct Uint24Array12110 |
| { |
| ubyte[] data; |
| |
| this(ubyte[] range) |
| { |
| data = range; |
| SliceOverIndexed12110(&this).front = 0; |
| assert(data.length == range.length * 2); |
| } |
| |
| void dupThisReference() |
| { |
| auto new_data = new ubyte[data.length * 2]; |
| data = new_data; |
| } |
| } |
| |
| static m12110 = Uint24Array12110([0x80]); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=12310 |
| // heap allocation for built-in sclar types |
| |
| bool test12310() |
| { |
| auto p1 = new int, p2 = p1; |
| assert(*p1 == 0); |
| assert(*p2 == 0); |
| *p1 = 10; |
| assert(*p1 == 10); |
| assert(*p2 == 10); |
| |
| auto q1 = new int(3), q2 = q1; |
| assert(*q1 == 3); |
| assert(*q2 == 3); |
| *q1 = 20; |
| assert(*q1 == 20); |
| assert(*q2 == 20); |
| |
| return true; |
| } |
| static assert(test12310()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=12499 |
| // initialize TupleDeclaraion in CTFE |
| |
| auto f12499() |
| { |
| //Initialize 3 ints to 5. |
| TypeTuple!(int, int, int) a = 5; |
| return a[0]; //Error: variable _a_field_0 cannot be read at compile time |
| } |
| static assert(f12499() == 5); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=12602 |
| // slice in struct literal members |
| |
| struct Result12602 |
| { |
| uint[] source; |
| } |
| |
| auto wrap12602a(uint[] r) |
| { |
| return Result12602(r); |
| } |
| |
| auto wrap12602b(uint[] r) |
| { |
| Result12602 x; |
| x.source = r; |
| return x; |
| } |
| |
| auto testWrap12602a() |
| { |
| uint[] dest = [1, 2, 3, 4]; |
| |
| auto ra = wrap12602a(dest[0 .. 2]); |
| auto rb = wrap12602a(dest[2 .. 4]); |
| |
| foreach (i; 0 .. 2) |
| rb.source[i] = ra.source[i]; |
| |
| assert(ra.source == [1,2]); |
| assert(rb.source == [1,2]); |
| assert(&ra.source[0] == &dest[0]); |
| assert(&rb.source[0] == &dest[2]); |
| assert(dest == [1,2,1,2]); |
| return dest; |
| } |
| |
| auto testWrap12602b() |
| { |
| uint[] dest = [1, 2, 3, 4]; |
| |
| auto ra = wrap12602b(dest[0 .. 2]); |
| auto rb = wrap12602b(dest[2 .. 4]); |
| |
| foreach (i; 0 .. 2) |
| rb.source[i] = ra.source[i]; |
| |
| assert(ra.source == [1,2]); |
| assert(rb.source == [1,2]); |
| assert(&ra.source[0] == &dest[0]); |
| assert(&rb.source[0] == &dest[2]); |
| assert(dest == [1,2,1,2]); |
| return dest; |
| } |
| |
| auto testWrap12602c() |
| { |
| uint[] dest = [1, 2, 3, 4]; |
| |
| auto ra = Result12602(dest[0 .. 2]); |
| auto rb = Result12602(dest[2 .. 4]); |
| |
| foreach (i; 0 .. 2) |
| rb.source[i] = ra.source[i]; |
| |
| assert(ra.source == [1,2]); |
| assert(rb.source == [1,2]); |
| assert(&ra.source[0] == &dest[0]); |
| assert(&rb.source[0] == &dest[2]); |
| assert(dest == [1,2,1,2]); |
| return dest; |
| } |
| |
| auto testWrap12602d() |
| { |
| uint[] dest = [1, 2, 3, 4]; |
| |
| Result12602 ra; ra.source = dest[0 .. 2]; |
| Result12602 rb; rb.source = dest[2 .. 4]; |
| |
| foreach (i; 0 .. 2) |
| rb.source[i] = ra.source[i]; |
| |
| assert(ra.source == [1,2]); |
| assert(rb.source == [1,2]); |
| assert(&ra.source[0] == &dest[0]); |
| assert(&rb.source[0] == &dest[2]); |
| assert(dest == [1,2,1,2]); |
| return dest; |
| } |
| |
| static assert(testWrap12602a() == [1,2,1,2]); |
| static assert(testWrap12602b() == [1,2,1,2]); |
| static assert(testWrap12602c() == [1,2,1,2]); |
| static assert(testWrap12602d() == [1,2,1,2]); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=12677 |
| // class type initializing from DotVarExp |
| |
| final class C12677 |
| { |
| TypeTuple!(Object, int[]) _test; |
| this() |
| { |
| auto t0 = _test[0]; // |
| auto t1 = _test[1]; // |
| assert(t0 is null); |
| assert(t1 is null); |
| } |
| } |
| |
| struct S12677 |
| { |
| auto f = new C12677(); |
| } |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=12851 |
| // interpret function local const static array |
| |
| void test12851() |
| { |
| const int[5] arr; |
| alias staticZip = TypeTuple!(arr[0]); |
| } |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=13630 |
| // indexing and setting array element via pointer |
| |
| struct S13630(T) |
| { |
| T[3] arr; |
| |
| this(A...)(auto ref in A args) |
| { |
| auto p = arr.ptr; |
| |
| foreach (ref v; args) |
| { |
| *p = 0; |
| } |
| } |
| } |
| |
| enum s13630 = S13630!float(1); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=13827 |
| |
| struct Matrix13827(T, uint N) |
| { |
| private static defaultMatrix() |
| { |
| T[N] arr; |
| return arr; |
| } |
| |
| union |
| { |
| T[N] A = defaultMatrix; |
| T[N] flat; |
| } |
| |
| this(A...)(auto ref in A args) |
| { |
| uint k; |
| |
| foreach (ref v; args) |
| flat[k++] = cast(T)v; |
| } |
| } |
| enum m13827 = Matrix13827!(int, 3)(1, 2, 3); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=13847 |
| // support DotTypeExp |
| |
| class B13847 |
| { |
| int foo() { return 1; } |
| } |
| |
| class C13847 : B13847 |
| { |
| override int foo() { return 2; } |
| |
| final void test(int n) |
| { |
| assert(foo() == n); |
| assert(B13847.foo() == 1); |
| assert(C13847.foo() == 2); |
| assert(this.B13847.foo() == 1); |
| assert(this.C13847.foo() == 2); |
| } |
| } |
| |
| class D13847 : C13847 |
| { |
| override int foo() { return 3; } |
| } |
| |
| static assert({ |
| C13847 c = new C13847(); |
| c.test(2); |
| assert(c.B13847.foo() == 1); |
| assert(c.C13847.foo() == 2); |
| |
| D13847 d = new D13847(); |
| d.test(3); |
| assert(d.B13847.foo() == 1); |
| assert(d.C13847.foo() == 2); |
| assert(d.D13847.foo() == 3); |
| |
| c = d; |
| c.test(3); |
| assert(c.B13847.foo() == 1); |
| assert(c.C13847.foo() == 2); |
| return true; |
| }()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=12495 |
| // cast from string to immutable(ubyte)[] |
| |
| string getStr12495() |
| { |
| char[1] buf = void; // dummy starting point. |
| string s = cast(string)buf[0..0]; // empty slice, .ptr points mutable. |
| assert(buf.ptr == s.ptr); |
| s ~= 'a'; // this should allocate. |
| assert(buf.ptr != s.ptr); |
| return s.idup; // this should allocate again, and |
| // definitely point immutable memory. |
| } |
| auto indexOf12495(string s) |
| { |
| auto p1 = s.ptr; |
| auto p2 = (cast(immutable(ubyte)[])s).ptr; |
| assert(cast(void*)p1 == cast(void*)p2); // OK <- fails |
| return cast(void*)p2 - cast(void*)p1; // OK <- "cannot subtract pointers ..." |
| } |
| static assert(indexOf12495(getStr12495()) == 0); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=13992 |
| // Repainting pointer arithmetic result |
| |
| enum hash13992 = hashOf13992("abcd".ptr); |
| |
| @trusted hashOf13992(const void* buf) |
| { |
| auto data = cast(const(ubyte)*) buf; |
| size_t hash; |
| data += 2; // problematic pointer arithmetic |
| hash += *data; // CTFE internal issue was shown by the dereference |
| return hash; |
| } |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=13739 |
| // Precise copy for ArrayLiteralExp elements |
| |
| static assert( |
| { |
| int[] a1 = [13]; |
| int[][] a2 = [a1]; |
| assert(a2[0] is a1); // OK |
| assert(a2[0].ptr is a1.ptr); // OK <- NG |
| |
| a1[0] = 1; |
| assert(a2[0][0] == 1); // OK <- NG |
| |
| a2[0][0] = 2; |
| assert(a1[0] == 2); // OK <- NG |
| |
| return 1; |
| }()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=14463 |
| // ICE on slice assignment without postblit |
| |
| struct Boo14463 |
| { |
| private int[1] c; |
| this(int[] x) |
| { |
| c = x; |
| } |
| } |
| immutable Boo14463 a14463 = Boo14463([1]); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=13295 |
| // Don't copy struct literal in VarExp::interpret() |
| |
| struct S13295 |
| { |
| int n; |
| } |
| |
| void f13295(ref const S13295 s) |
| { |
| *cast(int*) &s.n = 1; |
| assert(s.n == 1); // OK <- fail |
| } |
| |
| static assert( |
| { |
| S13295 s; |
| f13295(s); |
| return s.n == 1; // true <- false |
| }()); |
| |
| int foo14061(int[] a) |
| { |
| foreach (immutable x; a) |
| { |
| auto b = a ~ x; |
| return b == [1, 1]; |
| } |
| return 0; |
| } |
| static assert(foo14061([1])); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=14024 |
| // CTFE version |
| |
| bool test14024() |
| { |
| string op; |
| |
| struct S |
| { |
| char x = 'x'; |
| this(this) { op ~= x-0x20; } // upper case |
| ~this() { op ~= x; } // lower case |
| } |
| |
| S[4] mem; |
| ref S[2] slice(int a, int b) { return mem[a .. b][0 .. 2]; } |
| |
| op = null; |
| mem[0].x = 'a'; |
| mem[1].x = 'b'; |
| mem[2].x = 'x'; |
| mem[3].x = 'y'; |
| slice(0, 2) = slice(2, 4); // [ab] = [xy] |
| assert(op == "XaYb", op); |
| |
| op = null; |
| mem[0].x = 'x'; |
| mem[1].x = 'y'; |
| mem[2].x = 'a'; |
| mem[3].x = 'b'; |
| slice(2, 4) = slice(0, 2); // [ab] = [xy] |
| assert(op == "XaYb", op); |
| |
| op = null; |
| mem[0].x = 'a'; |
| mem[1].x = 'b'; |
| mem[2].x = 'c'; |
| slice(0, 2) = slice(1, 3); // [ab] = [bc] |
| assert(op == "BaCb", op); |
| |
| op = null; |
| mem[0].x = 'x'; |
| mem[1].x = 'y'; |
| mem[2].x = 'z'; |
| slice(1, 3) = slice(0, 2); // [yz] = [xy] |
| assert(op == "YzXy", op); |
| |
| return true; |
| } |
| static assert(test14024()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=14304 |
| // cache of static immutable value |
| |
| immutable struct Bug14304 |
| { |
| string s_name; |
| alias s_name this; |
| |
| string fun()() |
| { |
| return "fun"; |
| } |
| } |
| class Buggy14304 |
| { |
| static string fun(string str)() |
| { |
| return str; |
| } |
| static immutable val = immutable Bug14304("val"); |
| } |
| void test14304() |
| { |
| enum kt = Buggy14304.fun!(Buggy14304.val); |
| static assert(kt == "val"); |
| enum bt = Buggy14304.val.fun(); |
| static assert(bt == "fun"); |
| } |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=14371 |
| // evaluate BinAssignExp as lvalue |
| |
| int test14371() |
| { |
| int x; |
| ++(x += 1); |
| return x; |
| } |
| static assert(test14371() == 2); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=7151 |
| // [CTFE] cannot compare classes with == |
| |
| bool test7151() |
| { |
| auto a = new Object; |
| return a == a && a != new Object; |
| } |
| static assert(test7151()); |
| |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=12603 |
| // [CTFE] goto does not correctly call dtors |
| |
| struct S12603 |
| { |
| this(uint* dtorCalled) |
| { |
| *dtorCalled = 0; |
| this.dtorCalled = dtorCalled; |
| } |
| |
| @disable this(); |
| |
| ~this() |
| { |
| ++*dtorCalled; |
| } |
| |
| uint* dtorCalled; |
| } |
| |
| |
| auto numDtorCallsByGotoWithinScope() |
| { |
| uint dtorCalled; |
| { |
| S12603 s = S12603(&dtorCalled); |
| assert(dtorCalled == 0); |
| goto L_abc; |
| L_abc: |
| assert(dtorCalled == 0); |
| } |
| assert(dtorCalled == 1); |
| return dtorCalled; |
| } |
| static assert(numDtorCallsByGotoWithinScope() == 1); |
| |
| |
| auto numDtorCallsByGotoOutOfScope() |
| { |
| uint dtorCalled; |
| { |
| S12603 s = S12603(&dtorCalled); |
| assert(dtorCalled == 0); |
| goto L_abc; |
| } |
| L_abc: |
| assert(dtorCalled == 1); |
| return dtorCalled; |
| } |
| static assert(numDtorCallsByGotoOutOfScope() == 1); |
| |
| |
| uint numDtorCallsByGotoDifferentScopeAfter() |
| { |
| uint dtorCalled; |
| { |
| S12603 s = S12603(&dtorCalled); |
| assert(dtorCalled == 0); |
| } |
| assert(dtorCalled == 1); |
| goto L_abc; |
| L_abc: |
| assert(dtorCalled == 1); |
| return dtorCalled; |
| } |
| static assert(numDtorCallsByGotoDifferentScopeAfter() == 1); |
| |
| |
| auto numDtorCallsByGotoDifferentScopeBefore() |
| { |
| uint dtorCalled; |
| assert(dtorCalled == 0); |
| goto L_abc; |
| L_abc: |
| assert(dtorCalled == 0); |
| { |
| S12603 s = S12603(&dtorCalled); |
| assert(dtorCalled == 0); |
| } |
| assert(dtorCalled == 1); |
| return dtorCalled; |
| } |
| static assert(numDtorCallsByGotoDifferentScopeBefore() == 1); |
| |
| |
| struct S12603_2 |
| { |
| ~this() |
| { |
| dtorCalled = true; |
| } |
| |
| bool dtorCalled = false; |
| } |
| |
| auto structInCaseScope() |
| { |
| auto charsets = S12603_2(); |
| switch(1) |
| { |
| case 0: |
| auto set = charsets; |
| break; |
| default: |
| break; |
| } |
| return charsets.dtorCalled; |
| } |
| |
| static assert(!structInCaseScope()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=15233 |
| // ICE in TupleExp, Copy On Write bug |
| |
| alias TT15233(stuff ...) = stuff; |
| |
| struct Tok15233 {} |
| enum tup15233 = TT15233!(Tok15233(), "foo"); |
| static assert(tup15233[0] == Tok15233()); |
| static assert(tup15233[1] == "foo"); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=15251 |
| // void cast in ForStatement.increment |
| |
| int test15251() |
| { |
| for (ubyte lwr = 19; |
| lwr != 20; |
| cast(void)++lwr) // have to to be evaluated with CTFEGoal.Nothing |
| {} |
| return 1; |
| } |
| static assert(test15251()); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=15998 |
| // Sagfault caused by memory corruption |
| |
| immutable string[2] foo15998 = ["",""]; |
| immutable string[2][] bar15998a = foo15998 ~ baz15998; |
| immutable string[2][] bar15998b = baz15998 ~ foo15998; |
| |
| auto baz15998() |
| { |
| immutable(string[2])[] r; |
| return r; |
| } |
| |
| static assert(bar15998a == [["", ""]]); |
| static assert(bar15998b == [["", ""]]); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=16094 |
| // Non-overlapped slice assignment on an aggregate |
| |
| char[] f16094a() |
| { |
| char[] x = new char[](6); |
| x[3..6] = x[0..3]; |
| return x; |
| } |
| |
| int[] f16094b() |
| { |
| int[] x = new int[](6); |
| x[3..6] = x[0..3]; |
| return x; |
| } |
| |
| enum copy16094a = f16094a(); |
| enum copy16094b = f16094b(); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=17407 |
| |
| bool foo17407() |
| { |
| void delegate ( ) longest_convert; |
| return __traits(compiles, longest_convert = &doesNotExists); |
| } |
| |
| static assert(!foo17407); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=18057 |
| // Recursive field initializer causes segfault. |
| |
| struct RBNode(T) |
| { |
| RBNode!T *copy = new RBNode!T; |
| } |
| |
| static assert(!__traits(compiles, { alias bug18057 = RBNode!int; })); |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=19140 |
| |
| void test19140() |
| { |
| real f19140(); |
| static if (__traits(compiles, (){ enum real r = f19140(); })) {} |
| } |
| |
| /**************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=19074 |
| |
| struct S19074a { } |
| |
| struct S19074b |
| { |
| S19074a field; |
| this(S19074a) { } |
| |
| static const S19074b* data = new S19074b(S19074a()); |
| } |
| |
| void test19074() |
| { |
| auto var = S19074b.data; |
| } |
| |
| /************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=19447 |
| |
| bool f19447() |
| { |
| int[3] c=1; |
| assert(c[0]==1); |
| g19447(c[0..2]); |
| assert(c[0]!=1); //fails |
| assert(c[0]==2); |
| return true; |
| } |
| void g19447(ref int[2] a) |
| { |
| int[2] b=2; |
| a=b; |
| //a[]=b; // works |
| //a[] = b[]; // works |
| assert(a[0]==2); |
| } |
| static assert(f19447()); |
| |
| /***/ |
| |
| char[] mangle19447(char[] dst) |
| { |
| dst.length = 10; |
| size_t i = "_D".length; |
| dst[0 .. i] = "_D"; |
| return dst; |
| } |
| |
| static char[] x19447 = mangle19447(null); |
| |
| /***/ |
| enum KindEnum |
| { |
| integer, |
| arrayOf |
| } |
| |
| struct FullKind |
| { |
| KindEnum[] contents; |
| |
| this(KindEnum ) { opAssign; } |
| |
| this(KindEnum , FullKind contentKind) |
| { |
| contents = contentKind.contents; |
| } |
| |
| void opAssign() |
| { |
| contents = []; |
| } |
| } |
| |
| enum fk = FullKind(KindEnum.integer); |
| enum fk2 = FullKind(KindEnum.arrayOf, fk); |
| |
| /************************************************/ |
| // https://issues.dlang.org/show_bug.cgi?id=9937 |
| |
| int test9937() |
| { |
| import core.math; |
| |
| float x = float.max; |
| x *= 2; |
| x = toPrec!float(x); |
| x /= 2; |
| assert(x == float.infinity); |
| return 1; |
| } |
| |
| static assert(test9937()); |
| |
| /************************************************/ |
| // static array .tupleof |
| |
| struct SArrayTupleEquiv(T) |
| { |
| T f1; |
| T f2; |
| } |
| |
| // basic .tupleof invariants |
| bool testSArrayTupleA() |
| { |
| int[2] xs; |
| assert(xs.tupleof == TypeTuple!(0, 0)); |
| assert(xs.tupleof == (cast(int[2])[0, 0]).tupleof); |
| |
| xs.tupleof = TypeTuple!(1, 2); |
| assert(xs.tupleof == TypeTuple!(1, 2)); |
| |
| auto ys = SArrayTupleEquiv!int(1, 2); |
| assert(xs.tupleof == ys.tupleof); |
| |
| return true; |
| } |
| static assert(testSArrayTupleA()); |
| |
| // tuples with side effects |
| bool testSArrayTupleB() |
| { |
| // Counter records lifetime events in copies/dtors, as a cheap way to check that .tupleof for |
| // static arrays exhibit all the same side effects as an equivalent struct's .tupleof |
| int[int] copies; |
| int[int] dtors; |
| struct Counter |
| { |
| int id = -1; |
| |
| this(this) |
| { |
| copies[id] = copies.get(id, 0) + 1; |
| } |
| |
| ~this() |
| { |
| dtors[id] = dtors.get(id, 0) + 1; |
| } |
| } |
| |
| void consume(Counter, Counter) {} |
| Counter[2] produce(int id1, int id2) |
| { |
| return [Counter(id1), Counter(id2)]; |
| } |
| |
| // first sample expected behavior from struct .tupleof |
| // braces create a subscope, shortening lifetimes |
| { |
| auto a = SArrayTupleEquiv!Counter(Counter(0), Counter(1)); |
| |
| typeof(a) b; |
| b.tupleof = a.tupleof; |
| |
| Counter x, y; |
| TypeTuple!(x, y) = a.tupleof; |
| |
| a.tupleof[0] = Counter(2); |
| a.tupleof[1] = Counter(3); |
| consume(a.tupleof); |
| |
| a.tupleof = produce(4, 5).tupleof; |
| } |
| int[int][2] expected = [copies.dup, dtors.dup]; |
| copies = null; // .clear is not CTFE friendly |
| dtors = null; |
| |
| // the real test -- sample behavior of array .tupleof |
| { |
| Counter[2] a = [Counter(0), Counter(1)]; |
| |
| typeof(a) b; |
| b.tupleof = a.tupleof; |
| |
| Counter x, y; |
| TypeTuple!(x, y) = a.tupleof; |
| |
| a.tupleof[0] = Counter(2); |
| a.tupleof[1] = Counter(3); |
| consume(a.tupleof); |
| |
| a.tupleof = produce(4, 5).tupleof; |
| } |
| assert(expected[0] == copies); |
| assert(expected[1] == dtors); |
| |
| return true; |
| } |
| static assert(testSArrayTupleB()); |