1 // Compiler implementation of the D programming language
2 // Copyright (c) 1999-2016 by Digital Mars
3 // All Rights Reserved
4 // written by Walter Bright
5 // http://www.digitalmars.com
6 // Distributed under the Boost Software License, Version 1.0.
7 // http://www.boost.org/LICENSE_1_0.txt
8 
9 module ddmd.dinterpret;
10 
11 import core.stdc.stdio;
12 import core.stdc..string;
13 import ddmd.apply;
14 import ddmd.arraytypes;
15 import ddmd.attrib;
16 import ddmd.builtin;
17 import ddmd.constfold;
18 import ddmd.ctfeexpr;
19 import ddmd.dclass;
20 import ddmd.declaration;
21 import ddmd.dstruct;
22 import ddmd.dsymbol;
23 import ddmd.dtemplate;
24 import ddmd.errors;
25 import ddmd.expression;
26 import ddmd.func;
27 import ddmd.globals;
28 import ddmd.id;
29 import ddmd.identifier;
30 import ddmd.init;
31 import ddmd.mtype;
32 import ddmd.root.array;
33 import ddmd.root.rootobject;
34 import ddmd.statement;
35 import ddmd.tokens;
36 import ddmd.utf;
37 import ddmd.visitor;
38 
39 enum CtfeGoal : int
40 {
41     ctfeNeedRvalue,     // Must return an Rvalue (== CTFE value)
42     ctfeNeedLvalue,     // Must return an Lvalue (== CTFE reference)
43     ctfeNeedNothing,    // The return value is not required
44 }
45 
46 alias ctfeNeedRvalue = CtfeGoal.ctfeNeedRvalue;
47 alias ctfeNeedLvalue = CtfeGoal.ctfeNeedLvalue;
48 alias ctfeNeedNothing = CtfeGoal.ctfeNeedNothing;
49 
50 //debug = LOG;
51 //debug = LOGASSIGN;
52 //debug = LOGCOMPILE;
53 //debug = SHOWPERFORMANCE;
54 
55 // Maximum allowable recursive function calls in CTFE
56 enum CTFE_RECURSION_LIMIT = 1000;
57 
58 /**
59  The values of all CTFE variables
60  */
61 struct CtfeStack
62 {
63 private:
64     /* The stack. Every declaration we encounter is pushed here,
65      * together with the VarDeclaration, and the previous
66      * stack address of that variable, so that we can restore it
67      * when we leave the stack frame.
68      * Note that when a function is forward referenced, the interpreter must
69      * run semantic3, and that may start CTFE again with a NULL istate. Thus
70      * the stack might not be empty when CTFE begins.
71      *
72      * Ctfe Stack addresses are just 0-based integers, but we save
73      * them as 'void *' because Array can only do pointers.
74      */
75     Expressions values;         // values on the stack
76     VarDeclarations vars;       // corresponding variables
77     Array!(void*) savedId;      // id of the previous state of that var
78 
79     Array!(void*) frames;       // all previous frame pointers
80     Expressions savedThis;      // all previous values of localThis
81 
82     /* Global constants get saved here after evaluation, so we never
83      * have to redo them. This saves a lot of time and memory.
84      */
85     Expressions globalValues;   // values of global constants
86 
87     size_t framepointer;        // current frame pointer
88     size_t maxStackPointer;     // most stack we've ever used
89     Expression localThis;       // value of 'this', or NULL if none
90 
91 public:
92     extern (C++) size_t stackPointer()
93     {
94         return values.dim;
95     }
96 
97     // The current value of 'this', or NULL if none
98     extern (C++) Expression getThis()
99     {
100         return localThis;
101     }
102 
103     // Largest number of stack positions we've used
104     extern (C++) size_t maxStackUsage()
105     {
106         return maxStackPointer;
107     }
108 
109     // Start a new stack frame, using the provided 'this'.
110     extern (C++) void startFrame(Expression thisexp)
111     {
112         frames.push(cast(void*)cast(size_t)framepointer);
113         savedThis.push(localThis);
114         framepointer = stackPointer();
115         localThis = thisexp;
116     }
117 
118     extern (C++) void endFrame()
119     {
120         size_t oldframe = cast(size_t)frames[frames.dim - 1];
121         localThis = savedThis[savedThis.dim - 1];
122         popAll(framepointer);
123         framepointer = oldframe;
124         frames.setDim(frames.dim - 1);
125         savedThis.setDim(savedThis.dim - 1);
126     }
127 
128     extern (C++) bool isInCurrentFrame(VarDeclaration v)
129     {
130         if (v.isDataseg() && !v.isCTFE())
131             return false; // It's a global
132         return v.ctfeAdrOnStack >= framepointer;
133     }
134 
135     extern (C++) Expression getValue(VarDeclaration v)
136     {
137         if ((v.isDataseg() || v.storage_class & STCmanifest) && !v.isCTFE())
138         {
139             assert(v.ctfeAdrOnStack >= 0 && v.ctfeAdrOnStack < globalValues.dim);
140             return globalValues[v.ctfeAdrOnStack];
141         }
142         assert(v.ctfeAdrOnStack >= 0 && v.ctfeAdrOnStack < stackPointer());
143         return values[v.ctfeAdrOnStack];
144     }
145 
146     extern (C++) void setValue(VarDeclaration v, Expression e)
147     {
148         assert(!v.isDataseg() || v.isCTFE());
149         assert(v.ctfeAdrOnStack >= 0 && v.ctfeAdrOnStack < stackPointer());
150         values[v.ctfeAdrOnStack] = e;
151     }
152 
153     extern (C++) void push(VarDeclaration v)
154     {
155         assert(!v.isDataseg() || v.isCTFE());
156         if (v.ctfeAdrOnStack != cast(size_t)-1 && v.ctfeAdrOnStack >= framepointer)
157         {
158             // Already exists in this frame, reuse it.
159             values[v.ctfeAdrOnStack] = null;
160             return;
161         }
162         savedId.push(cast(void*)cast(size_t)v.ctfeAdrOnStack);
163         v.ctfeAdrOnStack = cast(int)values.dim;
164         vars.push(v);
165         values.push(null);
166     }
167 
168     extern (C++) void pop(VarDeclaration v)
169     {
170         assert(!v.isDataseg() || v.isCTFE());
171         assert(!(v.storage_class & (STCref | STCout)));
172         int oldid = v.ctfeAdrOnStack;
173         v.ctfeAdrOnStack = cast(int)cast(size_t)savedId[oldid];
174         if (v.ctfeAdrOnStack == values.dim - 1)
175         {
176             values.pop();
177             vars.pop();
178             savedId.pop();
179         }
180     }
181 
182     extern (C++) void popAll(size_t stackpointer)
183     {
184         if (stackPointer() > maxStackPointer)
185             maxStackPointer = stackPointer();
186         assert(values.dim >= stackpointer);
187         for (size_t i = stackpointer; i < values.dim; ++i)
188         {
189             VarDeclaration v = vars[i];
190             v.ctfeAdrOnStack = cast(int)cast(size_t)savedId[i];
191         }
192         values.setDim(stackpointer);
193         vars.setDim(stackpointer);
194         savedId.setDim(stackpointer);
195     }
196 
197     extern (C++) void saveGlobalConstant(VarDeclaration v, Expression e)
198     {
199         assert(v._init && (v.isConst() || v.isImmutable() || v.storage_class & STCmanifest) && !v.isCTFE());
200         v.ctfeAdrOnStack = cast(int)globalValues.dim;
201         globalValues.push(e);
202     }
203 }
204 
205 struct InterState
206 {
207     InterState* caller;     // calling function's InterState
208     FuncDeclaration fd;     // function being interpreted
209     Statement start;        // if !=NULL, start execution at this statement
210 
211     /* target of CTFEExp result; also
212      * target of labelled CTFEExp or
213      * CTFEExp. (null if no label).
214      */
215     Statement gotoTarget;
216 }
217 
218 extern (C++) __gshared CtfeStack ctfeStack;
219 
220 // CTFE diagnostic information
221 extern (C++) void printCtfePerformanceStats()
222 {
223     debug (SHOWPERFORMANCE)
224     {
225         printf("        ---- CTFE Performance ----\n");
226         printf("max call depth = %d\tmax stack = %d\n", CtfeStatus.maxCallDepth, ctfeStack.maxStackUsage());
227         printf("array allocs = %d\tassignments = %d\n\n", CtfeStatus.numArrayAllocs, CtfeStatus.numAssignments);
228     }
229 }
230 
231 /***********************************************************
232  * CTFE-object code for a single function
233  *
234  * Currently only counts the number of local variables in the function
235  */
236 struct CompiledCtfeFunction
237 {
238     FuncDeclaration func; // Function being compiled, NULL if global scope
239     int numVars; // Number of variables declared in this function
240     Loc callingloc;
241 
242     extern (D) this(FuncDeclaration f)
243     {
244         func = f;
245     }
246 
247     extern (C++) void onDeclaration(VarDeclaration v)
248     {
249         //printf("%s CTFE declare %s\n", v->loc.toChars(), v->toChars());
250         ++numVars;
251     }
252 
253     extern (C++) void onExpression(Expression e)
254     {
255         extern (C++) final class VarWalker : StoppableVisitor
256         {
257             alias visit = super.visit;
258         public:
259             CompiledCtfeFunction* ccf;
260 
261             extern (D) this(CompiledCtfeFunction* ccf)
262             {
263                 this.ccf = ccf;
264             }
265 
266             override void visit(Expression e)
267             {
268             }
269 
270             override void visit(ErrorExp e)
271             {
272                 // Currently there's a front-end bug: silent errors
273                 // can occur inside delegate literals inside is(typeof()).
274                 // Suppress the check in this case.
275                 if (global.gag && ccf.func)
276                 {
277                     stop = 1;
278                     return;
279                 }
280                 .error(e.loc, "CTFE internal error: ErrorExp in %s\n", ccf.func ? ccf.func.loc.toChars() : ccf.callingloc.toChars());
281                 assert(0);
282             }
283 
284             override void visit(DeclarationExp e)
285             {
286                 VarDeclaration v = e.declaration.isVarDeclaration();
287                 if (!v)
288                     return;
289                 TupleDeclaration td = v.toAlias().isTupleDeclaration();
290                 if (td)
291                 {
292                     if (!td.objects)
293                         return;
294                     for (size_t i = 0; i < td.objects.dim; ++i)
295                     {
296                         RootObject o = td.objects.tdata()[i];
297                         Expression ex = isExpression(o);
298                         DsymbolExp s = (ex && ex.op == TOKdsymbol) ? cast(DsymbolExp)ex : null;
299                         assert(s);
300                         VarDeclaration v2 = s.s.isVarDeclaration();
301                         assert(v2);
302                         if (!v2.isDataseg() || v2.isCTFE())
303                             ccf.onDeclaration(v2);
304                     }
305                 }
306                 else if (!(v.isDataseg() || v.storage_class & STCmanifest) || v.isCTFE())
307                     ccf.onDeclaration(v);
308                 Dsymbol s = v.toAlias();
309                 if (s == v && !v.isStatic() && v._init)
310                 {
311                     ExpInitializer ie = v._init.isExpInitializer();
312                     if (ie)
313                         ccf.onExpression(ie.exp);
314                 }
315             }
316 
317             override void visit(IndexExp e)
318             {
319                 if (e.lengthVar)
320                     ccf.onDeclaration(e.lengthVar);
321             }
322 
323             override void visit(SliceExp e)
324             {
325                 if (e.lengthVar)
326                     ccf.onDeclaration(e.lengthVar);
327             }
328         }
329 
330         scope VarWalker v = new VarWalker(&this);
331         walkPostorder(e, v);
332     }
333 }
334 
335 extern (C++) final class CtfeCompiler : Visitor
336 {
337     alias visit = super.visit;
338 public:
339     CompiledCtfeFunction* ccf;
340 
341     extern (D) this(CompiledCtfeFunction* ccf)
342     {
343         this.ccf = ccf;
344     }
345 
346     override void visit(Statement s)
347     {
348         debug (LOGCOMPILE)
349         {
350             printf("%s Statement::ctfeCompile %s\n", s.loc.toChars(), s.toChars());
351         }
352         assert(0);
353     }
354 
355     override void visit(ExpStatement s)
356     {
357         debug (LOGCOMPILE)
358         {
359             printf("%s ExpStatement::ctfeCompile\n", s.loc.toChars());
360         }
361         if (s.exp)
362             ccf.onExpression(s.exp);
363     }
364 
365     override void visit(CompoundStatement s)
366     {
367         debug (LOGCOMPILE)
368         {
369             printf("%s CompoundStatement::ctfeCompile\n", s.loc.toChars());
370         }
371         for (size_t i = 0; i < s.statements.dim; i++)
372         {
373             Statement sx = (*s.statements)[i];
374             if (sx)
375                 ctfeCompile(sx);
376         }
377     }
378 
379     override void visit(UnrolledLoopStatement s)
380     {
381         debug (LOGCOMPILE)
382         {
383             printf("%s UnrolledLoopStatement::ctfeCompile\n", s.loc.toChars());
384         }
385         for (size_t i = 0; i < s.statements.dim; i++)
386         {
387             Statement sx = (*s.statements)[i];
388             if (sx)
389                 ctfeCompile(sx);
390         }
391     }
392 
393     override void visit(IfStatement s)
394     {
395         debug (LOGCOMPILE)
396         {
397             printf("%s IfStatement::ctfeCompile\n", s.loc.toChars());
398         }
399         ccf.onExpression(s.condition);
400         if (s.ifbody)
401             ctfeCompile(s.ifbody);
402         if (s.elsebody)
403             ctfeCompile(s.elsebody);
404     }
405 
406     override void visit(ScopeStatement s)
407     {
408         debug (LOGCOMPILE)
409         {
410             printf("%s ScopeStatement::ctfeCompile\n", s.loc.toChars());
411         }
412         if (s.statement)
413             ctfeCompile(s.statement);
414     }
415 
416     override void visit(OnScopeStatement s)
417     {
418         debug (LOGCOMPILE)
419         {
420             printf("%s OnScopeStatement::ctfeCompile\n", s.loc.toChars());
421         }
422         // rewritten to try/catch/finally
423         assert(0);
424     }
425 
426     override void visit(DoStatement s)
427     {
428         debug (LOGCOMPILE)
429         {
430             printf("%s DoStatement::ctfeCompile\n", s.loc.toChars());
431         }
432         ccf.onExpression(s.condition);
433         if (s._body)
434             ctfeCompile(s._body);
435     }
436 
437     override void visit(WhileStatement s)
438     {
439         debug (LOGCOMPILE)
440         {
441             printf("%s WhileStatement::ctfeCompile\n", s.loc.toChars());
442         }
443         // rewritten to ForStatement
444         assert(0);
445     }
446 
447     override void visit(ForStatement s)
448     {
449         debug (LOGCOMPILE)
450         {
451             printf("%s ForStatement::ctfeCompile\n", s.loc.toChars());
452         }
453         if (s._init)
454             ctfeCompile(s._init);
455         if (s.condition)
456             ccf.onExpression(s.condition);
457         if (s.increment)
458             ccf.onExpression(s.increment);
459         if (s._body)
460             ctfeCompile(s._body);
461     }
462 
463     override void visit(ForeachStatement s)
464     {
465         debug (LOGCOMPILE)
466         {
467             printf("%s ForeachStatement::ctfeCompile\n", s.loc.toChars());
468         }
469         // rewritten for ForStatement
470         assert(0);
471     }
472 
473     override void visit(SwitchStatement s)
474     {
475         debug (LOGCOMPILE)
476         {
477             printf("%s SwitchStatement::ctfeCompile\n", s.loc.toChars());
478         }
479         ccf.onExpression(s.condition);
480         // Note that the body contains the the Case and Default
481         // statements, so we only need to compile the expressions
482         for (size_t i = 0; i < s.cases.dim; i++)
483         {
484             ccf.onExpression((*s.cases)[i].exp);
485         }
486         if (s._body)
487             ctfeCompile(s._body);
488     }
489 
490     override void visit(CaseStatement s)
491     {
492         debug (LOGCOMPILE)
493         {
494             printf("%s CaseStatement::ctfeCompile\n", s.loc.toChars());
495         }
496         if (s.statement)
497             ctfeCompile(s.statement);
498     }
499 
500     override void visit(DefaultStatement s)
501     {
502         debug (LOGCOMPILE)
503         {
504             printf("%s DefaultStatement::ctfeCompile\n", s.loc.toChars());
505         }
506         if (s.statement)
507             ctfeCompile(s.statement);
508     }
509 
510     override void visit(GotoDefaultStatement s)
511     {
512         debug (LOGCOMPILE)
513         {
514             printf("%s GotoDefaultStatement::ctfeCompile\n", s.loc.toChars());
515         }
516     }
517 
518     override void visit(GotoCaseStatement s)
519     {
520         debug (LOGCOMPILE)
521         {
522             printf("%s GotoCaseStatement::ctfeCompile\n", s.loc.toChars());
523         }
524     }
525 
526     override void visit(SwitchErrorStatement s)
527     {
528         debug (LOGCOMPILE)
529         {
530             printf("%s SwitchErrorStatement::ctfeCompile\n", s.loc.toChars());
531         }
532     }
533 
534     override void visit(ReturnStatement s)
535     {
536         debug (LOGCOMPILE)
537         {
538             printf("%s ReturnStatement::ctfeCompile\n", s.loc.toChars());
539         }
540         if (s.exp)
541             ccf.onExpression(s.exp);
542     }
543 
544     override void visit(BreakStatement s)
545     {
546         debug (LOGCOMPILE)
547         {
548             printf("%s BreakStatement::ctfeCompile\n", s.loc.toChars());
549         }
550     }
551 
552     override void visit(ContinueStatement s)
553     {
554         debug (LOGCOMPILE)
555         {
556             printf("%s ContinueStatement::ctfeCompile\n", s.loc.toChars());
557         }
558     }
559 
560     override void visit(WithStatement s)
561     {
562         debug (LOGCOMPILE)
563         {
564             printf("%s WithStatement::ctfeCompile\n", s.loc.toChars());
565         }
566         // If it is with(Enum) {...}, just execute the body.
567         if (s.exp.op == TOKscope || s.exp.op == TOKtype)
568         {
569         }
570         else
571         {
572             ccf.onDeclaration(s.wthis);
573             ccf.onExpression(s.exp);
574         }
575         if (s._body)
576             ctfeCompile(s._body);
577     }
578 
579     override void visit(TryCatchStatement s)
580     {
581         debug (LOGCOMPILE)
582         {
583             printf("%s TryCatchStatement::ctfeCompile\n", s.loc.toChars());
584         }
585         if (s._body)
586             ctfeCompile(s._body);
587         for (size_t i = 0; i < s.catches.dim; i++)
588         {
589             Catch ca = (*s.catches)[i];
590             if (ca.var)
591                 ccf.onDeclaration(ca.var);
592             if (ca.handler)
593                 ctfeCompile(ca.handler);
594         }
595     }
596 
597     override void visit(TryFinallyStatement s)
598     {
599         debug (LOGCOMPILE)
600         {
601             printf("%s TryFinallyStatement::ctfeCompile\n", s.loc.toChars());
602         }
603         if (s._body)
604             ctfeCompile(s._body);
605         if (s.finalbody)
606             ctfeCompile(s.finalbody);
607     }
608 
609     override void visit(ThrowStatement s)
610     {
611         debug (LOGCOMPILE)
612         {
613             printf("%s ThrowStatement::ctfeCompile\n", s.loc.toChars());
614         }
615         ccf.onExpression(s.exp);
616     }
617 
618     override void visit(GotoStatement s)
619     {
620         debug (LOGCOMPILE)
621         {
622             printf("%s GotoStatement::ctfeCompile\n", s.loc.toChars());
623         }
624     }
625 
626     override void visit(LabelStatement s)
627     {
628         debug (LOGCOMPILE)
629         {
630             printf("%s LabelStatement::ctfeCompile\n", s.loc.toChars());
631         }
632         if (s.statement)
633             ctfeCompile(s.statement);
634     }
635 
636     override void visit(ImportStatement s)
637     {
638         debug (LOGCOMPILE)
639         {
640             printf("%s ImportStatement::ctfeCompile\n", s.loc.toChars());
641         }
642         // Contains no variables or executable code
643     }
644 
645     override void visit(ForeachRangeStatement s)
646     {
647         debug (LOGCOMPILE)
648         {
649             printf("%s ForeachRangeStatement::ctfeCompile\n", s.loc.toChars());
650         }
651         // rewritten for ForStatement
652         assert(0);
653     }
654 
655     override void visit(AsmStatement s)
656     {
657         debug (LOGCOMPILE)
658         {
659             printf("%s AsmStatement::ctfeCompile\n", s.loc.toChars());
660         }
661         // we can't compile asm statements
662     }
663 
664     void ctfeCompile(Statement s)
665     {
666         s.accept(this);
667     }
668 }
669 
670 /*************************************
671  * Compile this function for CTFE.
672  * At present, this merely allocates variables.
673  */
674 extern (C++) void ctfeCompile(FuncDeclaration fd)
675 {
676     debug (LOGCOMPILE)
677     {
678         printf("\n%s FuncDeclaration::ctfeCompile %s\n", fd.loc.toChars(), fd.toChars());
679     }
680     assert(!fd.ctfeCode);
681     assert(!fd.semantic3Errors);
682     assert(fd.semanticRun == PASSsemantic3done);
683 
684     fd.ctfeCode = new CompiledCtfeFunction(fd);
685     if (fd.parameters)
686     {
687         Type tb = fd.type.toBasetype();
688         assert(tb.ty == Tfunction);
689         for (size_t i = 0; i < fd.parameters.dim; i++)
690         {
691             VarDeclaration v = (*fd.parameters)[i];
692             fd.ctfeCode.onDeclaration(v);
693         }
694     }
695     if (fd.vresult)
696         fd.ctfeCode.onDeclaration(fd.vresult);
697     scope CtfeCompiler v = new CtfeCompiler(fd.ctfeCode);
698     v.ctfeCompile(fd.fbody);
699 }
700 
701 /*************************************
702  * Entry point for CTFE.
703  * A compile-time result is required. Give an error if not possible.
704  *
705  * `e` must be semantically valid expression. In other words, it should not
706  * contain any `ErrorExp`s in it. But, CTFE interpretation will cross over
707  * functions and may invoke a function that contains `ErrorStatement` in its body.
708  * If that, the "CTFE failed because of previous errors" error is raised.
709  */
710 extern (C++) Expression ctfeInterpret(Expression e)
711 {
712     if (e.op == TOKerror)
713         return e;
714     assert(e.type); // Bugzilla 14642
715     //assert(e->type->ty != Terror);    // FIXME
716     if (e.type.ty == Terror)
717         return new ErrorExp();
718 
719     // This code is outside a function, but still needs to be compiled
720     // (there are compiler-generated temporary variables such as __dollar).
721     // However, this will only be run once and can then be discarded.
722     auto ctfeCodeGlobal = CompiledCtfeFunction(null);
723     ctfeCodeGlobal.callingloc = e.loc;
724     ctfeCodeGlobal.onExpression(e);
725 
726     Expression result = interpret(e, null);
727 
728     if (!CTFEExp.isCantExp(result))
729         result = scrubReturnValue(e.loc, result);
730     if (CTFEExp.isCantExp(result))
731         result = new ErrorExp();
732 
733     return result;
734 }
735 
736 /* Run CTFE on the expression, but allow the expression to be a TypeExp
737  *  or a tuple containing a TypeExp. (This is required by pragma(msg)).
738  */
739 extern (C++) Expression ctfeInterpretForPragmaMsg(Expression e)
740 {
741     if (e.op == TOKerror || e.op == TOKtype)
742         return e;
743 
744     // It's also OK for it to be a function declaration (happens only with
745     // __traits(getOverloads))
746     if (e.op == TOKvar && (cast(VarExp)e).var.isFuncDeclaration())
747     {
748         return e;
749     }
750 
751     if (e.op != TOKtuple)
752         return e.ctfeInterpret();
753 
754     // Tuples need to be treated seperately, since they are
755     // allowed to contain a TypeExp in this case.
756 
757     TupleExp tup = cast(TupleExp)e;
758     Expressions* expsx = null;
759     for (size_t i = 0; i < tup.exps.dim; ++i)
760     {
761         Expression g = (*tup.exps)[i];
762         Expression h = g;
763         h = ctfeInterpretForPragmaMsg(g);
764         if (h != g)
765         {
766             if (!expsx)
767             {
768                 expsx = new Expressions();
769                 expsx.setDim(tup.exps.dim);
770                 for (size_t j = 0; j < tup.exps.dim; j++)
771                     (*expsx)[j] = (*tup.exps)[j];
772             }
773             (*expsx)[i] = h;
774         }
775     }
776     if (expsx)
777     {
778         auto te = new TupleExp(e.loc, expsx);
779         expandTuples(te.exps);
780         te.type = new TypeTuple(te.exps);
781         return te;
782     }
783     return e;
784 }
785 
786 /*************************************
787  * Attempt to interpret a function given the arguments.
788  * Input:
789  *      istate     state for calling function (NULL if none)
790  *      arguments  function arguments
791  *      thisarg    'this', if a needThis() function, NULL if not.
792  *
793  * Return result expression if successful, TOKcantexp if not,
794  * or CTFEExp if function returned void.
795  */
796 extern (C++) Expression interpret(FuncDeclaration fd, InterState* istate, Expressions* arguments, Expression thisarg)
797 {
798     debug (LOG)
799     {
800         printf("\n********\n%s FuncDeclaration::interpret(istate = %p) %s\n", fd.loc.toChars(), istate, fd.toChars());
801     }
802     if (fd.semanticRun == PASSsemantic3)
803     {
804         fd.error("circular dependency. Functions cannot be interpreted while being compiled");
805         return CTFEExp.cantexp;
806     }
807     if (!fd.functionSemantic3())
808         return CTFEExp.cantexp;
809     if (fd.semanticRun < PASSsemantic3done)
810         return CTFEExp.cantexp;
811 
812     // CTFE-compile the function
813     if (!fd.ctfeCode)
814         ctfeCompile(fd);
815 
816     Type tb = fd.type.toBasetype();
817     assert(tb.ty == Tfunction);
818     TypeFunction tf = cast(TypeFunction)tb;
819     if (tf.varargs && arguments && ((fd.parameters && arguments.dim != fd.parameters.dim) || (!fd.parameters && arguments.dim)))
820     {
821         fd.error("C-style variadic functions are not yet implemented in CTFE");
822         return CTFEExp.cantexp;
823     }
824 
825     // Nested functions always inherit the 'this' pointer from the parent,
826     // except for delegates. (Note that the 'this' pointer may be null).
827     // Func literals report isNested() even if they are in global scope,
828     // so we need to check that the parent is a function.
829     if (fd.isNested() && fd.toParent2().isFuncDeclaration() && !thisarg && istate)
830         thisarg = ctfeStack.getThis();
831 
832     if (fd.needThis() && !thisarg)
833     {
834         // error, no this. Prevent segfault.
835         // Here should be unreachable by the strict 'this' check in front-end.
836         fd.error("need 'this' to access member %s", fd.toChars());
837         return CTFEExp.cantexp;
838     }
839 
840     // Place to hold all the arguments to the function while
841     // we are evaluating them.
842     Expressions eargs;
843     size_t dim = arguments ? arguments.dim : 0;
844     assert((fd.parameters ? fd.parameters.dim : 0) == dim);
845 
846     /* Evaluate all the arguments to the function,
847      * store the results in eargs[]
848      */
849     eargs.setDim(dim);
850     for (size_t i = 0; i < dim; i++)
851     {
852         Expression earg = (*arguments)[i];
853         Parameter fparam = Parameter.getNth(tf.parameters, i);
854 
855         if (fparam.storageClass & (STCout | STCref))
856         {
857             if (!istate && (fparam.storageClass & STCout))
858             {
859                 // initializing an out parameter involves writing to it.
860                 earg.error("global %s cannot be passed as an 'out' parameter at compile time", earg.toChars());
861                 return CTFEExp.cantexp;
862             }
863             // Convert all reference arguments into lvalue references
864             earg = interpret(earg, istate, ctfeNeedLvalue);
865             if (CTFEExp.isCantExp(earg))
866                 return earg;
867         }
868         else if (fparam.storageClass & STClazy)
869         {
870         }
871         else
872         {
873             /* Value parameters
874              */
875             Type ta = fparam.type.toBasetype();
876             if (ta.ty == Tsarray && earg.op == TOKaddress)
877             {
878                 /* Static arrays are passed by a simple pointer.
879                  * Skip past this to get at the actual arg.
880                  */
881                 earg = (cast(AddrExp)earg).e1;
882             }
883             earg = interpret(earg, istate);
884             if (CTFEExp.isCantExp(earg))
885                 return earg;
886 
887             /* Struct literals are passed by value, but we don't need to
888              * copy them if they are passed as const
889              */
890             if (earg.op == TOKstructliteral && !(fparam.storageClass & (STCconst | STCimmutable)))
891                 earg = copyLiteral(earg).copy();
892         }
893         if (earg.op == TOKthrownexception)
894         {
895             if (istate)
896                 return earg;
897             (cast(ThrownExceptionExp)earg).generateUncaughtError();
898             return CTFEExp.cantexp;
899         }
900         eargs[i] = earg;
901     }
902 
903     // Now that we've evaluated all the arguments, we can start the frame
904     // (this is the moment when the 'call' actually takes place).
905     InterState istatex;
906     istatex.caller = istate;
907     istatex.fd = fd;
908     ctfeStack.startFrame(thisarg);
909     if (fd.vthis && thisarg)
910     {
911         ctfeStack.push(fd.vthis);
912         setValue(fd.vthis, thisarg);
913     }
914 
915     for (size_t i = 0; i < dim; i++)
916     {
917         Expression earg = eargs[i];
918         Parameter fparam = Parameter.getNth(tf.parameters, i);
919         VarDeclaration v = (*fd.parameters)[i];
920         debug (LOG)
921         {
922             printf("arg[%d] = %s\n", i, earg.toChars());
923         }
924         ctfeStack.push(v);
925 
926         if ((fparam.storageClass & (STCout | STCref)) && earg.op == TOKvar && (cast(VarExp)earg).var.toParent2() == fd)
927         {
928             VarDeclaration vx = (cast(VarExp)earg).var.isVarDeclaration();
929             if (!vx)
930             {
931                 fd.error("cannot interpret %s as a ref parameter", earg.toChars());
932                 return CTFEExp.cantexp;
933             }
934 
935             /* vx is a variable that is declared in fd.
936              * It means that fd is recursively called. e.g.
937              *
938              *  void fd(int n, ref int v = dummy) {
939              *      int vx;
940              *      if (n == 1) fd(2, vx);
941              *  }
942              *  fd(1);
943              *
944              * The old value of vx on the stack in fd(1)
945              * should be saved at the start of fd(2, vx) call.
946              */
947             int oldadr = vx.ctfeAdrOnStack;
948 
949             ctfeStack.push(vx);
950             assert(!hasValue(vx)); // vx is made uninitialized
951 
952             // Bugzilla 14299: v->ctfeAdrOnStack should be saved already
953             // in the stack before the overwrite.
954             v.ctfeAdrOnStack = oldadr;
955             assert(hasValue(v)); // ref parameter v should refer existing value.
956         }
957         else
958         {
959             // Value parameters and non-trivial references
960             setValueWithoutChecking(v, earg);
961         }
962         debug (LOG)
963         {
964             printf("interpreted arg[%d] = %s\n", i, earg.toChars());
965             showCtfeExpr(earg);
966         }
967         debug (LOGASSIGN)
968         {
969             printf("interpreted arg[%d] = %s\n", i, earg.toChars());
970             showCtfeExpr(earg);
971         }
972     }
973 
974     if (fd.vresult)
975         ctfeStack.push(fd.vresult);
976 
977     // Enter the function
978     ++CtfeStatus.callDepth;
979     if (CtfeStatus.callDepth > CtfeStatus.maxCallDepth)
980         CtfeStatus.maxCallDepth = CtfeStatus.callDepth;
981 
982     Expression e = null;
983     while (1)
984     {
985         if (CtfeStatus.callDepth > CTFE_RECURSION_LIMIT)
986         {
987             // This is a compiler error. It must not be suppressed.
988             global.gag = 0;
989             fd.error("CTFE recursion limit exceeded");
990             e = CTFEExp.cantexp;
991             break;
992         }
993         e = interpret(fd.fbody, &istatex);
994         if (CTFEExp.isCantExp(e))
995         {
996             debug (LOG)
997             {
998                 printf("function body failed to interpret\n");
999             }
1000         }
1001 
1002         if (istatex.start)
1003         {
1004             fd.error("CTFE internal error: failed to resume at statement %s", istatex.start.toChars());
1005             return CTFEExp.cantexp;
1006         }
1007 
1008         /* This is how we deal with a recursive statement AST
1009          * that has arbitrary goto statements in it.
1010          * Bubble up a 'result' which is the target of the goto
1011          * statement, then go recursively down the AST looking
1012          * for that statement, then execute starting there.
1013          */
1014         if (CTFEExp.isGotoExp(e))
1015         {
1016             istatex.start = istatex.gotoTarget; // set starting statement
1017             istatex.gotoTarget = null;
1018         }
1019         else
1020         {
1021             assert(!e || (e.op != TOKcontinue && e.op != TOKbreak));
1022             break;
1023         }
1024     }
1025     // If fell off the end of a void function, return void
1026     if (!e && tf.next.ty == Tvoid)
1027         e = CTFEExp.voidexp;
1028     if (tf.isref && e.op == TOKvar && (cast(VarExp)e).var == fd.vthis)
1029         e = thisarg;
1030     assert(e !is null);
1031 
1032     // Leave the function
1033     --CtfeStatus.callDepth;
1034 
1035     ctfeStack.endFrame();
1036 
1037     // If it generated an uncaught exception, report error.
1038     if (!istate && e.op == TOKthrownexception)
1039     {
1040         (cast(ThrownExceptionExp)e).generateUncaughtError();
1041         e = CTFEExp.cantexp;
1042     }
1043 
1044     return e;
1045 }
1046 
1047 extern (C++) final class Interpreter : Visitor
1048 {
1049     alias visit = super.visit;
1050 public:
1051     InterState* istate;
1052     CtfeGoal goal;
1053     Expression result;
1054 
1055     extern (D) this(InterState* istate, CtfeGoal goal)
1056     {
1057         this.istate = istate;
1058         this.goal = goal;
1059     }
1060 
1061     // If e is TOKthrowexception or TOKcantexp,
1062     // set it to 'result' and returns true.
1063     bool exceptionOrCant(Expression e)
1064     {
1065         if (exceptionOrCantInterpret(e))
1066         {
1067             result = e;
1068             return true;
1069         }
1070         return false;
1071     }
1072 
1073     static Expressions* copyArrayOnWrite(Expressions* exps, Expressions* original)
1074     {
1075         if (exps is original)
1076         {
1077             if (!original)
1078                 exps = new Expressions();
1079             else
1080                 exps = original.copy();
1081             ++CtfeStatus.numArrayAllocs;
1082         }
1083         return exps;
1084     }
1085 
1086     /******************************** Statement ***************************/
1087 
1088     override void visit(Statement s)
1089     {
1090         debug (LOG)
1091         {
1092             printf("%s Statement::interpret()\n", s.loc.toChars());
1093         }
1094         if (istate.start)
1095         {
1096             if (istate.start != s)
1097                 return;
1098             istate.start = null;
1099         }
1100 
1101         s.error("statement %s cannot be interpreted at compile time", s.toChars());
1102         result = CTFEExp.cantexp;
1103     }
1104 
1105     override void visit(ExpStatement s)
1106     {
1107         debug (LOG)
1108         {
1109             printf("%s ExpStatement::interpret(%s)\n", s.loc.toChars(), s.exp ? s.exp.toChars() : "");
1110         }
1111         if (istate.start)
1112         {
1113             if (istate.start != s)
1114                 return;
1115             istate.start = null;
1116         }
1117 
1118         Expression e = interpret(s.exp, istate, ctfeNeedNothing);
1119         if (exceptionOrCant(e))
1120             return;
1121     }
1122 
1123     override void visit(CompoundStatement s)
1124     {
1125         debug (LOG)
1126         {
1127             printf("%s CompoundStatement::interpret()\n", s.loc.toChars());
1128         }
1129         if (istate.start == s)
1130             istate.start = null;
1131 
1132         size_t dim = s.statements ? s.statements.dim : 0;
1133         for (size_t i = 0; i < dim; i++)
1134         {
1135             Statement sx = (*s.statements)[i];
1136             result = interpret(sx, istate);
1137             if (result)
1138                 break;
1139         }
1140         debug (LOG)
1141         {
1142             printf("%s -CompoundStatement::interpret() %p\n", s.loc.toChars(), result);
1143         }
1144     }
1145 
1146     override void visit(UnrolledLoopStatement s)
1147     {
1148         debug (LOG)
1149         {
1150             printf("%s UnrolledLoopStatement::interpret()\n", s.loc.toChars());
1151         }
1152         if (istate.start == s)
1153             istate.start = null;
1154 
1155         size_t dim = s.statements ? s.statements.dim : 0;
1156         for (size_t i = 0; i < dim; i++)
1157         {
1158             Statement sx = (*s.statements)[i];
1159             Expression e = interpret(sx, istate);
1160             if (!e) // suceeds to interpret, or goto target was not found
1161                 continue;
1162             if (exceptionOrCant(e))
1163                 return;
1164             if (e.op == TOKbreak)
1165             {
1166                 if (istate.gotoTarget && istate.gotoTarget != s)
1167                 {
1168                     result = e; // break at a higher level
1169                     return;
1170                 }
1171                 istate.gotoTarget = null;
1172                 result = null;
1173                 return;
1174             }
1175             if (e.op == TOKcontinue)
1176             {
1177                 if (istate.gotoTarget && istate.gotoTarget != s)
1178                 {
1179                     result = e; // continue at a higher level
1180                     return;
1181                 }
1182                 istate.gotoTarget = null;
1183                 continue;
1184             }
1185 
1186             // expression from return statement, or thrown exception
1187             result = e;
1188             break;
1189         }
1190     }
1191 
1192     override void visit(IfStatement s)
1193     {
1194         debug (LOG)
1195         {
1196             printf("%s IfStatement::interpret(%s)\n", s.loc.toChars(), s.condition.toChars());
1197         }
1198         if (istate.start == s)
1199             istate.start = null;
1200         if (istate.start)
1201         {
1202             Expression e = null;
1203             e = interpret(s.ifbody, istate);
1204             if (!e && istate.start)
1205                 e = interpret(s.elsebody, istate);
1206             result = e;
1207             return;
1208         }
1209 
1210         Expression e = interpret(s.condition, istate);
1211         assert(e);
1212         if (exceptionOrCant(e))
1213             return;
1214 
1215         if (isTrueBool(e))
1216             result = interpret(s.ifbody, istate);
1217         else if (e.isBool(false))
1218             result = interpret(s.elsebody, istate);
1219         else
1220         {
1221             // no error, or assert(0)?
1222             result = CTFEExp.cantexp;
1223         }
1224     }
1225 
1226     override void visit(ScopeStatement s)
1227     {
1228         debug (LOG)
1229         {
1230             printf("%s ScopeStatement::interpret()\n", s.loc.toChars());
1231         }
1232         if (istate.start == s)
1233             istate.start = null;
1234 
1235         result = interpret(s.statement, istate);
1236     }
1237 
1238     /**
1239      Given an expression e which is about to be returned from the current
1240      function, generate an error if it contains pointers to local variables.
1241      Return true if it is safe to return, false if an error was generated.
1242 
1243      Only checks expressions passed by value (pointers to local variables
1244      may already be stored in members of classes, arrays, or AAs which
1245      were passed as mutable function parameters).
1246      */
1247     static bool stopPointersEscaping(Loc loc, Expression e)
1248     {
1249         if (!e.type.hasPointers())
1250             return true;
1251         if (isPointer(e.type))
1252         {
1253             Expression x = e;
1254             if (e.op == TOKaddress)
1255                 x = (cast(AddrExp)e).e1;
1256             VarDeclaration v;
1257             while (x.op == TOKvar && (v = (cast(VarExp)x).var.isVarDeclaration()) !is null)
1258             {
1259                 if (v.storage_class & STCref)
1260                 {
1261                     x = getValue(v);
1262                     if (e.op == TOKaddress)
1263                         (cast(AddrExp)e).e1 = x;
1264                     continue;
1265                 }
1266                 if (ctfeStack.isInCurrentFrame(v))
1267                 {
1268                     error(loc, "returning a pointer to a local stack variable");
1269                     return false;
1270                 }
1271                 else
1272                     break;
1273             }
1274             // TODO: If it is a TOKdotvar or TOKindex, we should check that it is not
1275             // pointing to a local struct or static array.
1276         }
1277         if (e.op == TOKstructliteral)
1278         {
1279             StructLiteralExp se = cast(StructLiteralExp)e;
1280             return stopPointersEscapingFromArray(loc, se.elements);
1281         }
1282         if (e.op == TOKarrayliteral)
1283         {
1284             return stopPointersEscapingFromArray(loc, (cast(ArrayLiteralExp)e).elements);
1285         }
1286         if (e.op == TOKassocarrayliteral)
1287         {
1288             AssocArrayLiteralExp aae = cast(AssocArrayLiteralExp)e;
1289             if (!stopPointersEscapingFromArray(loc, aae.keys))
1290                 return false;
1291             return stopPointersEscapingFromArray(loc, aae.values);
1292         }
1293         return true;
1294     }
1295 
1296     // Check all members of an array for escaping local variables. Return false if error
1297     static bool stopPointersEscapingFromArray(Loc loc, Expressions* elems)
1298     {
1299         for (size_t i = 0; i < elems.dim; i++)
1300         {
1301             Expression m = (*elems)[i];
1302             if (!m)
1303                 continue;
1304             if (!stopPointersEscaping(loc, m))
1305                 return false;
1306         }
1307         return true;
1308     }
1309 
1310     override void visit(ReturnStatement s)
1311     {
1312         debug (LOG)
1313         {
1314             printf("%s ReturnStatement::interpret(%s)\n", s.loc.toChars(), s.exp ? s.exp.toChars() : "");
1315         }
1316         if (istate.start)
1317         {
1318             if (istate.start != s)
1319                 return;
1320             istate.start = null;
1321         }
1322 
1323         if (!s.exp)
1324         {
1325             result = CTFEExp.voidexp;
1326             return;
1327         }
1328 
1329         assert(istate && istate.fd && istate.fd.type && istate.fd.type.ty == Tfunction);
1330         TypeFunction tf = cast(TypeFunction)istate.fd.type;
1331 
1332         /* If the function returns a ref AND it's been called from an assignment,
1333          * we need to return an lvalue. Otherwise, just do an (rvalue) interpret.
1334          */
1335         if (tf.isref)
1336         {
1337             result = interpret(s.exp, istate, ctfeNeedLvalue);
1338             return;
1339         }
1340         if (tf.next && tf.next.ty == Tdelegate && istate.fd.closureVars.dim > 0)
1341         {
1342             // To support this, we need to copy all the closure vars
1343             // into the delegate literal.
1344             s.error("closures are not yet supported in CTFE");
1345             result = CTFEExp.cantexp;
1346             return;
1347         }
1348 
1349         // We need to treat pointers specially, because TOKsymoff can be used to
1350         // return a value OR a pointer
1351         Expression e = interpret(s.exp, istate);
1352         if (exceptionOrCant(e))
1353             return;
1354 
1355         // Disallow returning pointers to stack-allocated variables (bug 7876)
1356         if (!stopPointersEscaping(s.loc, e))
1357         {
1358             result = CTFEExp.cantexp;
1359             return;
1360         }
1361 
1362         if (needToCopyLiteral(e))
1363             e = copyLiteral(e).copy();
1364         debug (LOGASSIGN)
1365         {
1366             printf("RETURN %s\n", s.loc.toChars());
1367             showCtfeExpr(e);
1368         }
1369         result = e;
1370     }
1371 
1372     static Statement findGotoTarget(InterState* istate, Identifier ident)
1373     {
1374         Statement target = null;
1375         if (ident)
1376         {
1377             LabelDsymbol label = istate.fd.searchLabel(ident);
1378             assert(label && label.statement);
1379             LabelStatement ls = label.statement;
1380             target = ls.gotoTarget ? ls.gotoTarget : ls.statement;
1381         }
1382         return target;
1383     }
1384 
1385     override void visit(BreakStatement s)
1386     {
1387         debug (LOG)
1388         {
1389             printf("%s BreakStatement::interpret()\n", s.loc.toChars());
1390         }
1391         if (istate.start)
1392         {
1393             if (istate.start != s)
1394                 return;
1395             istate.start = null;
1396         }
1397 
1398         istate.gotoTarget = findGotoTarget(istate, s.ident);
1399         result = CTFEExp.breakexp;
1400     }
1401 
1402     override void visit(ContinueStatement s)
1403     {
1404         debug (LOG)
1405         {
1406             printf("%s ContinueStatement::interpret()\n", s.loc.toChars());
1407         }
1408         if (istate.start)
1409         {
1410             if (istate.start != s)
1411                 return;
1412             istate.start = null;
1413         }
1414 
1415         istate.gotoTarget = findGotoTarget(istate, s.ident);
1416         result = CTFEExp.continueexp;
1417     }
1418 
1419     override void visit(WhileStatement s)
1420     {
1421         debug (LOG)
1422         {
1423             printf("WhileStatement::interpret()\n");
1424         }
1425         assert(0); // rewritten to ForStatement
1426     }
1427 
1428     override void visit(DoStatement s)
1429     {
1430         debug (LOG)
1431         {
1432             printf("%s DoStatement::interpret()\n", s.loc.toChars());
1433         }
1434         if (istate.start == s)
1435             istate.start = null;
1436 
1437         while (1)
1438         {
1439             Expression e = interpret(s._body, istate);
1440             if (!e && istate.start) // goto target was not found
1441                 return;
1442             assert(!istate.start);
1443 
1444             if (exceptionOrCant(e))
1445                 return;
1446             if (e && e.op == TOKbreak)
1447             {
1448                 if (istate.gotoTarget && istate.gotoTarget != s)
1449                 {
1450                     result = e; // break at a higher level
1451                     return;
1452                 }
1453                 istate.gotoTarget = null;
1454                 break;
1455             }
1456             if (e && e.op == TOKcontinue)
1457             {
1458                 if (istate.gotoTarget && istate.gotoTarget != s)
1459                 {
1460                     result = e; // continue at a higher level
1461                     return;
1462                 }
1463                 istate.gotoTarget = null;
1464                 e = null;
1465             }
1466             if (e)
1467             {
1468                 result = e; // bubbled up from ReturnStatement
1469                 return;
1470             }
1471 
1472             e = interpret(s.condition, istate);
1473             if (exceptionOrCant(e))
1474                 return;
1475             if (!e.isConst())
1476             {
1477                 result = CTFEExp.cantexp;
1478                 return;
1479             }
1480             if (e.isBool(false))
1481                 break;
1482             assert(isTrueBool(e));
1483         }
1484         assert(result is null);
1485     }
1486 
1487     override void visit(ForStatement s)
1488     {
1489         debug (LOG)
1490         {
1491             printf("%s ForStatement::interpret()\n", s.loc.toChars());
1492         }
1493         if (istate.start == s)
1494             istate.start = null;
1495 
1496         Expression ei = interpret(s._init, istate);
1497         if (exceptionOrCant(ei))
1498             return;
1499         assert(!ei); // s->init never returns from function, or jumps out from it
1500 
1501         while (1)
1502         {
1503             if (s.condition && !istate.start)
1504             {
1505                 Expression e = interpret(s.condition, istate);
1506                 if (exceptionOrCant(e))
1507                     return;
1508                 if (e.isBool(false))
1509                     break;
1510                 assert(isTrueBool(e));
1511             }
1512 
1513             Expression e = interpret(s._body, istate);
1514             if (!e && istate.start) // goto target was not found
1515                 return;
1516             assert(!istate.start);
1517 
1518             if (exceptionOrCant(e))
1519                 return;
1520             if (e && e.op == TOKbreak)
1521             {
1522                 if (istate.gotoTarget && istate.gotoTarget != s)
1523                 {
1524                     result = e; // break at a higher level
1525                     return;
1526                 }
1527                 istate.gotoTarget = null;
1528                 break;
1529             }
1530             if (e && e.op == TOKcontinue)
1531             {
1532                 if (istate.gotoTarget && istate.gotoTarget != s)
1533                 {
1534                     result = e; // continue at a higher level
1535                     return;
1536                 }
1537                 istate.gotoTarget = null;
1538                 e = null;
1539             }
1540             if (e)
1541             {
1542                 result = e; // bubbled up from ReturnStatement
1543                 return;
1544             }
1545 
1546             e = interpret(s.increment, istate, ctfeNeedNothing);
1547             if (exceptionOrCant(e))
1548                 return;
1549         }
1550         assert(result is null);
1551     }
1552 
1553     override void visit(ForeachStatement s)
1554     {
1555         assert(0); // rewritten to ForStatement
1556     }
1557 
1558     override void visit(ForeachRangeStatement s)
1559     {
1560         assert(0); // rewritten to ForStatement
1561     }
1562 
1563     override void visit(SwitchStatement s)
1564     {
1565         debug (LOG)
1566         {
1567             printf("%s SwitchStatement::interpret()\n", s.loc.toChars());
1568         }
1569         if (istate.start == s)
1570             istate.start = null;
1571         if (istate.start)
1572         {
1573             Expression e = interpret(s._body, istate);
1574             if (istate.start) // goto target was not found
1575                 return;
1576             if (exceptionOrCant(e))
1577                 return;
1578             if (e && e.op == TOKbreak)
1579             {
1580                 if (istate.gotoTarget && istate.gotoTarget != s)
1581                 {
1582                     result = e; // break at a higher level
1583                     return;
1584                 }
1585                 istate.gotoTarget = null;
1586                 e = null;
1587             }
1588             result = e;
1589             return;
1590         }
1591 
1592         Expression econdition = interpret(s.condition, istate);
1593         if (exceptionOrCant(econdition))
1594             return;
1595 
1596         Statement scase = null;
1597         size_t dim = s.cases ? s.cases.dim : 0;
1598         for (size_t i = 0; i < dim; i++)
1599         {
1600             CaseStatement cs = (*s.cases)[i];
1601             Expression ecase = interpret(cs.exp, istate);
1602             if (exceptionOrCant(ecase))
1603                 return;
1604             if (ctfeEqual(cs.exp.loc, TOKequal, econdition, ecase))
1605             {
1606                 scase = cs;
1607                 break;
1608             }
1609         }
1610         if (!scase)
1611         {
1612             if (s.hasNoDefault)
1613                 s.error("no default or case for %s in switch statement", econdition.toChars());
1614             scase = s.sdefault;
1615         }
1616 
1617         assert(scase);
1618 
1619         /* Jump to scase
1620          */
1621         istate.start = scase;
1622         Expression e = interpret(s._body, istate);
1623         assert(!istate.start); // jump must not fail
1624         if (e && e.op == TOKbreak)
1625         {
1626             if (istate.gotoTarget && istate.gotoTarget != s)
1627             {
1628                 result = e; // break at a higher level
1629                 return;
1630             }
1631             istate.gotoTarget = null;
1632             e = null;
1633         }
1634         result = e;
1635     }
1636 
1637     override void visit(CaseStatement s)
1638     {
1639         debug (LOG)
1640         {
1641             printf("%s CaseStatement::interpret(%s) this = %p\n", s.loc.toChars(), s.exp.toChars(), s);
1642         }
1643         if (istate.start == s)
1644             istate.start = null;
1645 
1646         result = interpret(s.statement, istate);
1647     }
1648 
1649     override void visit(DefaultStatement s)
1650     {
1651         debug (LOG)
1652         {
1653             printf("%s DefaultStatement::interpret()\n", s.loc.toChars());
1654         }
1655         if (istate.start == s)
1656             istate.start = null;
1657 
1658         result = interpret(s.statement, istate);
1659     }
1660 
1661     override void visit(GotoStatement s)
1662     {
1663         debug (LOG)
1664         {
1665             printf("%s GotoStatement::interpret()\n", s.loc.toChars());
1666         }
1667         if (istate.start)
1668         {
1669             if (istate.start != s)
1670                 return;
1671             istate.start = null;
1672         }
1673 
1674         assert(s.label && s.label.statement);
1675         istate.gotoTarget = s.label.statement;
1676         result = CTFEExp.gotoexp;
1677     }
1678 
1679     override void visit(GotoCaseStatement s)
1680     {
1681         debug (LOG)
1682         {
1683             printf("%s GotoCaseStatement::interpret()\n", s.loc.toChars());
1684         }
1685         if (istate.start)
1686         {
1687             if (istate.start != s)
1688                 return;
1689             istate.start = null;
1690         }
1691 
1692         assert(s.cs);
1693         istate.gotoTarget = s.cs;
1694         result = CTFEExp.gotoexp;
1695     }
1696 
1697     override void visit(GotoDefaultStatement s)
1698     {
1699         debug (LOG)
1700         {
1701             printf("%s GotoDefaultStatement::interpret()\n", s.loc.toChars());
1702         }
1703         if (istate.start)
1704         {
1705             if (istate.start != s)
1706                 return;
1707             istate.start = null;
1708         }
1709 
1710         assert(s.sw && s.sw.sdefault);
1711         istate.gotoTarget = s.sw.sdefault;
1712         result = CTFEExp.gotoexp;
1713     }
1714 
1715     override void visit(LabelStatement s)
1716     {
1717         debug (LOG)
1718         {
1719             printf("%s LabelStatement::interpret()\n", s.loc.toChars());
1720         }
1721         if (istate.start == s)
1722             istate.start = null;
1723 
1724         result = interpret(s.statement, istate);
1725     }
1726 
1727     override void visit(TryCatchStatement s)
1728     {
1729         debug (LOG)
1730         {
1731             printf("%s TryCatchStatement::interpret()\n", s.loc.toChars());
1732         }
1733         if (istate.start == s)
1734             istate.start = null;
1735         if (istate.start)
1736         {
1737             Expression e = null;
1738             e = interpret(s._body, istate);
1739             for (size_t i = 0; i < s.catches.dim; i++)
1740             {
1741                 if (e || !istate.start) // goto target was found
1742                     break;
1743                 Catch ca = (*s.catches)[i];
1744                 e = interpret(ca.handler, istate);
1745             }
1746             result = e;
1747             return;
1748         }
1749 
1750         Expression e = interpret(s._body, istate);
1751 
1752         // An exception was thrown
1753         if (e && e.op == TOKthrownexception)
1754         {
1755             ThrownExceptionExp ex = cast(ThrownExceptionExp)e;
1756             Type extype = ex.thrown.originalClass().type;
1757 
1758             // Search for an appropriate catch clause.
1759             for (size_t i = 0; i < s.catches.dim; i++)
1760             {
1761                 Catch ca = (*s.catches)[i];
1762                 Type catype = ca.type;
1763                 if (!catype.equals(extype) && !catype.isBaseOf(extype, null))
1764                     continue;
1765 
1766                 // Execute the handler
1767                 if (ca.var)
1768                 {
1769                     ctfeStack.push(ca.var);
1770                     setValue(ca.var, ex.thrown);
1771                 }
1772                 e = interpret(ca.handler, istate);
1773                 if (CTFEExp.isGotoExp(e))
1774                 {
1775                     /* This is an optimization that relies on the locality of the jump target.
1776                      * If the label is in the same catch handler, the following scan
1777                      * would find it quickly and can reduce jump cost.
1778                      * Otherwise, the catch block may be unnnecessary scanned again
1779                      * so it would make CTFE speed slower.
1780                      */
1781                     InterState istatex = *istate;
1782                     istatex.start = istate.gotoTarget; // set starting statement
1783                     istatex.gotoTarget = null;
1784                     Expression eh = interpret(ca.handler, &istatex);
1785                     if (!istatex.start)
1786                     {
1787                         istate.gotoTarget = null;
1788                         e = eh;
1789                     }
1790                 }
1791                 break;
1792             }
1793         }
1794         result = e;
1795     }
1796 
1797     static bool isAnErrorException(ClassDeclaration cd)
1798     {
1799         return cd == ClassDeclaration.errorException || ClassDeclaration.errorException.isBaseOf(cd, null);
1800     }
1801 
1802     static ThrownExceptionExp chainExceptions(ThrownExceptionExp oldest, ThrownExceptionExp newest)
1803     {
1804         debug (LOG)
1805         {
1806             printf("Collided exceptions %s %s\n", oldest.thrown.toChars(), newest.thrown.toChars());
1807         }
1808         // Little sanity check to make sure it's really a Throwable
1809         ClassReferenceExp boss = oldest.thrown;
1810         assert((*boss.value.elements)[4].type.ty == Tclass); // Throwable.next
1811         ClassReferenceExp collateral = newest.thrown;
1812         if (isAnErrorException(collateral.originalClass()) && !isAnErrorException(boss.originalClass()))
1813         {
1814             // The new exception bypass the existing chain
1815             assert((*collateral.value.elements)[5].type.ty == Tclass);
1816             (*collateral.value.elements)[5] = boss;
1817             return newest;
1818         }
1819         while ((*boss.value.elements)[4].op == TOKclassreference)
1820         {
1821             boss = cast(ClassReferenceExp)(*boss.value.elements)[4];
1822         }
1823         (*boss.value.elements)[4] = collateral;
1824         return oldest;
1825     }
1826 
1827     override void visit(TryFinallyStatement s)
1828     {
1829         debug (LOG)
1830         {
1831             printf("%s TryFinallyStatement::interpret()\n", s.loc.toChars());
1832         }
1833         if (istate.start == s)
1834             istate.start = null;
1835         if (istate.start)
1836         {
1837             Expression e = null;
1838             e = interpret(s._body, istate);
1839             // Jump into/out from finalbody is disabled in semantic analysis.
1840             // and jump inside will be handled by the ScopeStatement == finalbody.
1841             result = e;
1842             return;
1843         }
1844 
1845         Expression ex = interpret(s._body, istate);
1846         if (CTFEExp.isCantExp(ex))
1847         {
1848             result = ex;
1849             return;
1850         }
1851         while (CTFEExp.isGotoExp(ex))
1852         {
1853             // If the goto target is within the body, we must not interpret the finally statement,
1854             // because that will call destructors for objects within the scope, which we should not do.
1855             InterState istatex = *istate;
1856             istatex.start = istate.gotoTarget; // set starting statement
1857             istatex.gotoTarget = null;
1858             Expression bex = interpret(s._body, &istatex);
1859             if (istatex.start)
1860             {
1861                 // The goto target is outside the current scope.
1862                 break;
1863             }
1864             // The goto target was within the body.
1865             if (CTFEExp.isCantExp(bex))
1866             {
1867                 result = bex;
1868                 return;
1869             }
1870             *istate = istatex;
1871             ex = bex;
1872         }
1873 
1874         Expression ey = interpret(s.finalbody, istate);
1875         if (CTFEExp.isCantExp(ey))
1876         {
1877             result = ey;
1878             return;
1879         }
1880         if (ey && ey.op == TOKthrownexception)
1881         {
1882             // Check for collided exceptions
1883             if (ex && ex.op == TOKthrownexception)
1884                 ex = chainExceptions(cast(ThrownExceptionExp)ex, cast(ThrownExceptionExp)ey);
1885             else
1886                 ex = ey;
1887         }
1888         result = ex;
1889     }
1890 
1891     override void visit(ThrowStatement s)
1892     {
1893         debug (LOG)
1894         {
1895             printf("%s ThrowStatement::interpret()\n", s.loc.toChars());
1896         }
1897         if (istate.start)
1898         {
1899             if (istate.start != s)
1900                 return;
1901             istate.start = null;
1902         }
1903 
1904         Expression e = interpret(s.exp, istate);
1905         if (exceptionOrCant(e))
1906             return;
1907 
1908         assert(e.op == TOKclassreference);
1909         result = new ThrownExceptionExp(s.loc, cast(ClassReferenceExp)e);
1910     }
1911 
1912     override void visit(OnScopeStatement s)
1913     {
1914         assert(0);
1915     }
1916 
1917     override void visit(WithStatement s)
1918     {
1919         debug (LOG)
1920         {
1921             printf("%s WithStatement::interpret()\n", s.loc.toChars());
1922         }
1923         if (istate.start == s)
1924             istate.start = null;
1925         if (istate.start)
1926         {
1927             result = s._body ? interpret(s._body, istate) : null;
1928             return;
1929         }
1930 
1931         // If it is with(Enum) {...}, just execute the body.
1932         if (s.exp.op == TOKscope || s.exp.op == TOKtype)
1933         {
1934             result = interpret(s._body, istate);
1935             return;
1936         }
1937 
1938         Expression e = interpret(s.exp, istate);
1939         if (exceptionOrCant(e))
1940             return;
1941 
1942         if (s.wthis.type.ty == Tpointer && s.exp.type.ty != Tpointer)
1943         {
1944             e = new AddrExp(s.loc, e);
1945             e.type = s.wthis.type;
1946         }
1947         ctfeStack.push(s.wthis);
1948         setValue(s.wthis, e);
1949         e = interpret(s._body, istate);
1950         if (CTFEExp.isGotoExp(e))
1951         {
1952             /* This is an optimization that relies on the locality of the jump target.
1953              * If the label is in the same WithStatement, the following scan
1954              * would find it quickly and can reduce jump cost.
1955              * Otherwise, the statement body may be unnnecessary scanned again
1956              * so it would make CTFE speed slower.
1957              */
1958             InterState istatex = *istate;
1959             istatex.start = istate.gotoTarget; // set starting statement
1960             istatex.gotoTarget = null;
1961             Expression ex = interpret(s._body, &istatex);
1962             if (!istatex.start)
1963             {
1964                 istate.gotoTarget = null;
1965                 e = ex;
1966             }
1967         }
1968         ctfeStack.pop(s.wthis);
1969         result = e;
1970     }
1971 
1972     override void visit(AsmStatement s)
1973     {
1974         debug (LOG)
1975         {
1976             printf("%s AsmStatement::interpret()\n", s.loc.toChars());
1977         }
1978         if (istate.start)
1979         {
1980             if (istate.start != s)
1981                 return;
1982             istate.start = null;
1983         }
1984         s.error("asm statements cannot be interpreted at compile time");
1985         result = CTFEExp.cantexp;
1986     }
1987 
1988     override void visit(ImportStatement s)
1989     {
1990         debug (LOG)
1991         {
1992             printf("ImportStatement::interpret()\n");
1993         }
1994         if (istate.start)
1995         {
1996             if (istate.start != s)
1997                 return;
1998             istate.start = null;
1999         }
2000     }
2001 
2002     /******************************** Expression ***************************/
2003 
2004     override void visit(Expression e)
2005     {
2006         debug (LOG)
2007         {
2008             printf("%s Expression::interpret() '%s' %s\n", e.loc.toChars(), Token.toChars(e.op), e.toChars());
2009             printf("type = %s\n", e.type.toChars());
2010             e.print();
2011         }
2012         e.error("cannot interpret %s at compile time", e.toChars());
2013         result = CTFEExp.cantexp;
2014     }
2015 
2016     override void visit(ThisExp e)
2017     {
2018         debug (LOG)
2019         {
2020             printf("%s ThisExp::interpret() %s\n", e.loc.toChars(), e.toChars());
2021         }
2022         if (goal == ctfeNeedLvalue)
2023         {
2024             if (istate.fd.vthis)
2025             {
2026                 result = new VarExp(e.loc, istate.fd.vthis);
2027                 result.type = e.type;
2028             }
2029             else
2030                 result = e;
2031             return;
2032         }
2033 
2034         result = ctfeStack.getThis();
2035         if (result)
2036         {
2037             assert(result.op == TOKstructliteral || result.op == TOKclassreference);
2038             return;
2039         }
2040         e.error("value of 'this' is not known at compile time");
2041         result = CTFEExp.cantexp;
2042     }
2043 
2044     override void visit(NullExp e)
2045     {
2046         result = e;
2047     }
2048 
2049     override void visit(IntegerExp e)
2050     {
2051         debug (LOG)
2052         {
2053             printf("%s IntegerExp::interpret() %s\n", e.loc.toChars(), e.toChars());
2054         }
2055         result = e;
2056     }
2057 
2058     override void visit(RealExp e)
2059     {
2060         debug (LOG)
2061         {
2062             printf("%s RealExp::interpret() %s\n", e.loc.toChars(), e.toChars());
2063         }
2064         result = e;
2065     }
2066 
2067     override void visit(ComplexExp e)
2068     {
2069         result = e;
2070     }
2071 
2072     override void visit(StringExp e)
2073     {
2074         debug (LOG)
2075         {
2076             printf("%s StringExp::interpret() %s\n", e.loc.toChars(), e.toChars());
2077         }
2078         /* Attempts to modify string literals are prevented
2079          * in BinExp::interpretAssignCommon.
2080          */
2081         result = e;
2082     }
2083 
2084     override void visit(FuncExp e)
2085     {
2086         debug (LOG)
2087         {
2088             printf("%s FuncExp::interpret() %s\n", e.loc.toChars(), e.toChars());
2089         }
2090         result = e;
2091     }
2092 
2093     override void visit(SymOffExp e)
2094     {
2095         debug (LOG)
2096         {
2097             printf("%s SymOffExp::interpret() %s\n", e.loc.toChars(), e.toChars());
2098         }
2099         if (e.var.isFuncDeclaration() && e.offset == 0)
2100         {
2101             result = e;
2102             return;
2103         }
2104         if (isTypeInfo_Class(e.type) && e.offset == 0)
2105         {
2106             result = e;
2107             return;
2108         }
2109         if (e.type.ty != Tpointer)
2110         {
2111             // Probably impossible
2112             e.error("cannot interpret %s at compile time", e.toChars());
2113             result = CTFEExp.cantexp;
2114             return;
2115         }
2116         Type pointee = (cast(TypePointer)e.type).next;
2117         if (e.var.isThreadlocal())
2118         {
2119             e.error("cannot take address of thread-local variable %s at compile time", e.var.toChars());
2120             result = CTFEExp.cantexp;
2121             return;
2122         }
2123         // Check for taking an address of a shared variable.
2124         // If the shared variable is an array, the offset might not be zero.
2125         Type fromType = null;
2126         if (e.var.type.ty == Tarray || e.var.type.ty == Tsarray)
2127         {
2128             fromType = (cast(TypeArray)e.var.type).next;
2129         }
2130         if (e.var.isDataseg() && ((e.offset == 0 && isSafePointerCast(e.var.type, pointee)) || (fromType && isSafePointerCast(fromType, pointee))))
2131         {
2132             result = e;
2133             return;
2134         }
2135 
2136         Expression val = getVarExp(e.loc, istate, e.var, goal);
2137         if (exceptionOrCant(val))
2138             return;
2139         if (val.type.ty == Tarray || val.type.ty == Tsarray)
2140         {
2141             // Check for unsupported type painting operations
2142             Type elemtype = (cast(TypeArray)val.type).next;
2143             d_uns64 elemsize = elemtype.size();
2144 
2145             // It's OK to cast from fixed length to dynamic array, eg &int[3] to int[]*
2146             if (val.type.ty == Tsarray && pointee.ty == Tarray && elemsize == pointee.nextOf().size())
2147             {
2148                 result = new AddrExp(e.loc, val);
2149                 result.type = e.type;
2150                 return;
2151             }
2152 
2153             // It's OK to cast from fixed length to fixed length array, eg &int[n] to int[d]*.
2154             if (val.type.ty == Tsarray && pointee.ty == Tsarray && elemsize == pointee.nextOf().size())
2155             {
2156                 size_t d = cast(size_t)(cast(TypeSArray)pointee).dim.toInteger();
2157                 Expression elwr = new IntegerExp(e.loc, e.offset / elemsize, Type.tsize_t);
2158                 Expression eupr = new IntegerExp(e.loc, e.offset / elemsize + d, Type.tsize_t);
2159 
2160                 // Create a CTFE pointer &val[ofs..ofs+d]
2161                 result = new SliceExp(e.loc, val, elwr, eupr);
2162                 result.type = pointee;
2163                 result = new AddrExp(e.loc, result);
2164                 result.type = e.type;
2165                 return;
2166             }
2167 
2168             if (!isSafePointerCast(elemtype, pointee))
2169             {
2170                 // It's also OK to cast from &string to string*.
2171                 if (e.offset == 0 && isSafePointerCast(e.var.type, pointee))
2172                 {
2173                     // Create a CTFE pointer &var
2174                     result = new VarExp(e.loc, e.var);
2175                     result.type = elemtype;
2176                     result = new AddrExp(e.loc, result);
2177                     result.type = e.type;
2178                     return;
2179                 }
2180                 e.error("reinterpreting cast from %s to %s is not supported in CTFE", val.type.toChars(), e.type.toChars());
2181                 result = CTFEExp.cantexp;
2182                 return;
2183             }
2184 
2185             dinteger_t sz = pointee.size();
2186             dinteger_t indx = e.offset / sz;
2187             assert(sz * indx == e.offset);
2188             Expression aggregate = null;
2189             if (val.op == TOKarrayliteral || val.op == TOKstring)
2190             {
2191                 aggregate = val;
2192             }
2193             else if (val.op == TOKslice)
2194             {
2195                 aggregate = (cast(SliceExp)val).e1;
2196                 Expression lwr = interpret((cast(SliceExp)val).lwr, istate);
2197                 indx += lwr.toInteger();
2198             }
2199             if (aggregate)
2200             {
2201                 // Create a CTFE pointer &aggregate[ofs]
2202                 auto ofs = new IntegerExp(e.loc, indx, Type.tsize_t);
2203                 result = new IndexExp(e.loc, aggregate, ofs);
2204                 result.type = elemtype;
2205                 result = new AddrExp(e.loc, result);
2206                 result.type = e.type;
2207                 return;
2208             }
2209         }
2210         else if (e.offset == 0 && isSafePointerCast(e.var.type, pointee))
2211         {
2212             // Create a CTFE pointer &var
2213             auto ve = new VarExp(e.loc, e.var);
2214             ve.type = e.var.type;
2215             result = new AddrExp(e.loc, ve);
2216             result.type = e.type;
2217             return;
2218         }
2219 
2220         e.error("cannot convert &%s to %s at compile time", e.var.type.toChars(), e.type.toChars());
2221         result = CTFEExp.cantexp;
2222     }
2223 
2224     override void visit(AddrExp e)
2225     {
2226         debug (LOG)
2227         {
2228             printf("%s AddrExp::interpret() %s\n", e.loc.toChars(), e.toChars());
2229         }
2230         if (e.e1.op == TOKvar && (cast(VarExp)e.e1).var.isDataseg())
2231         {
2232             // Normally this is already done by optimize()
2233             // Do it here in case optimize(WANTvalue) wasn't run before CTFE
2234             result = new SymOffExp(e.loc, (cast(VarExp)e.e1).var, 0);
2235             result.type = e.type;
2236             return;
2237         }
2238         result = interpret(e.e1, istate, ctfeNeedLvalue);
2239         if (result.op == TOKvar && (cast(VarExp)result).var == istate.fd.vthis)
2240             result = interpret(result, istate);
2241         if (exceptionOrCant(result))
2242             return;
2243 
2244         // Return a simplified address expression
2245         result = new AddrExp(e.loc, result);
2246         result.type = e.type;
2247     }
2248 
2249     override void visit(DelegateExp e)
2250     {
2251         debug (LOG)
2252         {
2253             printf("%s DelegateExp::interpret() %s\n", e.loc.toChars(), e.toChars());
2254         }
2255         // TODO: Really we should create a CTFE-only delegate expression
2256         // of a pointer and a funcptr.
2257 
2258         // If it is &nestedfunc, just return it
2259         // TODO: We should save the context pointer
2260         if (e.e1.op == TOKvar && (cast(VarExp)e.e1).var == e.func)
2261         {
2262             result = e;
2263             return;
2264         }
2265 
2266         result = interpret(e.e1, istate);
2267         if (exceptionOrCant(result))
2268             return;
2269         if (result == e.e1)
2270         {
2271             // If it has already been CTFE'd, just return it
2272             result = e;
2273         }
2274         else
2275         {
2276             result = new DelegateExp(e.loc, result, e.func, false);
2277             result.type = e.type;
2278         }
2279     }
2280 
2281     static Expression getVarExp(Loc loc, InterState* istate, Declaration d, CtfeGoal goal)
2282     {
2283         Expression e = CTFEExp.cantexp;
2284         if (VarDeclaration v = d.isVarDeclaration())
2285         {
2286             /* Magic variable __ctfe always returns true when interpreting
2287              */
2288             if (v.ident == Id.ctfe)
2289                 return new IntegerExp(loc, 1, Type.tbool);
2290 
2291             if (!v.originalType && v._scope) // semantic() not yet run
2292             {
2293                 v.semantic(v._scope);
2294                 if (v.type.ty == Terror)
2295                     return CTFEExp.cantexp;
2296             }
2297 
2298             if ((v.isConst() || v.isImmutable() || v.storage_class & STCmanifest) && !hasValue(v) && v._init && !v.isCTFE())
2299             {
2300                 if (v.inuse)
2301                 {
2302                     error(loc, "circular initialization of %s '%s'", v.kind(), v.toPrettyChars());
2303                     return CTFEExp.cantexp;
2304                 }
2305                 if (v._scope)
2306                 {
2307                     v.inuse++;
2308                     v._init = v._init.semantic(v._scope, v.type, INITinterpret); // might not be run on aggregate members
2309                     v.inuse--;
2310                 }
2311                 e = v._init.toExpression(v.type);
2312                 if (!e)
2313                     return CTFEExp.cantexp;
2314                 assert(e.type);
2315 
2316                 if (e.op == TOKconstruct || e.op == TOKblit)
2317                 {
2318                     AssignExp ae = cast(AssignExp)e;
2319                     e = ae.e2;
2320                 }
2321 
2322                 if (e.op == TOKerror)
2323                 {
2324                     // FIXME: Ultimately all errors should be detected in prior semantic analysis stage.
2325                 }
2326                 else if (v.isDataseg() || (v.storage_class & STCmanifest))
2327                 {
2328                     /* Bugzilla 14304: e is a value that is not yet owned by CTFE.
2329                      * Mark as "cached", and use it directly during interpretation.
2330                      */
2331                     e = scrubCacheValue(v.loc, e);
2332                     ctfeStack.saveGlobalConstant(v, e);
2333                 }
2334                 else
2335                 {
2336                     v.inuse++;
2337                     e = interpret(e, istate);
2338                     v.inuse--;
2339                     if (CTFEExp.isCantExp(e) && !global.gag && !CtfeStatus.stackTraceCallsToSuppress)
2340                         errorSupplemental(loc, "while evaluating %s.init", v.toChars());
2341                     if (exceptionOrCantInterpret(e))
2342                         return e;
2343                 }
2344             }
2345             else if (v.isCTFE() && !hasValue(v))
2346             {
2347                 if (v._init && v.type.size() != 0)
2348                 {
2349                     if (v._init.isVoidInitializer())
2350                     {
2351                         // var should have been initialized when it was created
2352                         error(loc, "CTFE internal error: trying to access uninitialized var");
2353                         assert(0);
2354                     }
2355                     e = v._init.toExpression();
2356                 }
2357                 else
2358                     e = v.type.defaultInitLiteral(e.loc);
2359 
2360                 e = interpret(e, istate);
2361             }
2362             else if (!(v.isDataseg() || v.storage_class & STCmanifest) && !v.isCTFE() && !istate)
2363             {
2364                 error(loc, "variable %s cannot be read at compile time", v.toChars());
2365                 return CTFEExp.cantexp;
2366             }
2367             else
2368             {
2369                 e = hasValue(v) ? getValue(v) : null;
2370                 if (!e && !v.isCTFE() && v.isDataseg())
2371                 {
2372                     error(loc, "static variable %s cannot be read at compile time", v.toChars());
2373                     return CTFEExp.cantexp;
2374                 }
2375                 if (!e)
2376                 {
2377                     assert(!(v._init && v._init.isVoidInitializer()));
2378                     // CTFE initiated from inside a function
2379                     error(loc, "variable %s cannot be read at compile time", v.toChars());
2380                     return CTFEExp.cantexp;
2381                 }
2382                 if (e.op == TOKvoid)
2383                 {
2384                     VoidInitExp ve = cast(VoidInitExp)e;
2385                     error(loc, "cannot read uninitialized variable %s in ctfe", v.toPrettyChars());
2386                     errorSupplemental(ve.var.loc, "%s was uninitialized and used before set", ve.var.toChars());
2387                     return CTFEExp.cantexp;
2388                 }
2389                 if (goal != ctfeNeedLvalue && (v.isRef() || v.isOut()))
2390                     e = interpret(e, istate, goal);
2391             }
2392             if (!e)
2393                 e = CTFEExp.cantexp;
2394         }
2395         else if (SymbolDeclaration s = d.isSymbolDeclaration())
2396         {
2397             // Struct static initializers, for example
2398             e = s.dsym.type.defaultInitLiteral(loc);
2399             if (e.op == TOKerror)
2400                 error(loc, "CTFE failed because of previous errors in %s.init", s.toChars());
2401             e = e.semantic(null);
2402             if (e.op == TOKerror)
2403                 e = CTFEExp.cantexp;
2404             else // Convert NULL to CTFEExp
2405                 e = interpret(e, istate, goal);
2406         }
2407         else
2408             error(loc, "cannot interpret declaration %s at compile time", d.toChars());
2409         return e;
2410     }
2411 
2412     override void visit(VarExp e)
2413     {
2414         debug (LOG)
2415         {
2416             printf("%s VarExp::interpret() %s, goal = %d\n", e.loc.toChars(), e.toChars(), goal);
2417         }
2418         if (e.var.isFuncDeclaration())
2419         {
2420             result = e;
2421             return;
2422         }
2423 
2424         if (goal == ctfeNeedLvalue)
2425         {
2426             VarDeclaration v = e.var.isVarDeclaration();
2427             if (v && !v.isDataseg() && !v.isCTFE() && !istate)
2428             {
2429                 e.error("variable %s cannot be read at compile time", v.toChars());
2430                 result = CTFEExp.cantexp;
2431                 return;
2432             }
2433             if (v && !hasValue(v))
2434             {
2435                 if (!v.isCTFE() && v.isDataseg())
2436                     e.error("static variable %s cannot be read at compile time", v.toChars());
2437                 else // CTFE initiated from inside a function
2438                     e.error("variable %s cannot be read at compile time", v.toChars());
2439                 result = CTFEExp.cantexp;
2440                 return;
2441             }
2442             if (v && (v.storage_class & (STCout | STCref)) && hasValue(v))
2443             {
2444                 // Strip off the nest of ref variables
2445                 Expression ev = getValue(v);
2446                 if (ev.op == TOKvar || ev.op == TOKindex || ev.op == TOKdotvar)
2447                 {
2448                     result = interpret(ev, istate, goal);
2449                     return;
2450                 }
2451             }
2452             result = e;
2453             return;
2454         }
2455         result = getVarExp(e.loc, istate, e.var, goal);
2456         if (exceptionOrCant(result))
2457             return;
2458         if ((e.var.storage_class & (STCref | STCout)) == 0 && e.type.baseElemOf().ty != Tstruct)
2459         {
2460             /* Ultimately, STCref|STCout check should be enough to see the
2461              * necessity of type repainting. But currently front-end paints
2462              * non-ref struct variables by the const type.
2463              *
2464              *  auto foo(ref const S cs);
2465              *  S s;
2466              *  foo(s); // VarExp('s') will have const(S)
2467              */
2468             // A VarExp may include an implicit cast. It must be done explicitly.
2469             result = paintTypeOntoLiteral(e.type, result);
2470         }
2471     }
2472 
2473     override void visit(DeclarationExp e)
2474     {
2475         debug (LOG)
2476         {
2477             printf("%s DeclarationExp::interpret() %s\n", e.loc.toChars(), e.toChars());
2478         }
2479         Dsymbol s = e.declaration;
2480         if (VarDeclaration v = s.isVarDeclaration())
2481         {
2482             if (TupleDeclaration td = v.toAlias().isTupleDeclaration())
2483             {
2484                 result = null;
2485 
2486                 // Reserve stack space for all tuple members
2487                 if (!td.objects)
2488                     return;
2489                 for (size_t i = 0; i < td.objects.dim; ++i)
2490                 {
2491                     RootObject o = (*td.objects)[i];
2492                     Expression ex = isExpression(o);
2493                     DsymbolExp ds = (ex && ex.op == TOKdsymbol) ? cast(DsymbolExp)ex : null;
2494                     VarDeclaration v2 = ds ? ds.s.isVarDeclaration() : null;
2495                     assert(v2);
2496                     if (v2.isDataseg() && !v2.isCTFE())
2497                         continue;
2498 
2499                     ctfeStack.push(v2);
2500                     if (v2._init)
2501                     {
2502                         Expression einit;
2503                         if (ExpInitializer ie = v2._init.isExpInitializer())
2504                         {
2505                             einit = interpret(ie.exp, istate, goal);
2506                             if (exceptionOrCant(einit))
2507                                 return;
2508                         }
2509                         else if (v2._init.isVoidInitializer())
2510                         {
2511                             einit = voidInitLiteral(v2.type, v2).copy();
2512                         }
2513                         else
2514                         {
2515                             e.error("declaration %s is not yet implemented in CTFE", e.toChars());
2516                             result = CTFEExp.cantexp;
2517                             return;
2518                         }
2519                         setValue(v2, einit);
2520                     }
2521                 }
2522                 return;
2523             }
2524             if (v.isStatic())
2525             {
2526                 // Just ignore static variables which aren't read or written yet
2527                 result = null;
2528                 return;
2529             }
2530             if (!(v.isDataseg() || v.storage_class & STCmanifest) || v.isCTFE())
2531                 ctfeStack.push(v);
2532             if (v._init)
2533             {
2534                 if (ExpInitializer ie = v._init.isExpInitializer())
2535                 {
2536                     result = interpret(ie.exp, istate, goal);
2537                 }
2538                 else if (v._init.isVoidInitializer())
2539                 {
2540                     result = voidInitLiteral(v.type, v).copy();
2541                     // There is no AssignExp for void initializers,
2542                     // so set it here.
2543                     setValue(v, result);
2544                 }
2545                 else
2546                 {
2547                     e.error("declaration %s is not yet implemented in CTFE", e.toChars());
2548                     result = CTFEExp.cantexp;
2549                 }
2550             }
2551             else if (v.type.size() == 0)
2552             {
2553                 // Zero-length arrays don't need an initializer
2554                 result = v.type.defaultInitLiteral(e.loc);
2555             }
2556             else
2557             {
2558                 e.error("variable %s cannot be modified at compile time", v.toChars());
2559                 result = CTFEExp.cantexp;
2560             }
2561             return;
2562         }
2563         if (s.isAttribDeclaration() || s.isTemplateMixin() || s.isTupleDeclaration())
2564         {
2565             // Check for static struct declarations, which aren't executable
2566             AttribDeclaration ad = e.declaration.isAttribDeclaration();
2567             if (ad && ad.decl && ad.decl.dim == 1)
2568             {
2569                 Dsymbol sparent = (*ad.decl)[0];
2570                 if (sparent.isAggregateDeclaration() || sparent.isTemplateDeclaration() || sparent.isAliasDeclaration())
2571                 {
2572                     result = null;
2573                     return; // static (template) struct declaration. Nothing to do.
2574                 }
2575             }
2576 
2577             // These can be made to work, too lazy now
2578             e.error("declaration %s is not yet implemented in CTFE", e.toChars());
2579             result = CTFEExp.cantexp;
2580             return;
2581         }
2582 
2583         // Others should not contain executable code, so are trivial to evaluate
2584         result = null;
2585         debug (LOG)
2586         {
2587             printf("-DeclarationExp::interpret(%s): %p\n", e.toChars(), result);
2588         }
2589     }
2590 
2591     override void visit(TypeidExp e)
2592     {
2593         debug (LOG)
2594         {
2595             printf("%s TypeidExp::interpret() %s\n", e.loc.toChars(), e.toChars());
2596         }
2597         if (Type t = isType(e.obj))
2598         {
2599             result = e;
2600             return;
2601         }
2602         if (Expression ex = isExpression(e.obj))
2603         {
2604             result = interpret(ex, istate);
2605             if (exceptionOrCant(ex))
2606                 return;
2607 
2608             if (result.op == TOKnull)
2609             {
2610                 e.error("null pointer dereference evaluating typeid. '%s' is null", ex.toChars());
2611                 result = CTFEExp.cantexp;
2612                 return;
2613             }
2614             if (result.op != TOKclassreference)
2615             {
2616                 e.error("CTFE internal error: determining classinfo");
2617                 result = CTFEExp.cantexp;
2618                 return;
2619             }
2620 
2621             ClassDeclaration cd = (cast(ClassReferenceExp)result).originalClass();
2622             assert(cd);
2623 
2624             result = new TypeidExp(e.loc, cd.type);
2625             result.type = e.type;
2626             return;
2627         }
2628         visit(cast(Expression)e);
2629     }
2630 
2631     override void visit(TupleExp e)
2632     {
2633         debug (LOG)
2634         {
2635             printf("%s TupleExp::interpret() %s\n", e.loc.toChars(), e.toChars());
2636         }
2637         if (exceptionOrCant(interpret(e.e0, istate, ctfeNeedNothing)))
2638             return;
2639 
2640         auto expsx = e.exps;
2641         for (size_t i = 0; i < expsx.dim; i++)
2642         {
2643             Expression exp = (*expsx)[i];
2644             Expression ex = interpret(exp, istate);
2645             if (exceptionOrCant(ex))
2646                 return;
2647 
2648             // A tuple of assignments can contain void (Bug 5676).
2649             if (goal == ctfeNeedNothing)
2650                 continue;
2651             if (ex.op == TOKvoidexp)
2652             {
2653                 e.error("CTFE internal error: void element %s in tuple", exp.toChars());
2654                 assert(0);
2655             }
2656 
2657             /* If any changes, do Copy On Write
2658              */
2659             if (ex !is exp)
2660             {
2661                 expsx = copyArrayOnWrite(expsx, e.exps);
2662                 (*expsx)[i] = ex;
2663             }
2664         }
2665 
2666         if (expsx !is e.exps)
2667         {
2668             expandTuples(expsx);
2669             auto te = new TupleExp(e.loc, expsx);
2670             te.type = new TypeTuple(te.exps);
2671             result = te;
2672         }
2673         else
2674             result = e;
2675     }
2676 
2677     override void visit(ArrayLiteralExp e)
2678     {
2679         debug (LOG)
2680         {
2681             printf("%s ArrayLiteralExp::interpret() %s\n", e.loc.toChars(), e.toChars());
2682         }
2683         if (e.ownedByCtfe >= OWNEDctfe) // We've already interpreted all the elements
2684         {
2685             result = e;
2686             return;
2687         }
2688 
2689         Type tn = e.type.toBasetype().nextOf().toBasetype();
2690         bool wantCopy = (tn.ty == Tsarray || tn.ty == Tstruct);
2691 
2692         auto basis = interpret(e.basis, istate);
2693         if (exceptionOrCant(basis))
2694             return;
2695 
2696         auto expsx = e.elements;
2697         size_t dim = expsx ? expsx.dim : 0;
2698         for (size_t i = 0; i < dim; i++)
2699         {
2700             Expression exp = (*expsx)[i];
2701             Expression ex;
2702             if (!exp)
2703             {
2704                 ex = copyLiteral(basis).copy();
2705             }
2706             else
2707             {
2708                 // segfault bug 6250
2709                 assert(exp.op != TOKindex || (cast(IndexExp)exp).e1 != e);
2710 
2711                 ex = interpret(exp, istate);
2712                 if (exceptionOrCant(ex))
2713                     return;
2714 
2715                 /* Each elements should have distinct CTFE memory.
2716                  *  int[1] z = 7;
2717                  *  int[1][] pieces = [z,z];    // here
2718                  */
2719                 if (wantCopy)
2720                     ex = copyLiteral(ex).copy();
2721             }
2722 
2723             /* If any changes, do Copy On Write
2724              */
2725             if (ex !is exp)
2726             {
2727                 expsx = copyArrayOnWrite(expsx, e.elements);
2728                 (*expsx)[i] = ex;
2729             }
2730         }
2731 
2732         if (expsx !is e.elements)
2733         {
2734             // todo: all tuple expansions should go in semantic phase.
2735             expandTuples(expsx);
2736             if (expsx.dim != dim)
2737             {
2738                 e.error("CTFE internal error: invalid array literal");
2739                 result = CTFEExp.cantexp;
2740                 return;
2741             }
2742             auto ale = new ArrayLiteralExp(e.loc, basis, expsx);
2743             ale.type = e.type;
2744             ale.ownedByCtfe = OWNEDctfe;
2745             result = ale;
2746         }
2747         else if ((cast(TypeNext)e.type).next.mod & (MODconst | MODimmutable))
2748         {
2749             // If it's immutable, we don't need to dup it
2750             result = e;
2751         }
2752         else
2753             result = copyLiteral(e).copy();
2754     }
2755 
2756     override void visit(AssocArrayLiteralExp e)
2757     {
2758         debug (LOG)
2759         {
2760             printf("%s AssocArrayLiteralExp::interpret() %s\n", e.loc.toChars(), e.toChars());
2761         }
2762         if (e.ownedByCtfe >= OWNEDctfe) // We've already interpreted all the elements
2763         {
2764             result = e;
2765             return;
2766         }
2767 
2768         auto keysx = e.keys;
2769         auto valuesx = e.values;
2770         for (size_t i = 0; i < keysx.dim; i++)
2771         {
2772             auto ekey = (*keysx)[i];
2773             auto evalue = (*valuesx)[i];
2774 
2775             auto ek = interpret(ekey, istate);
2776             if (exceptionOrCant(ek))
2777                 return;
2778             auto ev = interpret(evalue, istate);
2779             if (exceptionOrCant(ev))
2780                 return;
2781 
2782             /* If any changes, do Copy On Write
2783              */
2784             if (ek !is ekey ||
2785                 ev !is evalue)
2786             {
2787                 keysx = copyArrayOnWrite(keysx, e.keys);
2788                 valuesx = copyArrayOnWrite(valuesx, e.values);
2789                 (*keysx)[i] = ek;
2790                 (*valuesx)[i] = ev;
2791             }
2792         }
2793         if (keysx !is e.keys)
2794             expandTuples(keysx);
2795         if (valuesx !is e.values)
2796             expandTuples(valuesx);
2797         if (keysx.dim != valuesx.dim)
2798         {
2799             e.error("CTFE internal error: invalid AA");
2800             result = CTFEExp.cantexp;
2801             return;
2802         }
2803 
2804         /* Remove duplicate keys
2805          */
2806         for (size_t i = 1; i < keysx.dim; i++)
2807         {
2808             auto ekey = (*keysx)[i - 1];
2809             for (size_t j = i; j < keysx.dim; j++)
2810             {
2811                 auto ekey2 = (*keysx)[j];
2812                 if (!ctfeEqual(e.loc, TOKequal, ekey, ekey2))
2813                     continue;
2814 
2815                 // Remove ekey
2816                 keysx = copyArrayOnWrite(keysx, e.keys);
2817                 valuesx = copyArrayOnWrite(valuesx, e.values);
2818                 keysx.remove(i - 1);
2819                 valuesx.remove(i - 1);
2820 
2821                 i -= 1; // redo the i'th iteration
2822                 break;
2823             }
2824         }
2825 
2826         if (keysx !is e.keys ||
2827             valuesx !is e.values)
2828         {
2829             assert(keysx !is e.keys &&
2830                    valuesx !is e.values);
2831             auto aae = new AssocArrayLiteralExp(e.loc, keysx, valuesx);
2832             aae.type = e.type;
2833             aae.ownedByCtfe = OWNEDctfe;
2834             result = aae;
2835         }
2836         else
2837             result = copyLiteral(e).copy();
2838     }
2839 
2840     override void visit(StructLiteralExp e)
2841     {
2842         debug (LOG)
2843         {
2844             printf("%s StructLiteralExp::interpret() %s ownedByCtfe = %d\n", e.loc.toChars(), e.toChars(), e.ownedByCtfe);
2845         }
2846         if (e.ownedByCtfe >= OWNEDctfe)
2847         {
2848             result = e;
2849             return;
2850         }
2851 
2852         size_t dim = e.elements ? e.elements.dim : 0;
2853         auto expsx = e.elements;
2854 
2855         if (dim != e.sd.fields.dim)
2856         {
2857             // guaranteed by AggregateDeclaration.fill and TypeStruct.defaultInitLiteral
2858             assert(e.sd.isNested() && dim == e.sd.fields.dim - 1);
2859 
2860             /* If a nested struct has no initialized hidden pointer,
2861              * set it to null to match the runtime behaviour.
2862              */
2863             auto ne = new NullExp(e.loc);
2864             ne.type = e.sd.vthis.type;
2865 
2866             expsx = copyArrayOnWrite(expsx, e.elements);
2867             expsx.push(ne);
2868             ++dim;
2869         }
2870         assert(dim == e.sd.fields.dim);
2871 
2872         foreach (i; 0 .. dim)
2873         {
2874             auto v = e.sd.fields[i];
2875             Expression exp = (*expsx)[i];
2876             Expression ex;
2877             if (!exp)
2878             {
2879                 ex = voidInitLiteral(v.type, v).copy();
2880             }
2881             else
2882             {
2883                 ex = interpret(exp, istate);
2884                 if (exceptionOrCant(ex))
2885                     return;
2886                 if ((v.type.ty != ex.type.ty) && v.type.ty == Tsarray)
2887                 {
2888                     // Block assignment from inside struct literals
2889                     auto tsa = cast(TypeSArray)v.type;
2890                     auto len = cast(size_t)tsa.dim.toInteger();
2891                     ex = createBlockDuplicatedArrayLiteral(ex.loc, v.type, ex, len);
2892                 }
2893             }
2894 
2895             /* If any changes, do Copy On Write
2896              */
2897             if (ex !is exp)
2898             {
2899                 expsx = copyArrayOnWrite(expsx, e.elements);
2900                 (*expsx)[i] = ex;
2901             }
2902         }
2903 
2904         if (expsx !is e.elements)
2905         {
2906             expandTuples(expsx);
2907             if (expsx.dim != e.sd.fields.dim)
2908             {
2909                 e.error("CTFE internal error: invalid struct literal");
2910                 result = CTFEExp.cantexp;
2911                 return;
2912             }
2913             auto sle = new StructLiteralExp(e.loc, e.sd, expsx);
2914             sle.type = e.type;
2915             sle.ownedByCtfe = OWNEDctfe;
2916             result = sle;
2917         }
2918         else
2919             result = copyLiteral(e).copy();
2920     }
2921 
2922     // Create an array literal of type 'newtype' with dimensions given by
2923     // 'arguments'[argnum..$]
2924     static Expression recursivelyCreateArrayLiteral(Loc loc, Type newtype, InterState* istate, Expressions* arguments, int argnum)
2925     {
2926         Expression lenExpr = interpret((*arguments)[argnum], istate);
2927         if (exceptionOrCantInterpret(lenExpr))
2928             return lenExpr;
2929         size_t len = cast(size_t)lenExpr.toInteger();
2930         Type elemType = (cast(TypeArray)newtype).next;
2931         if (elemType.ty == Tarray && argnum < arguments.dim - 1)
2932         {
2933             Expression elem = recursivelyCreateArrayLiteral(loc, elemType, istate, arguments, argnum + 1);
2934             if (exceptionOrCantInterpret(elem))
2935                 return elem;
2936 
2937             auto elements = new Expressions();
2938             elements.setDim(len);
2939             for (size_t i = 0; i < len; i++)
2940                 (*elements)[i] = copyLiteral(elem).copy();
2941             auto ae = new ArrayLiteralExp(loc, elements);
2942             ae.type = newtype;
2943             ae.ownedByCtfe = OWNEDctfe;
2944             return ae;
2945         }
2946         assert(argnum == arguments.dim - 1);
2947         if (elemType.ty == Tchar || elemType.ty == Twchar || elemType.ty == Tdchar)
2948         {
2949             const ch = cast(dchar)elemType.defaultInitLiteral(loc).toInteger();
2950             const sz = cast(ubyte)elemType.size();
2951             return createBlockDuplicatedStringLiteral(loc, newtype, ch, len, sz);
2952         }
2953         else
2954         {
2955             auto el = interpret(elemType.defaultInitLiteral(loc), istate);
2956             return createBlockDuplicatedArrayLiteral(loc, newtype, el, len);
2957         }
2958     }
2959 
2960     override void visit(NewExp e)
2961     {
2962         debug (LOG)
2963         {
2964             printf("%s NewExp::interpret() %s\n", e.loc.toChars(), e.toChars());
2965         }
2966         if (e.allocator)
2967         {
2968             e.error("member allocators not supported by CTFE");
2969             result = CTFEExp.cantexp;
2970             return;
2971         }
2972 
2973         result = interpret(e.argprefix, istate, ctfeNeedNothing);
2974         if (exceptionOrCant(result))
2975             return;
2976 
2977         if (e.newtype.ty == Tarray && e.arguments)
2978         {
2979             result = recursivelyCreateArrayLiteral(e.loc, e.newtype, istate, e.arguments, 0);
2980             return;
2981         }
2982         if (e.newtype.toBasetype().ty == Tstruct)
2983         {
2984             if (e.member)
2985             {
2986                 Expression se = e.newtype.defaultInitLiteral(e.loc);
2987                 se = interpret(se, istate);
2988                 if (exceptionOrCant(se))
2989                     return;
2990                 result = interpret(e.member, istate, e.arguments, se);
2991 
2992                 // Repaint as same as CallExp::interpret() does.
2993                 result.loc = e.loc;
2994             }
2995             else
2996             {
2997                 StructDeclaration sd = (cast(TypeStruct)e.newtype.toBasetype()).sym;
2998                 auto exps = new Expressions();
2999                 exps.reserve(sd.fields.dim);
3000                 if (e.arguments)
3001                 {
3002                     exps.setDim(e.arguments.dim);
3003                     for (size_t i = 0; i < exps.dim; i++)
3004                     {
3005                         Expression ex = (*e.arguments)[i];
3006                         ex = interpret(ex, istate);
3007                         if (exceptionOrCant(ex))
3008                             return;
3009                         (*exps)[i] = ex;
3010                     }
3011                 }
3012                 sd.fill(e.loc, exps, false);
3013 
3014                 auto se = new StructLiteralExp(e.loc, sd, exps, e.newtype);
3015                 se.type = e.newtype;
3016                 se.ownedByCtfe = OWNEDctfe;
3017                 result = interpret(se, istate);
3018             }
3019             if (exceptionOrCant(result))
3020                 return;
3021             result = new AddrExp(e.loc, result);
3022             result.type = e.type;
3023             return;
3024         }
3025         if (e.newtype.toBasetype().ty == Tclass)
3026         {
3027             ClassDeclaration cd = (cast(TypeClass)e.newtype.toBasetype()).sym;
3028             size_t totalFieldCount = 0;
3029             for (ClassDeclaration c = cd; c; c = c.baseClass)
3030                 totalFieldCount += c.fields.dim;
3031             auto elems = new Expressions();
3032             elems.setDim(totalFieldCount);
3033             size_t fieldsSoFar = totalFieldCount;
3034             for (ClassDeclaration c = cd; c; c = c.baseClass)
3035             {
3036                 fieldsSoFar -= c.fields.dim;
3037                 for (size_t i = 0; i < c.fields.dim; i++)
3038                 {
3039                     VarDeclaration v = c.fields[i];
3040                     if (v.inuse)
3041                     {
3042                         e.error("circular reference to '%s'", v.toPrettyChars());
3043                         result = CTFEExp.cantexp;
3044                         return;
3045                     }
3046                     Expression m;
3047                     if (v._init)
3048                     {
3049                         if (v._init.isVoidInitializer())
3050                             m = voidInitLiteral(v.type, v).copy();
3051                         else
3052                             m = v.getConstInitializer(true);
3053                     }
3054                     else
3055                         m = v.type.defaultInitLiteral(e.loc);
3056                     if (exceptionOrCant(m))
3057                         return;
3058                     (*elems)[fieldsSoFar + i] = copyLiteral(m).copy();
3059                 }
3060             }
3061             // Hack: we store a ClassDeclaration instead of a StructDeclaration.
3062             // We probably won't get away with this.
3063             auto se = new StructLiteralExp(e.loc, cast(StructDeclaration)cd, elems, e.newtype);
3064             se.ownedByCtfe = OWNEDctfe;
3065             Expression eref = new ClassReferenceExp(e.loc, se, e.type);
3066             if (e.member)
3067             {
3068                 // Call constructor
3069                 if (!e.member.fbody)
3070                 {
3071                     Expression ctorfail = evaluateIfBuiltin(istate, e.loc, e.member, e.arguments, eref);
3072                     if (ctorfail)
3073                     {
3074                         if (exceptionOrCant(ctorfail))
3075                             return;
3076                         result = eref;
3077                         return;
3078                     }
3079                     e.member.error("%s cannot be constructed at compile time, because the constructor has no available source code", e.newtype.toChars());
3080                     result = CTFEExp.cantexp;
3081                     return;
3082                 }
3083                 Expression ctorfail = interpret(e.member, istate, e.arguments, eref);
3084                 if (exceptionOrCant(ctorfail))
3085                     return;
3086 
3087                 /* Bugzilla 14465: Repaint the loc, because a super() call
3088                  * in the constructor modifies the loc of ClassReferenceExp
3089                  * in CallExp::interpret().
3090                  */
3091                 eref.loc = e.loc;
3092             }
3093             result = eref;
3094             return;
3095         }
3096         if (e.newtype.toBasetype().isscalar())
3097         {
3098             Expression newval;
3099             if (e.arguments && e.arguments.dim)
3100                 newval = (*e.arguments)[0];
3101             else
3102                 newval = e.newtype.defaultInitLiteral(e.loc);
3103             newval = interpret(newval, istate);
3104             if (exceptionOrCant(newval))
3105                 return;
3106 
3107             // Create a CTFE pointer &[newval][0]
3108             auto elements = new Expressions();
3109             elements.setDim(1);
3110             (*elements)[0] = newval;
3111             auto ae = new ArrayLiteralExp(e.loc, elements);
3112             ae.type = e.newtype.arrayOf();
3113             ae.ownedByCtfe = OWNEDctfe;
3114 
3115             result = new IndexExp(e.loc, ae, new IntegerExp(Loc(), 0, Type.tsize_t));
3116             result.type = e.newtype;
3117             result = new AddrExp(e.loc, result);
3118             result.type = e.type;
3119             return;
3120         }
3121         e.error("cannot interpret %s at compile time", e.toChars());
3122         result = CTFEExp.cantexp;
3123     }
3124 
3125     override void visit(UnaExp e)
3126     {
3127         debug (LOG)
3128         {
3129             printf("%s UnaExp::interpret() %s\n", e.loc.toChars(), e.toChars());
3130         }
3131         Expression e1 = interpret(e.e1, istate);
3132         if (exceptionOrCant(e1))
3133             return;
3134         UnionExp ue;
3135         switch (e.op)
3136         {
3137         case TOKneg:
3138             ue = Neg(e.type, e1);
3139             break;
3140 
3141         case TOKtilde:
3142             ue = Com(e.type, e1);
3143             break;
3144 
3145         case TOKnot:
3146             ue = Not(e.type, e1);
3147             break;
3148 
3149         case TOKvector:
3150             result = e;
3151             return; // do nothing
3152 
3153         default:
3154             assert(0);
3155         }
3156         result = ue.copy();
3157     }
3158 
3159     override void visit(DotTypeExp e)
3160     {
3161         debug (LOG)
3162         {
3163             printf("%s DotTypeExp::interpret() %s\n", e.loc.toChars(), e.toChars());
3164         }
3165         Expression e1 = interpret(e.e1, istate);
3166         if (exceptionOrCant(e1))
3167             return;
3168         if (e1 == e.e1)
3169             result = e; // optimize: reuse this CTFE reference
3170         else
3171         {
3172             result = e.copy();
3173             (cast(DotTypeExp)result).e1 = e1;
3174         }
3175     }
3176 
3177     void interpretCommon(BinExp e, fp_t fp)
3178     {
3179         debug (LOG)
3180         {
3181             printf("%s BinExp::interpretCommon() %s\n", e.loc.toChars(), e.toChars());
3182         }
3183         if (e.e1.type.ty == Tpointer && e.e2.type.ty == Tpointer && e.op == TOKmin)
3184         {
3185             Expression e1 = interpret(e.e1, istate);
3186             if (exceptionOrCant(e1))
3187                 return;
3188             Expression e2 = interpret(e.e2, istate);
3189             if (exceptionOrCant(e2))
3190                 return;
3191             result = pointerDifference(e.loc, e.type, e1, e2).copy();
3192             return;
3193         }
3194         if (e.e1.type.ty == Tpointer && e.e2.type.isintegral())
3195         {
3196             Expression e1 = interpret(e.e1, istate);
3197             if (exceptionOrCant(e1))
3198                 return;
3199             Expression e2 = interpret(e.e2, istate);
3200             if (exceptionOrCant(e2))
3201                 return;
3202             result = pointerArithmetic(e.loc, e.op, e.type, e1, e2).copy();
3203             return;
3204         }
3205         if (e.e2.type.ty == Tpointer && e.e1.type.isintegral() && e.op == TOKadd)
3206         {
3207             Expression e1 = interpret(e.e1, istate);
3208             if (exceptionOrCant(e1))
3209                 return;
3210             Expression e2 = interpret(e.e2, istate);
3211             if (exceptionOrCant(e2))
3212                 return;
3213             result = pointerArithmetic(e.loc, e.op, e.type, e2, e1).copy();
3214             return;
3215         }
3216         if (e.e1.type.ty == Tpointer || e.e2.type.ty == Tpointer)
3217         {
3218             e.error("pointer expression %s cannot be interpreted at compile time", e.toChars());
3219             result = CTFEExp.cantexp;
3220             return;
3221         }
3222 
3223         bool evalOperand(Expression ex, out Expression er)
3224         {
3225             er = interpret(ex, istate);
3226             if (exceptionOrCant(er))
3227                 return false;
3228             if (er.isConst() != 1)
3229             {
3230                 if (er.op == TOKarrayliteral)
3231                     // Until we get it to work, issue a reasonable error message
3232                     e.error("cannot interpret array literal expression %s at compile time", e.toChars());
3233                 else
3234                     e.error("CTFE internal error: non-constant value %s", ex.toChars());
3235                 result = CTFEExp.cantexp;
3236                 return false;
3237             }
3238             return true;
3239         }
3240 
3241         Expression e1;
3242         if (!evalOperand(e.e1, e1))
3243             return;
3244 
3245         Expression e2;
3246         if (!evalOperand(e.e2, e2))
3247             return;
3248 
3249         if (e.op == TOKshr || e.op == TOKshl || e.op == TOKushr)
3250         {
3251             sinteger_t i2 = e2.toInteger();
3252             d_uns64 sz = e1.type.size() * 8;
3253             if (i2 < 0 || i2 >= sz)
3254             {
3255                 e.error("shift by %lld is outside the range 0..%llu", i2, cast(ulong)sz - 1);
3256                 result = CTFEExp.cantexp;
3257                 return;
3258             }
3259         }
3260         result = (*fp)(e.loc, e.type, e1, e2).copy();
3261         if (CTFEExp.isCantExp(result))
3262             e.error("%s cannot be interpreted at compile time", e.toChars());
3263     }
3264 
3265     void interpretCompareCommon(BinExp e, fp2_t fp)
3266     {
3267         debug (LOG)
3268         {
3269             printf("%s BinExp::interpretCompareCommon() %s\n", e.loc.toChars(), e.toChars());
3270         }
3271         if (e.e1.type.ty == Tpointer && e.e2.type.ty == Tpointer)
3272         {
3273             Expression e1 = interpret(e.e1, istate);
3274             if (exceptionOrCant(e1))
3275                 return;
3276             Expression e2 = interpret(e.e2, istate);
3277             if (exceptionOrCant(e2))
3278                 return;
3279             //printf("e1 = %s %s, e2 = %s %s\n", e1->type->toChars(), e1->toChars(), e2->type->toChars(), e2->toChars());
3280             dinteger_t ofs1, ofs2;
3281             Expression agg1 = getAggregateFromPointer(e1, &ofs1);
3282             Expression agg2 = getAggregateFromPointer(e2, &ofs2);
3283             //printf("agg1 = %p %s, agg2 = %p %s\n", agg1, agg1->toChars(), agg2, agg2->toChars());
3284             int cmp = comparePointers(e.loc, e.op, e.type, agg1, ofs1, agg2, ofs2);
3285             if (cmp == -1)
3286             {
3287                 char dir = (e.op == TOKgt || e.op == TOKge) ? '<' : '>';
3288                 e.error("the ordering of pointers to unrelated memory blocks is indeterminate in CTFE. To check if they point to the same memory block, use both > and < inside && or ||, eg (%s && %s %c= %s + 1)", e.toChars(), e.e1.toChars(), dir, e.e2.toChars());
3289                 result = CTFEExp.cantexp;
3290                 return;
3291             }
3292             result = new IntegerExp(e.loc, cmp, e.type);
3293             return;
3294         }
3295         Expression e1 = interpret(e.e1, istate);
3296         if (exceptionOrCant(e1))
3297             return;
3298         if (!isCtfeComparable(e1))
3299         {
3300             e.error("cannot compare %s at compile time", e1.toChars());
3301             result = CTFEExp.cantexp;
3302             return;
3303         }
3304         Expression e2 = interpret(e.e2, istate);
3305         if (exceptionOrCant(e2))
3306             return;
3307         if (!isCtfeComparable(e2))
3308         {
3309             e.error("cannot compare %s at compile time", e2.toChars());
3310             result = CTFEExp.cantexp;
3311             return;
3312         }
3313         int cmp = (*fp)(e.loc, e.op, e1, e2);
3314         result = new IntegerExp(e.loc, cmp, e.type);
3315     }
3316 
3317     override void visit(BinExp e)
3318     {
3319         switch (e.op)
3320         {
3321         case TOKadd:
3322             interpretCommon(e, &Add);
3323             return;
3324 
3325         case TOKmin:
3326             interpretCommon(e, &Min);
3327             return;
3328 
3329         case TOKmul:
3330             interpretCommon(e, &Mul);
3331             return;
3332 
3333         case TOKdiv:
3334             interpretCommon(e, &Div);
3335             return;
3336 
3337         case TOKmod:
3338             interpretCommon(e, &Mod);
3339             return;
3340 
3341         case TOKshl:
3342             interpretCommon(e, &Shl);
3343             return;
3344 
3345         case TOKshr:
3346             interpretCommon(e, &Shr);
3347             return;
3348 
3349         case TOKushr:
3350             interpretCommon(e, &Ushr);
3351             return;
3352 
3353         case TOKand:
3354             interpretCommon(e, &And);
3355             return;
3356 
3357         case TOKor:
3358             interpretCommon(e, &Or);
3359             return;
3360 
3361         case TOKxor:
3362             interpretCommon(e, &Xor);
3363             return;
3364 
3365         case TOKpow:
3366             interpretCommon(e, &Pow);
3367             return;
3368 
3369         case TOKequal:
3370         case TOKnotequal:
3371             interpretCompareCommon(e, &ctfeEqual);
3372             return;
3373 
3374         case TOKidentity:
3375         case TOKnotidentity:
3376             interpretCompareCommon(e, &ctfeIdentity);
3377             return;
3378 
3379         case TOKlt:
3380         case TOKle:
3381         case TOKgt:
3382         case TOKge:
3383             interpretCompareCommon(e, &ctfeCmp);
3384             return;
3385 
3386         default:
3387             printf("be = '%s' %s at [%s]\n", Token.toChars(e.op), e.toChars(), e.loc.toChars());
3388             assert(0);
3389         }
3390     }
3391 
3392     /* Helper functions for BinExp::interpretAssignCommon
3393      */
3394     // Returns the variable which is eventually modified, or NULL if an rvalue.
3395     // thisval is the current value of 'this'.
3396     static VarDeclaration findParentVar(Expression e)
3397     {
3398         for (;;)
3399         {
3400             if (e.op == TOKvar)
3401                 break;
3402             if (e.op == TOKindex)
3403                 e = (cast(IndexExp)e).e1;
3404             else if (e.op == TOKdotvar)
3405                 e = (cast(DotVarExp)e).e1;
3406             else if (e.op == TOKdotti)
3407                 e = (cast(DotTemplateInstanceExp)e).e1;
3408             else if (e.op == TOKslice)
3409                 e = (cast(SliceExp)e).e1;
3410             else
3411                 return null;
3412         }
3413         VarDeclaration v = (cast(VarExp)e).var.isVarDeclaration();
3414         assert(v);
3415         return v;
3416     }
3417 
3418     void interpretAssignCommon(BinExp e, fp_t fp, int post = 0)
3419     {
3420         debug (LOG)
3421         {
3422             printf("%s BinExp::interpretAssignCommon() %s\n", e.loc.toChars(), e.toChars());
3423         }
3424         result = CTFEExp.cantexp;
3425 
3426         Expression e1 = e.e1;
3427         if (!istate)
3428         {
3429             e.error("value of %s is not known at compile time", e1.toChars());
3430             return;
3431         }
3432 
3433         ++CtfeStatus.numAssignments;
3434 
3435         /* Before we begin, we need to know if this is a reference assignment
3436          * (dynamic array, AA, or class) or a value assignment.
3437          * Determining this for slice assignments are tricky: we need to know
3438          * if it is a block assignment (a[] = e) rather than a direct slice
3439          * assignment (a[] = b[]). Note that initializers of multi-dimensional
3440          * static arrays can have 2D block assignments (eg, int[7][7] x = 6;).
3441          * So we need to recurse to determine if it is a block assignment.
3442          */
3443         bool isBlockAssignment = false;
3444         if (e1.op == TOKslice)
3445         {
3446             // a[] = e can have const e. So we compare the naked types.
3447             Type tdst = e1.type.toBasetype();
3448             Type tsrc = e.e2.type.toBasetype();
3449             while (tdst.ty == Tsarray || tdst.ty == Tarray)
3450             {
3451                 tdst = (cast(TypeArray)tdst).next.toBasetype();
3452                 if (tsrc.equivalent(tdst))
3453                 {
3454                     isBlockAssignment = true;
3455                     break;
3456                 }
3457             }
3458         }
3459 
3460         // ---------------------------------------
3461         //      Deal with reference assignment
3462         // ---------------------------------------
3463         // If it is a construction of a ref variable, it is a ref assignment
3464         if ((e.op == TOKconstruct || e.op == TOKblit) &&
3465             ((cast(AssignExp)e).memset & MemorySet.referenceInit))
3466         {
3467             assert(!fp);
3468 
3469             Expression newval = interpret(e.e2, istate, ctfeNeedLvalue);
3470             if (exceptionOrCant(newval))
3471                 return;
3472 
3473             VarDeclaration v = (cast(VarExp)e1).var.isVarDeclaration();
3474             setValue(v, newval);
3475 
3476             // Get the value to return. Note that 'newval' is an Lvalue,
3477             // so if we need an Rvalue, we have to interpret again.
3478             if (goal == ctfeNeedRvalue)
3479                 result = interpret(newval, istate);
3480             else
3481                 result = e1; // VarExp is a CTFE reference
3482             return;
3483         }
3484 
3485         if (fp)
3486         {
3487             while (e1.op == TOKcast)
3488             {
3489                 CastExp ce = cast(CastExp)e1;
3490                 e1 = ce.e1;
3491             }
3492         }
3493 
3494         // ---------------------------------------
3495         //      Interpret left hand side
3496         // ---------------------------------------
3497         AssocArrayLiteralExp existingAA = null;
3498         Expression lastIndex = null;
3499         Expression oldval = null;
3500         if (e1.op == TOKindex && (cast(IndexExp)e1).e1.type.toBasetype().ty == Taarray)
3501         {
3502             // ---------------------------------------
3503             //      Deal with AA index assignment
3504             // ---------------------------------------
3505             /* This needs special treatment if the AA doesn't exist yet.
3506              * There are two special cases:
3507              * (1) If the AA is itself an index of another AA, we may need to create
3508              *     multiple nested AA literals before we can insert the new value.
3509              * (2) If the ultimate AA is null, no insertion happens at all. Instead,
3510              *     we create nested AA literals, and change it into a assignment.
3511              */
3512             IndexExp ie = cast(IndexExp)e1;
3513             int depth = 0; // how many nested AA indices are there?
3514             while (ie.e1.op == TOKindex && (cast(IndexExp)ie.e1).e1.type.toBasetype().ty == Taarray)
3515             {
3516                 assert(ie.modifiable);
3517                 ie = cast(IndexExp)ie.e1;
3518                 ++depth;
3519             }
3520 
3521             // Get the AA value to be modified.
3522             Expression aggregate = interpret(ie.e1, istate);
3523             if (exceptionOrCant(aggregate))
3524                 return;
3525             if (aggregate.op == TOKassocarrayliteral)
3526             {
3527                 existingAA = cast(AssocArrayLiteralExp)aggregate;
3528 
3529                 // Normal case, ultimate parent AA already exists
3530                 // We need to walk from the deepest index up, checking that an AA literal
3531                 // already exists on each level.
3532                 lastIndex = interpret((cast(IndexExp)e1).e2, istate);
3533                 lastIndex = resolveSlice(lastIndex); // only happens with AA assignment
3534                 if (exceptionOrCant(lastIndex))
3535                     return;
3536 
3537                 while (depth > 0)
3538                 {
3539                     // Walk the syntax tree to find the indexExp at this depth
3540                     IndexExp xe = cast(IndexExp)e1;
3541                     for (int d = 0; d < depth; ++d)
3542                         xe = cast(IndexExp)xe.e1;
3543 
3544                     Expression ekey = interpret(xe.e2, istate);
3545                     if (exceptionOrCant(ekey))
3546                         return;
3547                     ekey = resolveSlice(ekey); // only happens with AA assignment
3548 
3549                     // Look up this index in it up in the existing AA, to get the next level of AA.
3550                     AssocArrayLiteralExp newAA = cast(AssocArrayLiteralExp)findKeyInAA(e.loc, existingAA, ekey);
3551                     if (exceptionOrCant(newAA))
3552                         return;
3553                     if (!newAA)
3554                     {
3555                         // Doesn't exist yet, create an empty AA...
3556                         auto keysx = new Expressions();
3557                         auto valuesx = new Expressions();
3558                         newAA = new AssocArrayLiteralExp(e.loc, keysx, valuesx);
3559                         newAA.type = xe.type;
3560                         newAA.ownedByCtfe = OWNEDctfe;
3561                         //... and insert it into the existing AA.
3562                         existingAA.keys.push(ekey);
3563                         existingAA.values.push(newAA);
3564                     }
3565                     existingAA = newAA;
3566                     --depth;
3567                 }
3568 
3569                 if (fp)
3570                 {
3571                     oldval = findKeyInAA(e.loc, existingAA, lastIndex);
3572                     if (!oldval)
3573                         oldval = copyLiteral(e.e1.type.defaultInitLiteral(e.loc)).copy();
3574                 }
3575             }
3576             else
3577             {
3578                 /* The AA is currently null. 'aggregate' is actually a reference to
3579                  * whatever contains it. It could be anything: var, dotvarexp, ...
3580                  * We rewrite the assignment from:
3581                  *     aa[i][j] op= newval;
3582                  * into:
3583                  *     aa = [i:[j:T.init]];
3584                  *     aa[j] op= newval;
3585                  */
3586                 oldval = copyLiteral(e.e1.type.defaultInitLiteral(e.loc)).copy();
3587 
3588                 Expression newaae = oldval;
3589                 while (e1.op == TOKindex && (cast(IndexExp)e1).e1.type.toBasetype().ty == Taarray)
3590                 {
3591                     Expression ekey = interpret((cast(IndexExp)e1).e2, istate);
3592                     if (exceptionOrCant(ekey))
3593                         return;
3594                     ekey = resolveSlice(ekey); // only happens with AA assignment
3595 
3596                     auto keysx = new Expressions();
3597                     auto valuesx = new Expressions();
3598                     keysx.push(ekey);
3599                     valuesx.push(newaae);
3600 
3601                     auto aae = new AssocArrayLiteralExp(e.loc, keysx, valuesx);
3602                     aae.type = (cast(IndexExp)e1).e1.type;
3603                     aae.ownedByCtfe = OWNEDctfe;
3604                     if (!existingAA)
3605                     {
3606                         existingAA = aae;
3607                         lastIndex = ekey;
3608                     }
3609                     newaae = aae;
3610                     e1 = (cast(IndexExp)e1).e1;
3611                 }
3612 
3613                 // We must set to aggregate with newaae
3614                 e1 = interpret(e1, istate, ctfeNeedLvalue);
3615                 if (exceptionOrCant(e1))
3616                     return;
3617                 e1 = assignToLvalue(e, e1, newaae);
3618                 if (exceptionOrCant(e1))
3619                     return;
3620             }
3621             assert(existingAA && lastIndex);
3622             e1 = null; // stomp
3623         }
3624         else if (e1.op == TOKarraylength)
3625         {
3626             oldval = interpret(e1, istate);
3627             if (exceptionOrCant(oldval))
3628                 return;
3629         }
3630         else if (e.op == TOKconstruct || e.op == TOKblit)
3631         {
3632             // Unless we have a simple var assignment, we're
3633             // only modifying part of the variable. So we need to make sure
3634             // that the parent variable exists.
3635             VarDeclaration ultimateVar = findParentVar(e1);
3636             if (e1.op == TOKvar)
3637             {
3638                 VarDeclaration v = (cast(VarExp)e1).var.isVarDeclaration();
3639                 assert(v);
3640                 if (v.storage_class & STCout)
3641                     goto L1;
3642             }
3643             else if (ultimateVar && !getValue(ultimateVar))
3644             {
3645                 Expression ex = interpret(ultimateVar.type.defaultInitLiteral(e.loc), istate);
3646                 if (exceptionOrCant(ex))
3647                     return;
3648                 setValue(ultimateVar, ex);
3649             }
3650             else
3651                 goto L1;
3652         }
3653         else
3654         {
3655         L1:
3656             e1 = interpret(e1, istate, ctfeNeedLvalue);
3657             if (exceptionOrCant(e1))
3658                 return;
3659 
3660             if (e1.op == TOKindex && (cast(IndexExp)e1).e1.type.toBasetype().ty == Taarray)
3661             {
3662                 IndexExp ie = cast(IndexExp)e1;
3663                 assert(ie.e1.op == TOKassocarrayliteral);
3664                 existingAA = cast(AssocArrayLiteralExp)ie.e1;
3665                 lastIndex = ie.e2;
3666             }
3667         }
3668 
3669         // ---------------------------------------
3670         //      Interpret right hand side
3671         // ---------------------------------------
3672         Expression newval = interpret(e.e2, istate);
3673         if (exceptionOrCant(newval))
3674             return;
3675         if (e.op == TOKblit && newval.op == TOKint64)
3676         {
3677             Type tbn = e.type.baseElemOf();
3678             if (tbn.ty == Tstruct)
3679             {
3680                 /* Look for special case of struct being initialized with 0.
3681                  */
3682                 newval = e.type.defaultInitLiteral(e.loc);
3683                 if (newval.op == TOKerror)
3684                 {
3685                     result = CTFEExp.cantexp;
3686                     return;
3687                 }
3688                 newval = interpret(newval, istate); // copy and set ownedByCtfe flag
3689                 if (exceptionOrCant(newval))
3690                     return;
3691             }
3692         }
3693 
3694         // ----------------------------------------------------
3695         //  Deal with read-modify-write assignments.
3696         //  Set 'newval' to the final assignment value
3697         //  Also determine the return value (except for slice
3698         //  assignments, which are more complicated)
3699         // ----------------------------------------------------
3700         if (fp)
3701         {
3702             if (!oldval)
3703             {
3704                 // Load the left hand side after interpreting the right hand side.
3705                 oldval = interpret(e1, istate);
3706                 if (exceptionOrCant(oldval))
3707                     return;
3708             }
3709 
3710             if (e.e1.type.ty != Tpointer)
3711             {
3712                 // ~= can create new values (see bug 6052)
3713                 if (e.op == TOKcatass)
3714                 {
3715                     // We need to dup it and repaint the type. For a dynamic array
3716                     // we can skip duplication, because it gets copied later anyway.
3717                     if (newval.type.ty != Tarray)
3718                     {
3719                         newval = copyLiteral(newval).copy();
3720                         newval.type = e.e2.type; // repaint type
3721                     }
3722                     else
3723                     {
3724                         newval = paintTypeOntoLiteral(e.e2.type, newval);
3725                         newval = resolveSlice(newval);
3726                     }
3727                 }
3728                 oldval = resolveSlice(oldval);
3729 
3730                 newval = (*fp)(e.loc, e.type, oldval, newval).copy();
3731             }
3732             else if (e.e2.type.isintegral() &&
3733                      (e.op == TOKaddass ||
3734                       e.op == TOKminass ||
3735                       e.op == TOKplusplus ||
3736                       e.op == TOKminusminus))
3737             {
3738                 newval = pointerArithmetic(e.loc, e.op, e.type, oldval, newval).copy();
3739             }
3740             else
3741             {
3742                 e.error("pointer expression %s cannot be interpreted at compile time", e.toChars());
3743                 result = CTFEExp.cantexp;
3744                 return;
3745             }
3746             if (exceptionOrCant(newval))
3747             {
3748                 if (CTFEExp.isCantExp(newval))
3749                     e.error("cannot interpret %s at compile time", e.toChars());
3750                 return;
3751             }
3752         }
3753 
3754         if (existingAA)
3755         {
3756             if (existingAA.ownedByCtfe != OWNEDctfe)
3757             {
3758                 e.error("cannot modify read-only constant %s", existingAA.toChars());
3759                 result = CTFEExp.cantexp;
3760                 return;
3761             }
3762 
3763             //printf("\t+L%d existingAA = %s, lastIndex = %s, oldval = %s, newval = %s\n",
3764             //    __LINE__, existingAA->toChars(), lastIndex->toChars(), oldval ? oldval->toChars() : NULL, newval->toChars());
3765             assignAssocArrayElement(e.loc, existingAA, lastIndex, newval);
3766 
3767             // Determine the return value
3768             result = ctfeCast(e.loc, e.type, e.type, fp && post ? oldval : newval);
3769             return;
3770         }
3771         if (e1.op == TOKarraylength)
3772         {
3773             /* Change the assignment from:
3774              *  arr.length = n;
3775              * into:
3776              *  arr = new_length_array; (result is n)
3777              */
3778 
3779             // Determine the return value
3780             result = ctfeCast(e.loc, e.type, e.type, fp && post ? oldval : newval);
3781             if (exceptionOrCant(result))
3782                 return;
3783 
3784             size_t oldlen = cast(size_t)oldval.toInteger();
3785             size_t newlen = cast(size_t)newval.toInteger();
3786             if (oldlen == newlen) // no change required -- we're done!
3787                 return;
3788 
3789             // We have changed it into a reference assignment
3790             // Note that returnValue is still the new length.
3791             e1 = (cast(ArrayLengthExp)e1).e1;
3792             Type t = e1.type.toBasetype();
3793             if (t.ty != Tarray)
3794             {
3795                 e.error("%s is not yet supported at compile time", e.toChars());
3796                 result = CTFEExp.cantexp;
3797                 return;
3798             }
3799             e1 = interpret(e1, istate, ctfeNeedLvalue);
3800             if (exceptionOrCant(e1))
3801                 return;
3802 
3803             if (oldlen != 0) // Get the old array literal.
3804                 oldval = interpret(e1, istate);
3805             newval = changeArrayLiteralLength(e.loc, cast(TypeArray)t, oldval, oldlen, newlen).copy();
3806 
3807             e1 = assignToLvalue(e, e1, newval);
3808             if (exceptionOrCant(e1))
3809                 return;
3810 
3811             return;
3812         }
3813 
3814         if (!isBlockAssignment)
3815         {
3816             newval = ctfeCast(e.loc, e.type, e.type, newval);
3817             if (exceptionOrCant(newval))
3818                 return;
3819 
3820             // Determine the return value
3821             if (goal == ctfeNeedLvalue) // Bugzilla 14371
3822                 result = e1;
3823             else
3824                 result = ctfeCast(e.loc, e.type, e.type, fp && post ? oldval : newval);
3825             if (exceptionOrCant(result))
3826                 return;
3827         }
3828         if (exceptionOrCant(newval))
3829             return;
3830 
3831         debug (LOGASSIGN)
3832         {
3833             printf("ASSIGN: %s=%s\n", e1.toChars(), newval.toChars());
3834             showCtfeExpr(newval);
3835         }
3836 
3837         /* Block assignment or element-wise assignment.
3838          */
3839         if (e1.op == TOKslice ||
3840             e1.op == TOKvector ||
3841             e1.op == TOKarrayliteral ||
3842             e1.op == TOKstring ||
3843             e1.op == TOKnull && e1.type.toBasetype().ty == Tarray)
3844         {
3845             // Note that slice assignments don't support things like ++, so
3846             // we don't need to remember 'returnValue'.
3847             result = interpretAssignToSlice(e, e1, newval, isBlockAssignment);
3848             if (exceptionOrCant(result))
3849                 return;
3850             if (e.e1.op == TOKslice)
3851             {
3852                 Expression e1x = interpret((cast(SliceExp)e.e1).e1, istate, ctfeNeedLvalue);
3853                 if (e1x.op == TOKdotvar)
3854                 {
3855                     auto dve = cast(DotVarExp)e1x;
3856                     auto ex = dve.e1;
3857                     auto sle = ex.op == TOKstructliteral ? (cast(StructLiteralExp)ex)
3858                              : ex.op == TOKclassreference ? (cast(ClassReferenceExp)ex).value
3859                              : null;
3860                     auto v = dve.var.isVarDeclaration();
3861                     if (!sle || !v)
3862                     {
3863                         e.error("CTFE internal error: dotvar slice assignment");
3864                         result = CTFEExp.cantexp;
3865                         return;
3866                     }
3867                     stompOverlappedFields(sle, v);
3868                 }
3869             }
3870             return;
3871         }
3872         assert(result);
3873 
3874         /* Assignment to a CTFE reference.
3875          */
3876         if (Expression ex = assignToLvalue(e, e1, newval))
3877             result = ex;
3878 
3879         return;
3880     }
3881 
3882     /* Set all sibling fields which overlap with v to VoidExp.
3883      */
3884     void stompOverlappedFields(StructLiteralExp sle, VarDeclaration v)
3885     {
3886         if (!v.overlapped)
3887             return;
3888         foreach (size_t i, v2; sle.sd.fields)
3889         {
3890             if (v is v2 || !v.isOverlappedWith(v2))
3891                 continue;
3892             auto e = (*sle.elements)[i];
3893             if (e.op != TOKvoid)
3894                 (*sle.elements)[i] = voidInitLiteral(e.type, v).copy();
3895         }
3896     }
3897 
3898     Expression assignToLvalue(BinExp e, Expression e1, Expression newval)
3899     {
3900         VarDeclaration vd = null;
3901         Expression* payload = null; // dead-store to prevent spurious warning
3902         Expression oldval;
3903 
3904         if (e1.op == TOKvar)
3905         {
3906             vd = (cast(VarExp)e1).var.isVarDeclaration();
3907             oldval = getValue(vd);
3908         }
3909         else if (e1.op == TOKdotvar)
3910         {
3911             /* Assignment to member variable of the form:
3912              *  e.v = newval
3913              */
3914             auto ex = (cast(DotVarExp)e1).e1;
3915             auto sle = ex.op == TOKstructliteral ? (cast(StructLiteralExp)ex)
3916                      : ex.op == TOKclassreference ? (cast(ClassReferenceExp)ex).value
3917                      : null;
3918             auto v = (cast(DotVarExp)e1).var.isVarDeclaration();
3919             if (!sle || !v)
3920             {
3921                 e.error("CTFE internal error: dotvar assignment");
3922                 return CTFEExp.cantexp;
3923             }
3924             if (sle.ownedByCtfe != OWNEDctfe)
3925             {
3926                 e.error("cannot modify read-only constant %s", sle.toChars());
3927                 return CTFEExp.cantexp;
3928             }
3929 
3930             int fieldi = ex.op == TOKstructliteral ? findFieldIndexByName(sle.sd, v)
3931                        : (cast(ClassReferenceExp)ex).findFieldIndexByName(v);
3932             if (fieldi == -1)
3933             {
3934                 e.error("CTFE internal error: cannot find field %s in %s", v.toChars(), ex.toChars());
3935                 return CTFEExp.cantexp;
3936             }
3937             assert(0 <= fieldi && fieldi < sle.elements.dim);
3938 
3939             // If it's a union, set all other members of this union to void
3940             stompOverlappedFields(sle, v);
3941 
3942             payload = &(*sle.elements)[fieldi];
3943             oldval = *payload;
3944         }
3945         else if (e1.op == TOKindex)
3946         {
3947             IndexExp ie = cast(IndexExp)e1;
3948             assert(ie.e1.type.toBasetype().ty != Taarray);
3949 
3950             Expression aggregate;
3951             uinteger_t indexToModify;
3952             if (!resolveIndexing(ie, istate, &aggregate, &indexToModify, true))
3953             {
3954                 return CTFEExp.cantexp;
3955             }
3956             size_t index = cast(size_t)indexToModify;
3957 
3958             if (aggregate.op == TOKstring)
3959             {
3960                 StringExp existingSE = cast(StringExp)aggregate;
3961                 if (existingSE.ownedByCtfe != OWNEDctfe)
3962                 {
3963                     e.error("cannot modify read-only string literal %s", ie.e1.toChars());
3964                     return CTFEExp.cantexp;
3965                 }
3966                 existingSE.setCodeUnit(index, cast(dchar)newval.toInteger());
3967                 return null;
3968             }
3969             if (aggregate.op != TOKarrayliteral)
3970             {
3971                 e.error("index assignment %s is not yet supported in CTFE ", e.toChars());
3972                 return CTFEExp.cantexp;
3973             }
3974 
3975             ArrayLiteralExp existingAE = cast(ArrayLiteralExp)aggregate;
3976             if (existingAE.ownedByCtfe != OWNEDctfe)
3977             {
3978                 e.error("cannot modify read-only constant %s", existingAE.toChars());
3979                 return CTFEExp.cantexp;
3980             }
3981 
3982             payload = &(*existingAE.elements)[index];
3983             oldval = *payload;
3984         }
3985         else
3986         {
3987             e.error("%s cannot be evaluated at compile time", e.toChars());
3988             return CTFEExp.cantexp;
3989         }
3990 
3991         Type t1b = e1.type.toBasetype();
3992         bool wantCopy = t1b.baseElemOf().ty == Tstruct;
3993 
3994         if (newval.op == TOKstructliteral && oldval)
3995         {
3996             newval = copyLiteral(newval).copy();
3997             assignInPlace(oldval, newval);
3998         }
3999         else if (wantCopy && e.op == TOKassign)
4000         {
4001             // Currently postblit/destructor calls on static array are done
4002             // in the druntime internal functions so they don't appear in AST.
4003             // Therefore interpreter should handle them specially.
4004 
4005             assert(oldval);
4006             version (all) // todo: instead we can directly access to each elements of the slice
4007             {
4008                 newval = resolveSlice(newval);
4009                 if (CTFEExp.isCantExp(newval))
4010                 {
4011                     e.error("CTFE internal error: assignment %s", e.toChars());
4012                     return CTFEExp.cantexp;
4013                 }
4014             }
4015             assert(oldval.op == TOKarrayliteral);
4016             assert(newval.op == TOKarrayliteral);
4017 
4018             Expressions* oldelems = (cast(ArrayLiteralExp)oldval).elements;
4019             Expressions* newelems = (cast(ArrayLiteralExp)newval).elements;
4020             assert(oldelems.dim == newelems.dim);
4021 
4022             Type elemtype = oldval.type.nextOf();
4023             for (size_t i = 0; i < newelems.dim; i++)
4024             {
4025                 Expression oldelem = (*oldelems)[i];
4026                 Expression newelem = paintTypeOntoLiteral(elemtype, (*newelems)[i]);
4027                 // Bugzilla 9245
4028                 if (e.e2.isLvalue())
4029                 {
4030                     if (Expression ex = evaluatePostblit(istate, newelem))
4031                         return ex;
4032                 }
4033                 // Bugzilla 13661
4034                 if (Expression ex = evaluateDtor(istate, oldelem))
4035                     return ex;
4036                 (*oldelems)[i] = newelem;
4037             }
4038         }
4039         else
4040         {
4041             // e1 has its own payload, so we have to create a new literal.
4042             if (wantCopy)
4043                 newval = copyLiteral(newval).copy();
4044 
4045             if (t1b.ty == Tsarray && e.op == TOKconstruct && e.e2.isLvalue())
4046             {
4047                 // Bugzilla 9245
4048                 if (Expression ex = evaluatePostblit(istate, newval))
4049                     return ex;
4050             }
4051 
4052             oldval = newval;
4053         }
4054 
4055         if (vd)
4056             setValue(vd, oldval);
4057         else
4058             *payload = oldval;
4059 
4060         // Blit assignment should return the newly created value.
4061         if (e.op == TOKblit)
4062             return oldval;
4063 
4064         return null;
4065     }
4066 
4067     /*************
4068      * Deal with assignments of the form:
4069      *  dest[] = newval
4070      *  dest[low..upp] = newval
4071      * where newval has already been interpreted
4072      *
4073      * This could be a slice assignment or a block assignment, and
4074      * dest could be either an array literal, or a string.
4075      *
4076      * Returns TOKcantexp on failure. If there are no errors,
4077      * it returns aggregate[low..upp], except that as an optimisation,
4078      * if goal == ctfeNeedNothing, it will return NULL
4079      */
4080     Expression interpretAssignToSlice(BinExp e, Expression e1, Expression newval, bool isBlockAssignment)
4081     {
4082         dinteger_t lowerbound;
4083         dinteger_t upperbound;
4084         dinteger_t firstIndex;
4085 
4086         Expression aggregate;
4087 
4088         if (e1.op == TOKvector)
4089             e1 = (cast(VectorExp)e1).e1;
4090         if (e1.op == TOKslice)
4091         {
4092             // ------------------------------
4093             //   aggregate[] = newval
4094             //   aggregate[low..upp] = newval
4095             // ------------------------------
4096             SliceExp se = cast(SliceExp)e1;
4097             version (all) // should be move in interpretAssignCommon as the evaluation of e1
4098             {
4099                 Expression oldval = interpret(se.e1, istate);
4100 
4101                 // Set the $ variable
4102                 uinteger_t dollar = resolveArrayLength(oldval);
4103                 if (se.lengthVar)
4104                 {
4105                     Expression dollarExp = new IntegerExp(e1.loc, dollar, Type.tsize_t);
4106                     ctfeStack.push(se.lengthVar);
4107                     setValue(se.lengthVar, dollarExp);
4108                 }
4109                 Expression lwr = interpret(se.lwr, istate);
4110                 if (exceptionOrCantInterpret(lwr))
4111                 {
4112                     if (se.lengthVar)
4113                         ctfeStack.pop(se.lengthVar);
4114                     return lwr;
4115                 }
4116                 Expression upr = interpret(se.upr, istate);
4117                 if (exceptionOrCantInterpret(upr))
4118                 {
4119                     if (se.lengthVar)
4120                         ctfeStack.pop(se.lengthVar);
4121                     return upr;
4122                 }
4123                 if (se.lengthVar)
4124                     ctfeStack.pop(se.lengthVar); // $ is defined only in [L..U]
4125 
4126                 const dim = dollar;
4127                 lowerbound = lwr ? lwr.toInteger() : 0;
4128                 upperbound = upr ? upr.toInteger() : dim;
4129 
4130                 if (lowerbound < 0 || dim < upperbound)
4131                 {
4132                     e.error("array bounds [0..%llu] exceeded in slice [%llu..%llu]",
4133                         ulong(dim), ulong(lowerbound), ulong(upperbound));
4134                     return CTFEExp.cantexp;
4135                 }
4136             }
4137             aggregate = oldval;
4138             firstIndex = lowerbound;
4139 
4140             if (aggregate.op == TOKslice)
4141             {
4142                 // Slice of a slice --> change the bounds
4143                 SliceExp oldse = cast(SliceExp)aggregate;
4144                 if (oldse.upr.toInteger() < upperbound + oldse.lwr.toInteger())
4145                 {
4146                     e.error("slice [%llu..%llu] exceeds array bounds [0..%llu]",
4147                         ulong(lowerbound), ulong(upperbound), oldse.upr.toInteger() - oldse.lwr.toInteger());
4148                     return CTFEExp.cantexp;
4149                 }
4150                 aggregate = oldse.e1;
4151                 firstIndex = lowerbound + oldse.lwr.toInteger();
4152             }
4153         }
4154         else
4155         {
4156             if (e1.op == TOKarrayliteral)
4157             {
4158                 lowerbound = 0;
4159                 upperbound = (cast(ArrayLiteralExp)e1).elements.dim;
4160             }
4161             else if (e1.op == TOKstring)
4162             {
4163                 lowerbound = 0;
4164                 upperbound = (cast(StringExp)e1).len;
4165             }
4166             else if (e1.op == TOKnull)
4167             {
4168                 lowerbound = 0;
4169                 upperbound = 0;
4170             }
4171             else
4172                 assert(0);
4173 
4174             aggregate = e1;
4175             firstIndex = lowerbound;
4176         }
4177         if (upperbound == lowerbound)
4178             return newval;
4179 
4180         // For slice assignment, we check that the lengths match.
4181         if (!isBlockAssignment)
4182         {
4183             const srclen = resolveArrayLength(newval);
4184             if (srclen != (upperbound - lowerbound))
4185             {
4186                 e.error("array length mismatch assigning [0..%llu] to [%llu..%llu]",
4187                     ulong(srclen), ulong(lowerbound), ulong(upperbound));
4188                 return CTFEExp.cantexp;
4189             }
4190         }
4191 
4192         if (aggregate.op == TOKstring)
4193         {
4194             StringExp existingSE = cast(StringExp)aggregate;
4195             if (existingSE.ownedByCtfe != OWNEDctfe)
4196             {
4197                 e.error("cannot modify read-only string literal %s", existingSE.toChars());
4198                 return CTFEExp.cantexp;
4199             }
4200 
4201             if (newval.op == TOKslice)
4202             {
4203                 auto se = cast(SliceExp)newval;
4204                 auto aggr2 = se.e1;
4205                 const srclower = se.lwr.toInteger();
4206                 const srcupper = se.upr.toInteger();
4207 
4208                 if (aggregate == aggr2 &&
4209                     lowerbound < srcupper && srclower < upperbound)
4210                 {
4211                     e.error("overlapping slice assignment [%llu..%llu] = [%llu..%llu]",
4212                         ulong(lowerbound), ulong(upperbound), ulong(srclower), ulong(srcupper));
4213                     return CTFEExp.cantexp;
4214                 }
4215                 version (all) // todo: instead we can directly access to each elements of the slice
4216                 {
4217                     Expression orignewval = newval;
4218                     newval = resolveSlice(newval);
4219                     if (CTFEExp.isCantExp(newval))
4220                     {
4221                         e.error("CTFE internal error: slice %s", orignewval.toChars());
4222                         return CTFEExp.cantexp;
4223                     }
4224                 }
4225                 assert(newval.op != TOKslice);
4226             }
4227             if (newval.op == TOKstring)
4228             {
4229                 sliceAssignStringFromString(existingSE, cast(StringExp)newval, cast(size_t)firstIndex);
4230                 return newval;
4231             }
4232             if (newval.op == TOKarrayliteral)
4233             {
4234                 /* Mixed slice: it was initialized as a string literal.
4235                  * Now a slice of it is being set with an array literal.
4236                  */
4237                 sliceAssignStringFromArrayLiteral(existingSE, cast(ArrayLiteralExp)newval, cast(size_t)firstIndex);
4238                 return newval;
4239             }
4240 
4241             // String literal block slice assign
4242             const value = cast(dchar)newval.toInteger();
4243             foreach (i; 0 .. upperbound - lowerbound)
4244             {
4245                 existingSE.setCodeUnit(cast(size_t)(i + firstIndex), value);
4246             }
4247             if (goal == ctfeNeedNothing)
4248                 return null; // avoid creating an unused literal
4249             auto retslice = new SliceExp(e.loc, existingSE, new IntegerExp(e.loc, firstIndex, Type.tsize_t), new IntegerExp(e.loc, firstIndex + upperbound - lowerbound, Type.tsize_t));
4250             retslice.type = e.type;
4251             return interpret(retslice, istate);
4252         }
4253         if (aggregate.op == TOKarrayliteral)
4254         {
4255             ArrayLiteralExp existingAE = cast(ArrayLiteralExp)aggregate;
4256             if (existingAE.ownedByCtfe != OWNEDctfe)
4257             {
4258                 e.error("cannot modify read-only constant %s", existingAE.toChars());
4259                 return CTFEExp.cantexp;
4260             }
4261 
4262             if (newval.op == TOKslice && !isBlockAssignment)
4263             {
4264                 auto se = cast(SliceExp)newval;
4265                 auto aggr2 = se.e1;
4266                 const srclower = se.lwr.toInteger();
4267                 const srcupper = se.upr.toInteger();
4268                 const wantCopy = (newval.type.toBasetype().nextOf().baseElemOf().ty == Tstruct);
4269 
4270                 //printf("oldval = %p %s[%d..%u]\nnewval = %p %s[%llu..%llu] wantCopy = %d\n",
4271                 //    aggregate, aggregate->toChars(), lowerbound, upperbound,
4272                 //    aggr2, aggr2->toChars(), srclower, srcupper, wantCopy);
4273                 if (wantCopy)
4274                 {
4275                     // Currently overlapping for struct array is allowed.
4276                     // The order of elements processing depends on the overlapping.
4277                     // See bugzilla 14024.
4278                     assert(aggr2.op == TOKarrayliteral);
4279                     Expressions* oldelems = existingAE.elements;
4280                     Expressions* newelems = (cast(ArrayLiteralExp)aggr2).elements;
4281 
4282                     Type elemtype = aggregate.type.nextOf();
4283                     bool needsPostblit = e.e2.isLvalue();
4284 
4285                     if (aggregate == aggr2 && srclower < lowerbound && lowerbound < srcupper)
4286                     {
4287                         // reverse order
4288                         for (auto i = upperbound - lowerbound; 0 < i--;)
4289                         {
4290                             Expression oldelem = (*oldelems)[cast(size_t)(i + firstIndex)];
4291                             Expression newelem = (*newelems)[cast(size_t)(i + srclower)];
4292                             newelem = copyLiteral(newelem).copy();
4293                             newelem.type = elemtype;
4294                             if (needsPostblit)
4295                             {
4296                                 if (Expression x = evaluatePostblit(istate, newelem))
4297                                     return x;
4298                             }
4299                             if (Expression x = evaluateDtor(istate, oldelem))
4300                                 return x;
4301                             (*oldelems)[cast(size_t)(lowerbound + i)] = newelem;
4302                         }
4303                     }
4304                     else
4305                     {
4306                         // normal order
4307                         for (auto i = 0; i < upperbound - lowerbound; i++)
4308                         {
4309                             Expression oldelem = (*oldelems)[cast(size_t)(i + firstIndex)];
4310                             Expression newelem = (*newelems)[cast(size_t)(i + srclower)];
4311                             newelem = copyLiteral(newelem).copy();
4312                             newelem.type = elemtype;
4313                             if (needsPostblit)
4314                             {
4315                                 if (Expression x = evaluatePostblit(istate, newelem))
4316                                     return x;
4317                             }
4318                             if (Expression x = evaluateDtor(istate, oldelem))
4319                                 return x;
4320                             (*oldelems)[cast(size_t)(lowerbound + i)] = newelem;
4321                         }
4322                     }
4323 
4324                     //assert(0);
4325                     return newval; // oldval?
4326                 }
4327                 if (aggregate == aggr2 &&
4328                     lowerbound < srcupper && srclower < upperbound)
4329                 {
4330                     e.error("overlapping slice assignment [%llu..%llu] = [%llu..%llu]",
4331                         ulong(lowerbound), ulong(upperbound), ulong(srclower), ulong(srcupper));
4332                     return CTFEExp.cantexp;
4333                 }
4334                 version (all) // todo: instead we can directly access to each elements of the slice
4335                 {
4336                     Expression orignewval = newval;
4337                     newval = resolveSlice(newval);
4338                     if (CTFEExp.isCantExp(newval))
4339                     {
4340                         e.error("CTFE internal error: slice %s", orignewval.toChars());
4341                         return CTFEExp.cantexp;
4342                     }
4343                 }
4344                 // no overlapping
4345                 //length?
4346                 assert(newval.op != TOKslice);
4347             }
4348             if (newval.op == TOKstring && !isBlockAssignment)
4349             {
4350                 /* Mixed slice: it was initialized as an array literal of chars/integers.
4351                  * Now a slice of it is being set with a string.
4352                  */
4353                 sliceAssignArrayLiteralFromString(existingAE, cast(StringExp)newval, cast(size_t)firstIndex);
4354                 return newval;
4355             }
4356             if (newval.op == TOKarrayliteral && !isBlockAssignment)
4357             {
4358                 Expressions* oldelems = existingAE.elements;
4359                 Expressions* newelems = (cast(ArrayLiteralExp)newval).elements;
4360                 Type elemtype = existingAE.type.nextOf();
4361                 bool needsPostblit = e.op != TOKblit && e.e2.isLvalue();
4362                 for (size_t j = 0; j < newelems.dim; j++)
4363                 {
4364                     Expression newelem = (*newelems)[j];
4365                     newelem = paintTypeOntoLiteral(elemtype, newelem);
4366                     if (needsPostblit)
4367                     {
4368                         Expression x = evaluatePostblit(istate, newelem);
4369                         if (exceptionOrCantInterpret(x))
4370                             return x;
4371                     }
4372                     (*oldelems)[cast(size_t)(j + firstIndex)] = newelem;
4373                 }
4374                 return newval;
4375             }
4376 
4377             /* Block assignment, initialization of static arrays
4378              *   x[] = newval
4379              *  x may be a multidimensional static array. (Note that this
4380              *  only happens with array literals, never with strings).
4381              */
4382             struct RecursiveBlock
4383             {
4384                 InterState* istate;
4385                 Expression newval;
4386                 bool refCopy;
4387                 bool needsPostblit;
4388                 bool needsDtor;
4389 
4390                 extern (C++) Expression assignTo(ArrayLiteralExp ae)
4391                 {
4392                     return assignTo(ae, 0, ae.elements.dim);
4393                 }
4394 
4395                 extern (C++) Expression assignTo(ArrayLiteralExp ae, size_t lwr, size_t upr)
4396                 {
4397                     Expressions* w = ae.elements;
4398                     assert(ae.type.ty == Tsarray || ae.type.ty == Tarray);
4399                     bool directblk = (cast(TypeArray)ae.type).next.equivalent(newval.type);
4400                     for (size_t k = lwr; k < upr; k++)
4401                     {
4402                         if (!directblk && (*w)[k].op == TOKarrayliteral)
4403                         {
4404                             // Multidimensional array block assign
4405                             if (Expression ex = assignTo(cast(ArrayLiteralExp)(*w)[k]))
4406                                 return ex;
4407                         }
4408                         else if (refCopy)
4409                         {
4410                             (*w)[k] = newval;
4411                         }
4412                         else if (!needsPostblit && !needsDtor)
4413                         {
4414                             assignInPlace((*w)[k], newval);
4415                         }
4416                         else
4417                         {
4418                             Expression oldelem = (*w)[k];
4419                             Expression tmpelem = needsDtor ? copyLiteral(oldelem).copy() : null;
4420                             assignInPlace(oldelem, newval);
4421                             if (needsPostblit)
4422                             {
4423                                 if (Expression ex = evaluatePostblit(istate, oldelem))
4424                                     return ex;
4425                             }
4426                             if (needsDtor)
4427                             {
4428                                 // Bugzilla 14860
4429                                 if (Expression ex = evaluateDtor(istate, tmpelem))
4430                                     return ex;
4431                             }
4432                         }
4433                     }
4434                     return null;
4435                 }
4436             }
4437 
4438             Type tn = newval.type.toBasetype();
4439             bool wantRef = (tn.ty == Tarray || isAssocArray(tn) || tn.ty == Tclass);
4440             bool cow = newval.op != TOKstructliteral && newval.op != TOKarrayliteral && newval.op != TOKstring;
4441             Type tb = tn.baseElemOf();
4442             StructDeclaration sd = (tb.ty == Tstruct ? (cast(TypeStruct)tb).sym : null);
4443 
4444             RecursiveBlock rb;
4445             rb.istate = istate;
4446             rb.newval = newval;
4447             rb.refCopy = wantRef || cow;
4448             rb.needsPostblit = sd && sd.postblit && e.op != TOKblit && e.e2.isLvalue();
4449             rb.needsDtor = sd && sd.dtor && e.op == TOKassign;
4450             if (Expression ex = rb.assignTo(existingAE, cast(size_t)lowerbound, cast(size_t)upperbound))
4451                 return ex;
4452 
4453             if (goal == ctfeNeedNothing)
4454                 return null; // avoid creating an unused literal
4455             auto retslice = new SliceExp(e.loc, existingAE, new IntegerExp(e.loc, firstIndex, Type.tsize_t), new IntegerExp(e.loc, firstIndex + upperbound - lowerbound, Type.tsize_t));
4456             retslice.type = e.type;
4457             return interpret(retslice, istate);
4458         }
4459 
4460         e.error("slice operation %s = %s cannot be evaluated at compile time", e1.toChars(), newval.toChars());
4461         return CTFEExp.cantexp;
4462     }
4463 
4464     override void visit(AssignExp e)
4465     {
4466         interpretAssignCommon(e, null);
4467     }
4468 
4469     override void visit(BinAssignExp e)
4470     {
4471         switch (e.op)
4472         {
4473         case TOKaddass:
4474             interpretAssignCommon(e, &Add);
4475             return;
4476 
4477         case TOKminass:
4478             interpretAssignCommon(e, &Min);
4479             return;
4480 
4481         case TOKcatass:
4482             interpretAssignCommon(e, &ctfeCat);
4483             return;
4484 
4485         case TOKmulass:
4486             interpretAssignCommon(e, &Mul);
4487             return;
4488 
4489         case TOKdivass:
4490             interpretAssignCommon(e, &Div);
4491             return;
4492 
4493         case TOKmodass:
4494             interpretAssignCommon(e, &Mod);
4495             return;
4496 
4497         case TOKshlass:
4498             interpretAssignCommon(e, &Shl);
4499             return;
4500 
4501         case TOKshrass:
4502             interpretAssignCommon(e, &Shr);
4503             return;
4504 
4505         case TOKushrass:
4506             interpretAssignCommon(e, &Ushr);
4507             return;
4508 
4509         case TOKandass:
4510             interpretAssignCommon(e, &And);
4511             return;
4512 
4513         case TOKorass:
4514             interpretAssignCommon(e, &Or);
4515             return;
4516 
4517         case TOKxorass:
4518             interpretAssignCommon(e, &Xor);
4519             return;
4520 
4521         case TOKpowass:
4522             interpretAssignCommon(e, &Pow);
4523             return;
4524 
4525         default:
4526             assert(0);
4527         }
4528     }
4529 
4530     override void visit(PostExp e)
4531     {
4532         debug (LOG)
4533         {
4534             printf("%s PostExp::interpret() %s\n", e.loc.toChars(), e.toChars());
4535         }
4536         if (e.op == TOKplusplus)
4537             interpretAssignCommon(e, &Add, 1);
4538         else
4539             interpretAssignCommon(e, &Min, 1);
4540         debug (LOG)
4541         {
4542             if (CTFEExp.isCantExp(result))
4543                 printf("PostExp::interpret() CANT\n");
4544         }
4545     }
4546 
4547     /* Return 1 if e is a p1 > p2 or p1 >= p2 pointer comparison;
4548      *       -1 if e is a p1 < p2 or p1 <= p2 pointer comparison;
4549      *        0 otherwise
4550      */
4551     static int isPointerCmpExp(Expression e, Expression* p1, Expression* p2)
4552     {
4553         int ret = 1;
4554         while (e.op == TOKnot)
4555         {
4556             ret *= -1;
4557             e = (cast(NotExp)e).e1;
4558         }
4559         switch (e.op)
4560         {
4561         case TOKlt:
4562         case TOKle:
4563             ret *= -1;
4564             goto case; /+ fall through +/
4565         case TOKgt:
4566         case TOKge:
4567             *p1 = (cast(BinExp)e).e1;
4568             *p2 = (cast(BinExp)e).e2;
4569             if (!(isPointer((*p1).type) && isPointer((*p2).type)))
4570                 ret = 0;
4571             break;
4572 
4573         default:
4574             ret = 0;
4575             break;
4576         }
4577         return ret;
4578     }
4579 
4580     /** Negate a relational operator, eg >= becomes <
4581      */
4582     static TOK reverseRelation(TOK op)
4583     {
4584         switch (op)
4585         {
4586         case TOKge:
4587             return TOKlt;
4588 
4589         case TOKgt:
4590             return TOKle;
4591 
4592         case TOKle:
4593             return TOKgt;
4594 
4595         case TOKlt:
4596             return TOKge;
4597 
4598         default:
4599             assert(0);
4600         }
4601     }
4602 
4603     /** If this is a four pointer relation, evaluate it, else return NULL.
4604      *
4605      *  This is an expression of the form (p1 > q1 && p2 < q2) or (p1 < q1 || p2 > q2)
4606      *  where p1, p2 are expressions yielding pointers to memory block p,
4607      *  and q1, q2 are expressions yielding pointers to memory block q.
4608      *  This expression is valid even if p and q are independent memory
4609      *  blocks and are therefore not normally comparable; the && form returns true
4610      *  if [p1..p2] lies inside [q1..q2], and false otherwise; the || form returns
4611      *  true if [p1..p2] lies outside [q1..q2], and false otherwise.
4612      *
4613      *  Within the expression, any ordering of p1, p2, q1, q2 is permissible;
4614      *  the comparison operators can be any of >, <, <=, >=, provided that
4615      *  both directions (p > q and p < q) are checked. Additionally the
4616      *  relational sub-expressions can be negated, eg
4617      *  (!(q1 < p1) && p2 <= q2) is valid.
4618      */
4619     void interpretFourPointerRelation(BinExp e)
4620     {
4621         assert(e.op == TOKandand || e.op == TOKoror);
4622 
4623         /*  It can only be an isInside expression, if both e1 and e2 are
4624          *  directional pointer comparisons.
4625          *  Note that this check can be made statically; it does not depends on
4626          *  any runtime values. This allows a JIT implementation to compile a
4627          *  special AndAndPossiblyInside, keeping the normal AndAnd case efficient.
4628          */
4629 
4630         // Save the pointer expressions and the comparison directions,
4631         // so we can use them later.
4632         Expression p1 = null;
4633         Expression p2 = null;
4634         Expression p3 = null;
4635         Expression p4 = null;
4636         int dir1 = isPointerCmpExp(e.e1, &p1, &p2);
4637         int dir2 = isPointerCmpExp(e.e2, &p3, &p4);
4638         if (dir1 == 0 || dir2 == 0)
4639         {
4640             result = null;
4641             return;
4642         }
4643 
4644         //printf("FourPointerRelation %s\n", toChars());
4645 
4646         // Evaluate the first two pointers
4647         p1 = interpret(p1, istate);
4648         if (exceptionOrCant(p1))
4649             return;
4650         p2 = interpret(p2, istate);
4651         if (exceptionOrCant(p2))
4652             return;
4653         dinteger_t ofs1, ofs2;
4654         Expression agg1 = getAggregateFromPointer(p1, &ofs1);
4655         Expression agg2 = getAggregateFromPointer(p2, &ofs2);
4656 
4657         if (!pointToSameMemoryBlock(agg1, agg2) && agg1.op != TOKnull && agg2.op != TOKnull)
4658         {
4659             // Here it is either CANT_INTERPRET,
4660             // or an IsInside comparison returning false.
4661             p3 = interpret(p3, istate);
4662             if (CTFEExp.isCantExp(p3))
4663                 return;
4664             // Note that it is NOT legal for it to throw an exception!
4665             Expression except = null;
4666             if (exceptionOrCantInterpret(p3))
4667                 except = p3;
4668             else
4669             {
4670                 p4 = interpret(p4, istate);
4671                 if (CTFEExp.isCantExp(p4))
4672                 {
4673                     result = p4;
4674                     return;
4675                 }
4676                 if (exceptionOrCantInterpret(p4))
4677                     except = p4;
4678             }
4679             if (except)
4680             {
4681                 e.error("comparison %s of pointers to unrelated memory blocks remains indeterminate at compile time because exception %s was thrown while evaluating %s", e.e1.toChars(), except.toChars(), e.e2.toChars());
4682                 result = CTFEExp.cantexp;
4683                 return;
4684             }
4685             dinteger_t ofs3, ofs4;
4686             Expression agg3 = getAggregateFromPointer(p3, &ofs3);
4687             Expression agg4 = getAggregateFromPointer(p4, &ofs4);
4688             // The valid cases are:
4689             // p1 > p2 && p3 > p4  (same direction, also for < && <)
4690             // p1 > p2 && p3 < p4  (different direction, also < && >)
4691             // Changing any > into >= doesnt affect the result
4692             if ((dir1 == dir2 && pointToSameMemoryBlock(agg1, agg4) && pointToSameMemoryBlock(agg2, agg3)) || (dir1 != dir2 && pointToSameMemoryBlock(agg1, agg3) && pointToSameMemoryBlock(agg2, agg4)))
4693             {
4694                 // it's a legal two-sided comparison
4695                 result = new IntegerExp(e.loc, (e.op == TOKandand) ? 0 : 1, e.type);
4696                 return;
4697             }
4698             // It's an invalid four-pointer comparison. Either the second
4699             // comparison is in the same direction as the first, or else
4700             // more than two memory blocks are involved (either two independent
4701             // invalid comparisons are present, or else agg3 == agg4).
4702             e.error("comparison %s of pointers to unrelated memory blocks is indeterminate at compile time, even when combined with %s.", e.e1.toChars(), e.e2.toChars());
4703             result = CTFEExp.cantexp;
4704             return;
4705         }
4706         // The first pointer expression didn't need special treatment, so we
4707         // we need to interpret the entire expression exactly as a normal && or ||.
4708         // This is easy because we haven't evaluated e2 at all yet, and we already
4709         // know it will return a bool.
4710         // But we mustn't evaluate the pointer expressions in e1 again, in case
4711         // they have side-effects.
4712         bool nott = false;
4713         Expression ex = e.e1;
4714         while (ex.op == TOKnot)
4715         {
4716             nott = !nott;
4717             ex = (cast(NotExp)ex).e1;
4718         }
4719         TOK cmpop = ex.op;
4720         if (nott)
4721             cmpop = reverseRelation(cmpop);
4722         int cmp = comparePointers(e.loc, cmpop, e.e1.type, agg1, ofs1, agg2, ofs2);
4723         // We already know this is a valid comparison.
4724         assert(cmp >= 0);
4725         if (e.op == TOKandand && cmp == 1 || e.op == TOKoror && cmp == 0)
4726         {
4727             result = interpret(e.e2, istate);
4728             return;
4729         }
4730         result = new IntegerExp(e.loc, (e.op == TOKandand) ? 0 : 1, e.type);
4731     }
4732 
4733     override void visit(AndAndExp e)
4734     {
4735         debug (LOG)
4736         {
4737             printf("%s AndAndExp::interpret() %s\n", e.loc.toChars(), e.toChars());
4738         }
4739         // Check for an insidePointer expression, evaluate it if so
4740         interpretFourPointerRelation(e);
4741         if (result)
4742             return;
4743 
4744         result = interpret(e.e1, istate);
4745         if (exceptionOrCant(result))
4746             return;
4747 
4748         int res;
4749         if (result.isBool(false))
4750             res = 0;
4751         else if (isTrueBool(result))
4752         {
4753             result = interpret(e.e2, istate);
4754             if (exceptionOrCant(result))
4755                 return;
4756             if (result.op == TOKvoidexp)
4757             {
4758                 assert(e.type.ty == Tvoid);
4759                 result = null;
4760                 return;
4761             }
4762             if (result.isBool(false))
4763                 res = 0;
4764             else if (isTrueBool(result))
4765                 res = 1;
4766             else
4767             {
4768                 result.error("%s does not evaluate to a boolean", result.toChars());
4769                 result = CTFEExp.cantexp;
4770                 return;
4771             }
4772         }
4773         else
4774         {
4775             result.error("%s cannot be interpreted as a boolean", result.toChars());
4776             result = CTFEExp.cantexp;
4777             return;
4778         }
4779         if (goal != ctfeNeedNothing)
4780             result = new IntegerExp(e.loc, res, e.type);
4781     }
4782 
4783     override void visit(OrOrExp e)
4784     {
4785         debug (LOG)
4786         {
4787             printf("%s OrOrExp::interpret() %s\n", e.loc.toChars(), e.toChars());
4788         }
4789         // Check for an insidePointer expression, evaluate it if so
4790         interpretFourPointerRelation(e);
4791         if (result)
4792             return;
4793 
4794         result = interpret(e.e1, istate);
4795         if (exceptionOrCant(result))
4796             return;
4797 
4798         int res;
4799         if (isTrueBool(result))
4800             res = 1;
4801         else if (result.isBool(false))
4802         {
4803             result = interpret(e.e2, istate);
4804             if (exceptionOrCant(result))
4805                 return;
4806             if (result.op == TOKvoidexp)
4807             {
4808                 assert(e.type.ty == Tvoid);
4809                 result = null;
4810                 return;
4811             }
4812             if (result.isBool(false))
4813                 res = 0;
4814             else if (isTrueBool(result))
4815                 res = 1;
4816             else
4817             {
4818                 result.error("%s cannot be interpreted as a boolean", result.toChars());
4819                 result = CTFEExp.cantexp;
4820                 return;
4821             }
4822         }
4823         else
4824         {
4825             result.error("%s cannot be interpreted as a boolean", result.toChars());
4826             result = CTFEExp.cantexp;
4827             return;
4828         }
4829         if (goal != ctfeNeedNothing)
4830             result = new IntegerExp(e.loc, res, e.type);
4831     }
4832 
4833     // Print a stack trace, starting from callingExp which called fd.
4834     // To shorten the stack trace, try to detect recursion.
4835     void showCtfeBackTrace(CallExp callingExp, FuncDeclaration fd)
4836     {
4837         if (CtfeStatus.stackTraceCallsToSuppress > 0)
4838         {
4839             --CtfeStatus.stackTraceCallsToSuppress;
4840             return;
4841         }
4842         errorSupplemental(callingExp.loc, "called from here: %s", callingExp.toChars());
4843         // Quit if it's not worth trying to compress the stack trace
4844         if (CtfeStatus.callDepth < 6 || global.params.verbose)
4845             return;
4846         // Recursion happens if the current function already exists in the call stack.
4847         int numToSuppress = 0;
4848         int recurseCount = 0;
4849         int depthSoFar = 0;
4850         InterState* lastRecurse = istate;
4851         for (InterState* cur = istate; cur; cur = cur.caller)
4852         {
4853             if (cur.fd == fd)
4854             {
4855                 ++recurseCount;
4856                 numToSuppress = depthSoFar;
4857                 lastRecurse = cur;
4858             }
4859             ++depthSoFar;
4860         }
4861         // We need at least three calls to the same function, to make compression worthwhile
4862         if (recurseCount < 2)
4863             return;
4864         // We found a useful recursion.  Print all the calls involved in the recursion
4865         errorSupplemental(fd.loc, "%d recursive calls to function %s", recurseCount, fd.toChars());
4866         for (InterState* cur = istate; cur.fd != fd; cur = cur.caller)
4867         {
4868             errorSupplemental(cur.fd.loc, "recursively called from function %s", cur.fd.toChars());
4869         }
4870         // We probably didn't enter the recursion in this function.
4871         // Go deeper to find the real beginning.
4872         InterState* cur = istate;
4873         while (lastRecurse.caller && cur.fd == lastRecurse.caller.fd)
4874         {
4875             cur = cur.caller;
4876             lastRecurse = lastRecurse.caller;
4877             ++numToSuppress;
4878         }
4879         CtfeStatus.stackTraceCallsToSuppress = numToSuppress;
4880     }
4881 
4882     override void visit(CallExp e)
4883     {
4884         debug (LOG)
4885         {
4886             printf("%s CallExp::interpret() %s\n", e.loc.toChars(), e.toChars());
4887         }
4888         Expression pthis = null;
4889         FuncDeclaration fd = null;
4890 
4891         Expression ecall = interpret(e.e1, istate);
4892         if (exceptionOrCant(ecall))
4893             return;
4894 
4895         if (ecall.op == TOKdotvar)
4896         {
4897             DotVarExp dve = cast(DotVarExp)ecall;
4898 
4899             // Calling a member function
4900             pthis = dve.e1;
4901             fd = dve.var.isFuncDeclaration();
4902             assert(fd);
4903 
4904             if (pthis.op == TOKdottype)
4905                 pthis = (cast(DotTypeExp)dve.e1).e1;
4906         }
4907         else if (ecall.op == TOKvar)
4908         {
4909             fd = (cast(VarExp)ecall).var.isFuncDeclaration();
4910             assert(fd);
4911 
4912             if (fd.ident == Id._ArrayPostblit || fd.ident == Id._ArrayDtor)
4913             {
4914                 assert(e.arguments.dim == 1);
4915                 Expression ea = (*e.arguments)[0];
4916                 //printf("1 ea = %s %s\n", ea->type->toChars(), ea->toChars());
4917                 if (ea.op == TOKslice)
4918                     ea = (cast(SliceExp)ea).e1;
4919                 if (ea.op == TOKcast)
4920                     ea = (cast(CastExp)ea).e1;
4921 
4922                 //printf("2 ea = %s, %s %s\n", ea->type->toChars(), Token::toChars(ea->op), ea->toChars());
4923                 if (ea.op == TOKvar || ea.op == TOKsymoff)
4924                     result = getVarExp(e.loc, istate, (cast(SymbolExp)ea).var, ctfeNeedRvalue);
4925                 else if (ea.op == TOKaddress)
4926                     result = interpret((cast(AddrExp)ea).e1, istate);
4927                 else
4928                     assert(0);
4929                 if (CTFEExp.isCantExp(result))
4930                     return;
4931 
4932                 if (fd.ident == Id._ArrayPostblit)
4933                     result = evaluatePostblit(istate, result);
4934                 else
4935                     result = evaluateDtor(istate, result);
4936                 if (!result)
4937                     result = CTFEExp.voidexp;
4938                 return;
4939             }
4940         }
4941         else if (ecall.op == TOKsymoff)
4942         {
4943             SymOffExp soe = cast(SymOffExp)ecall;
4944             fd = soe.var.isFuncDeclaration();
4945             assert(fd && soe.offset == 0);
4946         }
4947         else if (ecall.op == TOKdelegate)
4948         {
4949             // Calling a delegate
4950             fd = (cast(DelegateExp)ecall).func;
4951             pthis = (cast(DelegateExp)ecall).e1;
4952 
4953             // Special handling for: &nestedfunc --> DelegateExp(VarExp(nestedfunc), nestedfunc)
4954             if (pthis.op == TOKvar && (cast(VarExp)pthis).var == fd)
4955                 pthis = null; // context is not necessary for CTFE
4956         }
4957         else if (ecall.op == TOKfunction)
4958         {
4959             // Calling a delegate literal
4960             fd = (cast(FuncExp)ecall).fd;
4961         }
4962         else
4963         {
4964             // delegate.funcptr()
4965             // others
4966             e.error("cannot call %s at compile time", e.toChars());
4967             result = CTFEExp.cantexp;
4968             return;
4969         }
4970         if (!fd)
4971         {
4972             e.error("CTFE internal error: cannot evaluate %s at compile time", e.toChars());
4973             result = CTFEExp.cantexp;
4974             return;
4975         }
4976         if (pthis)
4977         {
4978             // Member function call
4979 
4980             // Currently this is satisfied because closure is not yet supported.
4981             assert(!fd.isNested());
4982 
4983             if (pthis.op == TOKtypeid)
4984             {
4985                 pthis.error("static variable %s cannot be read at compile time", pthis.toChars());
4986                 result = CTFEExp.cantexp;
4987                 return;
4988             }
4989             assert(pthis);
4990 
4991             if (pthis.op == TOKnull)
4992             {
4993                 assert(pthis.type.toBasetype().ty == Tclass);
4994                 e.error("function call through null class reference %s", pthis.toChars());
4995                 result = CTFEExp.cantexp;
4996                 return;
4997             }
4998             assert(pthis.op == TOKstructliteral || pthis.op == TOKclassreference);
4999 
5000             if (fd.isVirtual() && !e.directcall)
5001             {
5002                 // Make a virtual function call.
5003                 // Get the function from the vtable of the original class
5004                 assert(pthis.op == TOKclassreference);
5005                 ClassDeclaration cd = (cast(ClassReferenceExp)pthis).originalClass();
5006 
5007                 // We can't just use the vtable index to look it up, because
5008                 // vtables for interfaces don't get populated until the glue layer.
5009                 fd = cd.findFunc(fd.ident, cast(TypeFunction)fd.type);
5010                 assert(fd);
5011             }
5012         }
5013 
5014         if (fd && fd.semanticRun >= PASSsemantic3done && fd.semantic3Errors)
5015         {
5016             e.error("CTFE failed because of previous errors in %s", fd.toChars());
5017             result = CTFEExp.cantexp;
5018             return;
5019         }
5020 
5021         // Check for built-in functions
5022         result = evaluateIfBuiltin(istate, e.loc, fd, e.arguments, pthis);
5023         if (result)
5024             return;
5025 
5026         if (!fd.fbody)
5027         {
5028             e.error("%s cannot be interpreted at compile time, because it has no available source code", fd.toChars());
5029             result = CTFEExp.cantexp;
5030             return;
5031         }
5032 
5033         result = interpret(fd, istate, e.arguments, pthis);
5034         if (result.op == TOKvoidexp)
5035             return;
5036         if (!exceptionOrCantInterpret(result))
5037         {
5038             if (goal != ctfeNeedLvalue) // Peel off CTFE reference if it's unnesessary
5039                 result = interpret(result, istate);
5040         }
5041         if (!exceptionOrCantInterpret(result))
5042         {
5043             result = paintTypeOntoLiteral(e.type, result);
5044             result.loc = e.loc;
5045         }
5046         else if (CTFEExp.isCantExp(result) && !global.gag)
5047             showCtfeBackTrace(e, fd); // Print a stack trace.
5048     }
5049 
5050     override void visit(CommaExp e)
5051     {
5052         debug (LOG)
5053         {
5054             printf("%s CommaExp::interpret() %s\n", e.loc.toChars(), e.toChars());
5055         }
5056         CommaExp firstComma = e;
5057         while (firstComma.e1.op == TOKcomma)
5058             firstComma = cast(CommaExp)firstComma.e1;
5059 
5060         // If it creates a variable, and there's no context for
5061         // the variable to be created in, we need to create one now.
5062         InterState istateComma;
5063         if (!istate && firstComma.e1.op == TOKdeclaration)
5064         {
5065             ctfeStack.startFrame(null);
5066             istate = &istateComma;
5067         }
5068 
5069         result = CTFEExp.cantexp;
5070 
5071         // If the comma returns a temporary variable, it needs to be an lvalue
5072         // (this is particularly important for struct constructors)
5073         if (e.e1.op == TOKdeclaration &&
5074             e.e2.op == TOKvar &&
5075             (cast(DeclarationExp)e.e1).declaration == (cast(VarExp)e.e2).var &&
5076             (cast(VarExp)e.e2).var.storage_class & STCctfe)
5077         {
5078             VarExp ve = cast(VarExp)e.e2;
5079             VarDeclaration v = ve.var.isVarDeclaration();
5080             ctfeStack.push(v);
5081             if (!v._init && !getValue(v))
5082             {
5083                 setValue(v, copyLiteral(v.type.defaultInitLiteral(e.loc)).copy());
5084             }
5085             if (!getValue(v))
5086             {
5087                 Expression newval = v._init.toExpression();
5088                 // Bug 4027. Copy constructors are a weird case where the
5089                 // initializer is a void function (the variable is modified
5090                 // through a reference parameter instead).
5091                 newval = interpret(newval, istate);
5092                 if (exceptionOrCant(newval))
5093                     goto Lfin;
5094                 if (newval.op != TOKvoidexp)
5095                 {
5096                     // v isn't necessarily null.
5097                     setValueWithoutChecking(v, copyLiteral(newval).copy());
5098                 }
5099             }
5100             result = interpret(e.e2, istate, goal);
5101         }
5102         else
5103         {
5104             result = interpret(e.e1, istate, ctfeNeedNothing);
5105             if (exceptionOrCant(result))
5106                 goto Lfin;
5107             result = interpret(e.e2, istate, goal);
5108         }
5109     Lfin:
5110         // If we created a temporary stack frame, end it now.
5111         if (istate == &istateComma)
5112             ctfeStack.endFrame();
5113     }
5114 
5115     override void visit(CondExp e)
5116     {
5117         debug (LOG)
5118         {
5119             printf("%s CondExp::interpret() %s\n", e.loc.toChars(), e.toChars());
5120         }
5121         if (isPointer(e.econd.type))
5122         {
5123             result = interpret(e.econd, istate);
5124             if (exceptionOrCant(result))
5125                 return;
5126             if (result.op != TOKnull)
5127                 result = new IntegerExp(e.loc, 1, Type.tbool);
5128         }
5129         else
5130             result = interpret(e.econd, istate);
5131         if (exceptionOrCant(result))
5132             return;
5133         if (isTrueBool(result))
5134             result = interpret(e.e1, istate, goal);
5135         else if (result.isBool(false))
5136             result = interpret(e.e2, istate, goal);
5137         else
5138         {
5139             e.error("%s does not evaluate to boolean result at compile time", e.econd.toChars());
5140             result = CTFEExp.cantexp;
5141         }
5142     }
5143 
5144     override void visit(ArrayLengthExp e)
5145     {
5146         debug (LOG)
5147         {
5148             printf("%s ArrayLengthExp::interpret() %s\n", e.loc.toChars(), e.toChars());
5149         }
5150         Expression e1 = interpret(e.e1, istate);
5151         assert(e1);
5152         if (exceptionOrCant(e1))
5153             return;
5154         if (e1.op != TOKstring && e1.op != TOKarrayliteral && e1.op != TOKslice && e1.op != TOKnull)
5155         {
5156             e.error("%s cannot be evaluated at compile time", e.toChars());
5157             result = CTFEExp.cantexp;
5158             return;
5159         }
5160         result = new IntegerExp(e.loc, resolveArrayLength(e1), e.type);
5161     }
5162 
5163     override void visit(DelegatePtrExp e)
5164     {
5165         debug (LOG)
5166         {
5167             printf("%s DelegatePtrExp::interpret() %s\n", e.loc.toChars(), e.toChars());
5168         }
5169         Expression e1 = interpret(e.e1, istate);
5170         assert(e1);
5171         if (exceptionOrCant(e1))
5172             return;
5173         e.error("%s cannot be evaluated at compile time", e.toChars());
5174         result = CTFEExp.cantexp;
5175     }
5176 
5177     override void visit(DelegateFuncptrExp e)
5178     {
5179         debug (LOG)
5180         {
5181             printf("%s DelegateFuncptrExp::interpret() %s\n", e.loc.toChars(), e.toChars());
5182         }
5183         Expression e1 = interpret(e.e1, istate);
5184         assert(e1);
5185         if (exceptionOrCant(e1))
5186             return;
5187         e.error("%s cannot be evaluated at compile time", e.toChars());
5188         result = CTFEExp.cantexp;
5189     }
5190 
5191     static bool resolveIndexing(IndexExp e, InterState* istate, Expression* pagg, uinteger_t* pidx, bool modify)
5192     {
5193         assert(e.e1.type.toBasetype().ty != Taarray);
5194 
5195         if (e.e1.type.toBasetype().ty == Tpointer)
5196         {
5197             // Indexing a pointer. Note that there is no $ in this case.
5198             Expression e1 = interpret(e.e1, istate);
5199             if (exceptionOrCantInterpret(e1))
5200                 return false;
5201 
5202             Expression e2 = interpret(e.e2, istate);
5203             if (exceptionOrCantInterpret(e2))
5204                 return false;
5205             sinteger_t indx = e2.toInteger();
5206 
5207             dinteger_t ofs;
5208             Expression agg = getAggregateFromPointer(e1, &ofs);
5209 
5210             if (agg.op == TOKnull)
5211             {
5212                 e.error("cannot index through null pointer %s", e.e1.toChars());
5213                 return false;
5214             }
5215             if (agg.op == TOKint64)
5216             {
5217                 e.error("cannot index through invalid pointer %s of value %s", e.e1.toChars(), e1.toChars());
5218                 return false;
5219             }
5220             // Pointer to a non-array variable
5221             if (agg.op == TOKsymoff)
5222             {
5223                 e.error("mutable variable %s cannot be %s at compile time, even through a pointer", cast(char*)(modify ? "modified" : "read"), (cast(SymOffExp)agg).var.toChars());
5224                 return false;
5225             }
5226 
5227             if (agg.op == TOKarrayliteral || agg.op == TOKstring)
5228             {
5229                 dinteger_t len = resolveArrayLength(agg);
5230                 if (ofs + indx >= len)
5231                 {
5232                     e.error("pointer index [%lld] exceeds allocated memory block [0..%lld]", ofs + indx, len);
5233                     return false;
5234                 }
5235             }
5236             else
5237             {
5238                 if (ofs + indx != 0)
5239                 {
5240                     e.error("pointer index [%lld] lies outside memory block [0..1]", ofs + indx);
5241                     return false;
5242                 }
5243             }
5244             *pagg = agg;
5245             *pidx = ofs + indx;
5246             return true;
5247         }
5248 
5249         Expression e1 = interpret(e.e1, istate);
5250         if (exceptionOrCantInterpret(e1))
5251             return false;
5252         if (e1.op == TOKnull)
5253         {
5254             e.error("cannot index null array %s", e.e1.toChars());
5255             return false;
5256         }
5257         if (e1.op == TOKvector)
5258             e1 = (cast(VectorExp)e1).e1;
5259 
5260         // Set the $ variable, and find the array literal to modify
5261         if (e1.op != TOKarrayliteral && e1.op != TOKstring && e1.op != TOKslice)
5262         {
5263             e.error("cannot determine length of %s at compile time", e.e1.toChars());
5264             return false;
5265         }
5266 
5267         dinteger_t len = resolveArrayLength(e1);
5268         if (e.lengthVar)
5269         {
5270             Expression dollarExp = new IntegerExp(e.loc, len, Type.tsize_t);
5271             ctfeStack.push(e.lengthVar);
5272             setValue(e.lengthVar, dollarExp);
5273         }
5274         Expression e2 = interpret(e.e2, istate);
5275         if (e.lengthVar)
5276             ctfeStack.pop(e.lengthVar); // $ is defined only inside []
5277         if (exceptionOrCantInterpret(e2))
5278             return false;
5279         if (e2.op != TOKint64)
5280         {
5281             e.error("CTFE internal error: non-integral index [%s]", e.e2.toChars());
5282             return false;
5283         }
5284 
5285         if (e1.op == TOKslice)
5286         {
5287             // Simplify index of slice: agg[lwr..upr][indx] --> agg[indx']
5288             uinteger_t index = e2.toInteger();
5289             uinteger_t ilwr = (cast(SliceExp)e1).lwr.toInteger();
5290             uinteger_t iupr = (cast(SliceExp)e1).upr.toInteger();
5291 
5292             if (index > iupr - ilwr)
5293             {
5294                 e.error("index %llu exceeds array length %llu", index, iupr - ilwr);
5295                 return false;
5296             }
5297             *pagg = (cast(SliceExp)e1).e1;
5298             *pidx = index + ilwr;
5299         }
5300         else
5301         {
5302             *pagg = e1;
5303             *pidx = e2.toInteger();
5304             if (len <= *pidx)
5305             {
5306                 e.error("array index %lld is out of bounds [0..%lld]", *pidx, len);
5307                 return false;
5308             }
5309         }
5310         return true;
5311     }
5312 
5313     override void visit(IndexExp e)
5314     {
5315         debug (LOG)
5316         {
5317             printf("%s IndexExp::interpret() %s, goal = %d\n", e.loc.toChars(), e.toChars(), goal);
5318         }
5319         if (e.e1.type.toBasetype().ty == Tpointer)
5320         {
5321             Expression agg;
5322             uinteger_t indexToAccess;
5323             if (!resolveIndexing(e, istate, &agg, &indexToAccess, false))
5324             {
5325                 result = CTFEExp.cantexp;
5326                 return;
5327             }
5328             if (agg.op == TOKarrayliteral || agg.op == TOKstring)
5329             {
5330                 if (goal == ctfeNeedLvalue)
5331                 {
5332                     // if we need a reference, IndexExp shouldn't be interpreting
5333                     // the expression to a value, it should stay as a reference
5334                     result = new IndexExp(e.loc, agg, new IntegerExp(e.e2.loc, indexToAccess, e.e2.type));
5335                     result.type = e.type;
5336                     return;
5337                 }
5338                 result = ctfeIndex(e.loc, e.type, agg, indexToAccess);
5339                 return;
5340             }
5341             else
5342             {
5343                 assert(indexToAccess == 0);
5344                 result = interpret(agg, istate, goal);
5345                 if (exceptionOrCant(result))
5346                     return;
5347                 result = paintTypeOntoLiteral(e.type, result);
5348                 return;
5349             }
5350         }
5351 
5352         if (e.e1.type.toBasetype().ty == Taarray)
5353         {
5354             Expression e1 = interpret(e.e1, istate);
5355             if (exceptionOrCant(e1))
5356                 return;
5357             if (e1.op == TOKnull)
5358             {
5359                 if (goal == ctfeNeedLvalue && e1.type.ty == Taarray && e.modifiable)
5360                 {
5361                     assert(0); // does not reach here?
5362                 }
5363                 e.error("cannot index null array %s", e.e1.toChars());
5364                 result = CTFEExp.cantexp;
5365                 return;
5366             }
5367             Expression e2 = interpret(e.e2, istate);
5368             if (exceptionOrCant(e2))
5369                 return;
5370 
5371             if (goal == ctfeNeedLvalue)
5372             {
5373                 // Pointer or reference of a scalar type
5374                 if (e1 == e.e1 && e2 == e.e2)
5375                     result = e;
5376                 else
5377                 {
5378                     result = new IndexExp(e.loc, e1, e2);
5379                     result.type = e.type;
5380                 }
5381                 return;
5382             }
5383 
5384             assert(e1.op == TOKassocarrayliteral);
5385             e2 = resolveSlice(e2);
5386             result = findKeyInAA(e.loc, cast(AssocArrayLiteralExp)e1, e2);
5387             if (!result)
5388             {
5389                 e.error("key %s not found in associative array %s", e2.toChars(), e.e1.toChars());
5390                 result = CTFEExp.cantexp;
5391             }
5392             return;
5393         }
5394 
5395         Expression agg;
5396         uinteger_t indexToAccess;
5397         if (!resolveIndexing(e, istate, &agg, &indexToAccess, false))
5398         {
5399             result = CTFEExp.cantexp;
5400             return;
5401         }
5402 
5403         if (goal == ctfeNeedLvalue)
5404         {
5405             Expression e2 = new IntegerExp(e.e2.loc, indexToAccess, Type.tsize_t);
5406             result = new IndexExp(e.loc, agg, e2);
5407             result.type = e.type;
5408             return;
5409         }
5410 
5411         result = ctfeIndex(e.loc, e.type, agg, indexToAccess);
5412         if (exceptionOrCant(result))
5413             return;
5414         if (result.op == TOKvoid)
5415         {
5416             e.error("%s is used before initialized", e.toChars());
5417             errorSupplemental(result.loc, "originally uninitialized here");
5418             result = CTFEExp.cantexp;
5419             return;
5420         }
5421         result = paintTypeOntoLiteral(e.type, result);
5422     }
5423 
5424     override void visit(SliceExp e)
5425     {
5426         debug (LOG)
5427         {
5428             printf("%s SliceExp::interpret() %s\n", e.loc.toChars(), e.toChars());
5429         }
5430         if (e.e1.type.toBasetype().ty == Tpointer)
5431         {
5432             // Slicing a pointer. Note that there is no $ in this case.
5433             Expression e1 = interpret(e.e1, istate);
5434             if (exceptionOrCant(e1))
5435                 return;
5436             if (e1.op == TOKint64)
5437             {
5438                 e.error("cannot slice invalid pointer %s of value %s", e.e1.toChars(), e1.toChars());
5439                 result = CTFEExp.cantexp;
5440                 return;
5441             }
5442 
5443             /* Evaluate lower and upper bounds of slice
5444              */
5445             Expression lwr = interpret(e.lwr, istate);
5446             if (exceptionOrCant(lwr))
5447                 return;
5448             Expression upr = interpret(e.upr, istate);
5449             if (exceptionOrCant(upr))
5450                 return;
5451             uinteger_t ilwr = lwr.toInteger();
5452             uinteger_t iupr = upr.toInteger();
5453 
5454             dinteger_t ofs;
5455             Expression agg = getAggregateFromPointer(e1, &ofs);
5456             ilwr += ofs;
5457             iupr += ofs;
5458             if (agg.op == TOKnull)
5459             {
5460                 if (iupr == ilwr)
5461                 {
5462                     result = new NullExp(e.loc);
5463                     result.type = e.type;
5464                     return;
5465                 }
5466                 e.error("cannot slice null pointer %s", e.e1.toChars());
5467                 result = CTFEExp.cantexp;
5468                 return;
5469             }
5470             if (agg.op == TOKsymoff)
5471             {
5472                 e.error("slicing pointers to static variables is not supported in CTFE");
5473                 result = CTFEExp.cantexp;
5474                 return;
5475             }
5476             if (agg.op != TOKarrayliteral && agg.op != TOKstring)
5477             {
5478                 e.error("pointer %s cannot be sliced at compile time (it does not point to an array)", e.e1.toChars());
5479                 result = CTFEExp.cantexp;
5480                 return;
5481             }
5482             assert(agg.op == TOKarrayliteral || agg.op == TOKstring);
5483             dinteger_t len = ArrayLength(Type.tsize_t, agg).exp().toInteger();
5484             //Type *pointee = ((TypePointer *)agg->type)->next;
5485             if (iupr > (len + 1) || iupr < ilwr)
5486             {
5487                 e.error("pointer slice [%lld..%lld] exceeds allocated memory block [0..%lld]", ilwr, iupr, len);
5488                 result = CTFEExp.cantexp;
5489                 return;
5490             }
5491             if (ofs != 0)
5492             {
5493                 lwr = new IntegerExp(e.loc, ilwr, lwr.type);
5494                 upr = new IntegerExp(e.loc, iupr, upr.type);
5495             }
5496             result = new SliceExp(e.loc, agg, lwr, upr);
5497             result.type = e.type;
5498             return;
5499         }
5500 
5501         Expression e1 = interpret(e.e1, istate);
5502         if (exceptionOrCant(e1))
5503             return;
5504 
5505         if (!e.lwr)
5506         {
5507             result = paintTypeOntoLiteral(e.type, e1);
5508             return;
5509         }
5510 
5511         /* Set the $ variable
5512          */
5513         if (e1.op != TOKarrayliteral && e1.op != TOKstring && e1.op != TOKnull && e1.op != TOKslice)
5514         {
5515             e.error("cannot determine length of %s at compile time", e1.toChars());
5516             result = CTFEExp.cantexp;
5517             return;
5518         }
5519         uinteger_t dollar = resolveArrayLength(e1);
5520         if (e.lengthVar)
5521         {
5522             auto dollarExp = new IntegerExp(e.loc, dollar, Type.tsize_t);
5523             ctfeStack.push(e.lengthVar);
5524             setValue(e.lengthVar, dollarExp);
5525         }
5526 
5527         /* Evaluate lower and upper bounds of slice
5528          */
5529         Expression lwr = interpret(e.lwr, istate);
5530         if (exceptionOrCant(lwr))
5531         {
5532             if (e.lengthVar)
5533                 ctfeStack.pop(e.lengthVar);
5534             return;
5535         }
5536         Expression upr = interpret(e.upr, istate);
5537         if (exceptionOrCant(upr))
5538         {
5539             if (e.lengthVar)
5540                 ctfeStack.pop(e.lengthVar);
5541             return;
5542         }
5543         if (e.lengthVar)
5544             ctfeStack.pop(e.lengthVar); // $ is defined only inside [L..U]
5545 
5546         uinteger_t ilwr = lwr.toInteger();
5547         uinteger_t iupr = upr.toInteger();
5548         if (e1.op == TOKnull)
5549         {
5550             if (ilwr == 0 && iupr == 0)
5551             {
5552                 result = e1;
5553                 return;
5554             }
5555             e1.error("slice [%llu..%llu] is out of bounds", ilwr, iupr);
5556             result = CTFEExp.cantexp;
5557             return;
5558         }
5559         if (e1.op == TOKslice)
5560         {
5561             SliceExp se = cast(SliceExp)e1;
5562             // Simplify slice of slice:
5563             //  aggregate[lo1..up1][lwr..upr] ---> aggregate[lwr'..upr']
5564             uinteger_t lo1 = se.lwr.toInteger();
5565             uinteger_t up1 = se.upr.toInteger();
5566             if (ilwr > iupr || iupr > up1 - lo1)
5567             {
5568                 e.error("slice[%llu..%llu] exceeds array bounds[%llu..%llu]", ilwr, iupr, lo1, up1);
5569                 result = CTFEExp.cantexp;
5570                 return;
5571             }
5572             ilwr += lo1;
5573             iupr += lo1;
5574             result = new SliceExp(e.loc, se.e1, new IntegerExp(e.loc, ilwr, lwr.type), new IntegerExp(e.loc, iupr, upr.type));
5575             result.type = e.type;
5576             return;
5577         }
5578         if (e1.op == TOKarrayliteral || e1.op == TOKstring)
5579         {
5580             if (iupr < ilwr || dollar < iupr)
5581             {
5582                 e.error("slice [%lld..%lld] exceeds array bounds [0..%lld]", ilwr, iupr, dollar);
5583                 result = CTFEExp.cantexp;
5584                 return;
5585             }
5586         }
5587         result = new SliceExp(e.loc, e1, lwr, upr);
5588         result.type = e.type;
5589     }
5590 
5591     override void visit(InExp e)
5592     {
5593         debug (LOG)
5594         {
5595             printf("%s InExp::interpret() %s\n", e.loc.toChars(), e.toChars());
5596         }
5597         Expression e1 = interpret(e.e1, istate);
5598         if (exceptionOrCant(e1))
5599             return;
5600         Expression e2 = interpret(e.e2, istate);
5601         if (exceptionOrCant(e2))
5602             return;
5603         if (e2.op == TOKnull)
5604         {
5605             result = new NullExp(e.loc, e.type);
5606             return;
5607         }
5608         if (e2.op != TOKassocarrayliteral)
5609         {
5610             e.error("%s cannot be interpreted at compile time", e.toChars());
5611             result = CTFEExp.cantexp;
5612             return;
5613         }
5614 
5615         e1 = resolveSlice(e1);
5616         result = findKeyInAA(e.loc, cast(AssocArrayLiteralExp)e2, e1);
5617         if (exceptionOrCant(result))
5618             return;
5619         if (!result)
5620         {
5621             result = new NullExp(e.loc, e.type);
5622         }
5623         else
5624         {
5625             // Create a CTFE pointer &aa[index]
5626             result = new IndexExp(e.loc, e2, e1);
5627             result.type = e.type.nextOf();
5628             result = new AddrExp(e.loc, result);
5629             result.type = e.type;
5630         }
5631     }
5632 
5633     override void visit(CatExp e)
5634     {
5635         debug (LOG)
5636         {
5637             printf("%s CatExp::interpret() %s\n", e.loc.toChars(), e.toChars());
5638         }
5639         Expression e1 = interpret(e.e1, istate);
5640         if (exceptionOrCant(e1))
5641             return;
5642         Expression e2 = interpret(e.e2, istate);
5643         if (exceptionOrCant(e2))
5644             return;
5645 
5646         e1 = resolveSlice(e1);
5647         e2 = resolveSlice(e2);
5648         result = ctfeCat(e.loc, e.type, e1, e2).copy();
5649         if (CTFEExp.isCantExp(result))
5650         {
5651             e.error("%s cannot be interpreted at compile time", e.toChars());
5652             return;
5653         }
5654         // We know we still own it, because we interpreted both e1 and e2
5655         if (result.op == TOKarrayliteral)
5656         {
5657             ArrayLiteralExp ale = cast(ArrayLiteralExp)result;
5658             ale.ownedByCtfe = OWNEDctfe;
5659 
5660             // Bugzilla 14686
5661             for (size_t i = 0; i < ale.elements.dim; i++)
5662             {
5663                 Expression ex = evaluatePostblit(istate, (*ale.elements)[i]);
5664                 if (exceptionOrCant(ex))
5665                     return;
5666             }
5667         }
5668         if (result.op == TOKstring)
5669             (cast(StringExp)result).ownedByCtfe = OWNEDctfe;
5670     }
5671 
5672     override void visit(DeleteExp e)
5673     {
5674         debug (LOG)
5675         {
5676             printf("%s DeleteExp::interpret() %s\n", e.loc.toChars(), e.toChars());
5677         }
5678         result = interpret(e.e1, istate);
5679         if (exceptionOrCant(result))
5680             return;
5681 
5682         if (result.op == TOKnull)
5683         {
5684             result = CTFEExp.voidexp;
5685             return;
5686         }
5687 
5688         auto tb = e.e1.type.toBasetype();
5689         switch (tb.ty)
5690         {
5691         case Tclass:
5692             if (result.op != TOKclassreference)
5693             {
5694                 e.error("delete on invalid class reference '%s'", result.toChars());
5695                 result = CTFEExp.cantexp;
5696                 return;
5697             }
5698 
5699             auto cre = cast(ClassReferenceExp)result;
5700             auto cd = cre.originalClass();
5701             if (cd.aggDelete)
5702             {
5703                 e.error("member deallocators not supported by CTFE");
5704                 result = CTFEExp.cantexp;
5705                 return;
5706             }
5707 
5708             if (cd.dtor)
5709             {
5710                 result = interpret(cd.dtor, istate, null, cre);
5711                 if (exceptionOrCant(result))
5712                     return;
5713             }
5714             break;
5715 
5716         case Tpointer:
5717             tb = (cast(TypePointer)tb).next.toBasetype();
5718             if (tb.ty == Tstruct)
5719             {
5720                 if (result.op != TOKaddress ||
5721                     (cast(AddrExp)result).e1.op != TOKstructliteral)
5722                 {
5723                     e.error("delete on invalid struct pointer '%s'", result.toChars());
5724                     result = CTFEExp.cantexp;
5725                     return;
5726                 }
5727 
5728                 auto sd = (cast(TypeStruct)tb).sym;
5729                 auto sle = cast(StructLiteralExp)(cast(AddrExp)result).e1;
5730                 if (sd.aggDelete)
5731                 {
5732                     e.error("member deallocators not supported by CTFE");
5733                     result = CTFEExp.cantexp;
5734                     return;
5735                 }
5736 
5737                 if (sd.dtor)
5738                 {
5739                     result = interpret(sd.dtor, istate, null, sle);
5740                     if (exceptionOrCant(result))
5741                         return;
5742                 }
5743             }
5744             break;
5745 
5746         case Tarray:
5747             auto tv = tb.nextOf().baseElemOf();
5748             if (tv.ty == Tstruct)
5749             {
5750                 if (result.op != TOKarrayliteral)
5751                 {
5752                     e.error("delete on invalid struct array '%s'", result.toChars());
5753                     result = CTFEExp.cantexp;
5754                     return;
5755                 }
5756 
5757                 auto sd = (cast(TypeStruct)tv).sym;
5758                 if (sd.aggDelete)
5759                 {
5760                     e.error("member deallocators not supported by CTFE");
5761                     result = CTFEExp.cantexp;
5762                     return;
5763                 }
5764 
5765                 if (sd.dtor)
5766                 {
5767                     auto ale = cast(ArrayLiteralExp)result;
5768                     foreach (el; *ale.elements)
5769                     {
5770                         result = interpret(sd.dtor, istate, null, el);
5771                         if (exceptionOrCant(result))
5772                             return;
5773                     }
5774                 }
5775             }
5776             break;
5777 
5778         default:
5779             assert(0);
5780         }
5781         result = CTFEExp.voidexp;
5782     }
5783 
5784     override void visit(CastExp e)
5785     {
5786         debug (LOG)
5787         {
5788             printf("%s CastExp::interpret() %s\n", e.loc.toChars(), e.toChars());
5789         }
5790         Expression e1 = interpret(e.e1, istate, goal);
5791         if (exceptionOrCant(e1))
5792             return;
5793         // If the expression has been cast to void, do nothing.
5794         if (e.to.ty == Tvoid)
5795         {
5796             result = CTFEExp.voidexp;
5797             return;
5798         }
5799         if (e.to.ty == Tpointer && e1.op != TOKnull)
5800         {
5801             Type pointee = (cast(TypePointer)e.type).next;
5802             // Implement special cases of normally-unsafe casts
5803             if (e1.op == TOKint64)
5804             {
5805                 // Happens with Windows HANDLEs, for example.
5806                 result = paintTypeOntoLiteral(e.to, e1);
5807                 return;
5808             }
5809 
5810             bool castToSarrayPointer = false;
5811             bool castBackFromVoid = false;
5812             if (e1.type.ty == Tarray || e1.type.ty == Tsarray || e1.type.ty == Tpointer)
5813             {
5814                 // Check for unsupported type painting operations
5815                 // For slices, we need the type being sliced,
5816                 // since it may have already been type painted
5817                 Type elemtype = e1.type.nextOf();
5818                 if (e1.op == TOKslice)
5819                     elemtype = (cast(SliceExp)e1).e1.type.nextOf();
5820 
5821                 // Allow casts from X* to void *, and X** to void** for any X.
5822                 // But don't allow cast from X* to void**.
5823                 // So, we strip all matching * from source and target to find X.
5824                 // Allow casts to X* from void* only if the 'void' was originally an X;
5825                 // we check this later on.
5826                 Type ultimatePointee = pointee;
5827                 Type ultimateSrc = elemtype;
5828                 while (ultimatePointee.ty == Tpointer && ultimateSrc.ty == Tpointer)
5829                 {
5830                     ultimatePointee = ultimatePointee.nextOf();
5831                     ultimateSrc = ultimateSrc.nextOf();
5832                 }
5833                 if (ultimatePointee.ty == Tsarray && ultimatePointee.nextOf().equivalent(ultimateSrc))
5834                 {
5835                     castToSarrayPointer = true;
5836                 }
5837                 else if (ultimatePointee.ty != Tvoid && ultimateSrc.ty != Tvoid && !isSafePointerCast(elemtype, pointee))
5838                 {
5839                     e.error("reinterpreting cast from %s* to %s* is not supported in CTFE", elemtype.toChars(), pointee.toChars());
5840                     result = CTFEExp.cantexp;
5841                     return;
5842                 }
5843                 if (ultimateSrc.ty == Tvoid)
5844                     castBackFromVoid = true;
5845             }
5846 
5847             if (e1.op == TOKslice)
5848             {
5849                 if ((cast(SliceExp)e1).e1.op == TOKnull)
5850                 {
5851                     result = paintTypeOntoLiteral(e.type, (cast(SliceExp)e1).e1);
5852                     return;
5853                 }
5854                 // Create a CTFE pointer &aggregate[1..2]
5855                 result = new IndexExp(e.loc, (cast(SliceExp)e1).e1, (cast(SliceExp)e1).lwr);
5856                 result.type = e.type.nextOf();
5857                 result = new AddrExp(e.loc, result);
5858                 result.type = e.type;
5859                 return;
5860             }
5861             if (e1.op == TOKarrayliteral || e1.op == TOKstring)
5862             {
5863                 // Create a CTFE pointer &[1,2,3][0] or &"abc"[0]
5864                 result = new IndexExp(e.loc, e1, new IntegerExp(e.loc, 0, Type.tsize_t));
5865                 result.type = e.type.nextOf();
5866                 result = new AddrExp(e.loc, result);
5867                 result.type = e.type;
5868                 return;
5869             }
5870             if (e1.op == TOKindex && !(cast(IndexExp)e1).e1.type.equals(e1.type))
5871             {
5872                 // type painting operation
5873                 IndexExp ie = cast(IndexExp)e1;
5874                 result = new IndexExp(e1.loc, ie.e1, ie.e2);
5875                 if (castBackFromVoid)
5876                 {
5877                     // get the original type. For strings, it's just the type...
5878                     Type origType = ie.e1.type.nextOf();
5879                     // ..but for arrays of type void*, it's the type of the element
5880                     Expression xx = null;
5881                     if (ie.e1.op == TOKarrayliteral && ie.e2.op == TOKint64)
5882                     {
5883                         ArrayLiteralExp ale = cast(ArrayLiteralExp)ie.e1;
5884                         size_t indx = cast(size_t)ie.e2.toInteger();
5885                         if (indx < ale.elements.dim)
5886                             xx = (*ale.elements)[indx];
5887                     }
5888                     if (xx && xx.op == TOKindex)
5889                         origType = (cast(IndexExp)xx).e1.type.nextOf();
5890                     else if (xx && xx.op == TOKaddress)
5891                         origType = (cast(AddrExp)xx).e1.type;
5892                     else if (xx && xx.op == TOKvar)
5893                         origType = (cast(VarExp)xx).var.type;
5894                     if (!isSafePointerCast(origType, pointee))
5895                     {
5896                         e.error("using void* to reinterpret cast from %s* to %s* is not supported in CTFE", origType.toChars(), pointee.toChars());
5897                         result = CTFEExp.cantexp;
5898                         return;
5899                     }
5900                 }
5901                 result.type = e.type;
5902                 return;
5903             }
5904             if (e1.op == TOKaddress)
5905             {
5906                 Type origType = (cast(AddrExp)e1).e1.type;
5907                 if (isSafePointerCast(origType, pointee))
5908                 {
5909                     result = new AddrExp(e.loc, (cast(AddrExp)e1).e1);
5910                     result.type = e.type;
5911                     return;
5912                 }
5913                 if (castToSarrayPointer && pointee.toBasetype().ty == Tsarray && (cast(AddrExp)e1).e1.op == TOKindex)
5914                 {
5915                     // &val[idx]
5916                     dinteger_t dim = (cast(TypeSArray)pointee.toBasetype()).dim.toInteger();
5917                     IndexExp ie = cast(IndexExp)(cast(AddrExp)e1).e1;
5918                     Expression lwr = ie.e2;
5919                     Expression upr = new IntegerExp(ie.e2.loc, ie.e2.toInteger() + dim, Type.tsize_t);
5920 
5921                     // Create a CTFE pointer &val[idx..idx+dim]
5922                     result = new SliceExp(e.loc, ie.e1, lwr, upr);
5923                     result.type = pointee;
5924                     result = new AddrExp(e.loc, result);
5925                     result.type = e.type;
5926                     return;
5927                 }
5928             }
5929             if (e1.op == TOKvar || e1.op == TOKsymoff)
5930             {
5931                 // type painting operation
5932                 Type origType = (cast(SymbolExp)e1).var.type;
5933                 if (castBackFromVoid && !isSafePointerCast(origType, pointee))
5934                 {
5935                     e.error("using void* to reinterpret cast from %s* to %s* is not supported in CTFE", origType.toChars(), pointee.toChars());
5936                     result = CTFEExp.cantexp;
5937                     return;
5938                 }
5939                 if (e1.op == TOKvar)
5940                     result = new VarExp(e.loc, (cast(VarExp)e1).var);
5941                 else
5942                     result = new SymOffExp(e.loc, (cast(SymOffExp)e1).var, (cast(SymOffExp)e1).offset);
5943                 result.type = e.to;
5944                 return;
5945             }
5946 
5947             // Check if we have a null pointer (eg, inside a struct)
5948             e1 = interpret(e1, istate);
5949             if (e1.op != TOKnull)
5950             {
5951                 e.error("pointer cast from %s to %s is not supported at compile time", e1.type.toChars(), e.to.toChars());
5952                 result = CTFEExp.cantexp;
5953                 return;
5954             }
5955         }
5956         if (e.to.ty == Tsarray && e.e1.type.ty == Tvector)
5957         {
5958             // Special handling for: cast(float[4])__vector([w, x, y, z])
5959             e1 = interpret(e.e1, istate);
5960             if (exceptionOrCant(e1))
5961                 return;
5962             assert(e1.op == TOKvector);
5963             e1 = (cast(VectorExp)e1).e1;
5964         }
5965         if (e.to.ty == Tarray && e1.op == TOKslice)
5966         {
5967             // Note that the slice may be void[], so when checking for dangerous
5968             // casts, we need to use the original type, which is se->e1.
5969             SliceExp se = cast(SliceExp)e1;
5970             if (!isSafePointerCast(se.e1.type.nextOf(), e.to.nextOf()))
5971             {
5972                 e.error("array cast from %s to %s is not supported at compile time", se.e1.type.toChars(), e.to.toChars());
5973                 result = CTFEExp.cantexp;
5974                 return;
5975             }
5976             e1 = new SliceExp(e1.loc, se.e1, se.lwr, se.upr);
5977             e1.type = e.to;
5978             result = e1;
5979             return;
5980         }
5981         // Disallow array type painting, except for conversions between built-in
5982         // types of identical size.
5983         if ((e.to.ty == Tsarray || e.to.ty == Tarray) && (e1.type.ty == Tsarray || e1.type.ty == Tarray) && !isSafePointerCast(e1.type.nextOf(), e.to.nextOf()))
5984         {
5985             e.error("array cast from %s to %s is not supported at compile time", e1.type.toChars(), e.to.toChars());
5986             result = CTFEExp.cantexp;
5987             return;
5988         }
5989         if (e.to.ty == Tsarray)
5990             e1 = resolveSlice(e1);
5991         if (e.to.toBasetype().ty == Tbool && e1.type.ty == Tpointer)
5992         {
5993             result = new IntegerExp(e.loc, e1.op != TOKnull, e.to);
5994             return;
5995         }
5996         result = ctfeCast(e.loc, e.type, e.to, e1);
5997     }
5998 
5999     override void visit(AssertExp e)
6000     {
6001         debug (LOG)
6002         {
6003             printf("%s AssertExp::interpret() %s\n", e.loc.toChars(), e.toChars());
6004         }
6005         Expression e1 = interpret(e.e1, istate);
6006         if (exceptionOrCant(e1))
6007             return;
6008         if (isTrueBool(e1))
6009         {
6010         }
6011         else if (e1.isBool(false))
6012         {
6013             if (e.msg)
6014             {
6015                 result = interpret(e.msg, istate);
6016                 if (exceptionOrCant(result))
6017                     return;
6018                 e.error("%s", result.toChars());
6019             }
6020             else
6021                 e.error("%s failed", e.toChars());
6022             result = CTFEExp.cantexp;
6023             return;
6024         }
6025         else
6026         {
6027             e.error("%s is not a compile time boolean expression", e1.toChars());
6028             result = CTFEExp.cantexp;
6029             return;
6030         }
6031         result = e1;
6032         return;
6033     }
6034 
6035     override void visit(PtrExp e)
6036     {
6037         debug (LOG)
6038         {
6039             printf("%s PtrExp::interpret() %s\n", e.loc.toChars(), e.toChars());
6040         }
6041         // Check for int<->float and long<->double casts.
6042         if (e.e1.op == TOKsymoff && (cast(SymOffExp)e.e1).offset == 0 && (cast(SymOffExp)e.e1).var.isVarDeclaration() && isFloatIntPaint(e.type, (cast(SymOffExp)e.e1).var.type))
6043         {
6044             // *(cast(int*)&v), where v is a float variable
6045             result = paintFloatInt(getVarExp(e.loc, istate, (cast(SymOffExp)e.e1).var, ctfeNeedRvalue), e.type);
6046             return;
6047         }
6048         if (e.e1.op == TOKcast && (cast(CastExp)e.e1).e1.op == TOKaddress)
6049         {
6050             // *(cast(int*)&x), where x is a float expression
6051             Expression x = (cast(AddrExp)(cast(CastExp)e.e1).e1).e1;
6052             if (isFloatIntPaint(e.type, x.type))
6053             {
6054                 result = paintFloatInt(interpret(x, istate), e.type);
6055                 return;
6056             }
6057         }
6058 
6059         // Constant fold *(&structliteral + offset)
6060         if (e.e1.op == TOKadd)
6061         {
6062             AddExp ae = cast(AddExp)e.e1;
6063             if (ae.e1.op == TOKaddress && ae.e2.op == TOKint64)
6064             {
6065                 AddrExp ade = cast(AddrExp)ae.e1;
6066                 Expression ex = interpret(ade.e1, istate);
6067                 if (exceptionOrCant(ex))
6068                     return;
6069                 if (ex.op == TOKstructliteral)
6070                 {
6071                     StructLiteralExp se = cast(StructLiteralExp)ex;
6072                     dinteger_t offset = ae.e2.toInteger();
6073                     result = se.getField(e.type, cast(uint)offset);
6074                     if (result)
6075                         return;
6076                 }
6077             }
6078         }
6079 
6080         // It's possible we have an array bounds error. We need to make sure it
6081         // errors with this line number, not the one where the pointer was set.
6082         result = interpret(e.e1, istate);
6083         if (exceptionOrCant(result))
6084             return;
6085 
6086         if (result.op == TOKfunction)
6087             return;
6088         if (result.op == TOKsymoff)
6089         {
6090             SymOffExp soe = cast(SymOffExp)result;
6091             if (soe.offset == 0 && soe.var.isFuncDeclaration())
6092                 return;
6093             e.error("cannot dereference pointer to static variable %s at compile time", soe.var.toChars());
6094             result = CTFEExp.cantexp;
6095             return;
6096         }
6097 
6098         if (result.op != TOKaddress)
6099         {
6100             if (result.op == TOKnull)
6101                 e.error("dereference of null pointer '%s'", e.e1.toChars());
6102             else
6103                 e.error("dereference of invalid pointer '%s'", result.toChars());
6104             result = CTFEExp.cantexp;
6105             return;
6106         }
6107 
6108         // *(&x) ==> x
6109         result = (cast(AddrExp)result).e1;
6110 
6111         if (result.op == TOKslice && e.type.toBasetype().ty == Tsarray)
6112         {
6113             /* aggr[lwr..upr]
6114              * upr may exceed the upper boundary of aggr, but the check is deferred
6115              * until those out-of-bounds elements will be touched.
6116              */
6117             return;
6118         }
6119         result = interpret(result, istate, goal);
6120         if (exceptionOrCant(result))
6121             return;
6122 
6123         debug (LOG)
6124         {
6125             if (CTFEExp.isCantExp(result))
6126                 printf("PtrExp::interpret() %s = CTFEExp::cantexp\n", e.toChars());
6127         }
6128     }
6129 
6130     override void visit(DotVarExp e)
6131     {
6132         debug (LOG)
6133         {
6134             printf("%s DotVarExp::interpret() %s, goal = %d\n", e.loc.toChars(), e.toChars(), goal);
6135         }
6136         Expression ex = interpret(e.e1, istate);
6137         if (exceptionOrCant(ex))
6138             return;
6139 
6140         if (FuncDeclaration f = e.var.isFuncDeclaration())
6141         {
6142             if (ex == e.e1)
6143                 result = e; // optimize: reuse this CTFE reference
6144             else
6145             {
6146                 result = new DotVarExp(e.loc, ex, f, false);
6147                 result.type = e.type;
6148             }
6149             return;
6150         }
6151 
6152         VarDeclaration v = e.var.isVarDeclaration();
6153         if (!v)
6154         {
6155             e.error("CTFE internal error: %s", e.toChars());
6156             result = CTFEExp.cantexp;
6157             return;
6158         }
6159 
6160         if (ex.op == TOKnull)
6161         {
6162             if (ex.type.toBasetype().ty == Tclass)
6163                 e.error("class '%s' is null and cannot be dereferenced", e.e1.toChars());
6164             else
6165                 e.error("CTFE internal error: null this '%s'", e.e1.toChars());
6166             result = CTFEExp.cantexp;
6167             return;
6168         }
6169         if (ex.op != TOKstructliteral && ex.op != TOKclassreference)
6170         {
6171             e.error("%s.%s is not yet implemented at compile time", e.e1.toChars(), e.var.toChars());
6172             result = CTFEExp.cantexp;
6173             return;
6174         }
6175 
6176         StructLiteralExp se;
6177         int i;
6178 
6179         // We can't use getField, because it makes a copy
6180         if (ex.op == TOKclassreference)
6181         {
6182             se = (cast(ClassReferenceExp)ex).value;
6183             i = (cast(ClassReferenceExp)ex).findFieldIndexByName(v);
6184         }
6185         else
6186         {
6187             se = cast(StructLiteralExp)ex;
6188             i = findFieldIndexByName(se.sd, v);
6189         }
6190         if (i == -1)
6191         {
6192             e.error("couldn't find field %s of type %s in %s", v.toChars(), e.type.toChars(), se.toChars());
6193             result = CTFEExp.cantexp;
6194             return;
6195         }
6196 
6197         if (goal == ctfeNeedLvalue)
6198         {
6199             Expression ev = (*se.elements)[i];
6200             if (!ev || ev.op == TOKvoid)
6201                 (*se.elements)[i] = voidInitLiteral(e.type, v).copy();
6202             // just return the (simplified) dotvar expression as a CTFE reference
6203             if (e.e1 == ex)
6204                 result = e;
6205             else
6206             {
6207                 result = new DotVarExp(e.loc, ex, v);
6208                 result.type = e.type;
6209             }
6210             return;
6211         }
6212 
6213         result = (*se.elements)[i];
6214         if (!result)
6215         {
6216             e.error("Internal Compiler Error: null field %s", v.toChars());
6217             result = CTFEExp.cantexp;
6218             return;
6219         }
6220         if (result.op == TOKvoid)
6221         {
6222             VoidInitExp ve = cast(VoidInitExp)result;
6223             const(char)* s = ve.var.toChars();
6224             if (v.overlapped)
6225             {
6226                 e.error("reinterpretation through overlapped field %s is not allowed in CTFE", s);
6227                 result = CTFEExp.cantexp;
6228                 return;
6229             }
6230             e.error("cannot read uninitialized variable %s in CTFE", s);
6231             result = CTFEExp.cantexp;
6232             return;
6233         }
6234 
6235         if (v.type.ty != result.type.ty && v.type.ty == Tsarray)
6236         {
6237             // Block assignment from inside struct literals
6238             auto tsa = cast(TypeSArray)v.type;
6239             auto len = cast(size_t)tsa.dim.toInteger();
6240             result = createBlockDuplicatedArrayLiteral(ex.loc, v.type, ex, len);
6241             (*se.elements)[i] = result;
6242         }
6243         debug (LOG)
6244         {
6245             if (CTFEExp.isCantExp(result))
6246                 printf("DotVarExp::interpret() %s = CTFEExp::cantexp\n", e.toChars());
6247         }
6248     }
6249 
6250     override void visit(RemoveExp e)
6251     {
6252         debug (LOG)
6253         {
6254             printf("%s RemoveExp::interpret() %s\n", e.loc.toChars(), e.toChars());
6255         }
6256         Expression agg = interpret(e.e1, istate);
6257         if (exceptionOrCant(agg))
6258             return;
6259         Expression index = interpret(e.e2, istate);
6260         if (exceptionOrCant(index))
6261             return;
6262         if (agg.op == TOKnull)
6263         {
6264             result = CTFEExp.voidexp;
6265             return;
6266         }
6267 
6268         assert(agg.op == TOKassocarrayliteral);
6269         AssocArrayLiteralExp aae = cast(AssocArrayLiteralExp)agg;
6270         Expressions* keysx = aae.keys;
6271         Expressions* valuesx = aae.values;
6272         size_t removed = 0;
6273         for (size_t j = 0; j < valuesx.dim; ++j)
6274         {
6275             Expression ekey = (*keysx)[j];
6276             int eq = ctfeEqual(e.loc, TOKequal, ekey, index);
6277             if (eq)
6278                 ++removed;
6279             else if (removed != 0)
6280             {
6281                 (*keysx)[j - removed] = ekey;
6282                 (*valuesx)[j - removed] = (*valuesx)[j];
6283             }
6284         }
6285         valuesx.dim = valuesx.dim - removed;
6286         keysx.dim = keysx.dim - removed;
6287         result = new IntegerExp(e.loc, removed ? 1 : 0, Type.tbool);
6288     }
6289 
6290     override void visit(ClassReferenceExp e)
6291     {
6292         //printf("ClassReferenceExp::interpret() %s\n", e->value->toChars());
6293         result = e;
6294     }
6295 
6296     override void visit(VoidInitExp e)
6297     {
6298         e.error("CTFE internal error: trying to read uninitialized variable");
6299         assert(0);
6300     }
6301 
6302     override void visit(ThrownExceptionExp e)
6303     {
6304         assert(0); // This should never be interpreted
6305     }
6306 }
6307 
6308 extern (C++) Expression interpret(Expression e, InterState* istate, CtfeGoal goal = ctfeNeedRvalue)
6309 {
6310     if (!e)
6311         return null;
6312     scope Interpreter v = new Interpreter(istate, goal);
6313     e.accept(v);
6314     Expression ex = v.result;
6315     assert(goal == ctfeNeedNothing || ex !is null);
6316     return ex;
6317 }
6318 
6319 /***********************************
6320  * Interpret the statement.
6321  * Returns:
6322  *      NULL    continue to next statement
6323  *      TOKcantexp      cannot interpret statement at compile time
6324  *      !NULL   expression from return statement, or thrown exception
6325  */
6326 extern (C++) Expression interpret(Statement s, InterState* istate)
6327 {
6328     if (!s)
6329         return null;
6330     scope Interpreter v = new Interpreter(istate, ctfeNeedNothing);
6331     s.accept(v);
6332     return v.result;
6333 }
6334 
6335 /* All results destined for use outside of CTFE need to have their CTFE-specific
6336  * features removed.
6337  * In particular, all slices must be resolved.
6338  */
6339 extern (C++) Expression scrubReturnValue(Loc loc, Expression e)
6340 {
6341     if (e.op == TOKclassreference)
6342     {
6343         StructLiteralExp se = (cast(ClassReferenceExp)e).value;
6344         se.ownedByCtfe = OWNEDcode;
6345         if (!(se.stageflags & stageScrub))
6346         {
6347             int old = se.stageflags;
6348             se.stageflags |= stageScrub;
6349             if (Expression ex = scrubArray(loc, se.elements, true))
6350                 return ex;
6351             se.stageflags = old;
6352         }
6353     }
6354     if (e.op == TOKvoid)
6355     {
6356         error(loc, "uninitialized variable '%s' cannot be returned from CTFE", (cast(VoidInitExp)e).var.toChars());
6357         return new ErrorExp();
6358     }
6359     e = resolveSlice(e);
6360     if (e.op == TOKstructliteral)
6361     {
6362         StructLiteralExp se = cast(StructLiteralExp)e;
6363         se.ownedByCtfe = OWNEDcode;
6364         if (!(se.stageflags & stageScrub))
6365         {
6366             int old = se.stageflags;
6367             se.stageflags |= stageScrub;
6368             if (Expression ex = scrubArray(loc, se.elements, true))
6369                 return ex;
6370             se.stageflags = old;
6371         }
6372     }
6373     if (e.op == TOKstring)
6374     {
6375         (cast(StringExp)e).ownedByCtfe = OWNEDcode;
6376     }
6377     if (e.op == TOKarrayliteral)
6378     {
6379         (cast(ArrayLiteralExp)e).ownedByCtfe = OWNEDcode;
6380         if (Expression ex = scrubArray(loc, (cast(ArrayLiteralExp)e).elements))
6381             return ex;
6382     }
6383     if (e.op == TOKassocarrayliteral)
6384     {
6385         AssocArrayLiteralExp aae = cast(AssocArrayLiteralExp)e;
6386         aae.ownedByCtfe = OWNEDcode;
6387         if (Expression ex = scrubArray(loc, aae.keys))
6388             return ex;
6389         if (Expression ex = scrubArray(loc, aae.values))
6390             return ex;
6391         aae.type = toBuiltinAAType(aae.type);
6392     }
6393     return e;
6394 }
6395 
6396 // Return true if every element is either void,
6397 // or is an array literal or struct literal of void elements.
6398 extern (C++) bool isEntirelyVoid(Expressions* elems)
6399 {
6400     for (size_t i = 0; i < elems.dim; i++)
6401     {
6402         Expression m = (*elems)[i];
6403         // It can be NULL for performance reasons,
6404         // see StructLiteralExp::interpret().
6405         if (!m)
6406             continue;
6407 
6408         if (!(m.op == TOKvoid) && !(m.op == TOKarrayliteral && isEntirelyVoid((cast(ArrayLiteralExp)m).elements)) && !(m.op == TOKstructliteral && isEntirelyVoid((cast(StructLiteralExp)m).elements)))
6409         {
6410             return false;
6411         }
6412     }
6413     return true;
6414 }
6415 
6416 // Scrub all members of an array. Return false if error
6417 extern (C++) Expression scrubArray(Loc loc, Expressions* elems, bool structlit = false)
6418 {
6419     for (size_t i = 0; i < elems.dim; i++)
6420     {
6421         Expression m = (*elems)[i];
6422         // It can be NULL for performance reasons,
6423         // see StructLiteralExp::interpret().
6424         if (!m)
6425             continue;
6426 
6427         // A struct .init may contain void members.
6428         // Static array members are a weird special case (bug 10994).
6429         if (structlit && ((m.op == TOKvoid) || (m.op == TOKarrayliteral && m.type.ty == Tsarray && isEntirelyVoid((cast(ArrayLiteralExp)m).elements)) || (m.op == TOKstructliteral && isEntirelyVoid((cast(StructLiteralExp)m).elements))))
6430         {
6431             m = null;
6432         }
6433         else
6434         {
6435             m = scrubReturnValue(loc, m);
6436             if (CTFEExp.isCantExp(m) || m.op == TOKerror)
6437                 return m;
6438         }
6439         (*elems)[i] = m;
6440     }
6441     return null;
6442 }
6443 
6444 extern (C++) Expression scrubCacheValue(Loc loc, Expression e)
6445 {
6446     if (e.op == TOKclassreference)
6447     {
6448         StructLiteralExp sle = (cast(ClassReferenceExp)e).value;
6449         sle.ownedByCtfe = OWNEDcache;
6450         if (!(sle.stageflags & stageScrub))
6451         {
6452             int old = sle.stageflags;
6453             sle.stageflags |= stageScrub;
6454             if (Expression ex = scrubArrayCache(loc, sle.elements))
6455                 return ex;
6456             sle.stageflags = old;
6457         }
6458     }
6459     if (e.op == TOKstructliteral)
6460     {
6461         StructLiteralExp sle = cast(StructLiteralExp)e;
6462         sle.ownedByCtfe = OWNEDcache;
6463         if (!(sle.stageflags & stageScrub))
6464         {
6465             int old = sle.stageflags;
6466             sle.stageflags |= stageScrub;
6467             if (Expression ex = scrubArrayCache(loc, sle.elements))
6468                 return ex;
6469             sle.stageflags = old;
6470         }
6471     }
6472     if (e.op == TOKstring)
6473     {
6474         (cast(StringExp)e).ownedByCtfe = OWNEDcache;
6475     }
6476     if (e.op == TOKarrayliteral)
6477     {
6478         (cast(ArrayLiteralExp)e).ownedByCtfe = OWNEDcache;
6479         if (Expression ex = scrubArrayCache(loc, (cast(ArrayLiteralExp)e).elements))
6480             return ex;
6481     }
6482     if (e.op == TOKassocarrayliteral)
6483     {
6484         AssocArrayLiteralExp aae = cast(AssocArrayLiteralExp)e;
6485         aae.ownedByCtfe = OWNEDcache;
6486         if (Expression ex = scrubArrayCache(loc, aae.keys))
6487             return ex;
6488         if (Expression ex = scrubArrayCache(loc, aae.values))
6489             return ex;
6490     }
6491     return e;
6492 }
6493 
6494 extern (C++) Expression scrubArrayCache(Loc loc, Expressions* elems)
6495 {
6496     for (size_t i = 0; i < elems.dim; i++)
6497     {
6498         Expression m = (*elems)[i];
6499         if (!m)
6500             continue;
6501         (*elems)[i] = scrubCacheValue(loc, m);
6502     }
6503     return null;
6504 }
6505 
6506 /******************************* Special Functions ***************************/
6507 
6508 extern (C++) Expression interpret_length(InterState* istate, Expression earg)
6509 {
6510     //printf("interpret_length()\n");
6511     earg = interpret(earg, istate);
6512     if (exceptionOrCantInterpret(earg))
6513         return earg;
6514     dinteger_t len = 0;
6515     if (earg.op == TOKassocarrayliteral)
6516         len = (cast(AssocArrayLiteralExp)earg).keys.dim;
6517     else
6518         assert(earg.op == TOKnull);
6519     Expression e = new IntegerExp(earg.loc, len, Type.tsize_t);
6520     return e;
6521 }
6522 
6523 extern (C++) Expression interpret_keys(InterState* istate, Expression earg, Type returnType)
6524 {
6525     debug (LOG)
6526     {
6527         printf("interpret_keys()\n");
6528     }
6529     earg = interpret(earg, istate);
6530     if (exceptionOrCantInterpret(earg))
6531         return earg;
6532     if (earg.op == TOKnull)
6533         return new NullExp(earg.loc, returnType);
6534     if (earg.op != TOKassocarrayliteral && earg.type.toBasetype().ty != Taarray)
6535         return null;
6536     assert(earg.op == TOKassocarrayliteral);
6537     AssocArrayLiteralExp aae = cast(AssocArrayLiteralExp)earg;
6538     auto ae = new ArrayLiteralExp(aae.loc, aae.keys);
6539     ae.ownedByCtfe = aae.ownedByCtfe;
6540     ae.type = returnType;
6541     return copyLiteral(ae).copy();
6542 }
6543 
6544 extern (C++) Expression interpret_values(InterState* istate, Expression earg, Type returnType)
6545 {
6546     debug (LOG)
6547     {
6548         printf("interpret_values()\n");
6549     }
6550     earg = interpret(earg, istate);
6551     if (exceptionOrCantInterpret(earg))
6552         return earg;
6553     if (earg.op == TOKnull)
6554         return new NullExp(earg.loc, returnType);
6555     if (earg.op != TOKassocarrayliteral && earg.type.toBasetype().ty != Taarray)
6556         return null;
6557     assert(earg.op == TOKassocarrayliteral);
6558     AssocArrayLiteralExp aae = cast(AssocArrayLiteralExp)earg;
6559     auto ae = new ArrayLiteralExp(aae.loc, aae.values);
6560     ae.ownedByCtfe = aae.ownedByCtfe;
6561     ae.type = returnType;
6562     //printf("result is %s\n", e->toChars());
6563     return copyLiteral(ae).copy();
6564 }
6565 
6566 extern (C++) Expression interpret_dup(InterState* istate, Expression earg)
6567 {
6568     debug (LOG)
6569     {
6570         printf("interpret_dup()\n");
6571     }
6572     earg = interpret(earg, istate);
6573     if (exceptionOrCantInterpret(earg))
6574         return earg;
6575     if (earg.op == TOKnull)
6576         return new NullExp(earg.loc, earg.type);
6577     if (earg.op != TOKassocarrayliteral && earg.type.toBasetype().ty != Taarray)
6578         return null;
6579     assert(earg.op == TOKassocarrayliteral);
6580     AssocArrayLiteralExp aae = cast(AssocArrayLiteralExp)copyLiteral(earg).copy();
6581     for (size_t i = 0; i < aae.keys.dim; i++)
6582     {
6583         if (Expression e = evaluatePostblit(istate, (*aae.keys)[i]))
6584             return e;
6585         if (Expression e = evaluatePostblit(istate, (*aae.values)[i]))
6586             return e;
6587     }
6588     aae.type = earg.type.mutableOf(); // repaint type from const(int[int]) to const(int)[int]
6589     //printf("result is %s\n", aae->toChars());
6590     return aae;
6591 }
6592 
6593 // signature is int delegate(ref Value) OR int delegate(ref Key, ref Value)
6594 extern (C++) Expression interpret_aaApply(InterState* istate, Expression aa, Expression deleg)
6595 {
6596     aa = interpret(aa, istate);
6597     if (exceptionOrCantInterpret(aa))
6598         return aa;
6599     if (aa.op != TOKassocarrayliteral)
6600         return new IntegerExp(deleg.loc, 0, Type.tsize_t);
6601 
6602     FuncDeclaration fd = null;
6603     Expression pthis = null;
6604     if (deleg.op == TOKdelegate)
6605     {
6606         fd = (cast(DelegateExp)deleg).func;
6607         pthis = (cast(DelegateExp)deleg).e1;
6608     }
6609     else if (deleg.op == TOKfunction)
6610         fd = (cast(FuncExp)deleg).fd;
6611 
6612     assert(fd && fd.fbody);
6613     assert(fd.parameters);
6614     size_t numParams = fd.parameters.dim;
6615     assert(numParams == 1 || numParams == 2);
6616 
6617     Parameter fparam = Parameter.getNth((cast(TypeFunction)fd.type).parameters, numParams - 1);
6618     bool wantRefValue = 0 != (fparam.storageClass & (STCout | STCref));
6619 
6620     Expressions args;
6621     args.setDim(numParams);
6622 
6623     AssocArrayLiteralExp ae = cast(AssocArrayLiteralExp)aa;
6624     if (!ae.keys || ae.keys.dim == 0)
6625         return new IntegerExp(deleg.loc, 0, Type.tsize_t);
6626     Expression eresult;
6627 
6628     for (size_t i = 0; i < ae.keys.dim; ++i)
6629     {
6630         Expression ekey = (*ae.keys)[i];
6631         Expression evalue = (*ae.values)[i];
6632         if (wantRefValue)
6633         {
6634             Type t = evalue.type;
6635             evalue = new IndexExp(deleg.loc, ae, ekey);
6636             evalue.type = t;
6637         }
6638         args[numParams - 1] = evalue;
6639         if (numParams == 2)
6640             args[0] = ekey;
6641 
6642         eresult = interpret(fd, istate, &args, pthis);
6643         if (exceptionOrCantInterpret(eresult))
6644             return eresult;
6645 
6646         assert(eresult.op == TOKint64);
6647         if ((cast(IntegerExp)eresult).getInteger() != 0)
6648             return eresult;
6649     }
6650     return eresult;
6651 }
6652 
6653 // Helper function: given a function of type A[] f(...),
6654 // return A[].
6655 extern (C++) Type returnedArrayType(FuncDeclaration fd)
6656 {
6657     assert(fd.type.ty == Tfunction);
6658     assert(fd.type.nextOf().ty == Tarray);
6659     return (cast(TypeFunction)fd.type).nextOf();
6660 }
6661 
6662 /* Decoding UTF strings for foreach loops. Duplicates the functionality of
6663  * the twelve _aApplyXXn functions in aApply.d in the runtime.
6664  */
6665 extern (C++) Expression foreachApplyUtf(InterState* istate, Expression str, Expression deleg, bool rvs)
6666 {
6667     debug (LOG)
6668     {
6669         printf("foreachApplyUtf(%s, %s)\n", str.toChars(), deleg.toChars());
6670     }
6671     FuncDeclaration fd = null;
6672     Expression pthis = null;
6673     if (deleg.op == TOKdelegate)
6674     {
6675         fd = (cast(DelegateExp)deleg).func;
6676         pthis = (cast(DelegateExp)deleg).e1;
6677     }
6678     else if (deleg.op == TOKfunction)
6679         fd = (cast(FuncExp)deleg).fd;
6680 
6681     assert(fd && fd.fbody);
6682     assert(fd.parameters);
6683     size_t numParams = fd.parameters.dim;
6684     assert(numParams == 1 || numParams == 2);
6685     Type charType = (*fd.parameters)[numParams - 1].type;
6686     Type indexType = numParams == 2 ? (*fd.parameters)[0].type : Type.tsize_t;
6687     size_t len = cast(size_t)resolveArrayLength(str);
6688     if (len == 0)
6689         return new IntegerExp(deleg.loc, 0, indexType);
6690 
6691     str = resolveSlice(str);
6692 
6693     StringExp se = null;
6694     ArrayLiteralExp ale = null;
6695     if (str.op == TOKstring)
6696         se = cast(StringExp)str;
6697     else if (str.op == TOKarrayliteral)
6698         ale = cast(ArrayLiteralExp)str;
6699     else
6700     {
6701         str.error("CTFE internal error: cannot foreach %s", str.toChars());
6702         return CTFEExp.cantexp;
6703     }
6704     Expressions args;
6705     args.setDim(numParams);
6706 
6707     Expression eresult = null; // ded-store to prevent spurious warning
6708 
6709     // Buffers for encoding; also used for decoding array literals
6710     char[4] utf8buf;
6711     wchar[2] utf16buf;
6712 
6713     size_t start = rvs ? len : 0;
6714     size_t end = rvs ? 0 : len;
6715     for (size_t indx = start; indx != end;)
6716     {
6717         // Step 1: Decode the next dchar from the string.
6718 
6719         const(char)* errmsg = null; // Used for reporting decoding errors
6720         dchar rawvalue; // Holds the decoded dchar
6721         size_t currentIndex = indx; // The index of the decoded character
6722 
6723         if (ale)
6724         {
6725             // If it is an array literal, copy the code points into the buffer
6726             size_t buflen = 1; // #code points in the buffer
6727             size_t n = 1; // #code points in this char
6728             size_t sz = cast(size_t)ale.type.nextOf().size();
6729 
6730             switch (sz)
6731             {
6732             case 1:
6733                 if (rvs)
6734                 {
6735                     // find the start of the string
6736                     --indx;
6737                     buflen = 1;
6738                     while (indx > 0 && buflen < 4)
6739                     {
6740                         Expression r = (*ale.elements)[indx];
6741                         assert(r.op == TOKint64);
6742                         char x = cast(char)(cast(IntegerExp)r).getInteger();
6743                         if ((x & 0xC0) != 0x80)
6744                             break;
6745                         ++buflen;
6746                     }
6747                 }
6748                 else
6749                     buflen = (indx + 4 > len) ? len - indx : 4;
6750                 for (size_t i = 0; i < buflen; ++i)
6751                 {
6752                     Expression r = (*ale.elements)[indx + i];
6753                     assert(r.op == TOKint64);
6754                     utf8buf[i] = cast(char)(cast(IntegerExp)r).getInteger();
6755                 }
6756                 n = 0;
6757                 errmsg = utf_decodeChar(&utf8buf[0], buflen, n, rawvalue);
6758                 break;
6759 
6760             case 2:
6761                 if (rvs)
6762                 {
6763                     // find the start of the string
6764                     --indx;
6765                     buflen = 1;
6766                     Expression r = (*ale.elements)[indx];
6767                     assert(r.op == TOKint64);
6768                     ushort x = cast(ushort)(cast(IntegerExp)r).getInteger();
6769                     if (indx > 0 && x >= 0xDC00 && x <= 0xDFFF)
6770                     {
6771                         --indx;
6772                         ++buflen;
6773                     }
6774                 }
6775                 else
6776                     buflen = (indx + 2 > len) ? len - indx : 2;
6777                 for (size_t i = 0; i < buflen; ++i)
6778                 {
6779                     Expression r = (*ale.elements)[indx + i];
6780                     assert(r.op == TOKint64);
6781                     utf16buf[i] = cast(ushort)(cast(IntegerExp)r).getInteger();
6782                 }
6783                 n = 0;
6784                 errmsg = utf_decodeWchar(&utf16buf[0], buflen, n, rawvalue);
6785                 break;
6786 
6787             case 4:
6788                 {
6789                     if (rvs)
6790                         --indx;
6791                     Expression r = (*ale.elements)[indx];
6792                     assert(r.op == TOKint64);
6793                     rawvalue = cast(dchar)(cast(IntegerExp)r).getInteger();
6794                     n = 1;
6795                 }
6796                 break;
6797 
6798             default:
6799                 assert(0);
6800             }
6801             if (!rvs)
6802                 indx += n;
6803         }
6804         else
6805         {
6806             // String literals
6807             size_t saveindx; // used for reverse iteration
6808 
6809             switch (se.sz)
6810             {
6811             case 1:
6812                 if (rvs)
6813                 {
6814                     // find the start of the string
6815                     --indx;
6816                     while (indx > 0 && ((se.getCodeUnit(indx) & 0xC0) == 0x80))
6817                         --indx;
6818                     saveindx = indx;
6819                 }
6820                 errmsg = utf_decodeChar(se..string, se.len, indx, rawvalue);
6821                 if (rvs)
6822                     indx = saveindx;
6823                 break;
6824 
6825             case 2:
6826                 if (rvs)
6827                 {
6828                     // find the start
6829                     --indx;
6830                     auto wc = se.getCodeUnit(indx);
6831                     if (wc >= 0xDC00 && wc <= 0xDFFF)
6832                         --indx;
6833                     saveindx = indx;
6834                 }
6835                 errmsg = utf_decodeWchar(se.wstring, se.len, indx, rawvalue);
6836                 if (rvs)
6837                     indx = saveindx;
6838                 break;
6839 
6840             case 4:
6841                 if (rvs)
6842                     --indx;
6843                 rawvalue = se.getCodeUnit(indx);
6844                 if (!rvs)
6845                     ++indx;
6846                 break;
6847 
6848             default:
6849                 assert(0);
6850             }
6851         }
6852         if (errmsg)
6853         {
6854             deleg.error("%s", errmsg);
6855             return CTFEExp.cantexp;
6856         }
6857 
6858         // Step 2: encode the dchar in the target encoding
6859 
6860         int charlen = 1; // How many codepoints are involved?
6861         switch (charType.size())
6862         {
6863         case 1:
6864             charlen = utf_codeLengthChar(rawvalue);
6865             utf_encodeChar(&utf8buf[0], rawvalue);
6866             break;
6867         case 2:
6868             charlen = utf_codeLengthWchar(rawvalue);
6869             utf_encodeWchar(&utf16buf[0], rawvalue);
6870             break;
6871         case 4:
6872             break;
6873         default:
6874             assert(0);
6875         }
6876         if (rvs)
6877             currentIndex = indx;
6878 
6879         // Step 3: call the delegate once for each code point
6880 
6881         // The index only needs to be set once
6882         if (numParams == 2)
6883             args[0] = new IntegerExp(deleg.loc, currentIndex, indexType);
6884 
6885         Expression val = null;
6886 
6887         for (int k = 0; k < charlen; ++k)
6888         {
6889             dchar codepoint;
6890             switch (charType.size())
6891             {
6892             case 1:
6893                 codepoint = utf8buf[k];
6894                 break;
6895             case 2:
6896                 codepoint = utf16buf[k];
6897                 break;
6898             case 4:
6899                 codepoint = rawvalue;
6900                 break;
6901             default:
6902                 assert(0);
6903             }
6904             val = new IntegerExp(str.loc, codepoint, charType);
6905 
6906             args[numParams - 1] = val;
6907 
6908             eresult = interpret(fd, istate, &args, pthis);
6909             if (exceptionOrCantInterpret(eresult))
6910                 return eresult;
6911             assert(eresult.op == TOKint64);
6912             if ((cast(IntegerExp)eresult).getInteger() != 0)
6913                 return eresult;
6914         }
6915     }
6916     return eresult;
6917 }
6918 
6919 /* If this is a built-in function, return the interpreted result,
6920  * Otherwise, return NULL.
6921  */
6922 extern (C++) Expression evaluateIfBuiltin(InterState* istate, Loc loc, FuncDeclaration fd, Expressions* arguments, Expression pthis)
6923 {
6924     Expression e = null;
6925     size_t nargs = arguments ? arguments.dim : 0;
6926     if (!pthis)
6927     {
6928         if (isBuiltin(fd) == BUILTINyes)
6929         {
6930             Expressions args;
6931             args.setDim(nargs);
6932             for (size_t i = 0; i < args.dim; i++)
6933             {
6934                 Expression earg = (*arguments)[i];
6935                 earg = interpret(earg, istate);
6936                 if (exceptionOrCantInterpret(earg))
6937                     return earg;
6938                 args[i] = earg;
6939             }
6940             e = eval_builtin(loc, fd, &args);
6941             if (!e)
6942             {
6943                 error(loc, "cannot evaluate unimplemented builtin %s at compile time", fd.toChars());
6944                 e = CTFEExp.cantexp;
6945             }
6946         }
6947     }
6948     if (!pthis)
6949     {
6950         Expression firstarg = nargs > 0 ? (*arguments)[0] : null;
6951         if (firstarg && firstarg.type.toBasetype().ty == Taarray)
6952         {
6953             TypeAArray firstAAtype = cast(TypeAArray)firstarg.type;
6954             const id = fd.ident.toChars();
6955             if (nargs == 1 && fd.ident == Id.aaLen)
6956                 return interpret_length(istate, firstarg);
6957             if (nargs == 3 && !strcmp(id, "_aaApply"))
6958                 return interpret_aaApply(istate, firstarg, arguments.data[2]);
6959             if (nargs == 3 && !strcmp(id, "_aaApply2"))
6960                 return interpret_aaApply(istate, firstarg, arguments.data[2]);
6961             if (nargs == 1 && !strcmp(id, "keys") && !strcmp(fd.toParent2().ident.toChars(), "object"))
6962                 return interpret_keys(istate, firstarg, firstAAtype.index.arrayOf());
6963             if (nargs == 1 && !strcmp(id, "values") && !strcmp(fd.toParent2().ident.toChars(), "object"))
6964                 return interpret_values(istate, firstarg, firstAAtype.nextOf().arrayOf());
6965             if (nargs == 1 && !strcmp(id, "rehash") && !strcmp(fd.toParent2().ident.toChars(), "object"))
6966                 return interpret(firstarg, istate);
6967             if (nargs == 1 && !strcmp(id, "dup") && !strcmp(fd.toParent2().ident.toChars(), "object"))
6968                 return interpret_dup(istate, firstarg);
6969         }
6970     }
6971     if (pthis && !fd.fbody && fd.isCtorDeclaration() && fd.parent && fd.parent.parent && fd.parent.parent.ident == Id.object)
6972     {
6973         if (pthis.op == TOKclassreference && fd.parent.ident == Id.Throwable)
6974         {
6975             // At present, the constructors just copy their arguments into the struct.
6976             // But we might need some magic if stack tracing gets added to druntime.
6977             StructLiteralExp se = (cast(ClassReferenceExp)pthis).value;
6978             assert(arguments.dim <= se.elements.dim);
6979             for (size_t i = 0; i < arguments.dim; ++i)
6980             {
6981                 e = interpret((*arguments)[i], istate);
6982                 if (exceptionOrCantInterpret(e))
6983                     return e;
6984                 (*se.elements)[i] = e;
6985             }
6986             return CTFEExp.voidexp;
6987         }
6988     }
6989     if (nargs == 1 && !pthis && (fd.ident == Id.criticalenter || fd.ident == Id.criticalexit))
6990     {
6991         // Support synchronized{} as a no-op
6992         return CTFEExp.voidexp;
6993     }
6994     if (!pthis)
6995     {
6996         const idlen = fd.ident.toString().length;
6997         const id = fd.ident.toChars();
6998         if (nargs == 2 && (idlen == 10 || idlen == 11) && !strncmp(id, "_aApply", 7))
6999         {
7000             // Functions from aApply.d and aApplyR.d in the runtime
7001             bool rvs = (idlen == 11); // true if foreach_reverse
7002             char c = id[idlen - 3]; // char width: 'c', 'w', or 'd'
7003             char s = id[idlen - 2]; // string width: 'c', 'w', or 'd'
7004             char n = id[idlen - 1]; // numParams: 1 or 2.
7005             // There are 12 combinations
7006             if ((n == '1' || n == '2') && (c == 'c' || c == 'w' || c == 'd') && (s == 'c' || s == 'w' || s == 'd') && c != s)
7007             {
7008                 Expression str = (*arguments)[0];
7009                 str = interpret(str, istate);
7010                 if (exceptionOrCantInterpret(str))
7011                     return str;
7012                 return foreachApplyUtf(istate, str, (*arguments)[1], rvs);
7013             }
7014         }
7015     }
7016     return e;
7017 }
7018 
7019 extern (C++) Expression evaluatePostblit(InterState* istate, Expression e)
7020 {
7021     Type tb = e.type.baseElemOf();
7022     if (tb.ty != Tstruct)
7023         return null;
7024     StructDeclaration sd = (cast(TypeStruct)tb).sym;
7025     if (!sd.postblit)
7026         return null;
7027 
7028     if (e.op == TOKarrayliteral)
7029     {
7030         ArrayLiteralExp ale = cast(ArrayLiteralExp)e;
7031         for (size_t i = 0; i < ale.elements.dim; i++)
7032         {
7033             e = evaluatePostblit(istate, (*ale.elements)[i]);
7034             if (e)
7035                 return e;
7036         }
7037         return null;
7038     }
7039     if (e.op == TOKstructliteral)
7040     {
7041         // e.__postblit()
7042         e = interpret(sd.postblit, istate, null, e);
7043         if (exceptionOrCantInterpret(e))
7044             return e;
7045         return null;
7046     }
7047     assert(0);
7048 }
7049 
7050 extern (C++) Expression evaluateDtor(InterState* istate, Expression e)
7051 {
7052     Type tb = e.type.baseElemOf();
7053     if (tb.ty != Tstruct)
7054         return null;
7055     StructDeclaration sd = (cast(TypeStruct)tb).sym;
7056     if (!sd.dtor)
7057         return null;
7058 
7059     if (e.op == TOKarrayliteral)
7060     {
7061         ArrayLiteralExp alex = cast(ArrayLiteralExp)e;
7062         for (size_t i = alex.elements.dim; 0 < i--;)
7063             e = evaluateDtor(istate, (*alex.elements)[i]);
7064     }
7065     else if (e.op == TOKstructliteral)
7066     {
7067         // e.__dtor()
7068         e = interpret(sd.dtor, istate, null, e);
7069     }
7070     else
7071         assert(0);
7072     if (exceptionOrCantInterpret(e))
7073         return e;
7074     return null;
7075 }
7076 
7077 /*************************** CTFE Sanity Checks ***************************/
7078 /* Setter functions for CTFE variable values.
7079  * These functions exist to check for compiler CTFE bugs.
7080  */
7081 extern (C++) bool hasValue(VarDeclaration vd)
7082 {
7083     if (vd.ctfeAdrOnStack == cast(size_t)-1)
7084         return false;
7085     return null !is getValue(vd);
7086 }
7087 
7088 extern (C++) Expression getValue(VarDeclaration vd)
7089 {
7090     return ctfeStack.getValue(vd);
7091 }
7092 
7093 extern (C++) void setValueNull(VarDeclaration vd)
7094 {
7095     ctfeStack.setValue(vd, null);
7096 }
7097 
7098 // Don't check for validity
7099 extern (C++) void setValueWithoutChecking(VarDeclaration vd, Expression newval)
7100 {
7101     ctfeStack.setValue(vd, newval);
7102 }
7103 
7104 extern (C++) void setValue(VarDeclaration vd, Expression newval)
7105 {
7106     version (none)
7107     {
7108         if (!((vd.storage_class & (STCout | STCref)) ? isCtfeReferenceValid(newval) : isCtfeValueValid(newval)))
7109         {
7110             printf("[%s] vd = %s %s, newval = %s\n", vd.loc.toChars(), vd.type.toChars(), vd.toChars(), newval.toChars());
7111         }
7112     }
7113     assert((vd.storage_class & (STCout | STCref)) ? isCtfeReferenceValid(newval) : isCtfeValueValid(newval));
7114     ctfeStack.setValue(vd, newval);
7115 }