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