1
/**
2
 * The entry point for CTFE.
3
 *
4
 * Specification: ($LINK2 https://dlang.org/spec/function.html#interpretation, Compile Time Function Execution (CTFE))
5
 *
6
 * Copyright:   Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
7
 * Authors:     $(LINK2 http://www.digitalmars.com, Walter Bright)
8
 * License:     $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
9
 * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dinterpret.d, _dinterpret.d)
10
 * Documentation:  https://dlang.org/phobos/dmd_dinterpret.html
11
 * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dinterpret.d
12
 */
13

14
module dmd.dinterpret;
15

16
import core.stdc.stdio;
17
import core.stdc.stdlib;
18
import core.stdc.string;
19
import dmd.apply;
20
import dmd.arraytypes;
21
import dmd.attrib;
22
import dmd.builtin;
23
import dmd.constfold;
24
import dmd.ctfeexpr;
25
import dmd.dclass;
26
import dmd.declaration;
27
import dmd.dstruct;
28
import dmd.dsymbol;
29
import dmd.dsymbolsem;
30
import dmd.dtemplate;
31
import dmd.errors;
32
import dmd.expression;
33
import dmd.expressionsem;
34
import dmd.func;
35
import dmd.globals;
36
import dmd.id;
37
import dmd.identifier;
38
import dmd.init;
39
import dmd.initsem;
40
import dmd.mtype;
41
import dmd.root.rmem;
42
import dmd.root.array;
43
import dmd.root.region;
44
import dmd.root.rootobject;
45
import dmd.statement;
46
import dmd.tokens;
47
import dmd.utf;
48
import dmd.visitor;
49

50
/*************************************
51
 * Entry point for CTFE.
52
 * A compile-time result is required. Give an error if not possible.
53
 *
54
 * `e` must be semantically valid expression. In other words, it should not
55
 * contain any `ErrorExp`s in it. But, CTFE interpretation will cross over
56
 * functions and may invoke a function that contains `ErrorStatement` in its body.
57
 * If that, the "CTFE failed because of previous errors" error is raised.
58
 */
59
public Expression ctfeInterpret(Expression e)
60
{
61 1
    switch (e.op)
62
    {
63 1
        case TOK.int64:
64 1
        case TOK.float64:
65 1
        case TOK.complex80:
66 1
        case TOK.null_:
67 1
        case TOK.void_:
68 1
        case TOK.string_:
69 1
        case TOK.this_:
70 1
        case TOK.super_:
71 1
        case TOK.type:
72 1
        case TOK.typeid_:
73 1
             if (e.type.ty == Terror)
74 1
                return ErrorExp.get();
75 1
            goto case TOK.error;
76

77 1
        case TOK.error:
78 1
            return e;
79

80 1
        default:
81 1
            break;
82
    }
83

84 1
    assert(e.type); // https://issues.dlang.org/show_bug.cgi?id=14642
85
    //assert(e.type.ty != Terror);    // FIXME
86 1
    if (e.type.ty == Terror)
87 0
        return ErrorExp.get();
88

89 1
    auto rgnpos = ctfeGlobals.region.savePos();
90

91 1
    Expression result = interpret(e, null);
92

93 1
    result = copyRegionExp(result);
94

95 1
    if (!CTFEExp.isCantExp(result))
96 1
        result = scrubReturnValue(e.loc, result);
97 1
    if (CTFEExp.isCantExp(result))
98 1
        result = ErrorExp.get();
99

100 1
    ctfeGlobals.region.release(rgnpos);
101

102 1
    return result;
103
}
104

105
/* Run CTFE on the expression, but allow the expression to be a TypeExp
106
 *  or a tuple containing a TypeExp. (This is required by pragma(msg)).
107
 */
108
public Expression ctfeInterpretForPragmaMsg(Expression e)
109
{
110 1
    if (e.op == TOK.error || e.op == TOK.type)
111 1
        return e;
112

113
    // It's also OK for it to be a function declaration (happens only with
114
    // __traits(getOverloads))
115 1
    if (auto ve = e.isVarExp())
116 1
        if (ve.var.isFuncDeclaration())
117
        {
118 1
            return e;
119
        }
120

121 1
    auto tup = e.isTupleExp();
122 1
    if (!tup)
123 1
        return e.ctfeInterpret();
124

125
    // Tuples need to be treated separately, since they are
126
    // allowed to contain a TypeExp in this case.
127

128 1
    Expressions* expsx = null;
129 1
    foreach (i, g; *tup.exps)
130
    {
131 1
        auto h = ctfeInterpretForPragmaMsg(g);
132 1
        if (h != g)
133
        {
134 1
            if (!expsx)
135
            {
136 1
                expsx = tup.exps.copy();
137
            }
138 1
            (*expsx)[i] = h;
139
        }
140
    }
141 1
    if (expsx)
142
    {
143 1
        auto te = new TupleExp(e.loc, expsx);
144 1
        expandTuples(te.exps);
145 1
        te.type = new TypeTuple(te.exps);
146 1
        return te;
147
    }
148 1
    return e;
149
}
150

151
public extern (C++) Expression getValue(VarDeclaration vd)
152
{
153 1
    return ctfeGlobals.stack.getValue(vd);
154
}
155

156
/*************************************************
157
 * Allocate an Expression in the ctfe region.
158
 * Params:
159
 *      T = type of Expression to allocate
160
 *      args = arguments to Expression's constructor
161
 * Returns:
162
 *      allocated Expression
163
 */
164
T ctfeEmplaceExp(T : Expression, Args...)(Args args)
165
{
166 1
    if (mem.isGCEnabled)
167 1
        return new T(args);
168 1
    auto p = ctfeGlobals.region.malloc(__traits(classInstanceSize, T));
169 1
    emplaceExp!T(p, args);
170 1
    return cast(T)p;
171
}
172

173
// CTFE diagnostic information
174
public extern (C++) void printCtfePerformanceStats()
175
{
176
    debug (SHOWPERFORMANCE)
177
    {
178
        printf("        ---- CTFE Performance ----\n");
179
        printf("max call depth = %d\tmax stack = %d\n", ctfeGlobals.maxCallDepth, ctfeGlobals.stack.maxStackUsage());
180
        printf("array allocs = %d\tassignments = %d\n\n", ctfeGlobals.numArrayAllocs, ctfeGlobals.numAssignments);
181
    }
182
}
183

184
/**************************
185
 */
186

187
void incArrayAllocs()
188
{
189 1
    ++ctfeGlobals.numArrayAllocs;
190
}
191

192
/* ================================================ Implementation ======================================= */
193

194
private:
195

196
/***************
197
 * Collect together globals used by CTFE
198
 */
199
struct CtfeGlobals
200
{
201
    Region region;
202

203
    CtfeStack stack;
204

205
    int callDepth = 0;        // current number of recursive calls
206

207
    // When printing a stack trace, suppress this number of calls
208
    int stackTraceCallsToSuppress = 0;
209

210
    int maxCallDepth = 0;     // highest number of recursive calls
211
    int numArrayAllocs = 0;   // Number of allocated arrays
212
    int numAssignments = 0;   // total number of assignments executed
213
}
214

215
__gshared CtfeGlobals ctfeGlobals;
216

217
enum CTFEGoal : int
218
{
219
    RValue,     /// Must return an Rvalue (== CTFE value)
220
    LValue,     /// Must return an Lvalue (== CTFE reference)
221
    Nothing,    /// The return value is not required
222
}
223

224
//debug = LOG;
225
//debug = LOGASSIGN;
226
//debug = LOGCOMPILE;
227
//debug = SHOWPERFORMANCE;
228

229
// Maximum allowable recursive function calls in CTFE
230
enum CTFE_RECURSION_LIMIT = 1000;
231

232
/**
233
 The values of all CTFE variables
234
 */
235
struct CtfeStack
236
{
237
private:
238
    /* The stack. Every declaration we encounter is pushed here,
239
     * together with the VarDeclaration, and the previous
240
     * stack address of that variable, so that we can restore it
241
     * when we leave the stack frame.
242
     * Note that when a function is forward referenced, the interpreter must
243
     * run semantic3, and that may start CTFE again with a NULL istate. Thus
244
     * the stack might not be empty when CTFE begins.
245
     *
246
     * Ctfe Stack addresses are just 0-based integers, but we save
247
     * them as 'void *' because Array can only do pointers.
248
     */
249
    Expressions values;         // values on the stack
250
    VarDeclarations vars;       // corresponding variables
251
    Array!(void*) savedId;      // id of the previous state of that var
252

253
    Array!(void*) frames;       // all previous frame pointers
254
    Expressions savedThis;      // all previous values of localThis
255

256
    /* Global constants get saved here after evaluation, so we never
257
     * have to redo them. This saves a lot of time and memory.
258
     */
259
    Expressions globalValues;   // values of global constants
260

261
    size_t framepointer;        // current frame pointer
262
    size_t maxStackPointer;     // most stack we've ever used
263
    Expression localThis;       // value of 'this', or NULL if none
264

265
public:
266
    extern (C++) size_t stackPointer()
267
    {
268 1
        return values.dim;
269
    }
270

271
    // The current value of 'this', or NULL if none
272
    extern (C++) Expression getThis()
273
    {
274 1
        return localThis;
275
    }
276

277
    // Largest number of stack positions we've used
278
    extern (C++) size_t maxStackUsage()
279
    {
280 0
        return maxStackPointer;
281
    }
282

283
    // Start a new stack frame, using the provided 'this'.
284
    extern (C++) void startFrame(Expression thisexp)
285
    {
286 1
        frames.push(cast(void*)cast(size_t)framepointer);
287 1
        savedThis.push(localThis);
288 1
        framepointer = stackPointer();
289 1
        localThis = thisexp;
290
    }
291

292
    extern (C++) void endFrame()
293
    {
294 1
        size_t oldframe = cast(size_t)frames[frames.dim - 1];
295 1
        localThis = savedThis[savedThis.dim - 1];
296 1
        popAll(framepointer);
297 1
        framepointer = oldframe;
298 1
        frames.setDim(frames.dim - 1);
299 1
        savedThis.setDim(savedThis.dim - 1);
300
    }
301

302
    extern (C++) bool isInCurrentFrame(VarDeclaration v)
303
    {
304 1
        if (v.isDataseg() && !v.isCTFE())
305 0
            return false; // It's a global
306 1
        return v.ctfeAdrOnStack >= framepointer;
307
    }
308

309
    extern (C++) Expression getValue(VarDeclaration v)
310
    {
311 1
        if ((v.isDataseg() || v.storage_class & STC.manifest) && !v.isCTFE())
312
        {
313 1
            assert(v.ctfeAdrOnStack < globalValues.dim);
314 1
            return globalValues[v.ctfeAdrOnStack];
315
        }
316 1
        assert(v.ctfeAdrOnStack < stackPointer());
317 1
        return values[v.ctfeAdrOnStack];
318
    }
319

320
    extern (C++) void setValue(VarDeclaration v, Expression e)
321
    {
322 1
        assert(!v.isDataseg() || v.isCTFE());
323 1
        assert(v.ctfeAdrOnStack < stackPointer());
324 1
        values[v.ctfeAdrOnStack] = e;
325
    }
326

327
    extern (C++) void push(VarDeclaration v)
328
    {
329 1
        assert(!v.isDataseg() || v.isCTFE());
330 1
        if (v.ctfeAdrOnStack != VarDeclaration.AdrOnStackNone && v.ctfeAdrOnStack >= framepointer)
331
        {
332
            // Already exists in this frame, reuse it.
333 1
            values[v.ctfeAdrOnStack] = null;
334 1
            return;
335
        }
336 1
        savedId.push(cast(void*)cast(size_t)v.ctfeAdrOnStack);
337 1
        v.ctfeAdrOnStack = cast(uint)values.dim;
338 1
        vars.push(v);
339 1
        values.push(null);
340
    }
341

342
    extern (C++) void pop(VarDeclaration v)
343
    {
344 1
        assert(!v.isDataseg() || v.isCTFE());
345 1
        assert(!(v.storage_class & (STC.ref_ | STC.out_)));
346 1
        const oldid = v.ctfeAdrOnStack;
347 1
        v.ctfeAdrOnStack = cast(uint)cast(size_t)savedId[oldid];
348 1
        if (v.ctfeAdrOnStack == values.dim - 1)
349
        {
350 0
            values.pop();
351 0
            vars.pop();
352 0
            savedId.pop();
353
        }
354
    }
355

356
    extern (C++) void popAll(size_t stackpointer)
357
    {
358 1
        if (stackPointer() > maxStackPointer)
359 1
            maxStackPointer = stackPointer();
360 1
        assert(values.dim >= stackpointer);
361 1
        for (size_t i = stackpointer; i < values.dim; ++i)
362
        {
363 1
            VarDeclaration v = vars[i];
364 1
            v.ctfeAdrOnStack = cast(uint)cast(size_t)savedId[i];
365
        }
366 1
        values.setDim(stackpointer);
367 1
        vars.setDim(stackpointer);
368 1
        savedId.setDim(stackpointer);
369
    }
370

371
    extern (C++) void saveGlobalConstant(VarDeclaration v, Expression e)
372
    {
373 1
        assert(v._init && (v.isConst() || v.isImmutable() || v.storage_class & STC.manifest) && !v.isCTFE());
374 1
        v.ctfeAdrOnStack = cast(uint)globalValues.dim;
375 1
        globalValues.push(copyRegionExp(e));
376
    }
377
}
378

379
private struct InterState
380
{
381
    InterState* caller;     // calling function's InterState
382
    FuncDeclaration fd;     // function being interpreted
383
    Statement start;        // if !=NULL, start execution at this statement
384

385
    /* target of CTFEExp result; also
386
     * target of labelled CTFEExp or
387
     * CTFEExp. (null if no label).
388
     */
389
    Statement gotoTarget;
390
}
391

392
/*************************************
393
 * Attempt to interpret a function given the arguments.
394
 * Params:
395
 *      pue       = storage for result
396
 *      fd        = function being called
397
 *      istate    = state for calling function (NULL if none)
398
 *      arguments = function arguments
399
 *      thisarg   = 'this', if a needThis() function, NULL if not.
400
 *
401
 * Returns:
402
 * result expression if successful, TOK.cantExpression if not,
403
 * or CTFEExp if function returned void.
404
 */
405
private Expression interpretFunction(UnionExp* pue, FuncDeclaration fd, InterState* istate, Expressions* arguments, Expression thisarg)
406
{
407
    debug (LOG)
408
    {
409
        printf("\n********\n%s FuncDeclaration::interpret(istate = %p) %s\n", fd.loc.toChars(), istate, fd.toChars());
410
    }
411 1
    assert(pue);
412 1
    if (fd.semanticRun == PASS.semantic3)
413
    {
414 1
        fd.error("circular dependency. Functions cannot be interpreted while being compiled");
415 1
        return CTFEExp.cantexp;
416
    }
417 1
    if (!fd.functionSemantic3())
418 1
        return CTFEExp.cantexp;
419 1
    if (fd.semanticRun < PASS.semantic3done)
420 0
        return CTFEExp.cantexp;
421

422 1
    Type tb = fd.type.toBasetype();
423 1
    assert(tb.ty == Tfunction);
424 1
    TypeFunction tf = cast(TypeFunction)tb;
425 1
    if (tf.parameterList.varargs != VarArg.none && arguments &&
426 1
        ((fd.parameters && arguments.dim != fd.parameters.dim) || (!fd.parameters && arguments.dim)))
427
    {
428 1
        fd.error("C-style variadic functions are not yet implemented in CTFE");
429 1
        return CTFEExp.cantexp;
430
    }
431

432
    // Nested functions always inherit the 'this' pointer from the parent,
433
    // except for delegates. (Note that the 'this' pointer may be null).
434
    // Func literals report isNested() even if they are in global scope,
435
    // so we need to check that the parent is a function.
436 1
    if (fd.isNested() && fd.toParentLocal().isFuncDeclaration() && !thisarg && istate)
437 1
        thisarg = ctfeGlobals.stack.getThis();
438

439 1
    if (fd.needThis() && !thisarg)
440
    {
441
        // error, no this. Prevent segfault.
442
        // Here should be unreachable by the strict 'this' check in front-end.
443 0
        fd.error("need `this` to access member `%s`", fd.toChars());
444 0
        return CTFEExp.cantexp;
445
    }
446

447
    // Place to hold all the arguments to the function while
448
    // we are evaluating them.
449 1
    size_t dim = arguments ? arguments.dim : 0;
450 1
    assert((fd.parameters ? fd.parameters.dim : 0) == dim);
451

452
    /* Evaluate all the arguments to the function,
453
     * store the results in eargs[]
454
     */
455 1
    Expressions eargs = Expressions(dim);
456 1
    for (size_t i = 0; i < dim; i++)
457
    {
458 1
        Expression earg = (*arguments)[i];
459 1
        Parameter fparam = tf.parameterList[i];
460

461 1
        if (fparam.isReference())
462
        {
463 1
            if (!istate && (fparam.storageClass & STC.out_))
464
            {
465
                // initializing an out parameter involves writing to it.
466 0
                earg.error("global `%s` cannot be passed as an `out` parameter at compile time", earg.toChars());
467 0
                return CTFEExp.cantexp;
468
            }
469
            // Convert all reference arguments into lvalue references
470 1
            earg = interpretRegion(earg, istate, CTFEGoal.LValue);
471 1
            if (CTFEExp.isCantExp(earg))
472 1
                return earg;
473
        }
474 1
        else if (fparam.storageClass & STC.lazy_)
475
        {
476
        }
477
        else
478
        {
479
            /* Value parameters
480
             */
481 1
            Type ta = fparam.type.toBasetype();
482 1
            if (ta.ty == Tsarray)
483 1
                if (auto eaddr = earg.isAddrExp())
484
                {
485
                    /* Static arrays are passed by a simple pointer.
486
                     * Skip past this to get at the actual arg.
487
                     */
488 0
                    earg = eaddr.e1;
489
                }
490

491 1
            earg = interpretRegion(earg, istate);
492 1
            if (CTFEExp.isCantExp(earg))
493 1
                return earg;
494

495
            /* Struct literals are passed by value, but we don't need to
496
             * copy them if they are passed as const
497
             */
498 1
            if (earg.op == TOK.structLiteral && !(fparam.storageClass & (STC.const_ | STC.immutable_)))
499 1
                earg = copyLiteral(earg).copy();
500
        }
501 1
        if (earg.op == TOK.thrownException)
502
        {
503 1
            if (istate)
504 1
                return earg;
505 0
            (cast(ThrownExceptionExp)earg).generateUncaughtError();
506 0
            return CTFEExp.cantexp;
507
        }
508 1
        eargs[i] = earg;
509
    }
510

511
    // Now that we've evaluated all the arguments, we can start the frame
512
    // (this is the moment when the 'call' actually takes place).
513 1
    InterState istatex;
514 1
    istatex.caller = istate;
515 1
    istatex.fd = fd;
516

517 1
    if (fd.isThis2)
518
    {
519 1
        Expression arg0 = thisarg;
520 1
        if (arg0 && arg0.type.ty == Tstruct)
521
        {
522 1
            Type t = arg0.type.pointerTo();
523 1
            arg0 = ctfeEmplaceExp!AddrExp(arg0.loc, arg0);
524 1
            arg0.type = t;
525
        }
526 1
        auto elements = new Expressions(2);
527 1
        (*elements)[0] = arg0;
528 1
        (*elements)[1] = ctfeGlobals.stack.getThis();
529 1
        Type t2 = Type.tvoidptr.sarrayOf(2);
530 1
        const loc = thisarg ? thisarg.loc : fd.loc;
531 1
        thisarg = ctfeEmplaceExp!ArrayLiteralExp(loc, t2, elements);
532 1
        thisarg = ctfeEmplaceExp!AddrExp(loc, thisarg);
533 1
        thisarg.type = t2.pointerTo();
534
    }
535

536 1
    ctfeGlobals.stack.startFrame(thisarg);
537 1
    if (fd.vthis && thisarg)
538
    {
539 1
        ctfeGlobals.stack.push(fd.vthis);
540 1
        setValue(fd.vthis, thisarg);
541
    }
542

543 1
    for (size_t i = 0; i < dim; i++)
544
    {
545 1
        Expression earg = eargs[i];
546 1
        Parameter fparam = tf.parameterList[i];
547 1
        VarDeclaration v = (*fd.parameters)[i];
548
        debug (LOG)
549
        {
550
            printf("arg[%zu] = %s\n", i, earg.toChars());
551
        }
552 1
        ctfeGlobals.stack.push(v);
553

554 1
        if (fparam.isReference() && earg.op == TOK.variable &&
555 1
            (cast(VarExp)earg).var.toParent2() == fd)
556
        {
557 1
            VarDeclaration vx = (cast(VarExp)earg).var.isVarDeclaration();
558 1
            if (!vx)
559
            {
560 0
                fd.error("cannot interpret `%s` as a `ref` parameter", earg.toChars());
561 0
                return CTFEExp.cantexp;
562
            }
563

564
            /* vx is a variable that is declared in fd.
565
             * It means that fd is recursively called. e.g.
566
             *
567
             *  void fd(int n, ref int v = dummy) {
568
             *      int vx;
569
             *      if (n == 1) fd(2, vx);
570
             *  }
571
             *  fd(1);
572
             *
573
             * The old value of vx on the stack in fd(1)
574
             * should be saved at the start of fd(2, vx) call.
575
             */
576 1
            const oldadr = vx.ctfeAdrOnStack;
577

578 1
            ctfeGlobals.stack.push(vx);
579 1
            assert(!hasValue(vx)); // vx is made uninitialized
580

581
            // https://issues.dlang.org/show_bug.cgi?id=14299
582
            // v.ctfeAdrOnStack should be saved already
583
            // in the stack before the overwrite.
584 1
            v.ctfeAdrOnStack = oldadr;
585 1
            assert(hasValue(v)); // ref parameter v should refer existing value.
586
        }
587
        else
588
        {
589
            // Value parameters and non-trivial references
590 1
            setValueWithoutChecking(v, earg);
591
        }
592
        debug (LOG)
593
        {
594
            printf("interpreted arg[%zu] = %s\n", i, earg.toChars());
595
            showCtfeExpr(earg);
596
        }
597
        debug (LOGASSIGN)
598
        {
599
            printf("interpreted arg[%zu] = %s\n", i, earg.toChars());
600
            showCtfeExpr(earg);
601
        }
602
    }
603

604 1
    if (fd.vresult)
605 1
        ctfeGlobals.stack.push(fd.vresult);
606

607
    // Enter the function
608 1
    ++ctfeGlobals.callDepth;
609 1
    if (ctfeGlobals.callDepth > ctfeGlobals.maxCallDepth)
610 1
        ctfeGlobals.maxCallDepth = ctfeGlobals.callDepth;
611

612 1
    Expression e = null;
613 1
    while (1)
614
    {
615 1
        if (ctfeGlobals.callDepth > CTFE_RECURSION_LIMIT)
616
        {
617
            // This is a compiler error. It must not be suppressed.
618 1
            global.gag = 0;
619 1
            fd.error("CTFE recursion limit exceeded");
620 1
            e = CTFEExp.cantexp;
621 1
            break;
622
        }
623 1
        e = interpret(pue, fd.fbody, &istatex);
624 1
        if (CTFEExp.isCantExp(e))
625
        {
626
            debug (LOG)
627
            {
628
                printf("function body failed to interpret\n");
629
            }
630
        }
631

632 1
        if (istatex.start)
633
        {
634 0
            fd.error("CTFE internal error: failed to resume at statement `%s`", istatex.start.toChars());
635 0
            return CTFEExp.cantexp;
636
        }
637

638
        /* This is how we deal with a recursive statement AST
639
         * that has arbitrary goto statements in it.
640
         * Bubble up a 'result' which is the target of the goto
641
         * statement, then go recursively down the AST looking
642
         * for that statement, then execute starting there.
643
         */
644 1
        if (CTFEExp.isGotoExp(e))
645
        {
646 1
            istatex.start = istatex.gotoTarget; // set starting statement
647 1
            istatex.gotoTarget = null;
648
        }
649
        else
650
        {
651 1
            assert(!e || (e.op != TOK.continue_ && e.op != TOK.break_));
652 1
            break;
653
        }
654
    }
655
    // If fell off the end of a void function, return void
656 1
    if (!e && tf.next.ty == Tvoid)
657 1
        e = CTFEExp.voidexp;
658 1
    if (tf.isref && e.op == TOK.variable && (cast(VarExp)e).var == fd.vthis)
659 1
        e = thisarg;
660 1
    if (tf.isref && fd.isThis2 && e.op == TOK.index)
661
    {
662 1
        auto ie = cast(IndexExp)e;
663 1
        auto pe = ie.e1.isPtrExp();
664 1
        auto ve = !pe ?  null : pe.e1.isVarExp();
665 1
        if (ve && ve.var == fd.vthis)
666
        {
667 1
            auto ne = ie.e2.isIntegerExp();
668 1
            assert(ne);
669 1
            assert(thisarg.op == TOK.address);
670 1
            e = (cast(AddrExp)thisarg).e1;
671 1
            e = (*(cast(ArrayLiteralExp)e).elements)[cast(size_t)ne.getInteger()];
672 1
            if (e.op == TOK.address)
673
            {
674 1
                e = (cast(AddrExp)e).e1;
675
            }
676
        }
677
    }
678 1
    assert(e !is null);
679

680
    // Leave the function
681 1
    --ctfeGlobals.callDepth;
682

683 1
    ctfeGlobals.stack.endFrame();
684

685
    // If it generated an uncaught exception, report error.
686 1
    if (!istate && e.op == TOK.thrownException)
687
    {
688 1
        if (e == pue.exp())
689 0
            e = pue.copy();
690 1
        (cast(ThrownExceptionExp)e).generateUncaughtError();
691 1
        e = CTFEExp.cantexp;
692
    }
693

694 1
    return e;
695
}
696

697
/// used to collect coverage information in ctfe
698
void incUsageCtfe(InterState* istate, const ref Loc loc)
699
{
700 1
    if (global.params.ctfe_cov && istate)
701
    {
702 1
        auto line = loc.linnum;
703 1
        auto mod = istate.fd.getModule();
704

705 1
        ++mod.ctfe_cov[line];
706
    }
707
}
708

709
private extern (C++) final class Interpreter : Visitor
710
{
711
    alias visit = Visitor.visit;
712
public:
713
    InterState* istate;
714
    CTFEGoal goal;
715
    Expression result;
716
    UnionExp* pue;              // storage for `result`
717

718 1
    extern (D) this(UnionExp* pue, InterState* istate, CTFEGoal goal)
719
    {
720 1
        this.pue = pue;
721 1
        this.istate = istate;
722 1
        this.goal = goal;
723
    }
724

725
    // If e is TOK.throw_exception or TOK.cantExpression,
726
    // set it to 'result' and returns true.
727
    bool exceptionOrCant(Expression e)
728
    {
729 1
        if (exceptionOrCantInterpret(e))
730
        {
731
            // Make sure e is not pointing to a stack temporary
732 1
            result = (e.op == TOK.cantExpression) ? CTFEExp.cantexp : e;
733 1
            return true;
734
        }
735 1
        return false;
736
    }
737

738
    static Expressions* copyArrayOnWrite(Expressions* exps, Expressions* original)
739
    {
740 1
        if (exps is original)
741
        {
742 1
            if (!original)
743 0
                exps = new Expressions();
744
            else
745 1
                exps = original.copy();
746 1
            ++ctfeGlobals.numArrayAllocs;
747
        }
748 1
        return exps;
749
    }
750

751
    /******************************** Statement ***************************/
752

753
    override void visit(Statement s)
754
    {
755
        debug (LOG)
756
        {
757
            printf("%s Statement::interpret()\n", s.loc.toChars());
758
        }
759 1
        if (istate.start)
760
        {
761 1
            if (istate.start != s)
762 1
                return;
763 0
            istate.start = null;
764
        }
765

766 0
        s.error("statement `%s` cannot be interpreted at compile time", s.toChars());
767 0
        result = CTFEExp.cantexp;
768
    }
769

770
    override void visit(ExpStatement s)
771
    {
772
        debug (LOG)
773
        {
774
            printf("%s ExpStatement::interpret(%s)\n", s.loc.toChars(), s.exp ? s.exp.toChars() : "");
775
        }
776 1
        if (istate.start)
777
        {
778 1
            if (istate.start != s)
779 1
                return;
780 0
            istate.start = null;
781
        }
782 1
        if (s.exp && s.exp.hasCode)
783 1
            incUsageCtfe(istate, s.loc);
784

785 1
        Expression e = interpret(pue, s.exp, istate, CTFEGoal.Nothing);
786 1
        if (exceptionOrCant(e))
787 1
            return;
788
    }
789

790
    override void visit(CompoundStatement s)
791
    {
792
        debug (LOG)
793
        {
794
            printf("%s CompoundStatement::interpret()\n", s.loc.toChars());
795
        }
796 1
        if (istate.start == s)
797 0
            istate.start = null;
798

799 1
        const dim = s.statements ? s.statements.dim : 0;
800 1
        foreach (i; 0 .. dim)
801
        {
802 1
            Statement sx = (*s.statements)[i];
803 1
            result = interpret(pue, sx, istate);
804 1
            if (result)
805 1
                break;
806
        }
807
        debug (LOG)
808
        {
809
            printf("%s -CompoundStatement::interpret() %p\n", s.loc.toChars(), result);
810
        }
811
    }
812

813
    override void visit(UnrolledLoopStatement s)
814
    {
815
        debug (LOG)
816
        {
817
            printf("%s UnrolledLoopStatement::interpret()\n", s.loc.toChars());
818
        }
819 1
        if (istate.start == s)
820 0
            istate.start = null;
821

822 1
        const dim = s.statements ? s.statements.dim : 0;
823 1
        foreach (i; 0 .. dim)
824
        {
825 1
            Statement sx = (*s.statements)[i];
826 1
            Expression e = interpret(pue, sx, istate);
827 1
            if (!e) // succeeds to interpret, or goto target was not found
828 1
                continue;
829 1
            if (exceptionOrCant(e))
830 0
                return;
831 1
            if (e.op == TOK.break_)
832
            {
833 1
                if (istate.gotoTarget && istate.gotoTarget != s)
834
                {
835 1
                    result = e; // break at a higher level
836 1
                    return;
837
                }
838 1
                istate.gotoTarget = null;
839 1
                result = null;
840 1
                return;
841
            }
842 1
            if (e.op == TOK.continue_)
843
            {
844 1
                if (istate.gotoTarget && istate.gotoTarget != s)
845
                {
846 0
                    result = e; // continue at a higher level
847 0
                    return;
848
                }
849 1
                istate.gotoTarget = null;
850 1
                continue;
851
            }
852

853
            // expression from return statement, or thrown exception
854 1
            result = e;
855 1
            break;
856
        }
857
    }
858

859
    override void visit(IfStatement s)
860
    {
861
        debug (LOG)
862
        {
863
            printf("%s IfStatement::interpret(%s)\n", s.loc.toChars(), s.condition.toChars());
864
        }
865 1
        incUsageCtfe(istate, s.loc);
866 1
        if (istate.start == s)
867 0
            istate.start = null;
868 1
        if (istate.start)
869
        {
870 1
            Expression e = null;
871 1
            e = interpret(s.ifbody, istate);
872 1
            if (!e && istate.start)
873 1
                e = interpret(s.elsebody, istate);
874 1
            result = e;
875 1
            return;
876
        }
877

878 1
        UnionExp ue = void;
879 1
        Expression e = interpret(&ue, s.condition, istate);
880 1
        assert(e);
881 1
        if (exceptionOrCant(e))
882 0
            return;
883

884 1
        if (isTrueBool(e))
885 1
            result = interpret(pue, s.ifbody, istate);
886 1
        else if (e.isBool(false))
887 1
            result = interpret(pue, s.elsebody, istate);
888
        else
889
        {
890
            // no error, or assert(0)?
891 0
            result = CTFEExp.cantexp;
892
        }
893
    }
894

895
    override void visit(ScopeStatement s)
896
    {
897
        debug (LOG)
898
        {
899
            printf("%s ScopeStatement::interpret()\n", s.loc.toChars());
900
        }
901 1
        if (istate.start == s)
902 0
            istate.start = null;
903

904 1
        result = interpret(pue, s.statement, istate);
905
    }
906

907
    /**
908
     Given an expression e which is about to be returned from the current
909
     function, generate an error if it contains pointers to local variables.
910

911
     Only checks expressions passed by value (pointers to local variables
912
     may already be stored in members of classes, arrays, or AAs which
913
     were passed as mutable function parameters).
914
     Returns:
915
        true if it is safe to return, false if an error was generated.
916
     */
917
    static bool stopPointersEscaping(const ref Loc loc, Expression e)
918
    {
919 1
        if (!e.type.hasPointers())
920 1
            return true;
921 1
        if (isPointer(e.type))
922
        {
923 1
            Expression x = e;
924 1
            if (auto eaddr = e.isAddrExp())
925 1
                x = eaddr.e1;
926 1
            VarDeclaration v;
927 1
            while (x.op == TOK.variable && (v = (cast(VarExp)x).var.isVarDeclaration()) !is null)
928
            {
929 1
                if (v.storage_class & STC.ref_)
930
                {
931 0
                    x = getValue(v);
932 0
                    if (auto eaddr = e.isAddrExp())
933 0
                        eaddr.e1 = x;
934 0
                    continue;
935
                }
936 1
                if (ctfeGlobals.stack.isInCurrentFrame(v))
937
                {
938 1
                    error(loc, "returning a pointer to a local stack variable");
939 1
                    return false;
940
                }
941
                else
942 1
                    break;
943
            }
944
            // TODO: If it is a TOK.dotVariable or TOK.index, we should check that it is not
945
            // pointing to a local struct or static array.
946
        }
947 1
        if (auto se = e.isStructLiteralExp())
948
        {
949 1
            return stopPointersEscapingFromArray(loc, se.elements);
950
        }
951 1
        if (auto ale = e.isArrayLiteralExp())
952
        {
953 1
            return stopPointersEscapingFromArray(loc, ale.elements);
954
        }
955 1
        if (auto aae = e.isAssocArrayLiteralExp())
956
        {
957 1
            if (!stopPointersEscapingFromArray(loc, aae.keys))
958 0
                return false;
959 1
            return stopPointersEscapingFromArray(loc, aae.values);
960
        }
961 1
        return true;
962
    }
963

964
    // Check all elements of an array for escaping local variables. Return false if error
965
    static bool stopPointersEscapingFromArray(const ref Loc loc, Expressions* elems)
966
    {
967 1
        foreach (e; *elems)
968
        {
969 1
            if (e && !stopPointersEscaping(loc, e))
970 1
                return false;
971
        }
972 1
        return true;
973
    }
974

975
    override void visit(ReturnStatement s)
976
    {
977
        debug (LOG)
978
        {
979
            printf("%s ReturnStatement::interpret(%s)\n", s.loc.toChars(), s.exp ? s.exp.toChars() : "");
980
        }
981 1
        if (istate.start)
982
        {
983 1
            if (istate.start != s)
984 1
                return;
985 0
            istate.start = null;
986
        }
987

988 1
        if (!s.exp)
989
        {
990 1
            result = CTFEExp.voidexp;
991 1
            return;
992
        }
993

994 1
        incUsageCtfe(istate, s.loc);
995 1
        assert(istate && istate.fd && istate.fd.type && istate.fd.type.ty == Tfunction);
996 1
        TypeFunction tf = cast(TypeFunction)istate.fd.type;
997

998
        /* If the function returns a ref AND it's been called from an assignment,
999
         * we need to return an lvalue. Otherwise, just do an (rvalue) interpret.
1000
         */
1001 1
        if (tf.isref)
1002
        {
1003 1
            result = interpret(pue, s.exp, istate, CTFEGoal.LValue);
1004 1
            return;
1005
        }
1006 1
        if (tf.next && tf.next.ty == Tdelegate && istate.fd.closureVars.dim > 0)
1007
        {
1008
            // To support this, we need to copy all the closure vars
1009
            // into the delegate literal.
1010 1
            s.error("closures are not yet supported in CTFE");
1011 1
            result = CTFEExp.cantexp;
1012 1
            return;
1013
        }
1014

1015
        // We need to treat pointers specially, because TOK.symbolOffset can be used to
1016
        // return a value OR a pointer
1017 1
        Expression e = interpret(pue, s.exp, istate);
1018 1
        if (exceptionOrCant(e))
1019 1
            return;
1020

1021
        // Disallow returning pointers to stack-allocated variables (bug 7876)
1022 1
        if (!stopPointersEscaping(s.loc, e))
1023
        {
1024 1
            result = CTFEExp.cantexp;
1025 1
            return;
1026
        }
1027

1028 1
        if (needToCopyLiteral(e))
1029 1
            e = copyLiteral(e).copy();
1030
        debug (LOGASSIGN)
1031
        {
1032
            printf("RETURN %s\n", s.loc.toChars());
1033
            showCtfeExpr(e);
1034
        }
1035 1
        result = e;
1036
    }
1037

1038
    static Statement findGotoTarget(InterState* istate, Identifier ident)
1039
    {
1040 1
        Statement target = null;
1041 1
        if (ident)
1042
        {
1043 1
            LabelDsymbol label = istate.fd.searchLabel(ident);
1044 1
            assert(label && label.statement);
1045 1
            LabelStatement ls = label.statement;
1046 1
            target = ls.gotoTarget ? ls.gotoTarget : ls.statement;
1047
        }
1048 1
        return target;
1049
    }
1050

1051
    override void visit(BreakStatement s)
1052
    {
1053
        debug (LOG)
1054
        {
1055
            printf("%s BreakStatement::interpret()\n", s.loc.toChars());
1056
        }
1057 1
        incUsageCtfe(istate, s.loc);
1058 1
        if (istate.start)
1059
        {
1060 1
            if (istate.start != s)
1061 1
                return;
1062 0
            istate.start = null;
1063
        }
1064

1065 1
        istate.gotoTarget = findGotoTarget(istate, s.ident);
1066 1
        result = CTFEExp.breakexp;
1067
    }
1068

1069
    override void visit(ContinueStatement s)
1070
    {
1071
        debug (LOG)
1072
        {
1073
            printf("%s ContinueStatement::interpret()\n", s.loc.toChars());
1074
        }
1075 1
        incUsageCtfe(istate, s.loc);
1076 1
        if (istate.start)
1077
        {
1078 1
            if (istate.start != s)
1079 1
                return;
1080 0
            istate.start = null;
1081
        }
1082

1083 1
        istate.gotoTarget = findGotoTarget(istate, s.ident);
1084 1
        result = CTFEExp.continueexp;
1085
    }
1086

1087
    override void visit(WhileStatement s)
1088
    {
1089
        debug (LOG)
1090
        {
1091
            printf("WhileStatement::interpret()\n");
1092
        }
1093 0
        assert(0); // rewritten to ForStatement
1094
    }
1095

1096
    override void visit(DoStatement s)
1097
    {
1098
        debug (LOG)
1099
        {
1100
            printf("%s DoStatement::interpret()\n", s.loc.toChars());
1101
        }
1102 1
        if (istate.start == s)
1103 0
            istate.start = null;
1104

1105 1
        while (1)
1106
        {
1107 1
            Expression e = interpret(s._body, istate);
1108 1
            if (!e && istate.start) // goto target was not found
1109 1
                return;
1110 1
            assert(!istate.start);
1111

1112 1
            if (exceptionOrCant(e))
1113 0
                return;
1114 1
            if (e && e.op == TOK.break_)
1115
            {
1116 1
                if (istate.gotoTarget && istate.gotoTarget != s)
1117
                {
1118 0
                    result = e; // break at a higher level
1119 0
                    return;
1120
                }
1121 1
                istate.gotoTarget = null;
1122 1
                break;
1123
            }
1124 1
            if (e && e.op == TOK.continue_)
1125
            {
1126 1
                if (istate.gotoTarget && istate.gotoTarget != s)
1127
                {
1128 0
                    result = e; // continue at a higher level
1129 0
                    return;
1130
                }
1131 1
                istate.gotoTarget = null;
1132 1
                e = null;
1133
            }
1134 1
            if (e)
1135
            {
1136 1
                result = e; // bubbled up from ReturnStatement
1137 1
                return;
1138
            }
1139

1140 1
            UnionExp ue = void;
1141 1
            incUsageCtfe(istate, s.condition.loc);
1142 1
            e = interpret(&ue, s.condition, istate);
1143 1
            if (exceptionOrCant(e))
1144 0
                return;
1145 1
            if (!e.isConst())
1146
            {
1147 0
                result = CTFEExp.cantexp;
1148 0
                return;
1149
            }
1150 1
            if (e.isBool(false))
1151 1
                break;
1152 1
            assert(isTrueBool(e));
1153
        }
1154 1
        assert(result is null);
1155
    }
1156

1157
    override void visit(ForStatement s)
1158
    {
1159
        debug (LOG)
1160
        {
1161
            printf("%s ForStatement::interpret()\n", s.loc.toChars());
1162
        }
1163 1
        if (istate.start == s)
1164 0
            istate.start = null;
1165

1166 1
        UnionExp ueinit = void;
1167 1
        Expression ei = interpret(&ueinit, s._init, istate);
1168 1
        if (exceptionOrCant(ei))
1169 0
            return;
1170 1
        assert(!ei); // s.init never returns from function, or jumps out from it
1171

1172 1
        while (1)
1173
        {
1174 1
            if (s.condition && !istate.start)
1175
            {
1176 1
                UnionExp ue = void;
1177 1
                incUsageCtfe(istate, s.condition.loc);
1178 1
                Expression e = interpret(&ue, s.condition, istate);
1179 1
                if (exceptionOrCant(e))
1180 0
                    return;
1181 1
                if (e.isBool(false))
1182 1
                    break;
1183 1
                assert(isTrueBool(e));
1184
            }
1185

1186 1
            Expression e = interpret(pue, s._body, istate);
1187 1
            if (!e && istate.start) // goto target was not found
1188 1
                return;
1189 1
            assert(!istate.start);
1190

1191 1
            if (exceptionOrCant(e))
1192 0
                return;
1193 1
            if (e && e.op == TOK.break_)
1194
            {
1195 1
                if (istate.gotoTarget && istate.gotoTarget != s)
1196
                {
1197 0
                    result = e; // break at a higher level
1198 0
                    return;
1199
                }
1200 1
                istate.gotoTarget = null;
1201 1
                break;
1202
            }
1203 1
            if (e && e.op == TOK.continue_)
1204
            {
1205 1
                if (istate.gotoTarget && istate.gotoTarget != s)
1206
                {
1207 1
                    result = e; // continue at a higher level
1208 1
                    return;
1209
                }
1210 1
                istate.gotoTarget = null;
1211 1
                e = null;
1212
            }
1213 1
            if (e)
1214
            {
1215 1
                result = e; // bubbled up from ReturnStatement
1216 1
                return;
1217
            }
1218

1219 1
            UnionExp uei = void;
1220 1
            if (s.increment)
1221 1
                incUsageCtfe(istate, s.increment.loc);
1222 1
            e = interpret(&uei, s.increment, istate, CTFEGoal.Nothing);
1223 1
            if (exceptionOrCant(e))
1224 0
                return;
1225
        }
1226 1
        assert(result is null);
1227
    }
1228

1229
    override void visit(ForeachStatement s)
1230
    {
1231 0
        assert(0); // rewritten to ForStatement
1232
    }
1233

1234
    override void visit(ForeachRangeStatement s)
1235
    {
1236 0
        assert(0); // rewritten to ForStatement
1237
    }
1238

1239
    override void visit(SwitchStatement s)
1240
    {
1241
        debug (LOG)
1242
        {
1243
            printf("%s SwitchStatement::interpret()\n", s.loc.toChars());
1244
        }
1245 1
        incUsageCtfe(istate, s.loc);
1246 1
        if (istate.start == s)
1247 0
            istate.start = null;
1248 1
        if (istate.start)
1249
        {
1250 1
            Expression e = interpret(s._body, istate);
1251 1
            if (istate.start) // goto target was not found
1252 1
                return;
1253 1
            if (exceptionOrCant(e))
1254 0
                return;
1255 1
            if (e && e.op == TOK.break_)
1256
            {
1257 1
                if (istate.gotoTarget && istate.gotoTarget != s)
1258
                {
1259 1
                    result = e; // break at a higher level
1260 1
                    return;
1261
                }
1262 1
                istate.gotoTarget = null;
1263 1
                e = null;
1264
            }
1265 1
            result = e;
1266 1
            return;
1267
        }
1268

1269 1
        UnionExp uecond = void;
1270 1
        Expression econdition = interpret(&uecond, s.condition, istate);
1271 1
        if (exceptionOrCant(econdition))
1272 0
            return;
1273

1274 1
        Statement scase = null;
1275 1
        if (s.cases)
1276 1
            foreach (cs; *s.cases)
1277
            {
1278 1
                UnionExp uecase = void;
1279 1
                Expression ecase = interpret(&uecase, cs.exp, istate);
1280 1
                if (exceptionOrCant(ecase))
1281 0
                    return;
1282 1
                if (ctfeEqual(cs.exp.loc, TOK.equal, econdition, ecase))
1283
                {
1284 1
                    scase = cs;
1285 1
                    break;
1286
                }
1287
            }
1288 1
        if (!scase)
1289
        {
1290 1
            if (s.hasNoDefault)
1291 0
                s.error("no `default` or `case` for `%s` in `switch` statement", econdition.toChars());
1292 1
            scase = s.sdefault;
1293
        }
1294

1295 1
        assert(scase);
1296

1297
        /* Jump to scase
1298
         */
1299 1
        istate.start = scase;
1300 1
        Expression e = interpret(pue, s._body, istate);
1301 1
        assert(!istate.start); // jump must not fail
1302 1
        if (e && e.op == TOK.break_)
1303
        {
1304 1
            if (istate.gotoTarget && istate.gotoTarget != s)
1305
            {
1306 1
                result = e; // break at a higher level
1307 1
                return;
1308
            }
1309 1
            istate.gotoTarget = null;
1310 1
            e = null;
1311
        }
1312 1
        result = e;
1313
    }
1314

1315
    override void visit(CaseStatement s)
1316
    {
1317
        debug (LOG)
1318
        {
1319
            printf("%s CaseStatement::interpret(%s) this = %p\n", s.loc.toChars(), s.exp.toChars(), s);
1320
        }
1321 1
        incUsageCtfe(istate, s.loc);
1322 1
        if (istate.start == s)
1323 1
            istate.start = null;
1324

1325 1
        result = interpret(pue, s.statement, istate);
1326
    }
1327

1328
    override void visit(DefaultStatement s)
1329
    {
1330
        debug (LOG)
1331
        {
1332
            printf("%s DefaultStatement::interpret()\n", s.loc.toChars());
1333
        }
1334 1
        incUsageCtfe(istate, s.loc);
1335 1
        if (istate.start == s)
1336 1
            istate.start = null;
1337

1338 1
        result = interpret(pue, s.statement, istate);
1339
    }
1340

1341
    override void visit(GotoStatement s)
1342
    {
1343
        debug (LOG)
1344
        {
1345
            printf("%s GotoStatement::interpret()\n", s.loc.toChars());
1346
        }
1347 1
        if (istate.start)
1348
        {
1349 1
            if (istate.start != s)
1350 1
                return;
1351 0
            istate.start = null;
1352
        }
1353 1
        incUsageCtfe(istate, s.loc);
1354

1355 1
        assert(s.label && s.label.statement);
1356 1
        istate.gotoTarget = s.label.statement;
1357 1
        result = CTFEExp.gotoexp;
1358
    }
1359

1360
    override void visit(GotoCaseStatement s)
1361
    {
1362
        debug (LOG)
1363
        {
1364
            printf("%s GotoCaseStatement::interpret()\n", s.loc.toChars());
1365
        }
1366 1
        if (istate.start)
1367
        {
1368 1
            if (istate.start != s)
1369 1
                return;
1370 0
            istate.start = null;
1371
        }
1372 1
        incUsageCtfe(istate, s.loc);
1373

1374 1
        assert(s.cs);
1375 1
        istate.gotoTarget = s.cs;
1376 1
        result = CTFEExp.gotoexp;
1377
    }
1378

1379
    override void visit(GotoDefaultStatement s)
1380
    {
1381
        debug (LOG)
1382
        {
1383
            printf("%s GotoDefaultStatement::interpret()\n", s.loc.toChars());
1384
        }
1385 1
        if (istate.start)
1386
        {
1387 1
            if (istate.start != s)
1388 1
                return;
1389 0
            istate.start = null;
1390
        }
1391 1
        incUsageCtfe(istate, s.loc);
1392

1393 1
        assert(s.sw && s.sw.sdefault);
1394 1
        istate.gotoTarget = s.sw.sdefault;
1395 1
        result = CTFEExp.gotoexp;
1396
    }
1397

1398
    override void visit(LabelStatement s)
1399
    {
1400
        debug (LOG)
1401
        {
1402
            printf("%s LabelStatement::interpret()\n", s.loc.toChars());
1403
        }
1404 1
        if (istate.start == s)
1405 1
            istate.start = null;
1406

1407 1
        result = interpret(pue, s.statement, istate);
1408
    }
1409

1410
    override void visit(TryCatchStatement s)
1411
    {
1412
        debug (LOG)
1413
        {
1414
            printf("%s TryCatchStatement::interpret()\n", s.loc.toChars());
1415
        }
1416 1
        if (istate.start == s)
1417 0
            istate.start = null;
1418 1
        if (istate.start)
1419
        {
1420 1
            Expression e = null;
1421 1
            e = interpret(pue, s._body, istate);
1422 1
            foreach (ca; *s.catches)
1423
            {
1424 1
                if (e || !istate.start) // goto target was found
1425 1
                    break;
1426 1
                e = interpret(pue, ca.handler, istate);
1427
            }
1428 1
            result = e;
1429 1
            return;
1430
        }
1431

1432 1
        Expression e = interpret(s._body, istate);
1433

1434
        // An exception was thrown
1435 1
        if (e && e.op == TOK.thrownException)
1436
        {
1437 1
            ThrownExceptionExp ex = cast(ThrownExceptionExp)e;
1438 1
            Type extype = ex.thrown.originalClass().type;
1439

1440
            // Search for an appropriate catch clause.
1441 1
            foreach (ca; *s.catches)
1442
            {
1443 1
                Type catype = ca.type;
1444 1
                if (!catype.equals(extype) && !catype.isBaseOf(extype, null))
1445 1
                    continue;
1446

1447
                // Execute the handler
1448 1
                if (ca.var)
1449
                {
1450 1
                    ctfeGlobals.stack.push(ca.var);
1451 1
                    setValue(ca.var, ex.thrown);
1452
                }
1453 1
                e = interpret(ca.handler, istate);
1454 1
                if (CTFEExp.isGotoExp(e))
1455
                {
1456
                    /* This is an optimization that relies on the locality of the jump target.
1457
                     * If the label is in the same catch handler, the following scan
1458
                     * would find it quickly and can reduce jump cost.
1459
                     * Otherwise, the catch block may be unnnecessary scanned again
1460
                     * so it would make CTFE speed slower.
1461
                     */
1462 1
                    InterState istatex = *istate;
1463 1
                    istatex.start = istate.gotoTarget; // set starting statement
1464 1
                    istatex.gotoTarget = null;
1465 1
                    Expression eh = interpret(ca.handler, &istatex);
1466 1
                    if (!istatex.start)
1467
                    {
1468 1
                        istate.gotoTarget = null;
1469 1
                        e = eh;
1470
                    }
1471
                }
1472 1
                break;
1473
            }
1474
        }
1475 1
        result = e;
1476
    }
1477

1478
    static bool isAnErrorException(ClassDeclaration cd)
1479
    {
1480 1
        return cd == ClassDeclaration.errorException || ClassDeclaration.errorException.isBaseOf(cd, null);
1481
    }
1482

1483
    static ThrownExceptionExp chainExceptions(ThrownExceptionExp oldest, ThrownExceptionExp newest)
1484
    {
1485
        debug (LOG)
1486
        {
1487
            printf("Collided exceptions %s %s\n", oldest.thrown.toChars(), newest.thrown.toChars());
1488
        }
1489
        // Little sanity check to make sure it's really a Throwable
1490 1
        ClassReferenceExp boss = oldest.thrown;
1491 1
        const next = 4;                         // index of Throwable.next
1492 1
        assert((*boss.value.elements)[next].type.ty == Tclass); // Throwable.next
1493 1
        ClassReferenceExp collateral = newest.thrown;
1494 1
        if (isAnErrorException(collateral.originalClass()) && !isAnErrorException(boss.originalClass()))
1495
        {
1496
            /* Find the index of the Error.bypassException field
1497
             */
1498 1
            auto bypass = next + 1;
1499 1
            if ((*collateral.value.elements)[bypass].type.ty == Tuns32)
1500 1
                bypass += 1;  // skip over _refcount field
1501 1
            assert((*collateral.value.elements)[bypass].type.ty == Tclass);
1502

1503
            // The new exception bypass the existing chain
1504 1
            (*collateral.value.elements)[bypass] = boss;
1505 1
            return newest;
1506
        }
1507 1
        while ((*boss.value.elements)[next].op == TOK.classReference)
1508
        {
1509 1
            boss = cast(ClassReferenceExp)(*boss.value.elements)[next];
1510
        }
1511 1
        (*boss.value.elements)[next] = collateral;
1512 1
        return oldest;
1513
    }
1514

1515
    override void visit(TryFinallyStatement s)
1516
    {
1517
        debug (LOG)
1518
        {
1519
            printf("%s TryFinallyStatement::interpret()\n", s.loc.toChars());
1520
        }
1521 1
        if (istate.start == s)
1522 0
            istate.start = null;
1523 1
        if (istate.start)
1524
        {
1525 1
            Expression e = null;
1526 1
            e = interpret(pue, s._body, istate);
1527
            // Jump into/out from finalbody is disabled in semantic analysis.
1528
            // and jump inside will be handled by the ScopeStatement == finalbody.
1529 1
            result = e;
1530 1
            return;
1531
        }
1532

1533 1
        Expression ex = interpret(s._body, istate);
1534 1
        if (CTFEExp.isCantExp(ex))
1535
        {
1536 0
            result = ex;
1537 0
            return;
1538
        }
1539 1
        while (CTFEExp.isGotoExp(ex))
1540
        {
1541
            // If the goto target is within the body, we must not interpret the finally statement,
1542
            // because that will call destructors for objects within the scope, which we should not do.
1543 1
            InterState istatex = *istate;
1544 1
            istatex.start = istate.gotoTarget; // set starting statement
1545 1
            istatex.gotoTarget = null;
1546 1
            Expression bex = interpret(s._body, &istatex);
1547 1
            if (istatex.start)
1548
            {
1549
                // The goto target is outside the current scope.
1550 1
                break;
1551
            }
1552
            // The goto target was within the body.
1553 1
            if (CTFEExp.isCantExp(bex))
1554
            {
1555 0
                result = bex;
1556 0
                return;
1557
            }
1558 1
            *istate = istatex;
1559 1
            ex = bex;
1560
        }
1561

1562 1
        Expression ey = interpret(s.finalbody, istate);
1563 1
        if (CTFEExp.isCantExp(ey))
1564
        {
1565 0
            result = ey;
1566 0
            return;
1567
        }
1568 1
        if (ey && ey.op == TOK.thrownException)
1569
        {
1570
            // Check for collided exceptions
1571 1
            if (ex && ex.op == TOK.thrownException)
1572 1
                ex = chainExceptions(cast(ThrownExceptionExp)ex, cast(ThrownExceptionExp)ey);
1573
            else
1574 0
                ex = ey;
1575
        }
1576 1
        result = ex;
1577
    }
1578

1579
    override void visit(ThrowStatement s)
1580
    {
1581
        debug (LOG)
1582
        {
1583
            printf("%s ThrowStatement::interpret()\n", s.loc.toChars());
1584
        }
1585 1
        if (istate.start)
1586
        {
1587 1
            if (istate.start != s)
1588 1
                return;
1589 0
            istate.start = null;
1590
        }
1591

1592 1
        incUsageCtfe(istate, s.loc);
1593

1594 1
        Expression e = interpretRegion(s.exp, istate);
1595 1
        if (exceptionOrCant(e))
1596 0
            return;
1597

1598 1
        assert(e.op == TOK.classReference);
1599 1
        result = ctfeEmplaceExp!ThrownExceptionExp(s.loc, e.isClassReferenceExp());
1600
    }
1601

1602
    override void visit(ScopeGuardStatement s)
1603
    {
1604 0
        assert(0);
1605
    }
1606

1607
    override void visit(WithStatement s)
1608
    {
1609
        debug (LOG)
1610
        {
1611
            printf("%s WithStatement::interpret()\n", s.loc.toChars());
1612
        }
1613 1
        if (istate.start == s)
1614 0
            istate.start = null;
1615 1
        if (istate.start)
1616
        {
1617 1
            result = s._body ? interpret(s._body, istate) : null;
1618 1
            return;
1619
        }
1620

1621
        // If it is with(Enum) {...}, just execute the body.
1622 1
        if (s.exp.op == TOK.scope_ || s.exp.op == TOK.type)
1623
        {
1624 1
            result = interpret(pue, s._body, istate);
1625 1
            return;
1626
        }
1627

1628 1
        incUsageCtfe(istate, s.loc);
1629

1630 1
        Expression e = interpret(s.exp, istate);
1631 1
        if (exceptionOrCant(e))
1632 0
            return;
1633

1634 1
        if (s.wthis.type.ty == Tpointer && s.exp.type.ty != Tpointer)
1635
        {
1636 1
            e = ctfeEmplaceExp!AddrExp(s.loc, e, s.wthis.type);
1637
        }
1638 1
        ctfeGlobals.stack.push(s.wthis);
1639 1
        setValue(s.wthis, e);
1640 1
        e = interpret(s._body, istate);
1641 1
        if (CTFEExp.isGotoExp(e))
1642
        {
1643
            /* This is an optimization that relies on the locality of the jump target.
1644
             * If the label is in the same WithStatement, the following scan
1645
             * would find it quickly and can reduce jump cost.
1646
             * Otherwise, the statement body may be unnnecessary scanned again
1647
             * so it would make CTFE speed slower.
1648
             */
1649 1
            InterState istatex = *istate;
1650 1
            istatex.start = istate.gotoTarget; // set starting statement
1651 1
            istatex.gotoTarget = null;
1652 1
            Expression ex = interpret(s._body, &istatex);
1653 1
            if (!istatex.start)
1654
            {
1655 1
                istate.gotoTarget = null;
1656 1
                e = ex;
1657
            }
1658
        }
1659 1
        ctfeGlobals.stack.pop(s.wthis);
1660 1
        result = e;
1661
    }
1662

1663
    override void visit(AsmStatement s)
1664
    {
1665
        debug (LOG)
1666
        {
1667
            printf("%s AsmStatement::interpret()\n", s.loc.toChars());
1668
        }
1669 0
        if (istate.start)
1670
        {
1671 0
            if (istate.start != s)
1672 0
                return;
1673 0
            istate.start = null;
1674
        }
1675 0
        s.error("`asm` statements cannot be interpreted at compile time");
1676 0
        result = CTFEExp.cantexp;
1677
    }
1678

1679
    override void visit(ImportStatement s)
1680
    {
1681
        debug (LOG)
1682
        {
1683
            printf("ImportStatement::interpret()\n");
1684
        }
1685 1
        if (istate.start)
1686
        {
1687 1
            if (istate.start != s)
1688 1
                return;
1689 0
            istate.start = null;
1690
        }
1691
    }
1692

1693
    /******************************** Expression ***************************/
1694

1695
    override void visit(Expression e)
1696
    {
1697
        debug (LOG)
1698
        {
1699
            printf("%s Expression::interpret() '%s' %s\n", e.loc.toChars(), Token.toChars(e.op), e.toChars());
1700
            printf("type = %s\n", e.type.toChars());
1701
            showCtfeExpr(e);
1702
        }
1703 1
        e.error("cannot interpret `%s` at compile time", e.toChars());
1704 1
        result = CTFEExp.cantexp;
1705
    }
1706

1707
    override void visit(TypeExp e)
1708
    {
1709
        debug (LOG)
1710
        {
1711
            printf("%s TypeExp.interpret() %s\n", e.loc.toChars(), e.toChars());
1712
        }
1713 1
        result = e;
1714
    }
1715

1716
    override void visit(ThisExp e)
1717
    {
1718
        debug (LOG)
1719
        {
1720
            printf("%s ThisExp::interpret() %s\n", e.loc.toChars(), e.toChars());
1721
        }
1722 1
        if (goal == CTFEGoal.LValue)
1723
        {
1724
            // We might end up here with istate being zero
1725
            // https://issues.dlang.org/show_bug.cgi?id=16382
1726 1
            if (istate && istate.fd.vthis)
1727
            {
1728 1
                result = ctfeEmplaceExp!VarExp(e.loc, istate.fd.vthis);
1729 1
                if (istate.fd.isThis2)
1730
                {
1731 1
                    result = ctfeEmplaceExp!PtrExp(e.loc, result);
1732 1
                    result.type = Type.tvoidptr.sarrayOf(2);
1733 1
                    result = ctfeEmplaceExp!IndexExp(e.loc, result, IntegerExp.literal!0);
1734
                }
1735 1
                result.type = e.type;
1736
            }
1737
            else
1738 1
                result = e;
1739 1
            return;
1740
        }
1741

1742 1
        result = ctfeGlobals.stack.getThis();
1743 1
        if (result)
1744
        {
1745 1
            if (istate && istate.fd.isThis2)
1746
            {
1747 1
                assert(result.op == TOK.address);
1748 1
                result = (cast(AddrExp)result).e1;
1749 1
                assert(result.op == TOK.arrayLiteral);
1750 1
                result = (*(cast(ArrayLiteralExp)result).elements)[0];
1751 1
                if (e.type.ty == Tstruct)
1752
                {
1753 1
                    result = (cast(AddrExp)result).e1;
1754
                }
1755 1
                return;
1756
            }
1757 1
            assert(result.op == TOK.structLiteral || result.op == TOK.classReference || result.op == TOK.type);
1758 1
            return;
1759
        }
1760 1
        e.error("value of `this` is not known at compile time");
1761 1
        result = CTFEExp.cantexp;
1762
    }
1763

1764
    override void visit(NullExp e)
1765
    {
1766 1
        result = e;
1767
    }
1768

1769
    override void visit(IntegerExp e)
1770
    {
1771
        debug (LOG)
1772
        {
1773
            printf("%s IntegerExp::interpret() %s\n", e.loc.toChars(), e.toChars());
1774
        }
1775 1
        result = e;
1776
    }
1777

1778
    override void visit(RealExp e)
1779
    {
1780
        debug (LOG)
1781
        {
1782
            printf("%s RealExp::interpret() %s\n", e.loc.toChars(), e.toChars());
1783
        }
1784 1
        result = e;
1785
    }
1786

1787
    override void visit(ComplexExp e)
1788
    {
1789 1
        result = e;
1790
    }
1791

1792
    override void visit(StringExp e)
1793
    {
1794
        debug (LOG)
1795
        {
1796
            printf("%s StringExp::interpret() %s\n", e.loc.toChars(), e.toChars());
1797
        }
1798
        /* Attempts to modify string literals are prevented
1799
         * in BinExp::interpretAssignCommon.
1800
         */
1801 1
        result = e;
1802
    }
1803

1804
    override void visit(FuncExp e)
1805
    {
1806
        debug (LOG)
1807
        {
1808
            printf("%s FuncExp::interpret() %s\n", e.loc.toChars(), e.toChars());
1809
        }
1810 1
        result = e;
1811
    }
1812

1813
    override void visit(SymOffExp e)
1814
    {
1815
        debug (LOG)
1816
        {
1817
            printf("%s SymOffExp::interpret() %s\n", e.loc.toChars(), e.toChars());
1818
        }
1819 1
        if (e.var.isFuncDeclaration() && e.offset == 0)
1820
        {
1821 1
            result = e;
1822 1
            return;
1823
        }
1824 1
        if (isTypeInfo_Class(e.type) && e.offset == 0)
1825
        {
1826 1
            result = e;
1827 1
            return;
1828
        }
1829 1
        if (e.type.ty != Tpointer)
1830
        {
1831
            // Probably impossible
1832 0
            e.error("cannot interpret `%s` at compile time", e.toChars());
1833 0
            result = CTFEExp.cantexp;
1834 0
            return;
1835
        }
1836 1
        Type pointee = (cast(TypePointer)e.type).next;
1837 1
        if (e.var.isThreadlocal())
1838
        {
1839 1
            e.error("cannot take address of thread-local variable %s at compile time", e.var.toChars());
1840 1
            result = CTFEExp.cantexp;
1841 1
            return;
1842
        }
1843
        // Check for taking an address of a shared variable.
1844
        // If the shared variable is an array, the offset might not be zero.
1845 1
        Type fromType = null;
1846 1
        if (e.var.type.ty == Tarray || e.var.type.ty == Tsarray)
1847
        {
1848 1
            fromType = (cast(TypeArray)e.var.type).next;
1849
        }
1850 1
        if (e.var.isDataseg() && ((e.offset == 0 && isSafePointerCast(e.var.type, pointee)) || (fromType && isSafePointerCast(fromType, pointee))))
1851
        {
1852 1
            result = e;
1853 1
            return;
1854
        }
1855

1856 1
        Expression val = getVarExp(e.loc, istate, e.var, goal);
1857 1
        if (exceptionOrCant(val))
1858 1
            return;
1859 1
        if (val.type.ty == Tarray || val.type.ty == Tsarray)
1860
        {
1861
            // Check for unsupported type painting operations
1862 1
            Type elemtype = (cast(TypeArray)val.type).next;
1863 1
            d_uns64 elemsize = elemtype.size();
1864

1865
            // It's OK to cast from fixed length to fixed length array, eg &int[n] to int[d]*.
1866 1
            if (val.type.ty == Tsarray && pointee.ty == Tsarray && elemsize == pointee.nextOf().size())
1867
            {
1868 1
                size_t d = cast(size_t)(cast(TypeSArray)pointee).dim.toInteger();
1869 1
                Expression elwr = ctfeEmplaceExp!IntegerExp(e.loc, e.offset / elemsize, Type.tsize_t);
1870 1
                Expression eupr = ctfeEmplaceExp!IntegerExp(e.loc, e.offset / elemsize + d, Type.tsize_t);
1871

1872
                // Create a CTFE pointer &val[ofs..ofs+d]
1873 1
                auto se = ctfeEmplaceExp!SliceExp(e.loc, val, elwr, eupr);
1874 1
                se.type = pointee;
1875 1
                emplaceExp!(AddrExp)(pue, e.loc, se, e.type);
1876 1
                result = pue.exp();
1877 1
                return;
1878
            }
1879

1880 1
            if (!isSafePointerCast(elemtype, pointee))
1881
            {
1882
                // It's also OK to cast from &string to string*.
1883 1
                if (e.offset == 0 && isSafePointerCast(e.var.type, pointee))
1884
                {
1885
                    // Create a CTFE pointer &var
1886 1
                    auto ve = ctfeEmplaceExp!VarExp(e.loc, e.var);
1887 1
                    ve.type = elemtype;
1888 1
                    emplaceExp!(AddrExp)(pue, e.loc, ve, e.type);
1889 1
                    result = pue.exp();
1890 1
                    return;
1891
                }
1892 1
                e.error("reinterpreting cast from `%s` to `%s` is not supported in CTFE", val.type.toChars(), e.type.toChars());
1893 1
                result = CTFEExp.cantexp;
1894 1
                return;
1895
            }
1896

1897 1
            const dinteger_t sz = pointee.size();
1898 1
            dinteger_t indx = e.offset / sz;
1899 1
            assert(sz * indx == e.offset);
1900 1
            Expression aggregate = null;
1901 1
            if (val.op == TOK.arrayLiteral || val.op == TOK.string_)
1902
            {
1903 1
                aggregate = val;
1904
            }
1905 0
            else if (auto se = val.isSliceExp())
1906
            {
1907 0
                aggregate = se.e1;
1908 0
                UnionExp uelwr = void;
1909 0
                Expression lwr = interpret(&uelwr, se.lwr, istate);
1910 0
                indx += lwr.toInteger();
1911
            }
1912 1
            if (aggregate)
1913
            {
1914
                // Create a CTFE pointer &aggregate[ofs]
1915 1
                auto ofs = ctfeEmplaceExp!IntegerExp(e.loc, indx, Type.tsize_t);
1916 1
                auto ei = ctfeEmplaceExp!IndexExp(e.loc, aggregate, ofs);
1917 1
                ei.type = elemtype;
1918 1
                emplaceExp!(AddrExp)(pue, e.loc, ei, e.type);
1919 1
                result = pue.exp();
1920 1
                return;
1921
            }
1922
        }
1923 1
        else if (e.offset == 0 && isSafePointerCast(e.var.type, pointee))
1924
        {
1925
            // Create a CTFE pointer &var
1926 1
            auto ve = ctfeEmplaceExp!VarExp(e.loc, e.var);
1927 1
            ve.type = e.var.type;
1928 1
            emplaceExp!(AddrExp)(pue, e.loc, ve, e.type);
1929 1
            result = pue.exp();
1930 1
            return;
1931
        }
1932

1933 1
        e.error("cannot convert `&%s` to `%s` at compile time", e.var.type.toChars(), e.type.toChars());
1934 1
        result = CTFEExp.cantexp;
1935
    }
1936

1937
    override void visit(AddrExp e)
1938
    {
1939
        debug (LOG)
1940
        {
1941
            printf("%s AddrExp::interpret() %s\n", e.loc.toChars(), e.toChars());
1942
        }
1943 1
        if (auto ve = e.e1.isVarExp())
1944
        {
1945 1
            Declaration decl = ve.var;
1946

1947
            // We cannot take the address of an imported symbol at compile time
1948 1
            if (decl.isImportedSymbol()) {
1949 1
                e.error("cannot take address of imported symbol `%s` at compile time", decl.toChars());
1950 1
                result = CTFEExp.cantexp;
1951 1
                return;
1952
            }
1953

1954 1
            if (decl.isDataseg()) {
1955
                // Normally this is already done by optimize()
1956
                // Do it here in case optimize(WANTvalue) wasn't run before CTFE
1957 1
                emplaceExp!(SymOffExp)(pue, e.loc, (cast(VarExp)e.e1).var, 0);
1958 1
                result = pue.exp();
1959 1
                result.type = e.type;
1960 1
                return;
1961
            }
1962
        }
1963 1
        auto er = interpret(e.e1, istate, CTFEGoal.LValue);
1964 1
        if (auto ve = er.isVarExp())
1965 1
            if (ve.var == istate.fd.vthis)
1966 1
                er = interpret(er, istate);
1967

1968 1
        if (exceptionOrCant(er))
1969 1
            return;
1970

1971
        // Return a simplified address expression
1972 1
        emplaceExp!(AddrExp)(pue, e.loc, er, e.type);
1973 1
        result = pue.exp();
1974
    }
1975

1976
    override void visit(DelegateExp e)
1977
    {
1978
        debug (LOG)
1979
        {
1980
            printf("%s DelegateExp::interpret() %s\n", e.loc.toChars(), e.toChars());
1981
        }
1982
        // TODO: Really we should create a CTFE-only delegate expression
1983
        // of a pointer and a funcptr.
1984

1985
        // If it is &nestedfunc, just return it
1986
        // TODO: We should save the context pointer
1987 1
        if (auto ve1 = e.e1.isVarExp())
1988 1
            if (ve1.var == e.func)
1989
            {
1990 1
                result = e;
1991 1
                return;
1992
            }
1993

1994 1
        auto er = interpret(pue, e.e1, istate);
1995 1
        if (exceptionOrCant(er))
1996 0
            return;
1997 1
        if (er == e.e1)
1998
        {
1999
            // If it has already been CTFE'd, just return it
2000 1
            result = e;
2001
        }
2002
        else
2003
        {
2004 1
            er = (er == pue.exp()) ? pue.copy() : er;
2005 1
            emplaceExp!(DelegateExp)(pue, e.loc, er, e.func, false);
2006 1
            result = pue.exp();
2007 1
            result.type = e.type;
2008
        }
2009
    }
2010

2011
    static Expression getVarExp(const ref Loc loc, InterState* istate, Declaration d, CTFEGoal goal)
2012
    {
2013 1
        Expression e = CTFEExp.cantexp;
2014 1
        if (VarDeclaration v = d.isVarDeclaration())
2015
        {
2016
            /* Magic variable __ctfe always returns true when interpreting
2017
             */
2018 1
            if (v.ident == Id.ctfe)
2019 1
                return IntegerExp.createBool(true);
2020

2021 1
            if (!v.originalType && v.semanticRun < PASS.semanticdone) // semantic() not yet run
2022
            {
2023 1
                v.dsymbolSemantic(null);
2024 1
                if (v.type.ty == Terror)
2025 0
                    return CTFEExp.cantexp;
2026
            }
2027

2028 1
            if ((v.isConst() || v.isImmutable() || v.storage_class & STC.manifest) && !hasValue(v) && v._init && !v.isCTFE())
2029
            {
2030 1
                if (v.inuse)
2031
                {
2032 1
                    error(loc, "circular initialization of %s `%s`", v.kind(), v.toPrettyChars());
2033 1
                    return CTFEExp.cantexp;
2034
                }
2035 1
                if (v._scope)
2036
                {
2037 1
                    v.inuse++;
2038 1
                    v._init = v._init.initializerSemantic(v._scope, v.type, INITinterpret); // might not be run on aggregate members
2039 1
                    v.inuse--;
2040
                }
2041 1
                e = v._init.initializerToExpression(v.type);
2042 1
                if (!e)
2043 0
                    return CTFEExp.cantexp;
2044 1
                assert(e.type);
2045

2046 1
                if (e.op == TOK.construct || e.op == TOK.blit)
2047
                {
2048 1
                    AssignExp ae = cast(AssignExp)e;
2049 1
                    e = ae.e2;
2050
                }
2051

2052 1
                if (e.op == TOK.error)
2053
                {
2054
                    // FIXME: Ultimately all errors should be detected in prior semantic analysis stage.
2055
                }
2056 1
                else if (v.isDataseg() || (v.storage_class & STC.manifest))
2057
                {
2058
                    /* https://issues.dlang.org/show_bug.cgi?id=14304
2059
                     * e is a value that is not yet owned by CTFE.
2060
                     * Mark as "cached", and use it directly during interpretation.
2061
                     */
2062 1
                    e = scrubCacheValue(e);
2063 1
                    ctfeGlobals.stack.saveGlobalConstant(v, e);
2064
                }
2065
                else
2066
                {
2067 1
                    v.inuse++;
2068 1
                    e = interpret(e, istate);
2069 1
                    v.inuse--;
2070 1
                    if (CTFEExp.isCantExp(e) && !global.gag && !ctfeGlobals.stackTraceCallsToSuppress)
2071 0
                        errorSupplemental(loc, "while evaluating %s.init", v.toChars());
2072 1
                    if (exceptionOrCantInterpret(e))
2073 1
                        return e;
2074
                }
2075
            }
2076 1
            else if (v.isCTFE() && !hasValue(v))
2077
            {
2078 1
                if (v._init && v.type.size() != 0)
2079
                {
2080 1
                    if (v._init.isVoidInitializer())
2081
                    {
2082
                        // var should have been initialized when it was created
2083 0
                        error(loc, "CTFE internal error: trying to access uninitialized var");
2084 0
                        assert(0);
2085
                    }
2086 1
                    e = v._init.initializerToExpression();
2087
                }
2088
                else
2089 1
                    e = v.type.defaultInitLiteral(e.loc);
2090

2091 1
                e = interpret(e, istate);
2092
            }
2093 1
            else if (!(v.isDataseg() || v.storage_class & STC.manifest) && !v.isCTFE() && !istate)
2094
            {
2095 1
                error(loc, "variable `%s` cannot be read at compile time", v.toChars());
2096 1
                return CTFEExp.cantexp;
2097
            }
2098
            else
2099
            {
2100 1
                e = hasValue(v) ? getValue(v) : null;
2101 1
                if (!e && !v.isCTFE() && v.isDataseg())
2102
                {
2103 1
                    error(loc, "static variable `%s` cannot be read at compile time", v.toChars());
2104 1
                    return CTFEExp.cantexp;
2105
                }
2106 1
                if (!e)
2107
                {
2108 1
                    assert(!(v._init && v._init.isVoidInitializer()));
2109
                    // CTFE initiated from inside a function
2110 1
                    error(loc, "variable `%s` cannot be read at compile time", v.toChars());
2111 1
                    return CTFEExp.cantexp;
2112
                }
2113 1
                if (auto vie = e.isVoidInitExp())
2114
                {
2115 1
                    error(loc, "cannot read uninitialized variable `%s` in ctfe", v.toPrettyChars());
2116 1
                    errorSupplemental(vie.var.loc, "`%s` was uninitialized and used before set", vie.var.toChars());
2117 1
                    return CTFEExp.cantexp;
2118
                }
2119 1
                if (goal != CTFEGoal.LValue && (v.isRef() || v.isOut()))
2120 1
                    e = interpret(e, istate, goal);
2121
            }
2122 1
            if (!e)
2123 0
                e = CTFEExp.cantexp;
2124
        }
2125 1
        else if (SymbolDeclaration s = d.isSymbolDeclaration())
2126
        {
2127
            // Struct static initializers, for example
2128 1
            e = s.dsym.type.defaultInitLiteral(loc);
2129 1
            if (e.op == TOK.error)
2130 1
                error(loc, "CTFE failed because of previous errors in `%s.init`", s.toChars());
2131 1
            e = e.expressionSemantic(null);
2132 1
            if (e.op == TOK.error)
2133 1
                e = CTFEExp.cantexp;
2134
            else // Convert NULL to CTFEExp
2135 1
                e = interpret(e, istate, goal);
2136
        }
2137
        else
2138 0
            error(loc, "cannot interpret declaration `%s` at compile time", d.toChars());
2139 1
        return e;
2140
    }
2141

2142
    override void visit(VarExp e)
2143
    {
2144
        debug (LOG)
2145
        {
2146
            printf("%s VarExp::interpret() `%s`, goal = %d\n", e.loc.toChars(), e.toChars(), goal);
2147
        }
2148 1
        if (e.var.isFuncDeclaration())
2149
        {
2150 1
            result = e;
2151 1
            return;
2152
        }
2153

2154 1
        if (goal == CTFEGoal.LValue)
2155
        {
2156 1
            if (auto v = e.var.isVarDeclaration())
2157
            {
2158 1
                if (!v.isDataseg() && !v.isCTFE() && !istate)
2159
                {
2160 1
                    e.error("variable `%s` cannot be read at compile time", v.toChars());
2161 1
                    result = CTFEExp.cantexp;
2162 1
                    return;
2163
                }
2164 1
                if (!hasValue(v))
2165
                {
2166 1
                    if (!v.isCTFE() && v.isDataseg())
2167 1
                        e.error("static variable `%s` cannot be read at compile time", v.toChars());
2168
                    else // CTFE initiated from inside a function
2169 1
                        e.error("variable `%s` cannot be read at compile time", v.toChars());
2170 1
                    result = CTFEExp.cantexp;
2171 1
                    return;
2172
                }
2173

2174 1
                if (v.storage_class & (STC.out_ | STC.ref_))
2175
                {
2176
                    // Strip off the nest of ref variables
2177 1
                    Expression ev = getValue(v);
2178 1
                    if (ev.op == TOK.variable ||
2179 1
                        ev.op == TOK.index ||
2180 1
                        ev.op == TOK.slice ||
2181 1
                        ev.op == TOK.dotVariable)
2182
                    {
2183 1
                        result = interpret(pue, ev, istate, goal);
2184 1
                        return;
2185
                    }
2186
                }
2187
            }
2188 1
            result = e;
2189 1
            return;
2190
        }
2191 1
        result = getVarExp(e.loc, istate, e.var, goal);
2192 1
        if (exceptionOrCant(result))
2193 1
            return;
2194 1
        if ((e.var.storage_class & (STC.ref_ | STC.out_)) == 0 && e.type.baseElemOf().ty != Tstruct)
2195
        {
2196
            /* Ultimately, STC.ref_|STC.out_ check should be enough to see the
2197
             * necessity of type repainting. But currently front-end paints
2198
             * non-ref struct variables by the const type.
2199
             *
2200
             *  auto foo(ref const S cs);
2201
             *  S s;
2202
             *  foo(s); // VarExp('s') will have const(S)
2203
             */
2204
            // A VarExp may include an implicit cast. It must be done explicitly.
2205 1
            result = paintTypeOntoLiteral(pue, e.type, result);
2206
        }
2207
    }
2208

2209
    override void visit(DeclarationExp e)
2210
    {
2211
        debug (LOG)
2212
        {
2213
            printf("%s DeclarationExp::interpret() %s\n", e.loc.toChars(), e.toChars());
2214
        }
2215 1
        Dsymbol s = e.declaration;
2216 1
        if (VarDeclaration v = s.isVarDeclaration())
2217
        {
2218 1
            if (TupleDeclaration td = v.toAlias().isTupleDeclaration())
2219
            {
2220 1
                result = null;
2221

2222
                // Reserve stack space for all tuple members
2223 1
                if (!td.objects)
2224 0
                    return;
2225 1
                foreach (o; *td.objects)
2226
                {
2227 1
                    Expression ex = isExpression(o);
2228 1
                    DsymbolExp ds = ex ? ex.isDsymbolExp() : null;
2229 1
                    VarDeclaration v2 = ds ? ds.s.isVarDeclaration() : null;
2230 1
                    assert(v2);
2231 1
                    if (v2.isDataseg() && !v2.isCTFE())
2232 0
                        continue;
2233

2234 1
                    ctfeGlobals.stack.push(v2);
2235 1
                    if (v2._init)
2236
                    {
2237 1
                        Expression einit;
2238 1
                        if (ExpInitializer ie = v2._init.isExpInitializer())
2239
                        {
2240 1
                            einit = interpretRegion(ie.exp, istate, goal);
2241 1
                            if (exceptionOrCant(einit))
2242 0
                                return;
2243
                        }
2244 0
                        else if (v2._init.isVoidInitializer())
2245
                        {
2246 0
                            einit = voidInitLiteral(v2.type, v2).copy();
2247
                        }
2248
                        else
2249
                        {
2250 0
                            e.error("declaration `%s` is not yet implemented in CTFE", e.toChars());
2251 0
                            result = CTFEExp.cantexp;
2252 0
                            return;
2253
                        }
2254 1
                        setValue(v2, einit);
2255
                    }
2256
                }
2257 1
                return;
2258
            }
2259 1
            if (v.isStatic())
2260
            {
2261
                // Just ignore static variables which aren't read or written yet
2262 1
                result = null;
2263 1
                return;
2264
            }
2265 1
            if (!(v.isDataseg() || v.storage_class & STC.manifest) || v.isCTFE())
2266 1
                ctfeGlobals.stack.push(v);
2267 1
            if (v._init)
2268
            {
2269 1
                if (ExpInitializer ie = v._init.isExpInitializer())
2270
                {
2271 1
                    result = interpretRegion(ie.exp, istate, goal);
2272
                }
2273 1
                else if (v._init.isVoidInitializer())
2274
                {
2275 1
                    result = voidInitLiteral(v.type, v).copy();
2276
                    // There is no AssignExp for void initializers,
2277
                    // so set it here.
2278 1
                    setValue(v, result);
2279
                }
2280
                else
2281
                {
2282 0
                    e.error("declaration `%s` is not yet implemented in CTFE", e.toChars());
2283 0
                    result = CTFEExp.cantexp;
2284
                }
2285
            }
2286 1
            else if (v.type.size() == 0)
2287
            {
2288
                // Zero-length arrays don't need an initializer
2289 1
                result = v.type.defaultInitLiteral(e.loc);
2290
            }
2291
            else
2292
            {
2293 0
                e.error("variable `%s` cannot be modified at compile time", v.toChars());
2294 0
                result = CTFEExp.cantexp;
2295
            }
2296 1
            return;
2297
        }
2298 1
        if (s.isAttribDeclaration() || s.isTemplateMixin() || s.isTupleDeclaration())
2299
        {
2300
            // Check for static struct declarations, which aren't executable
2301 1
            AttribDeclaration ad = e.declaration.isAttribDeclaration();
2302 1
            if (ad && ad.decl && ad.decl.dim == 1)
2303
            {
2304 1
                Dsymbol sparent = (*ad.decl)[0];
2305 1
                if (sparent.isAggregateDeclaration() || sparent.isTemplateDeclaration() || sparent.isAliasDeclaration())
2306
                {
2307 1
                    result = null;
2308 1
                    return; // static (template) struct declaration. Nothing to do.
2309
                }
2310
            }
2311

2312
            // These can be made to work, too lazy now
2313 0
            e.error("declaration `%s` is not yet implemented in CTFE", e.toChars());
2314 0
            result = CTFEExp.cantexp;
2315 0
            return;
2316
        }
2317

2318
        // Others should not contain executable code, so are trivial to evaluate
2319 1
        result = null;
2320
        debug (LOG)
2321
        {
2322
            printf("-DeclarationExp::interpret(%s): %p\n", e.toChars(), result);
2323
        }
2324
    }
2325

2326
    override void visit(TypeidExp e)
2327
    {
2328
        debug (LOG)
2329
        {
2330
            printf("%s TypeidExp::interpret() %s\n", e.loc.toChars(), e.toChars());
2331
        }
2332 1
        if (Type t = isType(e.obj))
2333
        {
2334 1
            result = e;
2335 1
            return;
2336
        }
2337 1
        if (Expression ex = isExpression(e.obj))
2338
        {
2339 1
            result = interpret(pue, ex, istate);
2340 1
            if (exceptionOrCant(ex))
2341 0
                return;
2342

2343 1
            if (result.op == TOK.null_)
2344
            {
2345 1
                e.error("null pointer dereference evaluating typeid. `%s` is `null`", ex.toChars());
2346 1
                result = CTFEExp.cantexp;
2347 1
                return;
2348
            }
2349 1
            if (result.op != TOK.classReference)
2350
            {
2351 0
                e.error("CTFE internal error: determining classinfo");
2352 0
                result = CTFEExp.cantexp;
2353 0
                return;
2354
            }
2355

2356 1
            ClassDeclaration cd = (cast(ClassReferenceExp)result).originalClass();
2357 1
            assert(cd);
2358

2359 1
            emplaceExp!(TypeidExp)(pue, e.loc, cd.type);
2360 1
            result = pue.exp();
2361 1
            result.type = e.type;
2362 1
            return;
2363
        }
2364 0
        visit(cast(Expression)e);
2365
    }
2366

2367
    override void visit(TupleExp e)
2368
    {
2369
        debug (LOG)
2370
        {
2371
            printf("%s TupleExp::interpret() %s\n", e.loc.toChars(), e.toChars());
2372
        }
2373 1
        if (exceptionOrCant(interpretRegion(e.e0, istate, CTFEGoal.Nothing)))
2374 0
            return;
2375

2376 1
        auto expsx = e.exps;
2377 1
        foreach (i, exp; *expsx)
2378
        {
2379 1
            Expression ex = interpretRegion(exp, istate);
2380 1
            if (exceptionOrCant(ex))
2381 0
                return;
2382

2383
            // A tuple of assignments can contain void (Bug 5676).
2384 1
            if (goal == CTFEGoal.Nothing)
2385 1
                continue;
2386 1
            if (ex.op == TOK.voidExpression)
2387
            {
2388 0
                e.error("CTFE internal error: void element `%s` in tuple", exp.toChars());
2389 0
                assert(0);
2390
            }
2391

2392
            /* If any changes, do Copy On Write
2393
             */
2394 1
            if (ex !is exp)
2395
            {
2396 0
                expsx = copyArrayOnWrite(expsx, e.exps);
2397 0
                (*expsx)[i] = copyRegionExp(ex);
2398
            }
2399
        }
2400

2401 1
        if (expsx !is e.exps)
2402
        {
2403 0
            expandTuples(expsx);
2404 0
            emplaceExp!(TupleExp)(pue, e.loc, expsx);
2405 0
            result = pue.exp();
2406 0
            result.type = new TypeTuple(expsx);
2407
        }
2408
        else
2409 1
            result = e;
2410
    }
2411

2412
    override void visit(ArrayLiteralExp e)
2413
    {
2414
        debug (LOG)
2415
        {
2416
            printf("%s ArrayLiteralExp::interpret() %s\n", e.loc.toChars(), e.toChars());
2417
        }
2418 1
        if (e.ownedByCtfe >= OwnedBy.ctfe) // We've already interpreted all the elements
2419
        {
2420 1
            result = e;
2421 1
            return;
2422
        }
2423

2424 1
        Type tn = e.type.toBasetype().nextOf().toBasetype();
2425 1
        bool wantCopy = (tn.ty == Tsarray || tn.ty == Tstruct);
2426

2427 1
        auto basis = interpretRegion(e.basis, istate);
2428 1
        if (exceptionOrCant(basis))
2429 0
            return;
2430

2431 1
        auto expsx = e.elements;
2432 1
        size_t dim = expsx ? expsx.dim : 0;
2433 1
        for (size_t i = 0; i < dim; i++)
2434
        {
2435 1
            Expression exp = (*expsx)[i];
2436 1
            Expression ex;
2437 1
            if (!exp)
2438
            {
2439 1
                ex = copyLiteral(basis).copy();
2440
            }
2441
            else
2442
            {
2443
                // segfault bug 6250
2444 1
                assert(exp.op != TOK.index || (cast(IndexExp)exp).e1 != e);
2445

2446 1
                ex = interpretRegion(exp, istate);
2447 1
                if (exceptionOrCant(ex))
2448 1
                    return;
2449

2450
                /* Each elements should have distinct CTFE memory.
2451
                 *  int[1] z = 7;
2452
                 *  int[1][] pieces = [z,z];    // here
2453
                 */
2454 1
                if (wantCopy)
2455 1
                    ex = copyLiteral(ex).copy();
2456
            }
2457

2458
            /* If any changes, do Copy On Write
2459
             */
2460 1
            if (ex !is exp)
2461
            {
2462 1
                expsx = copyArrayOnWrite(expsx, e.elements);
2463 1
                (*expsx)[i] = ex;
2464
            }
2465
        }
2466

2467 1
        if (expsx !is e.elements)
2468
        {
2469
            // todo: all tuple expansions should go in semantic phase.
2470 1
            expandTuples(expsx);
2471 1
            if (expsx.dim != dim)
2472
            {
2473 0
                e.error("CTFE internal error: invalid array literal");
2474 0
                result = CTFEExp.cantexp;
2475 0
                return;
2476
            }
2477 1
            emplaceExp!(ArrayLiteralExp)(pue, e.loc, e.type, basis, expsx);
2478 1
            auto ale = cast(ArrayLiteralExp)pue.exp();
2479 1
            ale.ownedByCtfe = OwnedBy.ctfe;
2480 1
            result = ale;
2481
        }
2482 1
        else if ((cast(TypeNext)e.type).next.mod & (MODFlags.const_ | MODFlags.immutable_))
2483
        {
2484
            // If it's immutable, we don't need to dup it
2485 1
            result = e;
2486
        }
2487
        else
2488
        {
2489 1
            *pue = copyLiteral(e);
2490 1
            result = pue.exp();
2491
        }
2492
    }
2493

2494
    override void visit(AssocArrayLiteralExp e)
2495
    {
2496
        debug (LOG)
2497
        {
2498
            printf("%s AssocArrayLiteralExp::interpret() %s\n", e.loc.toChars(), e.toChars());
2499
        }
2500 1
        if (e.ownedByCtfe >= OwnedBy.ctfe) // We've already interpreted all the elements
2501
        {
2502 1
            result = e;
2503 1
            return;
2504
        }
2505

2506 1
        auto keysx = e.keys;
2507 1
        auto valuesx = e.values;
2508 1
        foreach (i, ekey; *keysx)
2509
        {
2510 1
            auto evalue = (*valuesx)[i];
2511

2512 1
            auto ek = interpretRegion(ekey, istate);
2513 1
            if (exceptionOrCant(ek))
2514 0
                return;
2515 1
            auto ev = interpretRegion(evalue, istate);
2516 1
            if (exceptionOrCant(ev))
2517 0
                return;
2518

2519
            /* If any changes, do Copy On Write
2520
             */
2521 1
            if (ek !is ekey ||
2522 1
                ev !is evalue)
2523
            {
2524 1
                keysx = copyArrayOnWrite(keysx, e.keys);
2525 1
                valuesx = copyArrayOnWrite(valuesx, e.values);
2526 1
                (*keysx)[i] = ek;
2527 1
                (*valuesx)[i] = ev;
2528
            }
2529
        }
2530 1
        if (keysx !is e.keys)
2531 1
            expandTuples(keysx);
2532 1
        if (valuesx !is e.values)
2533 1
            expandTuples(valuesx);
2534 1
        if (keysx.dim != valuesx.dim)
2535
        {
2536 0
            e.error("CTFE internal error: invalid AA");
2537 0
            result = CTFEExp.cantexp;
2538 0
            return;
2539
        }
2540

2541
        /* Remove duplicate keys
2542
         */
2543 1
        for (size_t i = 1; i < keysx.dim; i++)
2544
        {
2545 1
            auto ekey = (*keysx)[i - 1];
2546 1
            for (size_t j = i; j < keysx.dim; j++)
2547
            {
2548 1
                auto ekey2 = (*keysx)[j];
2549 1
                if (!ctfeEqual(e.loc, TOK.equal, ekey, ekey2))
2550 1
                    continue;
2551

2552
                // Remove ekey
2553 1
                keysx = copyArrayOnWrite(keysx, e.keys);
2554 1
                valuesx = copyArrayOnWrite(valuesx, e.values);
2555 1
                keysx.remove(i - 1);
2556 1
                valuesx.remove(i - 1);
2557

2558 1
                i -= 1; // redo the i'th iteration
2559 1
                break;
2560
            }
2561
        }
2562

2563 1
        if (keysx !is e.keys ||
2564 1
            valuesx !is e.values)
2565
        {
2566 1
            assert(keysx !is e.keys &&
2567 1
                   valuesx !is e.values);
2568 1
            auto aae = ctfeEmplaceExp!AssocArrayLiteralExp(e.loc, keysx, valuesx);
2569 1
            aae.type = e.type;
2570 1
            aae.ownedByCtfe = OwnedBy.ctfe;
2571 1
            result = aae;
2572
        }
2573
        else
2574
        {
2575 1
            *pue = copyLiteral(e);
2576 1
            result = pue.exp();
2577
        }
2578
    }
2579

2580
    override void visit(StructLiteralExp e)
2581
    {
2582
        debug (LOG)
2583
        {
2584
            printf("%s StructLiteralExp::interpret() %s ownedByCtfe = %d\n", e.loc.toChars(), e.toChars(), e.ownedByCtfe);
2585
        }
2586 1
        if (e.ownedByCtfe >= OwnedBy.ctfe)
2587
        {
2588 1
            result = e;
2589 1
            return;
2590
        }
2591

2592 1
        size_t dim = e.elements ? e.elements.dim : 0;
2593 1
        auto expsx = e.elements;
2594

2595 1
        if (dim != e.sd.fields.dim)
2596
        {
2597
            // guaranteed by AggregateDeclaration.fill and TypeStruct.defaultInitLiteral
2598 1
            const nvthis = e.sd.fields.dim - e.sd.nonHiddenFields();
2599 1
            assert(e.sd.fields.dim - dim == nvthis);
2600

2601
            /* If a nested struct has no initialized hidden pointer,
2602
             * set it to null to match the runtime behaviour.
2603
             */
2604 1
            foreach (const i; 0 .. nvthis)
2605
            {
2606 1
                auto ne = ctfeEmplaceExp!NullExp(e.loc);
2607 1
                auto vthis = i == 0 ? e.sd.vthis : e.sd.vthis2;
2608 1
                ne.type = vthis.type;
2609

2610 1
                expsx = copyArrayOnWrite(expsx, e.elements);
2611 1
                expsx.push(ne);
2612 1
                ++dim;
2613
            }
2614
        }
2615 1
        assert(dim == e.sd.fields.dim);
2616

2617 1
        foreach (i; 0 .. dim)
2618
        {
2619 1
            auto v = e.sd.fields[i];
2620 1
            Expression exp = (*expsx)[i];
2621 1
            Expression ex;
2622 1
            if (!exp)
2623
            {
2624 1
                ex = voidInitLiteral(v.type, v).copy();
2625
            }
2626
            else
2627
            {
2628 1
                ex = interpretRegion(exp, istate);
2629 1
                if (exceptionOrCant(ex))
2630 1
                    return;
2631 1
                if ((v.type.ty != ex.type.ty) && v.type.ty == Tsarray)
2632
                {
2633
                    // Block assignment from inside struct literals
2634 1
                    auto tsa = cast(TypeSArray)v.type;
2635 1
                    auto len = cast(size_t)tsa.dim.toInteger();
2636 1
                    UnionExp ue = void;
2637 1
                    ex = createBlockDuplicatedArrayLiteral(&ue, ex.loc, v.type, ex, len);
2638 1
                    if (ex == ue.exp())
2639 1
                        ex = ue.copy();
2640
                }
2641
            }
2642

2643
            /* If any changes, do Copy On Write
2644
             */
2645 1
            if (ex !is exp)
2646
            {
2647 1
                expsx = copyArrayOnWrite(expsx, e.elements);
2648 1
                (*expsx)[i] = ex;
2649
            }
2650
        }
2651

2652 1
        if (expsx !is e.elements)
2653
        {
2654 1
            expandTuples(expsx);
2655 1
            if (expsx.dim != e.sd.fields.dim)
2656
            {
2657 0
                e.error("CTFE internal error: invalid struct literal");
2658 0
                result = CTFEExp.cantexp;
2659 0
                return;
2660
            }
2661 1
            emplaceExp!(StructLiteralExp)(pue, e.loc, e.sd, expsx);
2662 1
            auto sle = cast(StructLiteralExp)pue.exp();
2663 1
            sle.type = e.type;
2664 1
            sle.ownedByCtfe = OwnedBy.ctfe;
2665 1
            sle.origin = e.origin;
2666 1
            result = sle;
2667
        }
2668
        else
2669
        {
2670 1
            *pue = copyLiteral(e);
2671 1
            result = pue.exp();
2672
        }
2673
    }
2674

2675
    // Create an array literal of type 'newtype' with dimensions given by
2676
    // 'arguments'[argnum..$]
2677
    static Expression recursivelyCreateArrayLiteral(UnionExp* pue, const ref Loc loc, Type newtype, InterState* istate, Expressions* arguments, int argnum)
2678
    {
2679 1
        Expression lenExpr = interpret(pue, (*arguments)[argnum], istate);
2680 1
        if (exceptionOrCantInterpret(lenExpr))
2681 0
            return lenExpr;
2682 1
        size_t len = cast(size_t)lenExpr.toInteger();
2683 1
        Type elemType = (cast(TypeArray)newtype).next;
2684 1
        if (elemType.ty == Tarray && argnum < arguments.dim - 1)
2685
        {
2686 1
            Expression elem = recursivelyCreateArrayLiteral(pue, loc, elemType, istate, arguments, argnum + 1);
2687 1
            if (exceptionOrCantInterpret(elem))
2688 0
                return elem;
2689

2690 1
            auto elements = new Expressions(len);
2691 1
            foreach (ref element; *elements)
2692 1
                element = copyLiteral(elem).copy();
2693 1
            emplaceExp!(ArrayLiteralExp)(pue, loc, newtype, elements);
2694 1
            auto ae = cast(ArrayLiteralExp)pue.exp();
2695 1
            ae.ownedByCtfe = OwnedBy.ctfe;
2696 1
            return ae;
2697
        }
2698 1
        assert(argnum == arguments.dim - 1);
2699 1
        if (elemType.ty.isSomeChar)
2700
        {
2701 1
            const ch = cast(dchar)elemType.defaultInitLiteral(loc).toInteger();
2702 1
            const sz = cast(ubyte)elemType.size();
2703 1
            return createBlockDuplicatedStringLiteral(pue, loc, newtype, ch, len, sz);
2704
        }
2705
        else
2706
        {
2707 1
            auto el = interpret(elemType.defaultInitLiteral(loc), istate);
2708 1
            return createBlockDuplicatedArrayLiteral(pue, loc, newtype, el, len);
2709
        }
2710
    }
2711

2712
    override void visit(NewExp e)
2713
    {
2714
        debug (LOG)
2715
        {
2716
            printf("%s NewExp::interpret() %s\n", e.loc.toChars(), e.toChars());
2717
        }
2718 1
        if (e.allocator)
2719
        {
2720 0
            e.error("member allocators not supported by CTFE");
2721 0
            result = CTFEExp.cantexp;
2722 0
            return;
2723
        }
2724

2725 1
        Expression epre = interpret(pue, e.argprefix, istate, CTFEGoal.Nothing);
2726 1
        if (exceptionOrCant(epre))
2727 0
            return;
2728

2729 1
        if (e.newtype.ty == Tarray && e.arguments)
2730
        {
2731 1
            result = recursivelyCreateArrayLiteral(pue, e.loc, e.newtype, istate, e.arguments, 0);
2732 1
            return;
2733
        }
2734 1
        if (auto ts = e.newtype.toBasetype().isTypeStruct())
2735
        {
2736 1
            if (e.member)
2737
            {
2738 1
                Expression se = e.newtype.defaultInitLiteral(e.loc);
2739 1
                se = interpret(se, istate);
2740 1
                if (exceptionOrCant(se))
2741 0
                    return;
2742 1
                result = interpretFunction(pue, e.member, istate, e.arguments, se);
2743

2744
                // Repaint as same as CallExp::interpret() does.
2745 1
                result.loc = e.loc;
2746
            }
2747
            else
2748
            {
2749 1
                StructDeclaration sd = ts.sym;
2750 1
                auto exps = new Expressions();
2751 1
                exps.reserve(sd.fields.dim);
2752 1
                if (e.arguments)
2753
                {
2754 1
                    exps.setDim(e.arguments.dim);
2755 1
                    foreach (i, ex; *e.arguments)
2756
                    {
2757 1
                        ex = interpretRegion(ex, istate);
2758 1
                        if (exceptionOrCant(ex))
2759 0
                            return;
2760 1
                        (*exps)[i] = ex;
2761
                    }
2762
                }
2763 1
                sd.fill(e.loc, exps, false);
2764

2765 1
                auto se = ctfeEmplaceExp!StructLiteralExp(e.loc, sd, exps, e.newtype);
2766 1
                se.origin = se;
2767 1
                se.type = e.newtype;
2768 1
                se.ownedByCtfe = OwnedBy.ctfe;
2769 1
                result = interpret(pue, se, istate);
2770
            }
2771 1
            if (exceptionOrCant(result))
2772 0
                return;
2773 1
            Expression ev = (result == pue.exp()) ? pue.copy() : result;
2774 1
            emplaceExp!(AddrExp)(pue, e.loc, ev, e.type);
2775 1
            result = pue.exp();
2776 1
            return;
2777
        }
2778 1
        if (auto tc = e.newtype.toBasetype().isTypeClass())
2779
        {
2780 1
            ClassDeclaration cd = tc.sym;
2781 1
            size_t totalFieldCount = 0;
2782 1
            for (ClassDeclaration c = cd; c; c = c.baseClass)
2783 1
                totalFieldCount += c.fields.dim;
2784 1
            auto elems = new Expressions(totalFieldCount);
2785 1
            size_t fieldsSoFar = totalFieldCount;
2786 1
            for (ClassDeclaration c = cd; c; c = c.baseClass)
2787
            {
2788 1
                fieldsSoFar -= c.fields.dim;
2789 1
                foreach (i, v; c.fields)
2790
                {
2791 1
                    if (v.inuse)
2792
                    {
2793 1
                        e.error("circular reference to `%s`", v.toPrettyChars());
2794 1
                        result = CTFEExp.cantexp;
2795 1
                        return;
2796
                    }
2797 1
                    Expression m;
2798 1
                    if (v._init)
2799
                    {
2800 1
                        if (v._init.isVoidInitializer())
2801 0
                            m = voidInitLiteral(v.type, v).copy();
2802
                        else
2803 1
                            m = v.getConstInitializer(true);
2804
                    }
2805
                    else
2806 1
                        m = v.type.defaultInitLiteral(e.loc);
2807 1
                    if (exceptionOrCant(m))
2808 0
                        return;
2809 1
                    (*elems)[fieldsSoFar + i] = copyLiteral(m).copy();
2810
                }
2811
            }
2812
            // Hack: we store a ClassDeclaration instead of a StructDeclaration.
2813
            // We probably won't get away with this.
2814
//            auto se = new StructLiteralExp(e.loc, cast(StructDeclaration)cd, elems, e.newtype);
2815 1
            auto se = ctfeEmplaceExp!StructLiteralExp(e.loc, cast(StructDeclaration)cd, elems, e.newtype);
2816 1
            se.origin = se;
2817 1
            se.ownedByCtfe = OwnedBy.ctfe;
2818 1
            emplaceExp!(ClassReferenceExp)(pue, e.loc, se, e.type);
2819 1
            Expression eref = pue.exp();
2820 1
            if (e.member)
2821
            {
2822
                // Call constructor
2823 1
                if (!e.member.fbody)
2824
                {
2825 0
                    Expression ctorfail = evaluateIfBuiltin(pue, istate, e.loc, e.member, e.arguments, eref);
2826 0
                    if (ctorfail)
2827
                    {
2828 0
                        if (exceptionOrCant(ctorfail))
2829 0
                            return;
2830 0
                        result = eref;
2831 0
                        return;
2832
                    }
2833 0
                    e.member.error("`%s` cannot be constructed at compile time, because the constructor has no available source code", e.newtype.toChars());
2834 0
                    result = CTFEExp.cantexp;
2835 0
                    return;
2836
                }
2837 1
                UnionExp ue = void;
2838 1
                Expression ctorfail = interpretFunction(&ue, e.member, istate, e.arguments, eref);
2839 1
                if (exceptionOrCant(ctorfail))
2840 1
                    return;
2841

2842
                /* https://issues.dlang.org/show_bug.cgi?id=14465
2843
                 * Repaint the loc, because a super() call
2844
                 * in the constructor modifies the loc of ClassReferenceExp
2845
                 * in CallExp::interpret().
2846
                 */
2847 1
                eref.loc = e.