blob: 8926fbd6aa75d61b5e20e3072fe9ef2a9d990c8c [file] [log] [blame]
/* REQUIRED_ARGS: -preview=dip1000 -preview=in -mcpu=native
*/
import core.stdc.time;
void fun(in int* inParam) @safe;
static assert([__traits(getParameterStorageClasses, fun, 0)] == ["in"]);
static assert (is(typeof(fun) P == __parameters) && is(P[0] == const int*));
struct Foo
{
int a;
double[100] b;
}
void fun2(in Foo inParam) @safe;
static assert([__traits(getParameterStorageClasses, fun2, 0)] == ["in"]);
static assert (is(typeof(fun2) P == __parameters) && is(P[0] == const Foo));
void test()
{
withDefaultValue(42);
withDefaultValue();
withDefaultRef(TimeRef.init);
withDefaultRef();
withInitDefaultValue();
withInitDefaultRef();
}
struct FooBar
{
string toString() const
{
string result;
// Type is const
this.toString((in char[] buf) {
static assert(is(typeof(buf) == const(char[])));
result ~= buf;
});
// Type inference works
this.toString((in buf) { result ~= buf; });
return result;
}
void toString(scope void delegate(in char[]) sink) const
{
sink("Hello world");
}
}
// Ensure that default parameter works even if non CTFEable
void withDefaultValue(in time_t currTime = time(null)) {}
struct TimeRef { time_t now; ulong[4] bloat; }
void withDefaultRef(in TimeRef currTime = TimeRef(time(null))) {}
// Ensure that default parameters work with `.init`
void withInitDefaultValue(in size_t defVal = size_t.init) {}
void withInitDefaultRef(in TimeRef defVal = TimeRef.init) {}
// Ensure that temporary aren't needlessly created
// (if they are, it'll trigger the "goto skips declaration" error)
void checkNotIdentity(in void* p1, in void* p2) { assert(p1 !is p2); }
void checkTemporary()
{
int* p = new int;
if (p is null)
goto LError;
// Should not generate temporary, pass the pointers by value
checkNotIdentity(/*lvalue*/ p, /*rvalue*/ null);
checkNotIdentity(new int, null);
LError:
assert(0);
}
// Some ABI-specific tests:
version (Win64)
{
void checkReal(in real p)
{
// ref for x87 real, value for double-precision real
static assert(__traits(isRef, p) == (real.sizeof > 8));
}
struct RGB { ubyte r, g, b; }
void checkNonPowerOf2(in RGB p)
{
static assert(__traits(isRef, p));
}
}
else version (X86_64) // Posix x86_64
{
struct Empty {} // 1 dummy byte passed on the stack
void checkEmptyStruct(in Empty p)
{
static assert(!__traits(isRef, p));
}
static if (is(__vector(double[4])))
{
struct AvxVectorWrapper { __vector(double[4]) a; } // 256 bits
void checkAvxVector(in AvxVectorWrapper p)
{
static assert(!__traits(isRef, p));
}
}
}
else version (AArch64)
{
alias HVA = __vector(float[4])[4]; // can be passed in 4 vector registers
void checkHVA(in HVA p)
{
static assert(!__traits(isRef, p));
}
}