/*
REQUIRED_ARGS: -HC -c -o-
PERMUTE_ARGS:
TEST_OUTPUT:
---
// Automatically generated by Digital Mars D Compiler

#pragma once

#include <assert.h>
#include <math.h>
#include <stddef.h>
#include <stdint.h>

#ifdef CUSTOM_D_ARRAY_TYPE
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
#else
/// Represents a D [] array
template<typename T>
struct _d_dynamicArray final
{
    size_t length;
    T *ptr;

    _d_dynamicArray() : length(0), ptr(NULL) { }

    _d_dynamicArray(size_t length_in, T *ptr_in)
        : length(length_in), ptr(ptr_in) { }

    T& operator[](const size_t idx) {
        assert(idx < length);
        return ptr[idx];
    }

    const T& operator[](const size_t idx) const {
        assert(idx < length);
        return ptr[idx];
    }
};
#endif

struct S final
{
    int8_t a;
    int32_t b;
    int64_t c;
    _d_dynamicArray< int32_t > arr;
private:
    ~S();
public:
    S() :
        a(),
        b(),
        c(),
        arr()
    {
    }
    S(int8_t a, int32_t b = 0, int64_t c = 0LL, _d_dynamicArray< int32_t > arr = {}) :
        a(a),
        b(b),
        c(c),
        arr(arr)
        {}
};

struct S2 final
{
    int32_t a;
    int32_t b;
    int64_t c;
    S d;
    S2(int32_t a);
    S2(char ) = delete;
    S2() :
        a(42),
        b(),
        c()
    {
    }
};

struct S3 final
{
    int32_t a;
    int32_t b;
    int64_t c;
    S3() :
        a(42),
        b(),
        c()
    {
    }
};

struct S4 final
{
    int32_t a;
    int64_t b;
    int32_t c;
    int8_t d;
    S4() :
        a(),
        b(),
        c(),
        d()
    {
    }
    S4(int32_t a, int64_t b = 0LL, int32_t c = 0, int8_t d = 0) :
        a(a),
        b(b),
        c(c),
        d(d)
        {}
};

#pragma pack(push, 1)
struct Aligned final
{
    int8_t a;
    int32_t b;
    int64_t c;
    Aligned(int32_t a);
    Aligned() :
        a(),
        b(),
        c()
    {
    }
};
#pragma pack(pop)

struct Null final
{
    void* field;
    Null() :
        field(nullptr)
    {
    }
    Null(void* field) :
        field(field)
        {}
};

struct A final
{
    int32_t a;
    S s;
    void baz(int32_t x = 42);
    struct
    {
        int32_t x;
        int32_t y;
    };
    union
    {
        int32_t u1;
        char u2[4$?:32=u|64=LLU$];
    };
    struct Inner final
    {
        int32_t x;
        Inner() :
            x()
        {
        }
        Inner(int32_t x) :
            x(x)
            {}
    };

    typedef Inner I;
    class C;

    A() :
        a(),
        s(),
        x(),
        y()
    {
    }
    A(int32_t a, S s = S(), int32_t x = 0, int32_t y = 0) :
        a(a),
        s(s),
        x(x),
        y(y)
        {}
};

union U
{
    int32_t i;
    char c;
};

struct Array final
{
    uint32_t length;
private:
    _d_dynamicArray< char > data;
    char smallarray[1$?:32=u|64=LLU$];
public:
    Array() :
        length(),
        data()
    {
    }
    Array(uint32_t length, _d_dynamicArray< char > data = {}) :
        length(length),
        data(data)
        {}
};

struct Params final
{
    bool obj;
    Array ddocfiles;
    Params() :
        obj(true),
        ddocfiles()
    {
    }
    Params(bool obj, Array ddocfiles = Array()) :
        obj(obj),
        ddocfiles(ddocfiles)
        {}
};
---
*/

/*
StructDeclaration has the following issues:
  * align different than 1 does nothing; we should support align(n), where `n` in [1, 2, 4, 8, 16]
  * align(n): inside struct definition doesn’t add alignment, but breaks generation of default ctors
*/

extern (C++) struct S
{
    byte a;
    int b;
    long c;
    int[] arr;
    extern(D) ~this() {}
}

extern (C++) struct S2
{
    int a = 42;
    int b;
    long c;
    S d = void;

    this(int a) {}
    extern(D) this(int, int, long) {}
    @disable this(char);
}

extern (C) struct S3
{
    int a = 42;
    int b;
    long c;

    this(int a) {}
}

extern (C) struct S4
{
    int a;
    long b;
    int c;
    byte d;
}

extern (C++) align(1) struct Aligned
{
    //align(1):
    byte a;
    int b;
    long c;

    this(int a) {}
}

extern (C++) struct Null
{
    void* field = null;
}

extern (C++) struct A
{
    int a;
    S s;

    extern (D) void foo();
    extern (C) void bar() {}
    extern (C++) void baz(int x = 42) {}

    struct
    {
        int x;
        int y;
    }

    union
    {
        int u1;
        char[4] u2;
    }

    struct Inner
    {
        int x;
    }

    alias I = Inner;

    extern(C++) class C;

}

extern(C++) union U
{
    int i;
    char c;
}

extern (C++) struct Array
{
    uint length;
private:
    char[] data;
    char[1] smallarray;
}

extern (C++) struct Params
{
    bool obj = true;
    Array ddocfiles;
}
