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