Skip to content

Commit

Permalink
Merge pull request #776 from 9rnsr/fix7618
Browse files Browse the repository at this point in the history
Issue 7618 - delegate/function pointer call bypass parameter storage class
  • Loading branch information
WalterBright committed Mar 2, 2012
2 parents bcfd90a + 40b290c commit f2eff28
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 30 deletions.
80 changes: 50 additions & 30 deletions src/expression.c
Expand Up @@ -7291,7 +7291,6 @@ Expression *CallExp::resolveUFCS(Scope *sc)

Expression *CallExp::semantic(Scope *sc)
{
TypeFunction *tf;
Type *t1;
int istemp;
Objects *targsi = NULL; // initial list of template arguments
Expand Down Expand Up @@ -7873,38 +7872,18 @@ Expression *CallExp::semantic(Scope *sc)
}
else if (t1->ty != Tfunction)
{
TypeFunction *tf;
const char *p;
if (t1->ty == Tdelegate)
{ TypeDelegate *td = (TypeDelegate *)t1;
assert(td->next->ty == Tfunction);
tf = (TypeFunction *)(td->next);
if (sc->func && !tf->purity && !(sc->flags & SCOPEdebug))
{
if (sc->func->setImpure())
error("pure function '%s' cannot call impure delegate '%s'", sc->func->toChars(), e1->toChars());
}
if (sc->func && tf->trust <= TRUSTsystem)
{
if (sc->func->setUnsafe())
error("safe function '%s' cannot call system delegate '%s'", sc->func->toChars(), e1->toChars());
}
goto Lcheckargs;
p = "delegate";
}
else if (t1->ty == Tpointer && ((TypePointer *)t1)->next->ty == Tfunction)
{
Expression *e = new PtrExp(loc, e1);
t1 = ((TypePointer *)t1)->next;
if (sc->func && !((TypeFunction *)t1)->purity && !(sc->flags & SCOPEdebug))
{
if (sc->func->setImpure())
error("pure function '%s' cannot call impure function pointer '%s'", sc->func->toChars(), e1->toChars());
}
if (sc->func && ((TypeFunction *)t1)->trust <= TRUSTsystem)
{
if (sc->func->setUnsafe())
error("safe function '%s' cannot call system function pointer '%s'", sc->func->toChars(), e1->toChars());
}
e->type = t1;
e1 = e;
tf = (TypeFunction *)(((TypePointer *)t1)->next);
p = "function pointer";
}
else if (e1->op == TOKtemplate)
{
Expand All @@ -7931,6 +7910,50 @@ Expression *CallExp::semantic(Scope *sc)
{ error("function expected before (), not %s of type %s", e1->toChars(), e1->type->toChars());
return new ErrorExp();
}

if (sc->func && !tf->purity && !(sc->flags & SCOPEdebug))
{
if (sc->func->setImpure())
error("pure function '%s' cannot call impure %s '%s'", sc->func->toChars(), p, e1->toChars());
}
if (sc->func && tf->trust <= TRUSTsystem)
{
if (sc->func->setUnsafe())
error("safe function '%s' cannot call system %s '%s'", sc->func->toChars(), p, e1->toChars());
}

if (!tf->callMatch(NULL, arguments))
{
OutBuffer buf;

buf.writeByte('(');
if (arguments)
{
HdrGenState hgs;

argExpTypesToCBuffer(&buf, arguments, &hgs);
buf.writeByte(')');
if (ethis)
ethis->type->modToBuffer(&buf);
}
else
buf.writeByte(')');

//printf("tf = %s, args = %s\n", tf->deco, arguments->tdata()[0]->type->deco);
::error(loc, "%s %s %s is not callable using argument types %s",
p, e1->toChars(), Parameter::argsTypesToChars(tf->parameters, tf->varargs),
buf.toChars());

return new ErrorExp();
}

if (t1->ty == Tpointer)
{
Expression *e = new PtrExp(loc, e1);
e->type = tf;
e1 = e;
}
t1 = tf;
}
else if (e1->op == TOKvar)
{
Expand Down Expand Up @@ -7968,10 +7991,7 @@ Expression *CallExp::semantic(Scope *sc)
t1 = f->type;
}
assert(t1->ty == Tfunction);
tf = (TypeFunction *)(t1);

Lcheckargs:
assert(tf->ty == Tfunction);
TypeFunction *tf = (TypeFunction *)(t1);

if (!arguments)
arguments = new Expressions();
Expand Down
19 changes: 19 additions & 0 deletions test/runnable/xtest46.d
Expand Up @@ -4714,6 +4714,24 @@ int bug7583() {

static assert (bug7583());

/***************************************************/
// 7618

void test7618(const int x = 1)
{
int func(ref int x) { return 1; }
static assert(!__traits(compiles, func(x)));
// Error: function test.foo.func (ref int _param_0) is not callable using argument types (const(int))

int delegate(ref int) dg = (ref int x) => 1;
static assert(!__traits(compiles, dg(x)));
// --> no error, bad!

int function(ref int) fp = (ref int x) => 1;
static assert(!__traits(compiles, fp(x)));
// --> no error, bad!
}

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

int main()
Expand Down Expand Up @@ -4934,6 +4952,7 @@ int main()
test7196();
test7285();
test7321();
test7618();

printf("Success\n");
return 0;
Expand Down

0 comments on commit f2eff28

Please sign in to comment.