mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 13:10:12 +03:00
380 lines
8.4 KiB
D
380 lines
8.4 KiB
D
/*
|
|
REQUIRED_ARGS: -checkaction=context -preview=dip1000
|
|
PERMUTE_ARGS: -O -g -inline
|
|
*/
|
|
|
|
void test8765()
|
|
{
|
|
string msg;
|
|
try
|
|
{
|
|
int a = 0;
|
|
assert(a);
|
|
}
|
|
catch (Throwable e)
|
|
{
|
|
// no-message -> assert expression
|
|
msg = e.msg;
|
|
}
|
|
assert(msg == "0 != true");
|
|
}
|
|
|
|
void test9255()
|
|
{
|
|
string file;
|
|
try
|
|
{
|
|
int x = 0;
|
|
assert(x);
|
|
}
|
|
catch (Throwable e)
|
|
{
|
|
file = e.file;
|
|
}
|
|
|
|
version(Windows)
|
|
assert(file && file == r"runnable\testassert.d");
|
|
else
|
|
assert(file && file == "runnable/testassert.d");
|
|
}
|
|
|
|
// https://issues.dlang.org/show_bug.cgi?id=20114
|
|
void test20114()
|
|
{
|
|
// Function call returning simple type
|
|
static int fun() {
|
|
static int i = 0;
|
|
assert(i++ == 0);
|
|
return 3;
|
|
}
|
|
|
|
const a = getMessage(assert(fun() == 4));
|
|
assert(a == "3 != 4");
|
|
|
|
// Function call returning complex type with opEquals
|
|
static struct S
|
|
{
|
|
bool opEquals(const int x) const
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
static S bar()
|
|
{
|
|
static int i = 0;
|
|
assert(i++ == 0);
|
|
return S.init;
|
|
}
|
|
|
|
const b = getMessage(assert(bar() == 4));
|
|
assert(b == "S() != 4");
|
|
|
|
// Non-call expression with side effects
|
|
int i = 0;
|
|
const c = getMessage(assert(++i == 0));
|
|
assert(c == "1 != 0");
|
|
}
|
|
|
|
version (DigitalMars) version (Win64) version = DMD_Win64;
|
|
|
|
void test20375() @safe
|
|
{
|
|
static struct RefCounted
|
|
{
|
|
// Force temporary through "impure" generator function
|
|
static RefCounted create() @trusted
|
|
{
|
|
__gshared int counter = 0;
|
|
return RefCounted(++counter > 0);
|
|
}
|
|
|
|
static int instances;
|
|
static int postblits;
|
|
|
|
this(bool) @safe
|
|
{
|
|
instances++;
|
|
}
|
|
|
|
this(this) @safe
|
|
{
|
|
instances++;
|
|
postblits++;
|
|
}
|
|
|
|
~this() @safe
|
|
{
|
|
// make the dtor non-nothrow (we are tracking clean-ups during AssertError unwinding)
|
|
if (postblits > 100)
|
|
throw new Exception("");
|
|
assert(instances > 0);
|
|
instances--;
|
|
}
|
|
|
|
bool opEquals(RefCounted) @safe
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
{
|
|
auto a = RefCounted.create();
|
|
RefCounted.instances++; // we're about to construct an instance below, increment manually
|
|
assert(a == RefCounted()); // both operands are pure expressions => no temporaries
|
|
}
|
|
|
|
assert(RefCounted.instances == 0);
|
|
assert(RefCounted.postblits == 0);
|
|
|
|
{
|
|
auto a = RefCounted.create();
|
|
assert(a == RefCounted.create()); // impure rhs is promoted to a temporary lvalue => copy for a.opEquals(rhs)
|
|
}
|
|
|
|
assert(RefCounted.instances == 0);
|
|
assert(RefCounted.postblits == 1);
|
|
RefCounted.postblits = 0;
|
|
|
|
{
|
|
const msg = getMessage(assert(RefCounted.create() != RefCounted.create())); // both operands promoted to temporary lvalues
|
|
assert(msg == "RefCounted() == RefCounted()");
|
|
}
|
|
|
|
version (DMD_Win64) // FIXME: temporaries apparently not destructed when unwinding via AssertError
|
|
{
|
|
assert(RefCounted.instances >= 0 && RefCounted.instances <= 2);
|
|
RefCounted.instances = 0;
|
|
}
|
|
else
|
|
assert(RefCounted.instances == 0);
|
|
assert(RefCounted.postblits == 1);
|
|
RefCounted.postblits = 0;
|
|
|
|
static int numGetLvalImpureCalls = 0;
|
|
ref RefCounted getLvalImpure() @trusted
|
|
{
|
|
numGetLvalImpureCalls++;
|
|
__gshared lval = RefCounted(); // not incrementing RefCounted.instances
|
|
return lval;
|
|
}
|
|
|
|
{
|
|
const msg = getMessage(assert(getLvalImpure() != getLvalImpure())); // both operands promoted to ref temporaries
|
|
assert(msg == "RefCounted() == RefCounted()");
|
|
}
|
|
|
|
assert(numGetLvalImpureCalls == 2);
|
|
assert(RefCounted.instances == 0);
|
|
assert(RefCounted.postblits == 1);
|
|
RefCounted.postblits = 0;
|
|
}
|
|
|
|
// https://issues.dlang.org/show_bug.cgi?id=21471
|
|
void test21471()
|
|
{
|
|
{
|
|
static struct S
|
|
{
|
|
S get()() const { return this; }
|
|
}
|
|
|
|
static auto f(S s) { return s; }
|
|
|
|
auto s = S();
|
|
assert(f(s.get) == s);
|
|
}
|
|
{
|
|
pragma(inline, true)
|
|
real exp(real x) pure nothrow
|
|
{
|
|
return x;
|
|
}
|
|
|
|
bool isClose(int lhs, real rhs) pure nothrow
|
|
{
|
|
return false;
|
|
}
|
|
auto c = 0;
|
|
assert(!isClose(c, exp(1)));
|
|
}
|
|
}
|
|
|
|
// https://issues.dlang.org/show_bug.cgi?id=20581
|
|
void test20581() @safe
|
|
{
|
|
static auto retro(return scope int[] s) @safe
|
|
{
|
|
static struct R
|
|
{
|
|
int[] source;
|
|
}
|
|
return R(s);
|
|
}
|
|
|
|
int[5] a = [ 1, 2, 3, 4, 5 ];
|
|
// Creates ref temporary __assertTmpXXXX for source
|
|
// Error: address of variable a assigned to __assertOp27 with longer lifetime
|
|
assert(retro(a[]).source is a[]);
|
|
}
|
|
|
|
string getMessage(T)(lazy T expr) @trusted
|
|
{
|
|
try
|
|
{
|
|
expr();
|
|
return null;
|
|
}
|
|
catch (Throwable t)
|
|
{
|
|
return t.msg;
|
|
}
|
|
}
|
|
|
|
void testMixinExpression() @safe
|
|
{
|
|
static struct S
|
|
{
|
|
bool opEquals(S) @safe { return true; }
|
|
}
|
|
|
|
const msg = getMessage(assert(mixin("S() != S()")));
|
|
assert(msg == "S() == S()");
|
|
}
|
|
|
|
void testUnaryFormat()
|
|
{
|
|
int zero = 0, one = 1;
|
|
assert(getMessage(assert(zero)) == "0 != true");
|
|
assert(getMessage(assert(!one)) == "1 == true");
|
|
|
|
assert(getMessage(assert(!cast(int) 1.5)) == "1 == true");
|
|
|
|
assert(getMessage(assert(!!__ctfe)) == "assert(__ctfe) failed!");
|
|
|
|
static struct S
|
|
{
|
|
int i;
|
|
bool opCast() const
|
|
{
|
|
return i < 2;
|
|
}
|
|
}
|
|
|
|
assert(getMessage(assert(S(4))) == "S(4) != true");
|
|
|
|
S s = S(4);
|
|
assert(getMessage(assert(*&s)) == "S(4) != true");
|
|
|
|
assert(getMessage(assert(--(++zero))) == "0 != true");
|
|
}
|
|
|
|
void testAssignments()
|
|
{
|
|
int a = 1;
|
|
int b = 2;
|
|
assert(getMessage(assert(a -= --b)) == "0 != true");
|
|
|
|
static ref int c()
|
|
{
|
|
static int counter;
|
|
counter++;
|
|
return counter;
|
|
}
|
|
|
|
assert(getMessage(assert(--c())) == "0 != true");
|
|
}
|
|
|
|
/// https://issues.dlang.org/show_bug.cgi?id=21472
|
|
void testTupleFormat()
|
|
{
|
|
alias AliasSeq(T...) = T;
|
|
|
|
// Default usage
|
|
{
|
|
alias a = AliasSeq!(1, "ab");
|
|
alias b = AliasSeq!(false, "xyz");
|
|
assert(getMessage(assert(a == b)) == `(1, "ab") != (false, "xyz")`);
|
|
}
|
|
|
|
// Single elements work but are not formatted as tuples
|
|
// Is this acceptable? (a workaround would probably require a
|
|
// different name for the tuple formatting hook)
|
|
{
|
|
alias a = AliasSeq!(1, "ab", []);
|
|
alias b = AliasSeq!(false, "xyz", [1]);
|
|
assert(getMessage(assert(a == b)) == `(1, "ab", []) != (false, "xyz", [1])`);
|
|
}
|
|
|
|
// Also works with tupleof (as taken from the bug report)
|
|
{
|
|
static struct Var { int a, b; }
|
|
const a = Var(1, 2);
|
|
const b = Var(3, 4);
|
|
const msg = getMessage(assert(a.tupleof == b.tupleof));
|
|
assert(msg == `(1, 2) != (3, 4)`);
|
|
}
|
|
|
|
// Also works when creating temporaries for the TupleExp
|
|
{
|
|
static struct S
|
|
{
|
|
int a, b;
|
|
}
|
|
|
|
static S get()
|
|
{
|
|
static int i;
|
|
return S(i++, i++);
|
|
}
|
|
|
|
auto a = get().tupleof;
|
|
auto b = get().tupleof;
|
|
|
|
string msg = getMessage(assert(a == b));
|
|
assert(msg == `(0, 1) != (2, 3)`);
|
|
|
|
msg = getMessage(assert(get().tupleof == AliasSeq!(2, 3)));
|
|
assert(msg == `(4, 5) != (2, 3)`);
|
|
|
|
msg = getMessage(assert(get().tupleof == get().tupleof));
|
|
assert(msg == `(6, 7) != (8, 9)`);
|
|
}
|
|
}
|
|
|
|
// https://issues.dlang.org/show_bug.cgi?id=21682
|
|
void testStaticOperators()
|
|
{
|
|
static class environment {
|
|
static bool opCmp(scope const(char)[] name)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
static bool opBinaryRight(string op : "in")(scope const(char)[] name)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
string msg = getMessage(assert(environment < "Hello"));
|
|
assert(msg == `"environment" >= "Hello"`);
|
|
|
|
msg = getMessage(assert("Hello" in environment));
|
|
assert(msg == `"Hello" !in "environment"`);
|
|
}
|
|
|
|
void main()
|
|
{
|
|
test8765();
|
|
test9255();
|
|
test20114();
|
|
test20375();
|
|
test21471();
|
|
test20581();
|
|
testMixinExpression();
|
|
testUnaryFormat();
|
|
testAssignments();
|
|
testTupleFormat();
|
|
testStaticOperators();
|
|
}
|