// PERMUTE_ARGS: -inline
// REQUIRED_ARGS: -verrors=simple
/*
TEST_OUTPUT:
---
compilable/interpret3.d(6351): 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(("" ~ "\&copy;"[0]).length == 1);
const char[] null5722 = null;
static assert((null5722 ~ "\&copy;"[0]).length == 1);
static assert(("\&copy;"[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;
}

enum 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;
}

enum 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)
    {
        this.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...)(const auto ref 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...)(const auto ref 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());
