Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[enh] Issue 8765 - Assert should print expression when no message is present #1203

Closed
wants to merge 11 commits into from
Closed
4 changes: 2 additions & 2 deletions src/ctfeexpr.c
Original file line number Diff line number Diff line change
Expand Up @@ -815,8 +815,8 @@ Expression *paintFloatInt(Expression *fromVal, Type *to)
return new RealExp(fromVal->loc, ldouble(v.f), to);
}
}
else
assert(0);
assert(0);
return NULL; // avoid warning
}


Expand Down
28 changes: 14 additions & 14 deletions src/e2ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -2033,6 +2033,16 @@ elem *AssertExp::toElem(IRState *irs)
Type *t1 = e1->type->toBasetype();

//printf("AssertExp::toElem() %s\n", toChars());
OutBuffer buf;
if (msg)
buf.printf("assert(%s), %s", e1->toChars(), msg->toChars());
else
buf.writestring(toChars());

Expression * msgExpr = new StringExp(0, (char *)buf.extractData());
msgExpr = msgExpr->semantic(NULL);
msgExpr->type = Type::tchar->arrayOf();

if (global.params.useAssert)
{
e = e1->toElem(irs);
Expand Down Expand Up @@ -2077,10 +2087,7 @@ elem *AssertExp::toElem(IRState *irs)
FuncDeclaration *fd = irs->getFunc();
UnitTestDeclaration *ud = fd ? fd->isUnitTestDeclaration() : NULL;

/* If the source file name has changed, probably due
* to a #line directive.
*/
if (loc.filename && (msg || strcmp(loc.filename, mname) != 0))
if (loc.filename)
{
/* Cache values.
*/
Expand Down Expand Up @@ -2112,16 +2119,9 @@ elem *AssertExp::toElem(IRState *irs)
elem *efilename = (config.exe == EX_WIN64) ? el_ptr(assertexp_sfilename)
: el_var(assertexp_sfilename);

if (msg)
{ elem *emsg = eval_Darray(irs, msg, false);
ea = el_var(rtlsym[ud ? RTLSYM_DUNITTEST_MSG : RTLSYM_DASSERT_MSG]);
ea = el_bin(OPcall, TYvoid, ea, el_params(el_long(TYint, loc.linnum), efilename, emsg, NULL));
}
else
{
ea = el_var(rtlsym[ud ? RTLSYM_DUNITTEST : RTLSYM_DASSERT]);
ea = el_bin(OPcall, TYvoid, ea, el_param(el_long(TYint, loc.linnum), efilename));
}
elem *emsg = eval_Darray(irs, msgExpr, false);
ea = el_var(rtlsym[ud ? RTLSYM_DUNITTEST_MSG : RTLSYM_DASSERT_MSG]);
ea = el_bin(OPcall, TYvoid, ea, el_params(el_long(TYint, loc.linnum), efilename, emsg, NULL));
}
else
{
Expand Down
63 changes: 62 additions & 1 deletion src/mtype.c
Original file line number Diff line number Diff line change
Expand Up @@ -1300,7 +1300,7 @@ Type *Type::aliasthisOf()
{
FuncDeclaration *fd = (FuncDeclaration *)d;
Expression *ethis = this->defaultInit(0);
fd = fd->overloadResolve(0, ethis, NULL);
fd = fd->overloadResolve(0, ethis, NULL, 1);
if (fd)
{ TypeFunction *tf = (TypeFunction *)fd->type;
if (!tf->next && fd->inferRetType)
Expand Down Expand Up @@ -5828,6 +5828,67 @@ void TypeFunction::purityLevel()
}
}

/********************************************
* FIXME: This function is a workaround for fixing Bugzilla 9210.
* In 2.061, TypeFunction::purityLevel() improved to make more functions
* strong purity, but immutable conversion on return statemet had broken by that.
* Because, it is essentially unrelated to PUREstrong. This function is
* necessary to check the convertibility.
*/
bool TypeFunction::hasMutableIndirectionParams()
{
TypeFunction *tf = this;
size_t dim = Parameter::dim(tf->parameters);
for (size_t i = 0; i < dim; i++)
{
Parameter *fparam = Parameter::getNth(tf->parameters, i);
if (fparam->storageClass & STClazy)
{
return true;
}
if (fparam->storageClass & STCout)
{
return true;
}
if (!fparam->type)
continue;
if (fparam->storageClass & STCref)
{
if (!(fparam->type->mod & (MODconst | MODimmutable | MODwild)))
return true;
if (fparam->type->mod & MODconst)
return true;
}
Type *t = fparam->type->toBasetype();
if (!t->hasPointers())
continue;
if (t->mod & (MODimmutable | MODwild))
continue;
/* The rest of this is too strict; fix later.
* For example, the only pointer members of a struct may be immutable,
* which would maintain strong purity.
*/
if (t->mod & MODconst)
return true;
Type *tn = t->nextOf();
if (tn)
{ tn = tn->toBasetype();
if (tn->ty == Tpointer || tn->ty == Tarray)
{ /* Accept immutable(T)* and immutable(T)[] as being strongly pure
*/
if (tn->mod & (MODimmutable | MODwild))
continue;
if (tn->mod & MODconst)
return true;
}
}
/* Should catch delegates and function pointers, and fold in their purity
*/
return true;
}
return false;
}


/********************************
* 'args' are being matched to function 'this'
Expand Down
1 change: 1 addition & 0 deletions src/mtype.h
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,7 @@ struct TypeFunction : TypeNext
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
void purityLevel();
bool hasMutableIndirectionParams();
void toDecoBuffer(OutBuffer *buf, int flag);
void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
void toCBufferWithAttributes(OutBuffer *buf, Identifier *ident, HdrGenState* hgs, TypeFunction *attrs, TemplateDeclaration *td);
Expand Down
5 changes: 4 additions & 1 deletion src/statement.c
Original file line number Diff line number Diff line change
Expand Up @@ -3954,7 +3954,10 @@ Statement *ReturnStatement::semantic(Scope *sc)
}
else if (tbret->ty != Tvoid)
{
if (fd->isPureBypassingInference() == PUREstrong &&
assert(fd->type->ty == Tfunction);
TypeFunction *tf = (TypeFunction *)fd->type;
if (fd->isPureBypassingInference() != PUREimpure &&
!tf->hasMutableIndirectionParams() &&
!exp->type->implicitConvTo(tret) &&
exp->type->invariantOf()->implicitConvTo(tret))
{
Expand Down
8 changes: 5 additions & 3 deletions src/template.c
Original file line number Diff line number Diff line change
Expand Up @@ -4293,11 +4293,13 @@ MATCH TemplateValueParameter::matchArg(Scope *sc,
if (!ei && oarg)
{
Dsymbol *si = isDsymbol(oarg);
if (si && si->isFuncDeclaration())
FuncDeclaration *f;
if (si && (f = si->isFuncDeclaration()) != NULL)
{
ei = new VarExp(loc, (FuncDeclaration *)si);
ei = new VarExp(loc, f);
ei = ei->semantic(sc);
ei = resolveProperties(sc, ei);
if (!f->needThis())
ei = resolveProperties(sc, ei);
ei = ei->ctfeInterpret();
}
else
Expand Down
2 changes: 1 addition & 1 deletion test/compilable/extra-files/ddoc1.html
Original file line number Diff line number Diff line change
Expand Up @@ -111,5 +111,5 @@ <h1>abc</h1>
</dd>
</dl>

<hr><small>Page generated by <a href="http://www.digitalmars.com/d/2.0/ddoc.html">Ddoc</a>. Copyright &copy; 2012</small>
<hr><small>Page generated by <a href="http://www.digitalmars.com/d/2.0/ddoc.html">Ddoc</a>. Copyright &copy; 2013</small>
</body></html>
29 changes: 29 additions & 0 deletions test/fail_compilation/test9230.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
TEST_OUTPUT:
---
fail_compilation/test9230.d(12): Error: cannot implicitly convert expression (s) of type const(char[]) to string
fail_compilation/test9230.d(18): Error: cannot implicitly convert expression (a) of type int[] to immutable(int[])
fail_compilation/test9230.d(23): Error: cannot implicitly convert expression (a) of type int[] to immutable(int[])
fail_compilation/test9230.d(28): Error: cannot implicitly convert expression (a) of type int[] to immutable(int[])
---
*/

string foo(in char[] s) pure {
return s; //
}

/*pure*/ immutable(int[]) x1()
{
int[] a = new int[](10);
return a;
}
/*pure */immutable(int[]) x2(int len)
{
int[] a = new int[](len);
return a;
}
/*pure */immutable(int[]) x3(immutable(int[]) org)
{
int[] a = new int[](org.length);
return a;
}
10 changes: 10 additions & 0 deletions test/runnable/aliasthis.d
Original file line number Diff line number Diff line change
Expand Up @@ -879,6 +879,16 @@ void test8169()
static assert(typeof(ValueUser.m_valueImpl).getValue() == 42); // #3, OK
}

/***************************************************/
// 9177

struct S9177
{
int foo(int){ return 0; }
alias foo this;
}
pragma(msg, is(S9177 : int));

/***************************************************/

int main()
Expand Down
12 changes: 12 additions & 0 deletions test/runnable/property2.d
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,18 @@ void test8251()
@property bool foo9063(){ return true; }
static assert(foo9063);

/*****************************************/
// 9234

class Fizz9234
{
void bar() {}
Foo9234!bar foobar;
}

struct Foo9234(alias F) {}
struct Foo9234(string thunk) {}

/*****************************************/

int main()
Expand Down
47 changes: 46 additions & 1 deletion test/runnable/test42.d
Original file line number Diff line number Diff line change
Expand Up @@ -5245,7 +5245,7 @@ int bar8840(long g) { assert(g == 4); return printf("%llx\n", g); }

void test8840()
{
long f1 = foo8840();
long f1 = foo8840();
long f2 = foo8840();

long f = (f1 < f2 ? f1 : f2);
Expand Down Expand Up @@ -5444,6 +5444,49 @@ void test9171()

/***************************************************/

void test8765()
{
try
{
int x = 0;
assert(x == 1);
}
catch (Throwable e)
{
assert(e.msg == "assert(x == 1)");
}

try
{
int x = 0;
assert(x == 1, "Custom Error");
}
catch (Throwable e)
{
assert(e.msg == `assert(x == 1, "Custom Error")`);
}
}

/***************************************************/

void test9255()
{
try
{
int x = 0;
assert(x == 1);
}
catch (Throwable e)
{
version(Windows)
assert(e.file == r"runnable\test42.d");
else
assert(e.file == "runnable/test42.d");
}
}

/***************************************************/

int main()
{
test1();
Expand Down Expand Up @@ -5715,6 +5758,8 @@ int main()
test8376();
test8796();
test9171();
test8765();
test9255();

writefln("Success");
return 0;
Expand Down
25 changes: 20 additions & 5 deletions test/runnable/xtest46.d
Original file line number Diff line number Diff line change
Expand Up @@ -1963,21 +1963,36 @@ void test99()
}

/***************************************************/
// 5081

void test5081()
{
static pure immutable(int[]) x()
static pure immutable(int[]) x1()
{
return new int[](10);
int[] a = new int[](10);
return a;
}
static pure immutable(int[]) x2(int len)
{
int[] a = new int[](len);
return a;
}
static pure immutable(int[]) x3(immutable(int[]) org)
{
int[] a = new int[](org.length);
return a;
}

immutable a1 = x1();
immutable a2 = x2(10);
immutable a3 = x3([1,2]);

static pure int[] y()
static pure int[] y1()
{
return new int[](10);
}

immutable a = x();
immutable b = y();
immutable b1 = y1();
}

/***************************************************/
Expand Down