Skip to content

Commit

Permalink
Fix Issue 18620 - error cannot be interpreted at compile time is miss…
Browse files Browse the repository at this point in the history
…ing context where error ocurrs
  • Loading branch information
RazvanN7 committed May 29, 2018
1 parent 6d27555 commit 304850d
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 11 deletions.
31 changes: 28 additions & 3 deletions src/dmd/ctfeexpr.d
Expand Up @@ -200,14 +200,15 @@ extern (C++) final class ThrownExceptionExp : Expression
}
}


/***********************************************************
* This type is only used by the interpreter.
*/
extern (C++) final class CTFEExp : Expression
extern (C++) class CTFEExp : Expression
{
extern (D) this(TOK tok)
extern (D) this(TOK tok, int size = __traits(classInstanceSize, CTFEExp))
{
super(Loc.initial, tok, __traits(classInstanceSize, CTFEExp));
super(Loc.initial, tok, size);
type = Type.tvoid;
}

Expand Down Expand Up @@ -247,6 +248,30 @@ extern (C++) final class CTFEExp : Expression
}
}

enum CTE : int
{
missingFuncBody,
}

/* This class is used to pass CTFE errors to
* higher levels in the AST so that error
* messages can be written on the call site
*/
extern (C++) final class CTErrorExp : CTFEExp
{
CTE err;
extern (D) this(CTE err)
{
super(TOK.cantExpression, __traits(classInstanceSize, CTErrorExp));
this.err = err;
}

override inout(CTErrorExp) isCTErrorExp() inout
{
return this;
}
}

// True if 'e' is CTFEExp::cantexp, or an exception
extern (C++) bool exceptionOrCantInterpret(const Expression e)
{
Expand Down
2 changes: 1 addition & 1 deletion src/dmd/dinterpret.d
Expand Up @@ -4997,7 +4997,7 @@ public:
if (!fd.fbody)
{
e.error("`%s` cannot be interpreted at compile time, because it has no available source code", fd.toChars());
result = CTFEExp.cantexp;
result = new CTErrorExp(CTE.missingFuncBody);
return;
}

Expand Down
23 changes: 19 additions & 4 deletions src/dmd/dsymbolsem.d
Expand Up @@ -22,6 +22,7 @@ import dmd.astcodegen;
import dmd.attrib;
import dmd.blockexit;
import dmd.clone;
import dmd.ctfeexpr;
import dmd.dcast;
import dmd.dclass;
import dmd.declaration;
Expand Down Expand Up @@ -560,10 +561,10 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
{
version (none)
{
printf("VarDeclaration::semantic('%s', parent = '%s') sem = %d\n", toChars(), sc.parent ? sc.parent.toChars() : null, sem);
printf(" type = %s\n", type ? type.toChars() : "null");
printf("VarDeclaration::semantic('%s', parent = '%s')\n", dsym.toChars(), sc.parent ? sc.parent.toChars() : null);
printf(" type = %s\n", dsym.type ? dsym.type.toChars() : "null");
printf(" stc = x%x\n", sc.stc);
printf(" storage_class = x%llx\n", storage_class);
printf(" storage_class = x%llx\n", dsym.storage_class);
printf("linkage = %d\n", sc.linkage);
//if (strcmp(toChars(), "mul") == 0) assert(0);
}
Expand Down Expand Up @@ -1139,7 +1140,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
// possibilities.
if (fd && !(dsym.storage_class & (STC.manifest | STC.static_ | STC.tls | STC.gshared | STC.extern_)) && !dsym._init.isVoidInitializer())
{
//printf("fd = '%s', var = '%s'\n", fd.toChars(), toChars());
//printf("fd = '%s', var = '%s'\n", fd.toChars(), dsym.toChars());
if (!ei)
{
ArrayInitializer ai = dsym._init.isArrayInitializer();
Expand Down Expand Up @@ -1215,9 +1216,23 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
}
else
{
import dmd.hdrgen : toCBuffer, HdrGenState;
OutBuffer buff;
HdrGenState hgs;
toCBuffer(dsym, &buff, &hgs);
if (buff.offset != 0)
buff.setsize(buff.offset-1);

// https://issues.dlang.org/show_bug.cgi?id=14166
// Don't run CTFE for the temporary variables inside typeof
dsym._init = dsym._init.initializerSemantic(sc, dsym.type, sc.intypeof == 1 ? INITnointerpret : INITinterpret);
const init_err = dsym._init.isExpInitializer();
if (init_err)
{
const errExp = init_err.exp.isCTErrorExp;
if (errExp && errExp.err == CTE.missingFuncBody)
errorSupplemental(dsym.loc, "compile time context created here: `%s`", buff.extractString());
}
}
}
else if (parent.isAggregateDeclaration())
Expand Down
5 changes: 5 additions & 0 deletions src/dmd/expression.d
Expand Up @@ -2546,6 +2546,11 @@ extern (C++) abstract class Expression : RootObject
return false;
}

inout(CTErrorExp) isCTErrorExp() inout
{
return null;
}

final Expression op_overload(Scope* sc)
{
return .op_overload(this, sc);
Expand Down
6 changes: 3 additions & 3 deletions src/dmd/initsem.d
Expand Up @@ -394,7 +394,7 @@ private extern(C++) final class InitializerSemanticVisitor : Visitor

override void visit(ExpInitializer i)
{
//printf("ExpInitializer::semantic(%s), type = %s\n", exp.toChars(), t.toChars());
//printf("ExpInitializer::semantic(%s), type = %s\n", i.exp.toChars(), t.toChars());
if (needInterpret)
sc = sc.startCTFE();
i.exp = i.exp.expressionSemantic(sc);
Expand Down Expand Up @@ -546,7 +546,7 @@ private extern(C++) final class InitializerSemanticVisitor : Visitor
i.exp = i.exp.ctfeInterpret();
else
i.exp = i.exp.optimize(WANTvalue);
//printf("-ExpInitializer::semantic(): "); exp.print();
//printf("-ExpInitializer::semantic(): "); i.exp.print();
result = i;
}
}
Expand Down Expand Up @@ -895,7 +895,7 @@ private extern(C++) final class InitToExpressionVisitor : Visitor
{
if (itype)
{
//printf("ExpInitializer::toExpression(t = %s) exp = %s\n", t.toChars(), exp.toChars());
//printf("ExpInitializer::toExpression(t = %s) exp = %s\n", itype.toChars(), i.exp.toChars());
Type tb = itype.toBasetype();
Expression e = (i.exp.op == TOK.construct || i.exp.op == TOK.blit) ? (cast(AssignExp)i.exp).e2 : i.exp;
if (tb.ty == Tsarray && e.implicitConvTo(tb.nextOf()))
Expand Down
21 changes: 21 additions & 0 deletions test/fail_compilation/fail18620.d
@@ -0,0 +1,21 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail18620.d(14): Error: `strlen` cannot be interpreted at compile time, because it has no available source code
fail_compilation/fail18620.d(19): compile time context created here: `static A a = new A("a");`
fail_compilation/fail18620.d(14): Error: `strlen` cannot be interpreted at compile time, because it has no available source code
fail_compilation/fail18620.d(20): compile time context created here: `__gshared A b = new A("b");`
---
*/
class A{
this(const(char)* s)
{
import core.stdc.string;
auto a=strlen(s);
}
}

void main(){
static a = new A("a");
__gshared b = new A("b");
}

0 comments on commit 304850d

Please sign in to comment.