/* 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)); } }