2 /* Compiler implementation of the D programming language
3 * Copyright (C) 1999-2018 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
11 #include "root/dsystem.h" // mem{cpy|set}()
12 #include "root/rmem.h"
15 #include "statement.h"
16 #include "expression.h"
19 #include "staticassert.h"
22 #include "declaration.h"
23 #include "aggregate.h"
26 #include "attrib.h" // for AttribDeclaration
31 /* Interpreter: what form of return value expression is required?
35 ctfeNeedRvalue
, // Must return an Rvalue (== CTFE value)
36 ctfeNeedLvalue
, // Must return an Lvalue (== CTFE reference)
37 ctfeNeedNothing
// The return value is not required
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
);
46 static Expression
*interpret(UnionExp
*pue
, Expression
*e
, InterState
*istate
, CtfeGoal goal
= ctfeNeedRvalue
);
47 static Expression
*interpret(UnionExp
*pue
, Statement
*s
, InterState
*istate
);
49 #define SHOWPERFORMANCE 0
51 // Maximum allowable recursive function calls in CTFE
52 #define CTFE_RECURSION_LIMIT 1000
55 The values of all CTFE variables
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.
68 Ctfe Stack addresses are just 0-based integers, but we save
69 them as 'void *' because Array can only do pointers.
71 Expressions values
; // values on the stack
72 VarDeclarations vars
; // corresponding variables
73 Array
<void *> savedId
; // id of the previous state of that var
75 Array
<void *> frames
; // all previous frame pointers
76 Expressions savedThis
; // all previous values of localThis
78 /* Global constants get saved here after evaluation, so we never
79 * have to redo them. This saves a lot of time and memory.
81 Expressions globalValues
; // values of global constants
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
89 size_t stackPointer();
91 // The current value of 'this', or NULL if none
92 Expression
*getThis();
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
);
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
);
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).
117 Statement
*gotoTarget
;
122 /************** CtfeStack ********************************************/
126 CtfeStack::CtfeStack() : framepointer(0), maxStackPointer(0)
130 size_t CtfeStack::stackPointer()
135 Expression
*CtfeStack::getThis()
140 // Largest number of stack positions we've used
141 size_t CtfeStack::maxStackUsage()
143 return maxStackPointer
;
146 void CtfeStack::startFrame(Expression
*thisexp
)
148 frames
.push((void *)(size_t)(framepointer
));
149 savedThis
.push(localThis
);
150 framepointer
= stackPointer();
154 void CtfeStack::endFrame()
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);
164 bool CtfeStack::isInCurrentFrame(VarDeclaration
*v
)
166 if (v
->isDataseg() && !v
->isCTFE())
167 return false; // It's a global
168 return v
->ctfeAdrOnStack
>= (int)framepointer
;
171 Expression
*CtfeStack::getValue(VarDeclaration
*v
)
173 if ((v
->isDataseg() || v
->storage_class
& STCmanifest
) && !v
->isCTFE())
175 assert(v
->ctfeAdrOnStack
>= 0 &&
176 v
->ctfeAdrOnStack
< (int)globalValues
.dim
);
177 return globalValues
[v
->ctfeAdrOnStack
];
179 assert(v
->ctfeAdrOnStack
>= 0 && v
->ctfeAdrOnStack
< (int)stackPointer());
180 return values
[v
->ctfeAdrOnStack
];
183 void CtfeStack::setValue(VarDeclaration
*v
, Expression
*e
)
185 assert(!v
->isDataseg() || v
->isCTFE());
186 assert(v
->ctfeAdrOnStack
>= 0 && v
->ctfeAdrOnStack
< (int)stackPointer());
187 values
[v
->ctfeAdrOnStack
] = e
;
190 void CtfeStack::push(VarDeclaration
*v
)
192 assert(!v
->isDataseg() || v
->isCTFE());
193 if (v
->ctfeAdrOnStack
!= -1 &&
194 v
->ctfeAdrOnStack
>= (int)framepointer
)
196 // Already exists in this frame, reuse it.
197 values
[v
->ctfeAdrOnStack
] = NULL
;
200 savedId
.push((void *)(size_t)(v
->ctfeAdrOnStack
));
201 v
->ctfeAdrOnStack
= (int)values
.dim
;
206 void CtfeStack::pop(VarDeclaration
*v
)
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)
220 void CtfeStack::popAll(size_t stackpointer
)
222 if (stackPointer() > maxStackPointer
)
223 maxStackPointer
= stackPointer();
224 assert(values
.dim
>= stackpointer
);
225 for (size_t i
= stackpointer
; i
< values
.dim
; ++i
)
227 VarDeclaration
*v
= vars
[i
];
228 v
->ctfeAdrOnStack
= (int)(size_t)(savedId
[i
]);
230 values
.setDim(stackpointer
);
231 vars
.setDim(stackpointer
);
232 savedId
.setDim(stackpointer
);
235 void CtfeStack::saveGlobalConstant(VarDeclaration
*v
, Expression
*e
)
237 assert(v
->_init
&& (v
->isConst() || v
->isImmutable() || v
->storage_class
& STCmanifest
) && !v
->isCTFE());
238 v
->ctfeAdrOnStack
= (int)globalValues
.dim
;
239 globalValues
.push(e
);
242 /************** InterState ********************************************/
244 InterState::InterState()
246 memset(this, 0, sizeof(InterState
));
249 /************** CtfeStatus ********************************************/
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;
257 // CTFE diagnostic information
258 void printCtfePerformanceStats()
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
);
267 VarDeclaration
*findParentVar(Expression
*e
);
268 Expression
*evaluateIfBuiltin(InterState
*istate
, Loc loc
,
269 FuncDeclaration
*fd
, Expressions
*arguments
, Expression
*pthis
);
270 Expression
*evaluatePostblit(InterState
*istate
, Expression
*e
);
271 Expression
*evaluateDtor(InterState
*istate
, Expression
*e
);
272 Expression
*scrubReturnValue(Loc loc
, Expression
*e
);
274 Expression
*scrubCacheValue(Loc loc
, Expression
*e
);
277 /*************************************
278 * CTFE-object code for a single function
280 * Currently only counts the number of local variables in the function
282 struct CompiledCtfeFunction
284 FuncDeclaration
*func
; // Function being compiled, NULL if global scope
285 int numVars
; // Number of variables declared in this function
288 CompiledCtfeFunction(FuncDeclaration
*f
)
294 void onDeclaration(VarDeclaration
*)
296 //printf("%s CTFE declare %s\n", v->loc.toChars(), v->toChars());
300 void onExpression(Expression
*e
)
302 class VarWalker
: public StoppableVisitor
305 CompiledCtfeFunction
*ccf
;
307 VarWalker(CompiledCtfeFunction
*ccf
)
312 void visit(Expression
*)
316 void visit(ErrorExp
*e
)
318 // Currently there's a front-end bug: silent errors
319 // can occur inside delegate literals inside is(typeof()).
320 // Suppress the check in this case.
321 if (global
.gag
&& ccf
->func
)
327 ::error(e
->loc
, "CTFE internal error: ErrorExp in %s\n", ccf
->func
? ccf
->func
->loc
.toChars() : ccf
->callingloc
.toChars());
331 void visit(DeclarationExp
*e
)
333 VarDeclaration
*v
= e
->declaration
->isVarDeclaration();
336 TupleDeclaration
*td
= v
->toAlias()->isTupleDeclaration();
341 for (size_t i
= 0; i
< td
->objects
->dim
; ++i
)
343 RootObject
*o
= td
->objects
->tdata()[i
];
344 Expression
*ex
= isExpression(o
);
345 DsymbolExp
*s
= (ex
&& ex
->op
== TOKdsymbol
) ? (DsymbolExp
*)ex
: NULL
;
347 VarDeclaration
*v2
= s
->s
->isVarDeclaration();
349 if (!v2
->isDataseg() || v2
->isCTFE())
350 ccf
->onDeclaration(v2
);
353 else if (!(v
->isDataseg() || v
->storage_class
& STCmanifest
) || v
->isCTFE())
354 ccf
->onDeclaration(v
);
355 Dsymbol
*s
= v
->toAlias();
356 if (s
== v
&& !v
->isStatic() && v
->_init
)
358 ExpInitializer
*ie
= v
->_init
->isExpInitializer();
360 ccf
->onExpression(ie
->exp
);
364 void visit(IndexExp
*e
)
367 ccf
->onDeclaration(e
->lengthVar
);
370 void visit(SliceExp
*e
)
373 ccf
->onDeclaration(e
->lengthVar
);
378 walkPostorder(e
, &v
);
382 class CtfeCompiler
: public Visitor
385 CompiledCtfeFunction
*ccf
;
387 CtfeCompiler(CompiledCtfeFunction
*ccf
)
392 void visit(Statement
*)
397 void visit(ExpStatement
*s
)
400 ccf
->onExpression(s
->exp
);
403 void visit(CompoundStatement
*s
)
405 for (size_t i
= 0; i
< s
->statements
->dim
; i
++)
407 Statement
*sx
= (*s
->statements
)[i
];
413 void visit(UnrolledLoopStatement
*s
)
415 for (size_t i
= 0; i
< s
->statements
->dim
; i
++)
417 Statement
*sx
= (*s
->statements
)[i
];
423 void visit(IfStatement
*s
)
425 ccf
->onExpression(s
->condition
);
427 ctfeCompile(s
->ifbody
);
429 ctfeCompile(s
->elsebody
);
432 void visit(ScopeStatement
*s
)
435 ctfeCompile(s
->statement
);
438 void visit(OnScopeStatement
*)
440 // rewritten to try/catch/finally
444 void visit(DoStatement
*s
)
446 ccf
->onExpression(s
->condition
);
448 ctfeCompile(s
->_body
);
451 void visit(WhileStatement
*)
453 // rewritten to ForStatement
457 void visit(ForStatement
*s
)
460 ctfeCompile(s
->_init
);
462 ccf
->onExpression(s
->condition
);
464 ccf
->onExpression(s
->increment
);
466 ctfeCompile(s
->_body
);
469 void visit(ForeachStatement
*)
471 // rewritten for ForStatement
475 void visit(SwitchStatement
*s
)
477 ccf
->onExpression(s
->condition
);
478 // Note that the body contains the the Case and Default
479 // statements, so we only need to compile the expressions
480 for (size_t i
= 0; i
< s
->cases
->dim
; i
++)
482 ccf
->onExpression((*s
->cases
)[i
]->exp
);
485 ctfeCompile(s
->_body
);
488 void visit(CaseStatement
*s
)
491 ctfeCompile(s
->statement
);
494 void visit(DefaultStatement
*s
)
497 ctfeCompile(s
->statement
);
500 void visit(GotoDefaultStatement
*)
504 void visit(GotoCaseStatement
*)
508 void visit(SwitchErrorStatement
*)
512 void visit(ReturnStatement
*s
)
515 ccf
->onExpression(s
->exp
);
518 void visit(BreakStatement
*)
522 void visit(ContinueStatement
*)
526 void visit(WithStatement
*s
)
528 // If it is with(Enum) {...}, just execute the body.
529 if (s
->exp
->op
== TOKscope
|| s
->exp
->op
== TOKtype
)
534 ccf
->onDeclaration(s
->wthis
);
535 ccf
->onExpression(s
->exp
);
538 ctfeCompile(s
->_body
);
541 void visit(TryCatchStatement
*s
)
544 ctfeCompile(s
->_body
);
545 for (size_t i
= 0; i
< s
->catches
->dim
; i
++)
547 Catch
*ca
= (*s
->catches
)[i
];
549 ccf
->onDeclaration(ca
->var
);
551 ctfeCompile(ca
->handler
);
555 void visit(TryFinallyStatement
*s
)
558 ctfeCompile(s
->_body
);
560 ctfeCompile(s
->finalbody
);
563 void visit(ThrowStatement
*s
)
565 ccf
->onExpression(s
->exp
);
568 void visit(GotoStatement
*)
572 void visit(LabelStatement
*s
)
575 ctfeCompile(s
->statement
);
578 void visit(ImportStatement
*)
580 // Contains no variables or executable code
583 void visit(ForeachRangeStatement
*)
585 // rewritten for ForStatement
589 void visit(AsmStatement
*)
591 // we can't compile asm statements
594 void ctfeCompile(Statement
*s
)
600 /*************************************
601 * Compile this function for CTFE.
602 * At present, this merely allocates variables.
604 void ctfeCompile(FuncDeclaration
*fd
)
606 assert(!fd
->ctfeCode
);
607 assert(!fd
->semantic3Errors
);
608 assert(fd
->semanticRun
== PASSsemantic3done
);
610 fd
->ctfeCode
= new CompiledCtfeFunction(fd
);
613 Type
*tb
= fd
->type
->toBasetype();
614 assert(tb
->ty
== Tfunction
);
615 for (size_t i
= 0; i
< fd
->parameters
->dim
; i
++)
617 VarDeclaration
*v
= (*fd
->parameters
)[i
];
618 fd
->ctfeCode
->onDeclaration(v
);
622 fd
->ctfeCode
->onDeclaration(fd
->vresult
);
623 CtfeCompiler
v(fd
->ctfeCode
);
624 v
.ctfeCompile(fd
->fbody
);
627 /*************************************
628 * Entry point for CTFE.
629 * A compile-time result is required. Give an error if not possible.
631 * `e` must be semantically valid expression. In other words, it should not
632 * contain any `ErrorExp`s in it. But, CTFE interpretation will cross over
633 * functions and may invoke a function that contains `ErrorStatement` in its body.
634 * If that, the "CTFE failed because of previous errors" error is raised.
636 Expression
*ctfeInterpret(Expression
*e
)
638 if (e
->op
== TOKerror
)
640 assert(e
->type
); // Bugzilla 14642
641 //assert(e->type->ty != Terror); // FIXME
642 if (e
->type
->ty
== Terror
)
643 return new ErrorExp();
645 // This code is outside a function, but still needs to be compiled
646 // (there are compiler-generated temporary variables such as __dollar).
647 // However, this will only be run once and can then be discarded.
648 CompiledCtfeFunction
ctfeCodeGlobal(NULL
);
649 ctfeCodeGlobal
.callingloc
= e
->loc
;
650 ctfeCodeGlobal
.onExpression(e
);
652 Expression
*result
= interpret(e
, NULL
);
653 if (!CTFEExp::isCantExp(result
))
654 result
= scrubReturnValue(e
->loc
, result
);
655 if (CTFEExp::isCantExp(result
))
656 result
= new ErrorExp();
660 /* Run CTFE on the expression, but allow the expression to be a TypeExp
661 * or a tuple containing a TypeExp. (This is required by pragma(msg)).
663 Expression
*ctfeInterpretForPragmaMsg(Expression
*e
)
665 if (e
->op
== TOKerror
|| e
->op
== TOKtype
)
668 // It's also OK for it to be a function declaration (happens only with
669 // __traits(getOverloads))
670 if (e
->op
== TOKvar
&& ((VarExp
*)e
)->var
->isFuncDeclaration())
675 if (e
->op
!= TOKtuple
)
676 return e
->ctfeInterpret();
678 // Tuples need to be treated seperately, since they are
679 // allowed to contain a TypeExp in this case.
681 TupleExp
*tup
= (TupleExp
*)e
;
682 Expressions
*expsx
= NULL
;
683 for (size_t i
= 0; i
< tup
->exps
->dim
; ++i
)
685 Expression
*g
= (*tup
->exps
)[i
];
687 h
= ctfeInterpretForPragmaMsg(g
);
692 expsx
= new Expressions();
693 expsx
->setDim(tup
->exps
->dim
);
694 for (size_t j
= 0; j
< tup
->exps
->dim
; j
++)
695 (*expsx
)[j
] = (*tup
->exps
)[j
];
702 TupleExp
*te
= new TupleExp(e
->loc
, expsx
);
703 expandTuples(te
->exps
);
704 te
->type
= new TypeTuple(te
->exps
);
710 /*************************************
711 * Attempt to interpret a function given the arguments.
713 * istate state for calling function (NULL if none)
714 * arguments function arguments
715 * thisarg 'this', if a needThis() function, NULL if not.
717 * Return result expression if successful, TOKcantexp if not,
718 * or CTFEExp if function returned void.
721 static Expression
*interpretFunction(FuncDeclaration
*fd
, InterState
*istate
, Expressions
*arguments
, Expression
*thisarg
)
723 if (fd
->semanticRun
== PASSsemantic3
)
725 fd
->error("circular dependency. Functions cannot be interpreted while being compiled");
726 return CTFEExp::cantexp
;
728 if (!fd
->functionSemantic3())
729 return CTFEExp::cantexp
;
730 if (fd
->semanticRun
< PASSsemantic3done
)
731 return CTFEExp::cantexp
;
733 // CTFE-compile the function
737 Type
*tb
= fd
->type
->toBasetype();
738 assert(tb
->ty
== Tfunction
);
739 TypeFunction
*tf
= (TypeFunction
*)tb
;
740 if (tf
->varargs
&& arguments
&&
741 ((fd
->parameters
&& arguments
->dim
!= fd
->parameters
->dim
) || (!fd
->parameters
&& arguments
->dim
)))
743 fd
->error("C-style variadic functions are not yet implemented in CTFE");
744 return CTFEExp::cantexp
;
747 // Nested functions always inherit the 'this' pointer from the parent,
748 // except for delegates. (Note that the 'this' pointer may be null).
749 // Func literals report isNested() even if they are in global scope,
750 // so we need to check that the parent is a function.
751 if (fd
->isNested() && fd
->toParent2()->isFuncDeclaration() && !thisarg
&& istate
)
752 thisarg
= ctfeStack
.getThis();
754 if (fd
->needThis() && !thisarg
)
756 // error, no this. Prevent segfault.
757 // Here should be unreachable by the strict 'this' check in front-end.
758 fd
->error("need 'this' to access member %s", fd
->toChars());
759 return CTFEExp::cantexp
;
762 // Place to hold all the arguments to the function while
763 // we are evaluating them.
765 size_t dim
= arguments
? arguments
->dim
: 0;
766 assert((fd
->parameters
? fd
->parameters
->dim
: 0) == dim
);
768 /* Evaluate all the arguments to the function,
769 * store the results in eargs[]
772 for (size_t i
= 0; i
< dim
; i
++)
774 Expression
*earg
= (*arguments
)[i
];
775 Parameter
*fparam
= Parameter::getNth(tf
->parameters
, i
);
777 if (fparam
->storageClass
& (STCout
| STCref
))
779 if (!istate
&& (fparam
->storageClass
& STCout
))
781 // initializing an out parameter involves writing to it.
782 earg
->error("global %s cannot be passed as an 'out' parameter at compile time", earg
->toChars());
783 return CTFEExp::cantexp
;
785 // Convert all reference arguments into lvalue references
786 earg
= interpret(earg
, istate
, ctfeNeedLvalue
);
787 if (CTFEExp::isCantExp(earg
))
790 else if (fparam
->storageClass
& STClazy
)
797 Type
*ta
= fparam
->type
->toBasetype();
798 if (ta
->ty
== Tsarray
&& earg
->op
== TOKaddress
)
800 /* Static arrays are passed by a simple pointer.
801 * Skip past this to get at the actual arg.
803 earg
= ((AddrExp
*)earg
)->e1
;
805 earg
= interpret(earg
, istate
);
806 if (CTFEExp::isCantExp(earg
))
808 /* Struct literals are passed by value, but we don't need to
809 * copy them if they are passed as const
811 if (earg
->op
== TOKstructliteral
&& !(fparam
->storageClass
& (STCconst
| STCimmutable
)))
812 earg
= copyLiteral(earg
).copy();
814 if (earg
->op
== TOKthrownexception
)
818 ((ThrownExceptionExp
*)earg
)->generateUncaughtError();
819 return CTFEExp::cantexp
;
824 // Now that we've evaluated all the arguments, we can start the frame
825 // (this is the moment when the 'call' actually takes place).
827 istatex
.caller
= istate
;
829 ctfeStack
.startFrame(thisarg
);
830 if (fd
->vthis
&& thisarg
)
832 ctfeStack
.push(fd
->vthis
);
833 setValue(fd
->vthis
, thisarg
);
836 for (size_t i
= 0; i
< dim
; i
++)
838 Expression
*earg
= eargs
[i
];
839 Parameter
*fparam
= Parameter::getNth(tf
->parameters
, i
);
840 VarDeclaration
*v
= (*fd
->parameters
)[i
];
843 if ((fparam
->storageClass
& (STCout
| STCref
)) &&
844 earg
->op
== TOKvar
&& ((VarExp
*)earg
)->var
->toParent2() == fd
)
846 VarDeclaration
*vx
= ((VarExp
*)earg
)->var
->isVarDeclaration();
849 fd
->error("cannot interpret %s as a ref parameter", earg
->toChars());
850 return CTFEExp::cantexp
;
853 /* vx is a variable that is declared in fd.
854 * It means that fd is recursively called. e.g.
856 * void fd(int n, ref int v = dummy) {
858 * if (n == 1) fd(2, vx);
862 * The old value of vx on the stack in fd(1)
863 * should be saved at the start of fd(2, vx) call.
865 int oldadr
= vx
->ctfeAdrOnStack
;
868 assert(!hasValue(vx
)); // vx is made uninitialized
870 // Bugzilla 14299: v->ctfeAdrOnStack should be saved already
871 // in the stack before the overwrite.
872 v
->ctfeAdrOnStack
= oldadr
;
873 assert(hasValue(v
)); // ref parameter v should refer existing value.
877 // Value parameters and non-trivial references
878 setValueWithoutChecking(v
, earg
);
883 ctfeStack
.push(fd
->vresult
);
885 // Enter the function
886 ++CtfeStatus::callDepth
;
887 if (CtfeStatus::callDepth
> CtfeStatus::maxCallDepth
)
888 CtfeStatus::maxCallDepth
= CtfeStatus::callDepth
;
890 Expression
*e
= NULL
;
893 if (CtfeStatus::callDepth
> CTFE_RECURSION_LIMIT
)
895 // This is a compiler error. It must not be suppressed.
897 fd
->error("CTFE recursion limit exceeded");
898 e
= CTFEExp::cantexp
;
901 e
= interpret(fd
->fbody
, &istatex
);
905 fd
->error("CTFE internal error: failed to resume at statement %s", istatex
.start
->toChars());
906 return CTFEExp::cantexp
;
909 /* This is how we deal with a recursive statement AST
910 * that has arbitrary goto statements in it.
911 * Bubble up a 'result' which is the target of the goto
912 * statement, then go recursively down the AST looking
913 * for that statement, then execute starting there.
915 if (CTFEExp::isGotoExp(e
))
917 istatex
.start
= istatex
.gotoTarget
; // set starting statement
918 istatex
.gotoTarget
= NULL
;
922 assert(!e
|| (e
->op
!= TOKcontinue
&& e
->op
!= TOKbreak
));
926 // If fell off the end of a void function, return void
927 if (!e
&& tf
->next
->ty
== Tvoid
)
928 e
= CTFEExp::voidexp
;
929 if (tf
->isref
&& e
->op
== TOKvar
&& ((VarExp
*)e
)->var
== fd
->vthis
)
933 // Leave the function
934 --CtfeStatus::callDepth
;
936 ctfeStack
.endFrame();
938 // If it generated an uncaught exception, report error.
939 if (!istate
&& e
->op
== TOKthrownexception
)
941 ((ThrownExceptionExp
*)e
)->generateUncaughtError();
942 e
= CTFEExp::cantexp
;
948 class Interpreter
: public Visitor
955 UnionExp
*pue
; // storage for `result`
957 Interpreter(UnionExp
*pue
, InterState
*istate
, CtfeGoal goal
)
958 : istate(istate
), goal(goal
), pue(pue
)
963 // If e is TOKthrowexception or TOKcantexp,
964 // set it to 'result' and returns true.
965 bool exceptionOrCant(Expression
*e
)
967 if (exceptionOrCantInterpret(e
))
969 // Make sure e is not pointing to a stack temporary
970 result
= (e
->op
== TOKcantexp
) ? CTFEExp::cantexp
: e
;
976 static Expressions
*copyArrayOnWrite(Expressions
*exps
, Expressions
*original
)
978 if (exps
== original
)
981 exps
= new Expressions();
983 exps
= original
->copy();
984 ++CtfeStatus::numArrayAllocs
;
989 /******************************** Statement ***************************/
991 void visit(Statement
*s
)
995 if (istate
->start
!= s
)
997 istate
->start
= NULL
;
1000 s
->error("statement %s cannot be interpreted at compile time", s
->toChars());
1001 result
= CTFEExp::cantexp
;
1004 void visit(ExpStatement
*s
)
1008 if (istate
->start
!= s
)
1010 istate
->start
= NULL
;
1013 Expression
*e
= interpret(pue
, s
->exp
, istate
, ctfeNeedNothing
);
1014 if (exceptionOrCant(e
))
1018 void visit(CompoundStatement
*s
)
1020 if (istate
->start
== s
)
1021 istate
->start
= NULL
;
1023 const size_t dim
= s
->statements
? s
->statements
->dim
: 0;
1024 for (size_t i
= 0; i
< dim
; i
++)
1026 Statement
*sx
= (*s
->statements
)[i
];
1027 result
= interpret(pue
, sx
, istate
);
1033 void visit(UnrolledLoopStatement
*s
)
1035 if (istate
->start
== s
)
1036 istate
->start
= NULL
;
1038 const size_t dim
= s
->statements
? s
->statements
->dim
: 0;
1039 for (size_t i
= 0; i
< dim
; i
++)
1041 Statement
*sx
= (*s
->statements
)[i
];
1042 Expression
*e
= interpret(pue
, sx
, istate
);
1043 if (!e
) // suceeds to interpret, or goto target
1044 continue; // was not fonnd when istate->start != NULL
1045 if (exceptionOrCant(e
))
1047 if (e
->op
== TOKbreak
)
1049 if (istate
->gotoTarget
&& istate
->gotoTarget
!= s
)
1051 result
= e
; // break at a higher level
1054 istate
->gotoTarget
= NULL
;
1058 if (e
->op
== TOKcontinue
)
1060 if (istate
->gotoTarget
&& istate
->gotoTarget
!= s
)
1062 result
= e
; // continue at a higher level
1065 istate
->gotoTarget
= NULL
;
1069 // expression from return statement, or thrown exception
1075 void visit(IfStatement
*s
)
1077 if (istate
->start
== s
)
1078 istate
->start
= NULL
;
1081 Expression
*e
= NULL
;
1082 e
= interpret(s
->ifbody
, istate
);
1083 if (!e
&& istate
->start
)
1084 e
= interpret(s
->elsebody
, istate
);
1090 Expression
*e
= interpret(&ue
, s
->condition
, istate
);
1092 if (exceptionOrCant(e
))
1096 result
= interpret(pue
, s
->ifbody
, istate
);
1097 else if (e
->isBool(false))
1098 result
= interpret(pue
, s
->elsebody
, istate
);
1101 // no error, or assert(0)?
1102 result
= CTFEExp::cantexp
;
1106 void visit(ScopeStatement
*s
)
1108 if (istate
->start
== s
)
1109 istate
->start
= NULL
;
1111 result
= interpret(pue
, s
->statement
, istate
);
1115 Given an expression e which is about to be returned from the current
1116 function, generate an error if it contains pointers to local variables.
1118 Only checks expressions passed by value (pointers to local variables
1119 may already be stored in members of classes, arrays, or AAs which
1120 were passed as mutable function parameters).
1122 true if it is safe to return, false if an error was generated.
1125 static bool stopPointersEscaping(Loc loc
, Expression
*e
)
1127 if (!e
->type
->hasPointers())
1129 if (isPointer(e
->type
))
1132 if (e
->op
== TOKaddress
)
1133 x
= ((AddrExp
*)e
)->e1
;
1135 while (x
->op
== TOKvar
&&
1136 (v
= ((VarExp
*)x
)->var
->isVarDeclaration()) != NULL
)
1138 if (v
->storage_class
& STCref
)
1141 if (e
->op
== TOKaddress
)
1142 ((AddrExp
*)e
)->e1
= x
;
1145 if (ctfeStack
.isInCurrentFrame(v
))
1147 error(loc
, "returning a pointer to a local stack variable");
1153 // TODO: If it is a TOKdotvar or TOKindex, we should check that it is not
1154 // pointing to a local struct or static array.
1156 if (e
->op
== TOKstructliteral
)
1158 StructLiteralExp
*se
= (StructLiteralExp
*)e
;
1159 return stopPointersEscapingFromArray(loc
, se
->elements
);
1161 if (e
->op
== TOKarrayliteral
)
1163 return stopPointersEscapingFromArray(loc
, ((ArrayLiteralExp
*)e
)->elements
);
1165 if (e
->op
== TOKassocarrayliteral
)
1167 AssocArrayLiteralExp
*aae
= (AssocArrayLiteralExp
*)e
;
1168 if (!stopPointersEscapingFromArray(loc
, aae
->keys
))
1170 return stopPointersEscapingFromArray(loc
, aae
->values
);
1175 // Check all members of an array for escaping local variables. Return false if error
1176 static bool stopPointersEscapingFromArray(Loc loc
, Expressions
*elems
)
1178 for (size_t i
= 0; i
< elems
->dim
; i
++)
1180 Expression
*m
= (*elems
)[i
];
1183 if (!stopPointersEscaping(loc
, m
))
1189 void visit(ReturnStatement
*s
)
1193 if (istate
->start
!= s
)
1195 istate
->start
= NULL
;
1200 result
= CTFEExp::voidexp
;
1204 assert(istate
&& istate
->fd
&& istate
->fd
->type
&& istate
->fd
->type
->ty
== Tfunction
);
1205 TypeFunction
*tf
= (TypeFunction
*)istate
->fd
->type
;
1207 /* If the function returns a ref AND it's been called from an assignment,
1208 * we need to return an lvalue. Otherwise, just do an (rvalue) interpret.
1212 result
= interpret(pue
, s
->exp
, istate
, ctfeNeedLvalue
);
1215 if (tf
->next
&& tf
->next
->ty
== Tdelegate
&& istate
->fd
->closureVars
.dim
> 0)
1217 // To support this, we need to copy all the closure vars
1218 // into the delegate literal.
1219 s
->error("closures are not yet supported in CTFE");
1220 result
= CTFEExp::cantexp
;
1224 // We need to treat pointers specially, because TOKsymoff can be used to
1225 // return a value OR a pointer
1226 Expression
*e
= interpret(pue
, s
->exp
, istate
);
1227 if (exceptionOrCant(e
))
1230 // Disallow returning pointers to stack-allocated variables (bug 7876)
1231 if (!stopPointersEscaping(s
->loc
, e
))
1233 result
= CTFEExp::cantexp
;
1237 if (needToCopyLiteral(e
))
1238 e
= copyLiteral(e
).copy();
1242 static Statement
*findGotoTarget(InterState
*istate
, Identifier
*ident
)
1244 Statement
*target
= NULL
;
1247 LabelDsymbol
*label
= istate
->fd
->searchLabel(ident
);
1248 assert(label
&& label
->statement
);
1249 LabelStatement
*ls
= label
->statement
;
1250 target
= ls
->gotoTarget
? ls
->gotoTarget
: ls
->statement
;
1255 void visit(BreakStatement
*s
)
1259 if (istate
->start
!= s
)
1261 istate
->start
= NULL
;
1264 istate
->gotoTarget
= findGotoTarget(istate
, s
->ident
);
1265 result
= CTFEExp::breakexp
;
1268 void visit(ContinueStatement
*s
)
1272 if (istate
->start
!= s
)
1274 istate
->start
= NULL
;
1277 istate
->gotoTarget
= findGotoTarget(istate
, s
->ident
);
1278 result
= CTFEExp::continueexp
;
1281 void visit(WhileStatement
*)
1283 assert(0); // rewritten to ForStatement
1286 void visit(DoStatement
*s
)
1288 if (istate
->start
== s
)
1289 istate
->start
= NULL
;
1293 Expression
*e
= interpret(s
->_body
, istate
);
1294 if (!e
&& istate
->start
) // goto target was not found
1296 assert(!istate
->start
);
1298 if (exceptionOrCant(e
))
1300 if (e
&& e
->op
== TOKbreak
)
1302 if (istate
->gotoTarget
&& istate
->gotoTarget
!= s
)
1304 result
= e
; // break at a higher level
1307 istate
->gotoTarget
= NULL
;
1310 if (e
&& e
->op
== TOKcontinue
)
1312 if (istate
->gotoTarget
&& istate
->gotoTarget
!= s
)
1314 result
= e
; // continue at a higher level
1317 istate
->gotoTarget
= NULL
;
1322 result
= e
; // bubbled up from ReturnStatement
1327 e
= interpret(&ue
, s
->condition
, istate
);
1328 if (exceptionOrCant(e
))
1332 result
= CTFEExp::cantexp
;
1335 if (e
->isBool(false))
1337 assert(isTrueBool(e
));
1339 assert(result
== NULL
);
1342 void visit(ForStatement
*s
)
1344 if (istate
->start
== s
)
1345 istate
->start
= NULL
;
1348 Expression
*ei
= interpret(&ueinit
, s
->_init
, istate
);
1349 if (exceptionOrCant(ei
))
1351 assert(!ei
); // s->init never returns from function, or jumps out from it
1355 if (s
->condition
&& !istate
->start
)
1358 Expression
*e
= interpret(&ue
, s
->condition
, istate
);
1359 if (exceptionOrCant(e
))
1361 if (e
->isBool(false))
1363 assert(isTrueBool(e
));
1366 Expression
*e
= interpret(pue
, s
->_body
, istate
);
1367 if (!e
&& istate
->start
) // goto target was not found
1369 assert(!istate
->start
);
1371 if (exceptionOrCant(e
))
1373 if (e
&& e
->op
== TOKbreak
)
1375 if (istate
->gotoTarget
&& istate
->gotoTarget
!= s
)
1377 result
= e
; // break at a higher level
1380 istate
->gotoTarget
= NULL
;
1383 if (e
&& e
->op
== TOKcontinue
)
1385 if (istate
->gotoTarget
&& istate
->gotoTarget
!= s
)
1387 result
= e
; // continue at a higher level
1390 istate
->gotoTarget
= NULL
;
1395 result
= e
; // bubbled up from ReturnStatement
1400 e
= interpret(&uei
, s
->increment
, istate
, ctfeNeedNothing
);
1401 if (exceptionOrCant(e
))
1404 assert(result
== NULL
);
1407 void visit(ForeachStatement
*)
1409 assert(0); // rewritten to ForStatement
1412 void visit(ForeachRangeStatement
*)
1414 assert(0); // rewritten to ForStatement
1417 void visit(SwitchStatement
*s
)
1419 if (istate
->start
== s
)
1420 istate
->start
= NULL
;
1423 Expression
*e
= interpret(s
->_body
, istate
);
1424 if (istate
->start
) // goto target was not found
1426 if (exceptionOrCant(e
))
1428 if (e
&& e
->op
== TOKbreak
)
1430 if (istate
->gotoTarget
&& istate
->gotoTarget
!= s
)
1432 result
= e
; // break at a higher level
1435 istate
->gotoTarget
= NULL
;
1443 Expression
*econdition
= interpret(&uecond
, s
->condition
, istate
);
1444 if (exceptionOrCant(econdition
))
1447 Statement
*scase
= NULL
;
1448 size_t dim
= s
->cases
? s
->cases
->dim
: 0;
1449 for (size_t i
= 0; i
< dim
; i
++)
1451 CaseStatement
*cs
= (*s
->cases
)[i
];
1453 Expression
*ecase
= interpret(&uecase
, cs
->exp
, istate
);
1454 if (exceptionOrCant(ecase
))
1456 if (ctfeEqual(cs
->exp
->loc
, TOKequal
, econdition
, ecase
))
1464 if (s
->hasNoDefault
)
1465 s
->error("no default or case for %s in switch statement", econdition
->toChars());
1466 scase
= s
->sdefault
;
1473 istate
->start
= scase
;
1474 Expression
*e
= interpret(pue
, s
->_body
, istate
);
1475 assert(!istate
->start
); // jump must not fail
1476 if (e
&& e
->op
== TOKbreak
)
1478 if (istate
->gotoTarget
&& istate
->gotoTarget
!= s
)
1480 result
= e
; // break at a higher level
1483 istate
->gotoTarget
= NULL
;
1489 void visit(CaseStatement
*s
)
1491 if (istate
->start
== s
)
1492 istate
->start
= NULL
;
1494 result
= interpret(pue
, s
->statement
, istate
);
1497 void visit(DefaultStatement
*s
)
1499 if (istate
->start
== s
)
1500 istate
->start
= NULL
;
1502 result
= interpret(pue
, s
->statement
, istate
);
1505 void visit(GotoStatement
*s
)
1509 if (istate
->start
!= s
)
1511 istate
->start
= NULL
;
1514 assert(s
->label
&& s
->label
->statement
);
1515 istate
->gotoTarget
= s
->label
->statement
;
1516 result
= CTFEExp::gotoexp
;
1519 void visit(GotoCaseStatement
*s
)
1523 if (istate
->start
!= s
)
1525 istate
->start
= NULL
;
1529 istate
->gotoTarget
= s
->cs
;
1530 result
= CTFEExp::gotoexp
;
1533 void visit(GotoDefaultStatement
*s
)
1537 if (istate
->start
!= s
)
1539 istate
->start
= NULL
;
1542 assert(s
->sw
&& s
->sw
->sdefault
);
1543 istate
->gotoTarget
= s
->sw
->sdefault
;
1544 result
= CTFEExp::gotoexp
;
1547 void visit(LabelStatement
*s
)
1549 if (istate
->start
== s
)
1550 istate
->start
= NULL
;
1552 result
= interpret(pue
, s
->statement
, istate
);
1555 void visit(TryCatchStatement
*s
)
1557 if (istate
->start
== s
)
1558 istate
->start
= NULL
;
1561 Expression
*e
= NULL
;
1562 e
= interpret(pue
, s
->_body
, istate
);
1563 for (size_t i
= 0; i
< s
->catches
->dim
; i
++)
1565 if (e
|| !istate
->start
) // goto target was found
1567 Catch
*ca
= (*s
->catches
)[i
];
1568 e
= interpret(ca
->handler
, istate
);
1574 Expression
*e
= interpret(pue
, s
->_body
, istate
);
1576 // An exception was thrown
1577 if (e
&& e
->op
== TOKthrownexception
)
1579 ThrownExceptionExp
*ex
= (ThrownExceptionExp
*)e
;
1580 Type
*extype
= ex
->thrown
->originalClass()->type
;
1582 // Search for an appropriate catch clause.
1583 for (size_t i
= 0; i
< s
->catches
->dim
; i
++)
1585 Catch
*ca
= (*s
->catches
)[i
];
1586 Type
*catype
= ca
->type
;
1587 if (!catype
->equals(extype
) && !catype
->isBaseOf(extype
, NULL
))
1590 // Execute the handler
1593 ctfeStack
.push(ca
->var
);
1594 setValue(ca
->var
, ex
->thrown
);
1596 e
= interpret(ca
->handler
, istate
);
1597 if (CTFEExp::isGotoExp(e
))
1599 /* This is an optimization that relies on the locality of the jump target.
1600 * If the label is in the same catch handler, the following scan
1601 * would find it quickly and can reduce jump cost.
1602 * Otherwise, the catch block may be unnnecessary scanned again
1603 * so it would make CTFE speed slower.
1605 InterState istatex
= *istate
;
1606 istatex
.start
= istate
->gotoTarget
; // set starting statement
1607 istatex
.gotoTarget
= NULL
;
1608 Expression
*eh
= interpret(ca
->handler
, &istatex
);
1611 istate
->gotoTarget
= NULL
;
1621 static bool isAnErrorException(ClassDeclaration
*cd
)
1623 return cd
== ClassDeclaration::errorException
|| ClassDeclaration::errorException
->isBaseOf(cd
, NULL
);
1626 static ThrownExceptionExp
*chainExceptions(ThrownExceptionExp
*oldest
, ThrownExceptionExp
*newest
)
1628 // Little sanity check to make sure it's really a Throwable
1629 ClassReferenceExp
*boss
= oldest
->thrown
;
1630 assert((*boss
->value
->elements
)[4]->type
->ty
== Tclass
); // Throwable.next
1631 ClassReferenceExp
*collateral
= newest
->thrown
;
1632 if ( isAnErrorException(collateral
->originalClass()) &&
1633 !isAnErrorException(boss
->originalClass()))
1635 // The new exception bypass the existing chain
1636 assert((*collateral
->value
->elements
)[5]->type
->ty
== Tclass
);
1637 (*collateral
->value
->elements
)[5] = boss
;
1640 while ((*boss
->value
->elements
)[4]->op
== TOKclassreference
)
1642 boss
= (ClassReferenceExp
*)(*boss
->value
->elements
)[4];
1644 (*boss
->value
->elements
)[4] = collateral
;
1648 void visit(TryFinallyStatement
*s
)
1650 if (istate
->start
== s
)
1651 istate
->start
= NULL
;
1654 Expression
*e
= NULL
;
1655 e
= interpret(pue
, s
->_body
, istate
);
1656 // Jump into/out from finalbody is disabled in semantic analysis.
1657 // and jump inside will be handled by the ScopeStatement == finalbody.
1662 Expression
*ex
= interpret(s
->_body
, istate
);
1663 if (CTFEExp::isCantExp(ex
))
1668 while (CTFEExp::isGotoExp(ex
))
1670 // If the goto target is within the body, we must not interpret the finally statement,
1671 // because that will call destructors for objects within the scope, which we should not do.
1672 InterState istatex
= *istate
;
1673 istatex
.start
= istate
->gotoTarget
; // set starting statement
1674 istatex
.gotoTarget
= NULL
;
1675 Expression
*bex
= interpret(s
->_body
, &istatex
);
1678 // The goto target is outside the current scope.
1681 // The goto target was within the body.
1682 if (CTFEExp::isCantExp(bex
))
1690 Expression
*ey
= interpret(s
->finalbody
, istate
);
1691 if (CTFEExp::isCantExp(ey
))
1696 if (ey
&& ey
->op
== TOKthrownexception
)
1698 // Check for collided exceptions
1699 if (ex
&& ex
->op
== TOKthrownexception
)
1700 ex
= chainExceptions((ThrownExceptionExp
*)ex
, (ThrownExceptionExp
*)ey
);
1707 void visit(ThrowStatement
*s
)
1711 if (istate
->start
!= s
)
1713 istate
->start
= NULL
;
1716 Expression
*e
= interpret(s
->exp
, istate
);
1717 if (exceptionOrCant(e
))
1720 assert(e
->op
== TOKclassreference
);
1721 result
= new ThrownExceptionExp(s
->loc
, (ClassReferenceExp
*)e
);
1724 void visit(OnScopeStatement
*)
1729 void visit(WithStatement
*s
)
1731 if (istate
->start
== s
)
1732 istate
->start
= NULL
;
1735 result
= s
->_body
? interpret(s
->_body
, istate
) : NULL
;
1739 // If it is with(Enum) {...}, just execute the body.
1740 if (s
->exp
->op
== TOKscope
|| s
->exp
->op
== TOKtype
)
1742 result
= interpret(pue
, s
->_body
, istate
);
1746 Expression
*e
= interpret(s
->exp
, istate
);
1747 if (exceptionOrCant(e
))
1750 if (s
->wthis
->type
->ty
== Tpointer
&& s
->exp
->type
->ty
!= Tpointer
)
1752 e
= new AddrExp(s
->loc
, e
, s
->wthis
->type
);
1754 ctfeStack
.push(s
->wthis
);
1755 setValue(s
->wthis
, e
);
1756 e
= interpret(s
->_body
, istate
);
1757 if (CTFEExp::isGotoExp(e
))
1759 /* This is an optimization that relies on the locality of the jump target.
1760 * If the label is in the same WithStatement, the following scan
1761 * would find it quickly and can reduce jump cost.
1762 * Otherwise, the statement body may be unnnecessary scanned again
1763 * so it would make CTFE speed slower.
1765 InterState istatex
= *istate
;
1766 istatex
.start
= istate
->gotoTarget
; // set starting statement
1767 istatex
.gotoTarget
= NULL
;
1768 Expression
*ex
= interpret(s
->_body
, &istatex
);
1771 istate
->gotoTarget
= NULL
;
1775 ctfeStack
.pop(s
->wthis
);
1779 void visit(AsmStatement
*s
)
1783 if (istate
->start
!= s
)
1785 istate
->start
= NULL
;
1788 s
->error("asm statements cannot be interpreted at compile time");
1789 result
= CTFEExp::cantexp
;
1792 void visit(ImportStatement
*s
)
1796 if (istate
->start
!= s
)
1798 istate
->start
= NULL
;
1802 /******************************** Expression ***************************/
1804 void visit(Expression
*e
)
1806 e
->error("cannot interpret %s at compile time", e
->toChars());
1807 result
= CTFEExp::cantexp
;
1810 void visit(ThisExp
*e
)
1812 if (goal
== ctfeNeedLvalue
)
1814 // We might end up here with istate being zero (see bugzilla 16382)
1815 if (istate
&& istate
->fd
->vthis
)
1817 result
= new VarExp(e
->loc
, istate
->fd
->vthis
);
1818 result
->type
= e
->type
;
1825 result
= ctfeStack
.getThis();
1828 assert(result
->op
== TOKstructliteral
||
1829 result
->op
== TOKclassreference
);
1832 e
->error("value of 'this' is not known at compile time");
1833 result
= CTFEExp::cantexp
;
1836 void visit(NullExp
*e
)
1841 void visit(IntegerExp
*e
)
1846 void visit(RealExp
*e
)
1851 void visit(ComplexExp
*e
)
1856 void visit(StringExp
*e
)
1858 /* Attempts to modify string literals are prevented
1859 * in BinExp::interpretAssignCommon.
1864 void visit(FuncExp
*e
)
1869 void visit(SymOffExp
*e
)
1871 if (e
->var
->isFuncDeclaration() && e
->offset
== 0)
1876 if (isTypeInfo_Class(e
->type
) && e
->offset
== 0)
1881 if (e
->type
->ty
!= Tpointer
)
1883 // Probably impossible
1884 e
->error("cannot interpret %s at compile time", e
->toChars());
1885 result
= CTFEExp::cantexp
;
1888 Type
*pointee
= ((TypePointer
*)e
->type
)->next
;
1889 if (e
->var
->isThreadlocal())
1891 e
->error("cannot take address of thread-local variable %s at compile time", e
->var
->toChars());
1892 result
= CTFEExp::cantexp
;
1895 // Check for taking an address of a shared variable.
1896 // If the shared variable is an array, the offset might not be zero.
1897 Type
*fromType
= NULL
;
1898 if (e
->var
->type
->ty
== Tarray
|| e
->var
->type
->ty
== Tsarray
)
1900 fromType
= ((TypeArray
*)(e
->var
->type
))->next
;
1902 if (e
->var
->isDataseg() &&
1903 ((e
->offset
== 0 && isSafePointerCast(e
->var
->type
, pointee
)) ||
1904 (fromType
&& isSafePointerCast(fromType
, pointee
))))
1909 Expression
*val
= getVarExp(e
->loc
, istate
, e
->var
, goal
);
1910 if (exceptionOrCant(val
))
1912 if (val
->type
->ty
== Tarray
|| val
->type
->ty
== Tsarray
)
1914 // Check for unsupported type painting operations
1915 Type
*elemtype
= ((TypeArray
*)(val
->type
))->next
;
1916 d_uns64 elemsize
= elemtype
->size();
1918 // It's OK to cast from fixed length to dynamic array, eg &int[3] to int[]*
1919 if (val
->type
->ty
== Tsarray
&& pointee
->ty
== Tarray
&&
1920 elemsize
== pointee
->nextOf()->size())
1922 new(pue
) AddrExp(e
->loc
, val
, e
->type
);
1923 result
= pue
->exp();
1927 // It's OK to cast from fixed length to fixed length array, eg &int[n] to int[d]*.
1928 if (val
->type
->ty
== Tsarray
&& pointee
->ty
== Tsarray
&&
1929 elemsize
== pointee
->nextOf()->size())
1931 size_t d
= (size_t)((TypeSArray
*)pointee
)->dim
->toInteger();
1932 Expression
*elwr
= new IntegerExp(e
->loc
, e
->offset
/ elemsize
, Type::tsize_t
);
1933 Expression
*eupr
= new IntegerExp(e
->loc
, e
->offset
/ elemsize
+ d
, Type::tsize_t
);
1935 // Create a CTFE pointer &val[ofs..ofs+d]
1936 SliceExp
*se
= new SliceExp(e
->loc
, val
, elwr
, eupr
);
1938 new(pue
) AddrExp(e
->loc
, se
, e
->type
);
1939 result
= pue
->exp();
1943 if (!isSafePointerCast(elemtype
, pointee
))
1945 // It's also OK to cast from &string to string*.
1946 if (e
->offset
== 0 && isSafePointerCast(e
->var
->type
, pointee
))
1948 // Create a CTFE pointer &var
1949 VarExp
*ve
= new VarExp(e
->loc
, e
->var
);
1950 ve
->type
= elemtype
;
1951 new(pue
) AddrExp(e
->loc
, ve
, e
->type
);
1952 result
= pue
->exp();
1955 e
->error("reinterpreting cast from %s to %s is not supported in CTFE",
1956 val
->type
->toChars(), e
->type
->toChars());
1957 result
= CTFEExp::cantexp
;
1961 const dinteger_t sz
= pointee
->size();
1962 dinteger_t indx
= e
->offset
/ sz
;
1963 assert(sz
* indx
== e
->offset
);
1964 Expression
*aggregate
= NULL
;
1965 if (val
->op
== TOKarrayliteral
|| val
->op
== TOKstring
)
1969 else if (val
->op
== TOKslice
)
1971 aggregate
= ((SliceExp
*)val
)->e1
;
1973 Expression
*lwr
= interpret(&uelwr
, ((SliceExp
*)val
)->lwr
, istate
);
1974 indx
+= lwr
->toInteger();
1978 // Create a CTFE pointer &aggregate[ofs]
1979 IntegerExp
*ofs
= new IntegerExp(e
->loc
, indx
, Type::tsize_t
);
1980 IndexExp
*ei
= new IndexExp(e
->loc
, aggregate
, ofs
);
1981 ei
->type
= elemtype
;
1982 new(pue
) AddrExp(e
->loc
, ei
, e
->type
);
1983 result
= pue
->exp();
1987 else if (e
->offset
== 0 && isSafePointerCast(e
->var
->type
, pointee
))
1989 // Create a CTFE pointer &var
1990 VarExp
*ve
= new VarExp(e
->loc
, e
->var
);
1991 ve
->type
= e
->var
->type
;
1992 new(pue
) AddrExp(e
->loc
, ve
, e
->type
);
1993 result
= pue
->exp();
1997 e
->error("cannot convert &%s to %s at compile time", e
->var
->type
->toChars(), e
->type
->toChars());
1998 result
= CTFEExp::cantexp
;
2001 void visit(AddrExp
*e
)
2003 if (e
->e1
->op
== TOKvar
&& ((VarExp
*)e
->e1
)->var
->isDataseg())
2005 // Normally this is already done by optimize()
2006 // Do it here in case optimize(WANTvalue) wasn't run before CTFE
2007 result
= new SymOffExp(e
->loc
, ((VarExp
*)e
->e1
)->var
, 0);
2008 result
->type
= e
->type
;
2011 Expression
*er
= interpret(e
->e1
, istate
, ctfeNeedLvalue
);
2012 if (er
->op
== TOKvar
&& ((VarExp
*)er
)->var
== istate
->fd
->vthis
)
2013 er
= interpret(er
, istate
);
2014 if (exceptionOrCant(er
))
2017 // Return a simplified address expression
2018 new(pue
) AddrExp(e
->loc
, er
, e
->type
);
2019 result
= pue
->exp();
2022 void visit(DelegateExp
*e
)
2024 // TODO: Really we should create a CTFE-only delegate expression
2025 // of a pointer and a funcptr.
2027 // If it is &nestedfunc, just return it
2028 // TODO: We should save the context pointer
2029 if (e
->e1
->op
== TOKvar
&& ((VarExp
*)e
->e1
)->var
== e
->func
)
2035 Expression
*er
= interpret(e
->e1
, istate
);
2036 if (exceptionOrCant(er
))
2040 // If it has already been CTFE'd, just return it
2045 new(pue
) DelegateExp(e
->loc
, er
, e
->func
, false);
2046 result
= pue
->exp();
2047 result
->type
= e
->type
;
2051 static Expression
*getVarExp(Loc loc
, InterState
*istate
, Declaration
*d
, CtfeGoal goal
)
2053 Expression
*e
= CTFEExp::cantexp
;
2054 if (VarDeclaration
*v
= d
->isVarDeclaration())
2056 /* Magic variable __ctfe always returns true when interpreting
2058 if (v
->ident
== Id::ctfe
)
2059 return new IntegerExp(loc
, 1, Type::tbool
);
2061 if (!v
->originalType
&& v
->_scope
) // semantic() not yet run
2063 v
->semantic (v
->_scope
);
2064 if (v
->type
->ty
== Terror
)
2065 return CTFEExp::cantexp
;
2068 if ((v
->isConst() || v
->isImmutable() || v
->storage_class
& STCmanifest
) &&
2070 v
->_init
&& !v
->isCTFE())
2074 error(loc
, "circular initialization of %s '%s'", v
->kind(), v
->toPrettyChars());
2075 return CTFEExp::cantexp
;
2080 v
->_init
= ::semantic(v
->_init
, v
->_scope
, v
->type
, INITinterpret
); // might not be run on aggregate members
2083 e
= initializerToExpression(v
->_init
, v
->type
);
2085 return CTFEExp::cantexp
;
2088 if (e
->op
== TOKconstruct
|| e
->op
== TOKblit
)
2090 AssignExp
*ae
= (AssignExp
*)e
;
2094 if (e
->op
== TOKerror
)
2096 // FIXME: Ultimately all errors should be detected in prior semantic analysis stage.
2098 else if (v
->isDataseg() || (v
->storage_class
& STCmanifest
))
2100 /* Bugzilla 14304: e is a value that is not yet owned by CTFE.
2101 * Mark as "cached", and use it directly during interpretation.
2103 e
= scrubCacheValue(v
->loc
, e
);
2104 ctfeStack
.saveGlobalConstant(v
, e
);
2109 e
= interpret(e
, istate
);
2111 if (CTFEExp::isCantExp(e
) && !global
.gag
&& !CtfeStatus::stackTraceCallsToSuppress
)
2112 errorSupplemental(loc
, "while evaluating %s.init", v
->toChars());
2113 if (exceptionOrCantInterpret(e
))
2117 else if (v
->isCTFE() && !hasValue(v
))
2119 if (v
->_init
&& v
->type
->size() != 0)
2121 if (v
->_init
->isVoidInitializer())
2123 // var should have been initialized when it was created
2124 error(loc
, "CTFE internal error: trying to access uninitialized var");
2126 return CTFEExp::cantexp
;
2128 e
= initializerToExpression(v
->_init
);
2131 e
= v
->type
->defaultInitLiteral(e
->loc
);
2133 e
= interpret(e
, istate
);
2135 else if (!(v
->isDataseg() || v
->storage_class
& STCmanifest
) && !v
->isCTFE() && !istate
)
2137 error(loc
, "variable %s cannot be read at compile time", v
->toChars());
2138 return CTFEExp::cantexp
;
2142 e
= hasValue(v
) ? getValue(v
) : NULL
;
2143 if (!e
&& !v
->isCTFE() && v
->isDataseg())
2145 error(loc
, "static variable %s cannot be read at compile time", v
->toChars());
2146 return CTFEExp::cantexp
;
2150 assert(!(v
->_init
&& v
->_init
->isVoidInitializer()));
2151 // CTFE initiated from inside a function
2152 error(loc
, "variable %s cannot be read at compile time", v
->toChars());
2153 return CTFEExp::cantexp
;
2155 if (e
->op
== TOKvoid
)
2157 VoidInitExp
*ve
= (VoidInitExp
*)e
;
2158 error(loc
, "cannot read uninitialized variable %s in ctfe", v
->toPrettyChars());
2159 errorSupplemental(ve
->var
->loc
, "%s was uninitialized and used before set", ve
->var
->toChars());
2160 return CTFEExp::cantexp
;
2162 if (goal
!= ctfeNeedLvalue
&& (v
->isRef() || v
->isOut()))
2163 e
= interpret(e
, istate
, goal
);
2166 e
= CTFEExp::cantexp
;
2168 else if (SymbolDeclaration
*s
= d
->isSymbolDeclaration())
2170 // Struct static initializers, for example
2171 e
= s
->dsym
->type
->defaultInitLiteral(loc
);
2172 if (e
->op
== TOKerror
)
2173 error(loc
, "CTFE failed because of previous errors in %s.init", s
->toChars());
2174 e
= ::semantic(e
, NULL
);
2175 if (e
->op
== TOKerror
)
2176 e
= CTFEExp::cantexp
;
2177 else // Convert NULL to CTFEExp
2178 e
= interpret(e
, istate
, goal
);
2181 error(loc
, "cannot interpret declaration %s at compile time", d
->toChars());
2185 void visit(VarExp
*e
)
2187 if (e
->var
->isFuncDeclaration())
2193 if (goal
== ctfeNeedLvalue
)
2195 VarDeclaration
*v
= e
->var
->isVarDeclaration();
2196 if (v
&& !v
->isDataseg() && !v
->isCTFE() && !istate
)
2198 e
->error("variable %s cannot be read at compile time", v
->toChars());
2199 result
= CTFEExp::cantexp
;
2202 if (v
&& !hasValue(v
))
2204 if (!v
->isCTFE() && v
->isDataseg())
2205 e
->error("static variable %s cannot be read at compile time", v
->toChars());
2206 else // CTFE initiated from inside a function
2207 e
->error("variable %s cannot be read at compile time", v
->toChars());
2208 result
= CTFEExp::cantexp
;
2211 if (v
&& (v
->storage_class
& (STCout
| STCref
)) && hasValue(v
))
2213 // Strip off the nest of ref variables
2214 Expression
*ev
= getValue(v
);
2215 if (ev
->op
== TOKvar
|| ev
->op
== TOKindex
|| ev
->op
== TOKdotvar
)
2217 result
= interpret(pue
, ev
, istate
, goal
);
2224 result
= getVarExp(e
->loc
, istate
, e
->var
, goal
);
2225 if (exceptionOrCant(result
))
2227 if ((e
->var
->storage_class
& (STCref
| STCout
)) == 0 &&
2228 e
->type
->baseElemOf()->ty
!= Tstruct
)
2230 /* Ultimately, STCref|STCout check should be enough to see the
2231 * necessity of type repainting. But currently front-end paints
2232 * non-ref struct variables by the const type.
2234 * auto foo(ref const S cs);
2236 * foo(s); // VarExp('s') will have const(S)
2238 // A VarExp may include an implicit cast. It must be done explicitly.
2239 result
= paintTypeOntoLiteral(e
->type
, result
);
2243 void visit(DeclarationExp
*e
)
2245 Dsymbol
*s
= e
->declaration
;
2246 if (VarDeclaration
*v
= s
->isVarDeclaration())
2248 if (TupleDeclaration
*td
= v
->toAlias()->isTupleDeclaration())
2252 // Reserve stack space for all tuple members
2255 for (size_t i
= 0; i
< td
->objects
->dim
; ++i
)
2257 RootObject
* o
= (*td
->objects
)[i
];
2258 Expression
*ex
= isExpression(o
);
2259 DsymbolExp
*ds
= (ex
&& ex
->op
== TOKdsymbol
) ? (DsymbolExp
*)ex
: NULL
;
2260 VarDeclaration
*v2
= ds
? ds
->s
->isVarDeclaration() : NULL
;
2262 if (v2
->isDataseg() && !v2
->isCTFE())
2269 if (ExpInitializer
*ie
= v2
->_init
->isExpInitializer())
2271 einit
= interpret(ie
->exp
, istate
, goal
);
2272 if (exceptionOrCant(einit
))
2275 else if (v2
->_init
->isVoidInitializer())
2277 einit
= voidInitLiteral(v2
->type
, v2
).copy();
2281 e
->error("declaration %s is not yet implemented in CTFE", e
->toChars());
2282 result
= CTFEExp::cantexp
;
2285 setValue(v2
, einit
);
2292 // Just ignore static variables which aren't read or written yet
2296 if (!(v
->isDataseg() || v
->storage_class
& STCmanifest
) || v
->isCTFE())
2300 if (ExpInitializer
*ie
= v
->_init
->isExpInitializer())
2302 result
= interpret(ie
->exp
, istate
, goal
);
2304 else if (v
->_init
->isVoidInitializer())
2306 result
= voidInitLiteral(v
->type
, v
).copy();
2307 // There is no AssignExp for void initializers,
2309 setValue(v
, result
);
2313 e
->error("declaration %s is not yet implemented in CTFE", e
->toChars());
2314 result
= CTFEExp::cantexp
;
2317 else if (v
->type
->size() == 0)
2319 // Zero-length arrays don't need an initializer
2320 result
= v
->type
->defaultInitLiteral(e
->loc
);
2324 e
->error("variable %s cannot be modified at compile time", v
->toChars());
2325 result
= CTFEExp::cantexp
;
2329 if (s
->isAttribDeclaration() ||
2330 s
->isTemplateMixin() ||
2331 s
->isTupleDeclaration())
2333 // Check for static struct declarations, which aren't executable
2334 AttribDeclaration
*ad
= e
->declaration
->isAttribDeclaration();
2335 if (ad
&& ad
->decl
&& ad
->decl
->dim
== 1)
2337 Dsymbol
*sparent
= (*ad
->decl
)[0];
2338 if (sparent
->isAggregateDeclaration() ||
2339 sparent
->isTemplateDeclaration() ||
2340 sparent
->isAliasDeclaration())
2343 return; // static (template) struct declaration. Nothing to do.
2347 // These can be made to work, too lazy now
2348 e
->error("declaration %s is not yet implemented in CTFE", e
->toChars());
2349 result
= CTFEExp::cantexp
;
2353 // Others should not contain executable code, so are trivial to evaluate
2357 void visit(TypeidExp
*e
)
2364 if (Expression
*ex
= isExpression(e
->obj
))
2366 result
= interpret(ex
, istate
);
2367 if (exceptionOrCant(ex
))
2370 if (result
->op
== TOKnull
)
2372 e
->error("null pointer dereference evaluating typeid. '%s' is null", ex
->toChars());
2373 result
= CTFEExp::cantexp
;
2376 if (result
->op
!= TOKclassreference
)
2378 e
->error("CTFE internal error: determining classinfo");
2379 result
= CTFEExp::cantexp
;
2383 ClassDeclaration
*cd
= ((ClassReferenceExp
*)result
)->originalClass();
2386 new(pue
) TypeidExp(e
->loc
, cd
->type
);
2387 result
= pue
->exp();
2388 result
->type
= e
->type
;
2391 visit((Expression
*)e
);
2394 void visit(TupleExp
*e
)
2396 if (exceptionOrCant(interpret(e
->e0
, istate
, ctfeNeedNothing
)))
2399 Expressions
*expsx
= e
->exps
;
2400 for (size_t i
= 0; i
< expsx
->dim
; i
++)
2402 Expression
*exp
= (*expsx
)[i
];
2403 Expression
*ex
= interpret(exp
, istate
);
2404 if (exceptionOrCant(ex
))
2407 // A tuple of assignments can contain void (Bug 5676).
2408 if (goal
== ctfeNeedNothing
)
2410 if (ex
->op
== TOKvoidexp
)
2412 e
->error("CTFE internal error: void element %s in tuple", exp
->toChars());
2416 /* If any changes, do Copy On Write
2420 expsx
= copyArrayOnWrite(expsx
, e
->exps
);
2424 if (expsx
!= e
->exps
)
2426 expandTuples(expsx
);
2427 new(pue
) TupleExp(e
->loc
, expsx
);
2428 result
= pue
->exp();
2429 result
->type
= new TypeTuple(expsx
);
2435 void visit(ArrayLiteralExp
*e
)
2437 if (e
->ownedByCtfe
>= OWNEDctfe
) // We've already interpreted all the elements
2443 Type
*tn
= e
->type
->toBasetype()->nextOf()->toBasetype();
2444 bool wantCopy
= (tn
->ty
== Tsarray
|| tn
->ty
== Tstruct
);
2446 Expression
*basis
= interpret(e
->basis
, istate
);
2447 if (exceptionOrCant(basis
))
2450 Expressions
*expsx
= e
->elements
;
2451 size_t dim
= expsx
? expsx
->dim
: 0;
2452 for (size_t i
= 0; i
< dim
; i
++)
2454 Expression
*exp
= (*expsx
)[i
];
2458 ex
= copyLiteral(basis
).copy();
2462 // segfault bug 6250
2463 assert(exp
->op
!= TOKindex
|| ((IndexExp
*)exp
)->e1
!= e
);
2465 ex
= interpret(exp
, istate
);
2466 if (exceptionOrCant(ex
))
2469 /* Each elements should have distinct CFE memory.
2471 * int[1][] pieces = [z,z]; // here
2474 ex
= copyLiteral(ex
).copy();
2477 /* If any changes, do Copy On Write
2481 expsx
= copyArrayOnWrite(expsx
, e
->elements
);
2486 if (expsx
!= e
->elements
)
2488 // todo: all tuple expansions should go in semantic phase.
2489 expandTuples(expsx
);
2490 if (expsx
->dim
!= dim
)
2492 e
->error("CTFE internal error: invalid array literal");
2493 result
= CTFEExp::cantexp
;
2496 new(pue
) ArrayLiteralExp(e
->loc
, basis
, expsx
);
2497 ArrayLiteralExp
*ale
= (ArrayLiteralExp
*)pue
->exp();
2498 ale
->type
= e
->type
;
2499 ale
->ownedByCtfe
= OWNEDctfe
;
2502 else if (((TypeNext
*)e
->type
)->next
->mod
& (MODconst
| MODimmutable
))
2504 // If it's immutable, we don't need to dup it
2508 result
= copyLiteral(e
).copy();
2511 void visit(AssocArrayLiteralExp
*e
)
2513 if (e
->ownedByCtfe
>= OWNEDctfe
) // We've already interpreted all the elements
2519 Expressions
*keysx
= e
->keys
;
2520 Expressions
*valuesx
= e
->values
;
2521 for (size_t i
= 0; i
< keysx
->dim
; i
++)
2523 Expression
*ekey
= (*keysx
)[i
];
2524 Expression
*evalue
= (*valuesx
)[i
];
2526 Expression
*ek
= interpret(ekey
, istate
);
2527 if (exceptionOrCant(ek
))
2529 Expression
*ev
= interpret(evalue
, istate
);
2530 if (exceptionOrCant(ev
))
2533 /* If any changes, do Copy On Write
2538 keysx
= copyArrayOnWrite(keysx
, e
->keys
);
2539 valuesx
= copyArrayOnWrite(valuesx
, e
->values
);
2544 if (keysx
!= e
->keys
)
2545 expandTuples(keysx
);
2546 if (valuesx
!= e
->values
)
2547 expandTuples(valuesx
);
2548 if (keysx
->dim
!= valuesx
->dim
)
2550 e
->error("CTFE internal error: invalid AA");
2551 result
= CTFEExp::cantexp
;
2555 /* Remove duplicate keys
2557 for (size_t i
= 1; i
< keysx
->dim
; i
++)
2559 Expression
*ekey
= (*keysx
)[i
- 1];
2560 for (size_t j
= i
; j
< keysx
->dim
; j
++)
2562 Expression
*ekey2
= (*keysx
)[j
];
2563 if (!ctfeEqual(e
->loc
, TOKequal
, ekey
, ekey2
))
2567 keysx
= copyArrayOnWrite(keysx
, e
->keys
);
2568 valuesx
= copyArrayOnWrite(valuesx
, e
->values
);
2569 keysx
->remove(i
- 1);
2570 valuesx
->remove(i
- 1);
2572 i
-= 1; // redo the i'th iteration
2577 if (keysx
!= e
->keys
||
2578 valuesx
!= e
->values
)
2580 assert(keysx
!= e
->keys
&&
2581 valuesx
!= e
->values
);
2582 AssocArrayLiteralExp
*ae
= new AssocArrayLiteralExp(e
->loc
, keysx
, valuesx
);
2584 ae
->ownedByCtfe
= OWNEDctfe
;
2588 result
= copyLiteral(e
).copy();
2591 void visit(StructLiteralExp
*e
)
2593 if (e
->ownedByCtfe
>= OWNEDctfe
)
2599 size_t dim
= e
->elements
? e
->elements
->dim
: 0;
2600 Expressions
*expsx
= e
->elements
;
2602 if (dim
!= e
->sd
->fields
.dim
)
2604 // guaranteed by AggregateDeclaration.fill and TypeStruct.defaultInitLiteral
2605 assert(e
->sd
->isNested() && dim
== e
->sd
->fields
.dim
- 1);
2607 /* If a nested struct has no initialized hidden pointer,
2608 * set it to null to match the runtime behaviour.
2610 NullExp
*ne
= new NullExp(e
->loc
);
2611 ne
->type
= e
->sd
->vthis
->type
;
2613 expsx
= copyArrayOnWrite(expsx
, e
->elements
);
2617 assert(dim
== e
->sd
->fields
.dim
);
2619 for (size_t i
= 0; i
< dim
; i
++)
2621 VarDeclaration
*v
= e
->sd
->fields
[i
];
2622 Expression
*exp
= (*expsx
)[i
];
2623 Expression
*ex
= NULL
;
2626 ex
= voidInitLiteral(v
->type
, v
).copy();
2630 ex
= interpret(exp
, istate
);
2631 if (exceptionOrCant(ex
))
2633 if ((v
->type
->ty
!= ex
->type
->ty
) && v
->type
->ty
== Tsarray
)
2635 // Block assignment from inside struct literals
2636 TypeSArray
*tsa
= (TypeSArray
*)v
->type
;
2637 size_t len
= (size_t)tsa
->dim
->toInteger();
2638 ex
= createBlockDuplicatedArrayLiteral(ex
->loc
, v
->type
, ex
, len
);
2642 /* If any changes, do Copy On Write
2646 expsx
= copyArrayOnWrite(expsx
, e
->elements
);
2651 if (expsx
!= e
->elements
)
2653 expandTuples(expsx
);
2654 if (expsx
->dim
!= e
->sd
->fields
.dim
)
2656 e
->error("CTFE internal error: invalid struct literal");
2657 result
= CTFEExp::cantexp
;
2660 new(pue
) StructLiteralExp(e
->loc
, e
->sd
, expsx
);
2661 StructLiteralExp
*sle
= (StructLiteralExp
*)pue
->exp();
2662 sle
->type
= e
->type
;
2663 sle
->ownedByCtfe
= OWNEDctfe
;
2664 sle
->origin
= e
->origin
;
2668 result
= copyLiteral(e
).copy();
2671 // Create an array literal of type 'newtype' with dimensions given by
2672 // 'arguments'[argnum..$]
2673 static Expression
*recursivelyCreateArrayLiteral(Loc loc
, Type
*newtype
, InterState
*istate
,
2674 Expressions
*arguments
, int argnum
)
2676 Expression
*lenExpr
= interpret((*arguments
)[argnum
], istate
);
2677 if (exceptionOrCantInterpret(lenExpr
))
2679 size_t len
= (size_t)(lenExpr
->toInteger());
2680 Type
*elemType
= ((TypeArray
*)newtype
)->next
;
2681 if (elemType
->ty
== Tarray
&& argnum
< (int)arguments
->dim
- 1)
2683 Expression
*elem
= recursivelyCreateArrayLiteral(loc
, elemType
, istate
,
2684 arguments
, argnum
+ 1);
2685 if (exceptionOrCantInterpret(elem
))
2688 Expressions
*elements
= new Expressions();
2689 elements
->setDim(len
);
2690 for (size_t i
= 0; i
< len
; i
++)
2691 (*elements
)[i
] = copyLiteral(elem
).copy();
2692 ArrayLiteralExp
*ae
= new ArrayLiteralExp(loc
, elements
);
2694 ae
->ownedByCtfe
= OWNEDctfe
;
2697 assert(argnum
== (int)arguments
->dim
- 1);
2698 if (elemType
->ty
== Tchar
|| elemType
->ty
== Twchar
|| elemType
->ty
== Tdchar
)
2700 const unsigned ch
= (unsigned)elemType
->defaultInitLiteral(loc
)->toInteger();
2701 const unsigned char sz
= (unsigned char)elemType
->size();
2702 return createBlockDuplicatedStringLiteral(loc
, newtype
, ch
, len
, sz
);
2706 Expression
*el
= interpret(elemType
->defaultInitLiteral(loc
), istate
);
2707 return createBlockDuplicatedArrayLiteral(loc
, newtype
, el
, len
);
2711 void visit(NewExp
*e
)
2715 e
->error("member allocators not supported by CTFE");
2716 result
= CTFEExp::cantexp
;
2720 result
= interpret(e
->argprefix
, istate
, ctfeNeedNothing
);
2721 if (exceptionOrCant(result
))
2724 if (e
->newtype
->ty
== Tarray
&& e
->arguments
)
2726 result
= recursivelyCreateArrayLiteral(e
->loc
, e
->newtype
, istate
, e
->arguments
, 0);
2729 if (e
->newtype
->toBasetype()->ty
== Tstruct
)
2733 Expression
*se
= e
->newtype
->defaultInitLiteral(e
->loc
);
2734 se
= interpret(se
, istate
);
2735 if (exceptionOrCant(se
))
2737 result
= interpretFunction(e
->member
, istate
, e
->arguments
, se
);
2739 // Repaint as same as CallExp::interpret() does.
2740 result
->loc
= e
->loc
;
2744 StructDeclaration
*sd
= ((TypeStruct
*)e
->newtype
->toBasetype())->sym
;
2745 Expressions
*exps
= new Expressions();
2746 exps
->reserve(sd
->fields
.dim
);
2749 exps
->setDim(e
->arguments
->dim
);
2750 for (size_t i
= 0; i
< exps
->dim
; i
++)
2752 Expression
*ex
= (*e
->arguments
)[i
];
2753 ex
= interpret(ex
, istate
);
2754 if (exceptionOrCant(ex
))
2759 sd
->fill(e
->loc
, exps
, false);
2761 StructLiteralExp
*se
= new StructLiteralExp(e
->loc
, sd
, exps
, e
->newtype
);
2762 se
->type
= e
->newtype
;
2763 se
->ownedByCtfe
= OWNEDctfe
;
2764 result
= interpret(se
, istate
);
2766 if (exceptionOrCant(result
))
2768 new(pue
) AddrExp(e
->loc
, result
, e
->type
);
2769 result
= pue
->exp();
2772 if (e
->newtype
->toBasetype()->ty
== Tclass
)
2774 ClassDeclaration
*cd
= ((TypeClass
*)e
->newtype
->toBasetype())->sym
;
2775 size_t totalFieldCount
= 0;
2776 for (ClassDeclaration
*c
= cd
; c
; c
= c
->baseClass
)
2777 totalFieldCount
+= c
->fields
.dim
;
2778 Expressions
*elems
= new Expressions
;
2779 elems
->setDim(totalFieldCount
);
2780 size_t fieldsSoFar
= totalFieldCount
;
2781 for (ClassDeclaration
*c
= cd
; c
; c
= c
->baseClass
)
2783 fieldsSoFar
-= c
->fields
.dim
;
2784 for (size_t i
= 0; i
< c
->fields
.dim
; i
++)
2786 VarDeclaration
*v
= c
->fields
[i
];
2789 e
->error("circular reference to '%s'", v
->toPrettyChars());
2790 result
= CTFEExp::cantexp
;
2796 if (v
->_init
->isVoidInitializer())
2797 m
= voidInitLiteral(v
->type
, v
).copy();
2799 m
= v
->getConstInitializer(true);
2802 m
= v
->type
->defaultInitLiteral(e
->loc
);
2803 if (exceptionOrCant(m
))
2805 (*elems
)[fieldsSoFar
+i
] = copyLiteral(m
).copy();
2808 // Hack: we store a ClassDeclaration instead of a StructDeclaration.
2809 // We probably won't get away with this.
2810 StructLiteralExp
*se
= new StructLiteralExp(e
->loc
, (StructDeclaration
*)cd
, elems
, e
->newtype
);
2811 se
->ownedByCtfe
= OWNEDctfe
;
2812 Expression
*eref
= new ClassReferenceExp(e
->loc
, se
, e
->type
);
2816 if (!e
->member
->fbody
)
2818 Expression
*ctorfail
= evaluateIfBuiltin(istate
, e
->loc
, e
->member
, e
->arguments
, eref
);
2821 if (exceptionOrCant(ctorfail
))
2826 e
->member
->error("%s cannot be constructed at compile time, because the constructor has no available source code", e
->newtype
->toChars());
2827 result
= CTFEExp::cantexp
;
2830 Expression
*ctorfail
= interpretFunction(e
->member
, istate
, e
->arguments
, eref
);
2831 if (exceptionOrCant(ctorfail
))
2834 /* Bugzilla 14465: Repaint the loc, because a super() call
2835 * in the constructor modifies the loc of ClassReferenceExp
2836 * in CallExp::interpret().
2843 if (e
->newtype
->toBasetype()->isscalar())
2846 if (e
->arguments
&& e
->arguments
->dim
)
2847 newval
= (*e
->arguments
)[0];
2849 newval
= e
->newtype
->defaultInitLiteral(e
->loc
);
2850 newval
= interpret(newval
, istate
);
2851 if (exceptionOrCant(newval
))
2854 // Create a CTFE pointer &[newval][0]
2855 Expressions
*elements
= new Expressions();
2856 elements
->setDim(1);
2857 (*elements
)[0] = newval
;
2858 ArrayLiteralExp
*ae
= new ArrayLiteralExp(e
->loc
, elements
);
2859 ae
->type
= e
->newtype
->arrayOf();
2860 ae
->ownedByCtfe
= OWNEDctfe
;
2862 IndexExp
*ei
= new IndexExp(e
->loc
, ae
, new IntegerExp(Loc(), 0, Type::tsize_t
));
2863 ei
->type
= e
->newtype
;
2864 new(pue
) AddrExp(e
->loc
, ei
, e
->type
);
2865 result
= pue
->exp();
2868 e
->error("cannot interpret %s at compile time", e
->toChars());
2869 result
= CTFEExp::cantexp
;
2872 void visit(UnaExp
*e
)
2875 Expression
*e1
= interpret(&ue
, e
->e1
, istate
);
2876 if (exceptionOrCant(e1
))
2880 case TOKneg
: *pue
= Neg(e
->type
, e1
); break;
2881 case TOKtilde
: *pue
= Com(e
->type
, e1
); break;
2882 case TOKnot
: *pue
= Not(e
->type
, e1
); break;
2883 case TOKvector
: result
= e
; return; // do nothing
2886 result
= (*pue
).exp();
2889 void visit(DotTypeExp
*e
)
2892 Expression
*e1
= interpret(&ue
, e
->e1
, istate
);
2893 if (exceptionOrCant(e1
))
2897 result
= e
; // optimize: reuse this CTFE reference
2900 DotTypeExp
*edt
= (DotTypeExp
*)e
->copy();
2901 edt
->e1
= (e1
== ue
.exp()) ? e1
->copy() : e1
; // don't return pointer to ue
2906 bool evalOperand(UnionExp
*pue
, Expression
*e
, Expression
*ex
, Expression
*&er
)
2908 er
= interpret(pue
, ex
, istate
);
2909 if (exceptionOrCant(er
))
2911 if (er
->isConst() != 1)
2913 if (er
->op
== TOKarrayliteral
)
2914 // Until we get it to work, issue a reasonable error message
2915 e
->error("cannot interpret array literal expression %s at compile time", e
->toChars());
2917 e
->error("CTFE internal error: non-constant value %s", ex
->toChars());
2918 result
= CTFEExp::cantexp
;
2924 void interpretCommon(BinExp
*e
, fp_t fp
)
2926 if (e
->e1
->type
->ty
== Tpointer
&& e
->e2
->type
->ty
== Tpointer
&& e
->op
== TOKmin
)
2929 Expression
*e1
= interpret(&ue1
, e
->e1
, istate
);
2930 if (exceptionOrCant(e1
))
2933 Expression
*e2
= interpret(&ue2
, e
->e2
, istate
);
2934 if (exceptionOrCant(e2
))
2936 *pue
= pointerDifference(e
->loc
, e
->type
, e1
, e2
);
2937 result
= (*pue
).exp();
2940 if (e
->e1
->type
->ty
== Tpointer
&& e
->e2
->type
->isintegral())
2943 Expression
*e1
= interpret(&ue1
, e
->e1
, istate
);
2944 if (exceptionOrCant(e1
))
2947 Expression
*e2
= interpret(&ue2
, e
->e2
, istate
);
2948 if (exceptionOrCant(e2
))
2950 *pue
= pointerArithmetic(e
->loc
, e
->op
, e
->type
, e1
, e2
);
2951 result
= (*pue
).exp();
2954 if (e
->e2
->type
->ty
== Tpointer
&& e
->e1
->type
->isintegral() && e
->op
== TOKadd
)
2957 Expression
*e1
= interpret(&ue1
, e
->e1
, istate
);
2958 if (exceptionOrCant(e1
))
2961 Expression
*e2
= interpret(&ue2
, e
->e2
, istate
);
2962 if (exceptionOrCant(e2
))
2964 *pue
= pointerArithmetic(e
->loc
, e
->op
, e
->type
, e2
, e1
);
2965 result
= (*pue
).exp();
2968 if (e
->e1
->type
->ty
== Tpointer
|| e
->e2
->type
->ty
== Tpointer
)
2970 e
->error("pointer expression %s cannot be interpreted at compile time", e
->toChars());
2971 result
= CTFEExp::cantexp
;
2977 if (!evalOperand(&ue1
, e
, e
->e1
, e1
))
2981 if (!evalOperand(&ue2
, e
, e
->e2
, e2
))
2984 if (e
->op
== TOKshr
|| e
->op
== TOKshl
|| e
->op
== TOKushr
)
2986 const sinteger_t i2
= e2
->toInteger();
2987 const d_uns64 sz
= e1
->type
->size() * 8;
2988 if (i2
< 0 || (d_uns64
)i2
>= sz
)
2990 e
->error("shift by %lld is outside the range 0..%llu", i2
, (ulonglong
)sz
- 1);
2991 result
= CTFEExp::cantexp
;
2995 *pue
= (*fp
)(e
->loc
, e
->type
, e1
, e2
);
2996 result
= (*pue
).exp();
2997 if (CTFEExp::isCantExp(result
))
2998 e
->error("%s cannot be interpreted at compile time", e
->toChars());
3001 void interpretCompareCommon(BinExp
*e
, fp2_t fp
)
3005 if (e
->e1
->type
->ty
== Tpointer
&& e
->e2
->type
->ty
== Tpointer
)
3007 Expression
*e1
= interpret(&ue1
, e
->e1
, istate
);
3008 if (exceptionOrCant(e1
))
3010 Expression
*e2
= interpret(&ue2
, e
->e2
, istate
);
3011 if (exceptionOrCant(e2
))
3013 //printf("e1 = %s %s, e2 = %s %s\n", e1->type->toChars(), e1->toChars(), e2->type->toChars(), e2->toChars());
3014 dinteger_t ofs1
, ofs2
;
3015 Expression
*agg1
= getAggregateFromPointer(e1
, &ofs1
);
3016 Expression
*agg2
= getAggregateFromPointer(e2
, &ofs2
);
3017 //printf("agg1 = %p %s, agg2 = %p %s\n", agg1, agg1->toChars(), agg2, agg2->toChars());
3018 const int cmp
= comparePointers(e
->op
, agg1
, ofs1
, agg2
, ofs2
);
3021 char dir
= (e
->op
== TOKgt
|| e
->op
== TOKge
) ? '<' : '>';
3022 e
->error("the ordering of pointers to unrelated memory blocks is indeterminate in CTFE."
3023 " To check if they point to the same memory block, use both > and < inside && or ||, "
3024 "eg (%s && %s %c= %s + 1)",
3025 e
->toChars(), e
->e1
->toChars(), dir
, e
->e2
->toChars());
3026 result
= CTFEExp::cantexp
;
3029 new(pue
) IntegerExp(e
->loc
, cmp
, e
->type
);
3030 result
= (*pue
).exp();
3033 Expression
*e1
= interpret(&ue1
, e
->e1
, istate
);
3034 if (exceptionOrCant(e1
))
3036 if (!isCtfeComparable(e1
))
3038 e
->error("cannot compare %s at compile time", e1
->toChars());
3039 result
= CTFEExp::cantexp
;
3042 Expression
*e2
= interpret(&ue2
, e
->e2
, istate
);
3043 if (exceptionOrCant(e2
))
3045 if (!isCtfeComparable(e2
))
3047 e
->error("cannot compare %s at compile time", e2
->toChars());
3048 result
= CTFEExp::cantexp
;
3051 const int cmp
= (*fp
)(e
->loc
, e
->op
, e1
, e2
);
3052 new(pue
) IntegerExp(e
->loc
, cmp
, e
->type
);
3053 result
= (*pue
).exp();
3056 void visit(BinExp
*e
)
3060 case TOKadd
: interpretCommon(e
, &Add
); return;
3061 case TOKmin
: interpretCommon(e
, &Min
); return;
3062 case TOKmul
: interpretCommon(e
, &Mul
); return;
3063 case TOKdiv
: interpretCommon(e
, &Div
); return;
3064 case TOKmod
: interpretCommon(e
, &Mod
); return;
3065 case TOKshl
: interpretCommon(e
, &Shl
); return;
3066 case TOKshr
: interpretCommon(e
, &Shr
); return;
3067 case TOKushr
: interpretCommon(e
, &Ushr
); return;
3068 case TOKand
: interpretCommon(e
, &And
); return;
3069 case TOKor
: interpretCommon(e
, &Or
); return;
3070 case TOKxor
: interpretCommon(e
, &Xor
); return;
3071 case TOKpow
: interpretCommon(e
, &Pow
); return;
3074 interpretCompareCommon(e
, &ctfeEqual
);
3077 case TOKnotidentity
:
3078 interpretCompareCommon(e
, &ctfeIdentity
);
3084 interpretCompareCommon(e
, &ctfeCmp
);
3087 printf("be = '%s' %s at [%s]\n", Token::toChars(e
->op
), e
->toChars(), e
->loc
.toChars());
3093 /* Helper functions for BinExp::interpretAssignCommon
3096 // Returns the variable which is eventually modified, or NULL if an rvalue.
3097 // thisval is the current value of 'this'.
3098 static VarDeclaration
*findParentVar(Expression
*e
)
3102 if (e
->op
== TOKvar
)
3104 if (e
->op
== TOKindex
)
3105 e
= ((IndexExp
*)e
)->e1
;
3106 else if (e
->op
== TOKdotvar
)
3107 e
= ((DotVarExp
*)e
)->e1
;
3108 else if (e
->op
== TOKdotti
)
3109 e
= ((DotTemplateInstanceExp
*)e
)->e1
;
3110 else if (e
->op
== TOKslice
)
3111 e
= ((SliceExp
*)e
)->e1
;
3115 VarDeclaration
*v
= ((VarExp
*)e
)->var
->isVarDeclaration();
3120 void interpretAssignCommon(BinExp
*e
, fp_t fp
, int post
= 0)
3122 result
= CTFEExp::cantexp
;
3123 Expression
*e1
= e
->e1
;
3126 e
->error("value of %s is not known at compile time", e1
->toChars());
3130 ++CtfeStatus::numAssignments
;
3132 /* Before we begin, we need to know if this is a reference assignment
3133 * (dynamic array, AA, or class) or a value assignment.
3134 * Determining this for slice assignments are tricky: we need to know
3135 * if it is a block assignment (a[] = e) rather than a direct slice
3136 * assignment (a[] = b[]). Note that initializers of multi-dimensional
3137 * static arrays can have 2D block assignments (eg, int[7][7] x = 6;).
3138 * So we need to recurse to determine if it is a block assignment.
3140 bool isBlockAssignment
= false;
3141 if (e1
->op
== TOKslice
)
3143 // a[] = e can have const e. So we compare the naked types.
3144 Type
*tdst
= e1
->type
->toBasetype();
3145 Type
*tsrc
= e
->e2
->type
->toBasetype();
3146 while (tdst
->ty
== Tsarray
|| tdst
->ty
== Tarray
)
3148 tdst
= ((TypeArray
*)tdst
)->next
->toBasetype();
3149 if (tsrc
->equivalent(tdst
))
3151 isBlockAssignment
= true;
3157 // ---------------------------------------
3158 // Deal with reference assignment
3159 // ---------------------------------------
3160 // If it is a construction of a ref variable, it is a ref assignment
3161 if ((e
->op
== TOKconstruct
|| e
->op
== TOKblit
) &&
3162 (((AssignExp
*)e
)->memset
& referenceInit
))
3166 Expression
*newval
= interpret(e
->e2
, istate
, ctfeNeedLvalue
);
3167 if (exceptionOrCant(newval
))
3170 VarDeclaration
*v
= ((VarExp
*)e1
)->var
->isVarDeclaration();
3171 setValue(v
, newval
);
3173 // Get the value to return. Note that 'newval' is an Lvalue,
3174 // so if we need an Rvalue, we have to interpret again.
3175 if (goal
== ctfeNeedRvalue
)
3176 result
= interpret(newval
, istate
);
3178 result
= e1
; // VarExp is a CTFE reference
3184 while (e1
->op
== TOKcast
)
3186 CastExp
*ce
= (CastExp
*)e1
;
3191 // ---------------------------------------
3192 // Interpret left hand side
3193 // ---------------------------------------
3194 AssocArrayLiteralExp
*existingAA
= NULL
;
3195 Expression
*lastIndex
= NULL
;
3196 Expression
*oldval
= NULL
;
3197 if (e1
->op
== TOKindex
&& ((IndexExp
*)e1
)->e1
->type
->toBasetype()->ty
== Taarray
)
3199 // ---------------------------------------
3200 // Deal with AA index assignment
3201 // ---------------------------------------
3202 /* This needs special treatment if the AA doesn't exist yet.
3203 * There are two special cases:
3204 * (1) If the AA is itself an index of another AA, we may need to create
3205 * multiple nested AA literals before we can insert the new value.
3206 * (2) If the ultimate AA is null, no insertion happens at all. Instead,
3207 * we create nested AA literals, and change it into a assignment.
3209 IndexExp
*ie
= (IndexExp
*)e1
;
3210 int depth
= 0; // how many nested AA indices are there?
3211 while (ie
->e1
->op
== TOKindex
&&
3212 ((IndexExp
*)ie
->e1
)->e1
->type
->toBasetype()->ty
== Taarray
)
3214 assert(ie
->modifiable
);
3215 ie
= (IndexExp
*)ie
->e1
;
3219 // Get the AA value to be modified.
3220 Expression
*aggregate
= interpret(ie
->e1
, istate
);
3221 if (exceptionOrCant(aggregate
))
3223 if (aggregate
->op
== TOKassocarrayliteral
)
3225 existingAA
= (AssocArrayLiteralExp
*)aggregate
;
3227 // Normal case, ultimate parent AA already exists
3228 // We need to walk from the deepest index up, checking that an AA literal
3229 // already exists on each level.
3230 lastIndex
= interpret(((IndexExp
*)e1
)->e2
, istate
);
3231 lastIndex
= resolveSlice(lastIndex
); // only happens with AA assignment
3232 if (exceptionOrCant(lastIndex
))
3237 // Walk the syntax tree to find the indexExp at this depth
3238 IndexExp
*xe
= (IndexExp
*)e1
;
3239 for (int d
= 0; d
< depth
; ++d
)
3240 xe
= (IndexExp
*)xe
->e1
;
3242 Expression
*ekey
= interpret(xe
->e2
, istate
);
3243 if (exceptionOrCant(ekey
))
3246 ekey
= resolveSlice(ekey
, &ekeyTmp
); // only happens with AA assignment
3248 // Look up this index in it up in the existing AA, to get the next level of AA.
3249 AssocArrayLiteralExp
*newAA
= (AssocArrayLiteralExp
*)findKeyInAA(e
->loc
, existingAA
, ekey
);
3250 if (exceptionOrCant(newAA
))
3254 // Doesn't exist yet, create an empty AA...
3255 Expressions
*keysx
= new Expressions();
3256 Expressions
*valuesx
= new Expressions();
3257 newAA
= new AssocArrayLiteralExp(e
->loc
, keysx
, valuesx
);
3258 newAA
->type
= xe
->type
;
3259 newAA
->ownedByCtfe
= OWNEDctfe
;
3260 //... and insert it into the existing AA.
3261 existingAA
->keys
->push(ekey
);
3262 existingAA
->values
->push(newAA
);
3270 oldval
= findKeyInAA(e
->loc
, existingAA
, lastIndex
);
3272 oldval
= copyLiteral(e
->e1
->type
->defaultInitLiteral(e
->loc
)).copy();
3277 /* The AA is currently null. 'aggregate' is actually a reference to
3278 * whatever contains it. It could be anything: var, dotvarexp, ...
3279 * We rewrite the assignment from:
3280 * aa[i][j] op= newval;
3282 * aa = [i:[j:T.init]];
3285 oldval
= copyLiteral(e
->e1
->type
->defaultInitLiteral(e
->loc
)).copy();
3287 Expression
*newaae
= oldval
;
3288 while (e1
->op
== TOKindex
&& ((IndexExp
*)e1
)->e1
->type
->toBasetype()->ty
== Taarray
)
3290 Expression
*ekey
= interpret(((IndexExp
*)e1
)->e2
, istate
);
3291 if (exceptionOrCant(ekey
))
3293 ekey
= resolveSlice(ekey
); // only happens with AA assignment
3294 Expressions
*keysx
= new Expressions();
3295 Expressions
*valuesx
= new Expressions();
3297 valuesx
->push(newaae
);
3298 AssocArrayLiteralExp
*aae
= new AssocArrayLiteralExp(e
->loc
, keysx
, valuesx
);
3299 aae
->type
= ((IndexExp
*)e1
)->e1
->type
;
3300 aae
->ownedByCtfe
= OWNEDctfe
;
3307 e1
= ((IndexExp
*)e1
)->e1
;
3310 // We must set to aggregate with newaae
3311 e1
= interpret(e1
, istate
, ctfeNeedLvalue
);
3312 if (exceptionOrCant(e1
))
3314 e1
= assignToLvalue(e
, e1
, newaae
);
3315 if (exceptionOrCant(e1
))
3318 assert(existingAA
&& lastIndex
);
3321 else if (e1
->op
== TOKarraylength
)
3323 oldval
= interpret(e1
, istate
);
3324 if (exceptionOrCant(oldval
))
3327 else if (e
->op
== TOKconstruct
|| e
->op
== TOKblit
)
3329 // Unless we have a simple var assignment, we're
3330 // only modifying part of the variable. So we need to make sure
3331 // that the parent variable exists.
3332 VarDeclaration
*ultimateVar
= findParentVar(e1
);
3333 if (e1
->op
== TOKvar
)
3335 VarDeclaration
*v
= ((VarExp
*)e1
)->var
->isVarDeclaration();
3337 if (v
->storage_class
& STCout
)
3340 else if (ultimateVar
&& !getValue(ultimateVar
))
3342 Expression
*ex
= interpret(ultimateVar
->type
->defaultInitLiteral(e
->loc
), istate
);
3343 if (exceptionOrCant(ex
))
3345 setValue(ultimateVar
, ex
);
3353 e1
= interpret(e1
, istate
, ctfeNeedLvalue
);
3354 if (exceptionOrCant(e1
))
3357 if (e1
->op
== TOKindex
&& ((IndexExp
*)e1
)->e1
->type
->toBasetype()->ty
== Taarray
)
3359 IndexExp
*ie
= (IndexExp
*)e1
;
3360 assert(ie
->e1
->op
== TOKassocarrayliteral
);
3361 existingAA
= (AssocArrayLiteralExp
*)ie
->e1
;
3366 // ---------------------------------------
3367 // Interpret right hand side
3368 // ---------------------------------------
3369 Expression
*newval
= interpret(e
->e2
, istate
);
3370 if (exceptionOrCant(newval
))
3372 if (e
->op
== TOKblit
&& newval
->op
== TOKint64
)
3374 Type
*tbn
= e
->type
->baseElemOf();
3375 if (tbn
->ty
== Tstruct
)
3377 /* Look for special case of struct being initialized with 0.
3379 newval
= e
->type
->defaultInitLiteral(e
->loc
);
3380 if (newval
->op
== TOKerror
)
3382 result
= CTFEExp::cantexp
;
3385 newval
= interpret(newval
, istate
); // copy and set ownedByCtfe flag
3386 if (exceptionOrCant(newval
))
3391 // ----------------------------------------------------
3392 // Deal with read-modify-write assignments.
3393 // Set 'newval' to the final assignment value
3394 // Also determine the return value (except for slice
3395 // assignments, which are more complicated)
3396 // ----------------------------------------------------
3401 // Load the left hand side after interpreting the right hand side.
3402 oldval
= interpret(e1
, istate
);
3403 if (exceptionOrCant(oldval
))
3407 if (e
->e1
->type
->ty
!= Tpointer
)
3409 // ~= can create new values (see bug 6052)
3410 if (e
->op
== TOKcatass
)
3412 // We need to dup it and repaint the type. For a dynamic array
3413 // we can skip duplication, because it gets copied later anyway.
3414 if (newval
->type
->ty
!= Tarray
)
3416 newval
= copyLiteral(newval
).copy();
3417 newval
->type
= e
->e2
->type
; // repaint type
3421 newval
= paintTypeOntoLiteral(e
->e2
->type
, newval
);
3422 newval
= resolveSlice(newval
);
3425 oldval
= resolveSlice(oldval
);
3427 newval
= (*fp
)(e
->loc
, e
->type
, oldval
, newval
).copy();
3429 else if (e
->e2
->type
->isintegral() &&
3430 (e
->op
== TOKaddass
||
3431 e
->op
== TOKminass
||
3432 e
->op
== TOKplusplus
||
3433 e
->op
== TOKminusminus
))
3435 newval
= pointerArithmetic(e
->loc
, e
->op
, e
->type
, oldval
, newval
).copy();
3439 e
->error("pointer expression %s cannot be interpreted at compile time", e
->toChars());
3440 result
= CTFEExp::cantexp
;
3443 if (exceptionOrCant(newval
))
3445 if (CTFEExp::isCantExp(newval
))
3446 e
->error("cannot interpret %s at compile time", e
->toChars());
3453 if (existingAA
->ownedByCtfe
!= OWNEDctfe
)
3455 e
->error("cannot modify read-only constant %s", existingAA
->toChars());
3456 result
= CTFEExp::cantexp
;
3460 //printf("\t+L%d existingAA = %s, lastIndex = %s, oldval = %s, newval = %s\n",
3461 // __LINE__, existingAA->toChars(), lastIndex->toChars(), oldval ? oldval->toChars() : NULL, newval->toChars());
3462 assignAssocArrayElement(e
->loc
, existingAA
, lastIndex
, newval
);
3464 // Determine the return value
3465 result
= ctfeCast(e
->loc
, e
->type
, e
->type
, fp
&& post
? oldval
: newval
);
3468 if (e1
->op
== TOKarraylength
)
3470 /* Change the assignment from:
3473 * arr = new_length_array; (result is n)
3476 // Determine the return value
3477 result
= ctfeCast(e
->loc
, e
->type
, e
->type
, fp
&& post
? oldval
: newval
);
3478 if (exceptionOrCant(result
))
3481 size_t oldlen
= (size_t)oldval
->toInteger();
3482 size_t newlen
= (size_t)newval
->toInteger();
3483 if (oldlen
== newlen
) // no change required -- we're done!
3486 // We have changed it into a reference assignment
3487 // Note that returnValue is still the new length.
3488 e1
= ((ArrayLengthExp
*)e1
)->e1
;
3489 Type
*t
= e1
->type
->toBasetype();
3490 if (t
->ty
!= Tarray
)
3492 e
->error("%s is not yet supported at compile time", e
->toChars());
3493 result
= CTFEExp::cantexp
;
3496 e1
= interpret(e1
, istate
, ctfeNeedLvalue
);
3497 if (exceptionOrCant(e1
))
3500 if (oldlen
!= 0) // Get the old array literal.
3501 oldval
= interpret(e1
, istate
);
3502 newval
= changeArrayLiteralLength(e
->loc
, (TypeArray
*)t
, oldval
,
3503 oldlen
, newlen
).copy();
3505 e1
= assignToLvalue(e
, e1
, newval
);
3506 if (exceptionOrCant(e1
))
3512 if (!isBlockAssignment
)
3514 newval
= ctfeCast(e
->loc
, e
->type
, e
->type
, newval
);
3515 if (exceptionOrCant(newval
))
3518 // Determine the return value
3519 if (goal
== ctfeNeedLvalue
) // Bugzilla 14371
3522 result
= ctfeCast(e
->loc
, e
->type
, e
->type
, fp
&& post
? oldval
: newval
);
3523 if (exceptionOrCant(result
))
3526 if (exceptionOrCant(newval
))
3529 /* Block assignment or element-wise assignment.
3531 if (e1
->op
== TOKslice
||
3532 e1
->op
== TOKvector
||
3533 e1
->op
== TOKarrayliteral
||
3534 e1
->op
== TOKstring
||
3535 (e1
->op
== TOKnull
&& e1
->type
->toBasetype()->ty
== Tarray
))
3537 // Note that slice assignments don't support things like ++, so
3538 // we don't need to remember 'returnValue'.
3539 result
= interpretAssignToSlice(e
, e1
, newval
, isBlockAssignment
);
3540 if (exceptionOrCant(result
))
3542 if (e
->e1
->op
== TOKslice
)
3544 Expression
*e1x
= interpret(((SliceExp
*)e
->e1
)->e1
, istate
, ctfeNeedLvalue
);
3545 if (e1x
->op
== TOKdotvar
)
3547 DotVarExp
*dve
= (DotVarExp
*)e1x
;
3548 Expression
*ex
= dve
->e1
;
3549 StructLiteralExp
*sle
= ex
->op
== TOKstructliteral
? ((StructLiteralExp
*)ex
)
3550 : ex
->op
== TOKclassreference
? ((ClassReferenceExp
*)ex
)->value
3552 VarDeclaration
*v
= dve
->var
->isVarDeclaration();
3555 e
->error("CTFE internal error: dotvar slice assignment");
3556 result
= CTFEExp::cantexp
;
3559 stompOverlappedFields(sle
, v
);
3567 /* Assignment to a CTFE reference.
3569 if (Expression
*ex
= assignToLvalue(e
, e1
, newval
))
3575 /* Set all sibling fields which overlap with v to VoidExp.
3577 void stompOverlappedFields(StructLiteralExp
*sle
, VarDeclaration
*v
)
3582 for (size_t i
= 0; i
< sle
->sd
->fields
.dim
; i
++)
3584 VarDeclaration
*v2
= sle
->sd
->fields
[i
];
3585 if (v
== v2
|| !v
->isOverlappedWith(v2
))
3587 Expression
*e
= (*sle
->elements
)[i
];
3588 if (e
->op
!= TOKvoid
)
3589 (*sle
->elements
)[i
] = voidInitLiteral(e
->type
, v
).copy();
3593 Expression
*assignToLvalue(BinExp
*e
, Expression
*e1
, Expression
*newval
)
3595 VarDeclaration
*vd
= NULL
;
3596 Expression
**payload
= NULL
; // dead-store to prevent spurious warning
3599 if (e1
->op
== TOKvar
)
3601 vd
= ((VarExp
*)e1
)->var
->isVarDeclaration();
3602 oldval
= getValue(vd
);
3604 else if (e1
->op
== TOKdotvar
)
3606 /* Assignment to member variable of the form:
3609 Expression
*ex
= ((DotVarExp
*)e1
)->e1
;
3610 StructLiteralExp
*sle
=
3611 ex
->op
== TOKstructliteral
? ((StructLiteralExp
*)ex
):
3612 ex
->op
== TOKclassreference
? ((ClassReferenceExp
*)ex
)->value
3614 VarDeclaration
*v
= ((DotVarExp
*)e1
)->var
->isVarDeclaration();
3617 e
->error("CTFE internal error: dotvar assignment");
3618 return CTFEExp::cantexp
;
3620 if (sle
->ownedByCtfe
!= OWNEDctfe
)
3622 e
->error("cannot modify read-only constant %s", sle
->toChars());
3623 return CTFEExp::cantexp
;
3626 int fieldi
= ex
->op
== TOKstructliteral
3627 ? findFieldIndexByName(sle
->sd
, v
)
3628 : ((ClassReferenceExp
*)ex
)->findFieldIndexByName(v
);
3631 e
->error("CTFE internal error: cannot find field %s in %s", v
->toChars(), ex
->toChars());
3632 return CTFEExp::cantexp
;
3634 assert(0 <= fieldi
&& fieldi
< (int)sle
->elements
->dim
);
3636 // If it's a union, set all other members of this union to void
3637 stompOverlappedFields(sle
, v
);
3639 payload
= &(*sle
->elements
)[fieldi
];
3642 else if (e1
->op
== TOKindex
)
3644 IndexExp
*ie
= (IndexExp
*)e1
;
3645 assert(ie
->e1
->type
->toBasetype()->ty
!= Taarray
);
3647 Expression
*aggregate
;
3648 uinteger_t indexToModify
;
3649 if (!resolveIndexing(ie
, istate
, &aggregate
, &indexToModify
, true))
3651 return CTFEExp::cantexp
;
3653 size_t index
= (size_t)indexToModify
;
3655 if (aggregate
->op
== TOKstring
)
3657 StringExp
*existingSE
= (StringExp
*)aggregate
;
3658 if (existingSE
->ownedByCtfe
!= OWNEDctfe
)
3660 e
->error("cannot modify read-only string literal %s", ie
->e1
->toChars());
3661 return CTFEExp::cantexp
;
3663 void *s
= existingSE
->string
;
3664 dinteger_t value
= newval
->toInteger();
3665 switch (existingSE
->sz
)
3667 case 1: (( utf8_t
*)s
)[index
] = ( utf8_t
)value
; break;
3668 case 2: ((utf16_t
*)s
)[index
] = (utf16_t
)value
; break;
3669 case 4: ((utf32_t
*)s
)[index
] = (utf32_t
)value
; break;
3670 default: assert(0); break;
3674 if (aggregate
->op
!= TOKarrayliteral
)
3676 e
->error("index assignment %s is not yet supported in CTFE ", e
->toChars());
3677 return CTFEExp::cantexp
;
3680 ArrayLiteralExp
*existingAE
= (ArrayLiteralExp
*)aggregate
;
3681 if (existingAE
->ownedByCtfe
!= OWNEDctfe
)
3683 e
->error("cannot modify read-only constant %s", existingAE
->toChars());
3684 return CTFEExp::cantexp
;
3687 payload
= &(*existingAE
->elements
)[index
];
3692 e
->error("%s cannot be evaluated at compile time", e
->toChars());
3693 return CTFEExp::cantexp
;
3696 Type
*t1b
= e1
->type
->toBasetype();
3697 bool wantCopy
= t1b
->baseElemOf()->ty
== Tstruct
;
3699 if (newval
->op
== TOKstructliteral
&& oldval
)
3701 newval
= copyLiteral(newval
).copy();
3702 assignInPlace(oldval
, newval
);
3704 else if (wantCopy
&& e
->op
== TOKassign
)
3706 // Currently postblit/destructor calls on static array are done
3707 // in the druntime internal functions so they don't appear in AST.
3708 // Therefore interpreter should handle them specially.
3711 #if 1 // todo: instead we can directly access to each elements of the slice
3712 newval
= resolveSlice(newval
);
3713 if (CTFEExp::isCantExp(newval
))
3715 e
->error("CTFE internal error: assignment %s", e
->toChars());
3716 return CTFEExp::cantexp
;
3719 assert(oldval
->op
== TOKarrayliteral
);
3720 assert(newval
->op
== TOKarrayliteral
);
3722 Expressions
*oldelems
= ((ArrayLiteralExp
*)oldval
)->elements
;
3723 Expressions
*newelems
= ((ArrayLiteralExp
*)newval
)->elements
;
3724 assert(oldelems
->dim
== newelems
->dim
);
3726 Type
*elemtype
= oldval
->type
->nextOf();
3727 for (size_t i
= 0; i
< newelems
->dim
; i
++)
3729 Expression
*oldelem
= (*oldelems
)[i
];
3730 Expression
*newelem
= paintTypeOntoLiteral(elemtype
, (*newelems
)[i
]);
3732 if (e
->e2
->isLvalue())
3734 if (Expression
*ex
= evaluatePostblit(istate
, newelem
))
3738 if (Expression
*ex
= evaluateDtor(istate
, oldelem
))
3740 (*oldelems
)[i
] = newelem
;
3745 // e1 has its own payload, so we have to create a new literal.
3747 newval
= copyLiteral(newval
).copy();
3749 if (t1b
->ty
== Tsarray
&& e
->op
== TOKconstruct
&& e
->e2
->isLvalue())
3752 if (Expression
*ex
= evaluatePostblit(istate
, newval
))
3760 setValue(vd
, oldval
);
3764 // Blit assignment should return the newly created value.
3765 if (e
->op
== TOKblit
)
3772 * Deal with assignments of the form:
3774 * dest[low..upp] = newval
3775 * where newval has already been interpreted
3777 * This could be a slice assignment or a block assignment, and
3778 * dest could be either an array literal, or a string.
3780 * Returns TOKcantexp on failure. If there are no errors,
3781 * it returns aggregate[low..upp], except that as an optimisation,
3782 * if goal == ctfeNeedNothing, it will return NULL
3784 Expression
*interpretAssignToSlice(BinExp
*e
,
3785 Expression
*e1
, Expression
*newval
, bool isBlockAssignment
)
3787 dinteger_t lowerbound
;
3788 dinteger_t upperbound
;
3790 Expression
*aggregate
;
3791 dinteger_t firstIndex
;
3793 if (e1
->op
== TOKvector
)
3794 e1
= ((VectorExp
*)e1
)->e1
;
3795 if (e1
->op
== TOKslice
)
3797 // ------------------------------
3798 // aggregate[] = newval
3799 // aggregate[low..upp] = newval
3800 // ------------------------------
3802 SliceExp
*se
= (SliceExp
*)e1
;
3803 #if 1 // should be move in interpretAssignCommon as the evaluation of e1
3804 Expression
*oldval
= interpret(se
->e1
, istate
);
3806 // Set the $ variable
3807 uinteger_t dollar
= resolveArrayLength(oldval
);
3810 Expression
*dollarExp
= new IntegerExp(e1
->loc
, dollar
, Type::tsize_t
);
3811 ctfeStack
.push(se
->lengthVar
);
3812 setValue(se
->lengthVar
, dollarExp
);
3814 Expression
*lwr
= interpret(se
->lwr
, istate
);
3815 if (exceptionOrCantInterpret(lwr
))
3818 ctfeStack
.pop(se
->lengthVar
);
3821 Expression
*upr
= interpret(se
->upr
, istate
);
3822 if (exceptionOrCantInterpret(upr
))
3825 ctfeStack
.pop(se
->lengthVar
);
3829 ctfeStack
.pop(se
->lengthVar
); // $ is defined only in [L..U]
3831 unsigned dim
= (unsigned)dollar
;
3832 lowerbound
= (int)(lwr
? lwr
->toInteger() : 0);
3833 upperbound
= (size_t)(upr
? upr
->toInteger() : dim
);
3835 if ((int)lowerbound
< 0 || dim
< upperbound
)
3837 e
->error("array bounds [0..%d] exceeded in slice [%d..%d]",
3838 dim
, lowerbound
, upperbound
);
3839 return CTFEExp::cantexp
;
3843 firstIndex
= lowerbound
;
3845 if (aggregate
->op
== TOKslice
)
3847 // Slice of a slice --> change the bounds
3848 SliceExp
*oldse
= (SliceExp
*)aggregate
;
3849 if (oldse
->upr
->toInteger() < upperbound
+ oldse
->lwr
->toInteger())
3851 e
->error("slice [%d..%d] exceeds array bounds [0..%lld]",
3852 lowerbound
, upperbound
,
3853 oldse
->upr
->toInteger() - oldse
->lwr
->toInteger());
3854 return CTFEExp::cantexp
;
3856 aggregate
= oldse
->e1
;
3857 firstIndex
= lowerbound
+ oldse
->lwr
->toInteger();
3862 if (e1
->op
== TOKarrayliteral
)
3865 upperbound
= ((ArrayLiteralExp
*)e1
)->elements
->dim
;
3867 else if (e1
->op
== TOKstring
)
3870 upperbound
= ((StringExp
*)e1
)->len
;
3872 else if (e1
->op
== TOKnull
)
3881 firstIndex
= lowerbound
;
3883 if (upperbound
== lowerbound
)
3886 // For slice assignment, we check that the lengths match.
3887 if (!isBlockAssignment
)
3889 size_t srclen
= (size_t)resolveArrayLength(newval
);
3890 if (srclen
!= (upperbound
- lowerbound
))
3892 e
->error("array length mismatch assigning [0..%d] to [%d..%d]",
3893 srclen
, lowerbound
, upperbound
);
3894 return CTFEExp::cantexp
;
3898 if (aggregate
->op
== TOKstring
)
3900 StringExp
*existingSE
= (StringExp
*)aggregate
;
3901 if (existingSE
->ownedByCtfe
!= OWNEDctfe
)
3903 e
->error("cannot modify read-only string literal %s", existingSE
->toChars());
3904 return CTFEExp::cantexp
;
3907 if (newval
->op
== TOKslice
)
3909 SliceExp
*se
= (SliceExp
*)newval
;
3910 Expression
*aggr2
= se
->e1
;
3911 const dinteger_t srclower
= se
->lwr
->toInteger();
3912 const dinteger_t srcupper
= se
->upr
->toInteger();
3914 if (aggregate
== aggr2
&&
3915 lowerbound
< srcupper
&& srclower
< upperbound
)
3917 e
->error("overlapping slice assignment [%d..%d] = [%llu..%llu]",
3918 lowerbound
, upperbound
, srclower
, srcupper
);
3919 return CTFEExp::cantexp
;
3921 #if 1 // todo: instead we can directly access to each elements of the slice
3922 Expression
*orignewval
= newval
;
3923 newval
= resolveSlice(newval
);
3924 if (CTFEExp::isCantExp(newval
))
3926 e
->error("CTFE internal error: slice %s", orignewval
->toChars());
3927 return CTFEExp::cantexp
;
3930 assert(newval
->op
!= TOKslice
);
3932 if (newval
->op
== TOKstring
)
3934 sliceAssignStringFromString((StringExp
*)existingSE
, (StringExp
*)newval
, (size_t)firstIndex
);
3937 if (newval
->op
== TOKarrayliteral
)
3939 /* Mixed slice: it was initialized as a string literal.
3940 * Now a slice of it is being set with an array literal.
3942 sliceAssignStringFromArrayLiteral(existingSE
, (ArrayLiteralExp
*)newval
, (size_t)firstIndex
);
3946 // String literal block slice assign
3947 dinteger_t value
= newval
->toInteger();
3948 void *s
= existingSE
->string
;
3949 for (size_t i
= 0; i
< upperbound
- lowerbound
; i
++)
3951 switch (existingSE
->sz
)
3953 case 1: (( utf8_t
*)s
)[(size_t)(i
+ firstIndex
)] = ( utf8_t
)value
; break;
3954 case 2: ((utf16_t
*)s
)[(size_t)(i
+ firstIndex
)] = (utf16_t
)value
; break;
3955 case 4: ((utf32_t
*)s
)[(size_t)(i
+ firstIndex
)] = (utf32_t
)value
; break;
3956 default: assert(0); break;
3959 if (goal
== ctfeNeedNothing
)
3960 return NULL
; // avoid creating an unused literal
3961 SliceExp
*retslice
= new SliceExp(e
->loc
, existingSE
,
3962 new IntegerExp(e
->loc
, firstIndex
, Type::tsize_t
),
3963 new IntegerExp(e
->loc
, firstIndex
+ upperbound
- lowerbound
, Type::tsize_t
));
3964 retslice
->type
= e
->type
;
3965 return interpret(retslice
, istate
);
3967 if (aggregate
->op
== TOKarrayliteral
)
3969 ArrayLiteralExp
*existingAE
= (ArrayLiteralExp
*)aggregate
;
3970 if (existingAE
->ownedByCtfe
!= OWNEDctfe
)
3972 e
->error("cannot modify read-only constant %s", existingAE
->toChars());
3973 return CTFEExp::cantexp
;
3976 if (newval
->op
== TOKslice
&& !isBlockAssignment
)
3978 SliceExp
*se
= (SliceExp
*)newval
;
3979 Expression
*aggr2
= se
->e1
;
3980 const dinteger_t srclower
= se
->lwr
->toInteger();
3981 const dinteger_t srcupper
= se
->upr
->toInteger();
3982 const bool wantCopy
= (newval
->type
->toBasetype()->nextOf()->baseElemOf()->ty
== Tstruct
);
3984 //printf("oldval = %p %s[%d..%u]\nnewval = %p %s[%llu..%llu] wantCopy = %d\n",
3985 // aggregate, aggregate->toChars(), lowerbound, upperbound,
3986 // aggr2, aggr2->toChars(), srclower, srcupper, wantCopy);
3989 // Currently overlapping for struct array is allowed.
3990 // The order of elements processing depends on the overlapping.
3991 // See bugzilla 14024.
3992 assert(aggr2
->op
== TOKarrayliteral
);
3993 Expressions
*oldelems
= existingAE
->elements
;
3994 Expressions
*newelems
= ((ArrayLiteralExp
*)aggr2
)->elements
;
3996 Type
*elemtype
= aggregate
->type
->nextOf();
3997 bool needsPostblit
= e
->e2
->isLvalue();
3999 if (aggregate
== aggr2
&&
4000 srclower
< lowerbound
&& lowerbound
< srcupper
)
4003 for (size_t i
= upperbound
- lowerbound
; 0 < i
--; )
4005 Expression
*oldelem
= (*oldelems
)[(size_t)(i
+ firstIndex
)];
4006 Expression
*newelem
= (*newelems
)[(size_t)(i
+ srclower
)];
4007 newelem
= copyLiteral(newelem
).copy();
4008 newelem
->type
= elemtype
;
4011 if (Expression
*x
= evaluatePostblit(istate
, newelem
))
4014 if (Expression
*x
= evaluateDtor(istate
, oldelem
))
4016 (*oldelems
)[lowerbound
+ i
] = newelem
;
4022 for (size_t i
= 0; i
< upperbound
- lowerbound
; i
++)
4024 Expression
*oldelem
= (*oldelems
)[(size_t)(i
+ firstIndex
)];
4025 Expression
*newelem
= (*newelems
)[(size_t)(i
+ srclower
)];
4026 newelem
= copyLiteral(newelem
).copy();
4027 newelem
->type
= elemtype
;
4030 if (Expression
*x
= evaluatePostblit(istate
, newelem
))
4033 if (Expression
*x
= evaluateDtor(istate
, oldelem
))
4035 (*oldelems
)[lowerbound
+ i
] = newelem
;
4040 return newval
; // oldval?
4042 if (aggregate
== aggr2
&&
4043 lowerbound
< srcupper
&& srclower
< upperbound
)
4045 e
->error("overlapping slice assignment [%d..%d] = [%llu..%llu]",
4046 lowerbound
, upperbound
, srclower
, srcupper
);
4047 return CTFEExp::cantexp
;
4049 #if 1 // todo: instead we can directly access to each elements of the slice
4050 Expression
*orignewval
= newval
;
4051 newval
= resolveSlice(newval
);
4052 if (CTFEExp::isCantExp(newval
))
4054 e
->error("CTFE internal error: slice %s", orignewval
->toChars());
4055 return CTFEExp::cantexp
;
4060 assert(newval
->op
!= TOKslice
);
4062 if (newval
->op
== TOKstring
&& !isBlockAssignment
)
4064 /* Mixed slice: it was initialized as an array literal of chars/integers.
4065 * Now a slice of it is being set with a string.
4067 sliceAssignArrayLiteralFromString(existingAE
, (StringExp
*)newval
, (size_t)firstIndex
);
4070 if (newval
->op
== TOKarrayliteral
&& !isBlockAssignment
)
4072 Expressions
*oldelems
= existingAE
->elements
;
4073 Expressions
*newelems
= ((ArrayLiteralExp
*)newval
)->elements
;
4074 Type
*elemtype
= existingAE
->type
->nextOf();
4075 bool needsPostblit
= e
->op
!= TOKblit
&& e
->e2
->isLvalue();
4076 for (size_t j
= 0; j
< newelems
->dim
; j
++)
4078 Expression
*newelem
= (*newelems
)[j
];
4079 newelem
= paintTypeOntoLiteral(elemtype
, newelem
);
4082 Expression
*x
= evaluatePostblit(istate
, newelem
);
4083 if (exceptionOrCantInterpret(x
))
4086 (*oldelems
)[(size_t)(j
+ firstIndex
)] = newelem
;
4091 /* Block assignment, initialization of static arrays
4093 * x may be a multidimensional static array. (Note that this
4094 * only happens with array literals, never with strings).
4096 struct RecursiveBlock
4104 Expression
*assignTo(ArrayLiteralExp
*ae
)
4106 return assignTo(ae
, 0, ae
->elements
->dim
);
4109 Expression
*assignTo(ArrayLiteralExp
*ae
, size_t lwr
, size_t upr
)
4111 Expressions
*w
= ae
->elements
;
4113 assert(ae
->type
->ty
== Tsarray
||
4114 ae
->type
->ty
== Tarray
);
4115 bool directblk
= ((TypeArray
*)ae
->type
)->next
->equivalent(newval
->type
);
4117 for (size_t k
= lwr
; k
< upr
; k
++)
4119 if (!directblk
&& (*w
)[k
]->op
== TOKarrayliteral
)
4121 // Multidimensional array block assign
4122 if (Expression
*ex
= assignTo((ArrayLiteralExp
*)(*w
)[k
]))
4129 else if (!needsPostblit
&& !needsDtor
)
4131 assignInPlace((*w
)[k
], newval
);
4135 Expression
*oldelem
= (*w
)[k
];
4136 Expression
*tmpelem
= needsDtor
? copyLiteral(oldelem
).copy() : NULL
;
4138 assignInPlace(oldelem
, newval
);
4142 if (Expression
*ex
= evaluatePostblit(istate
, oldelem
))
4148 if (Expression
*ex
= evaluateDtor(istate
, tmpelem
))
4157 Type
*tn
= newval
->type
->toBasetype();
4158 bool wantRef
= (tn
->ty
== Tarray
|| isAssocArray(tn
) ||tn
->ty
== Tclass
);
4159 bool cow
= newval
->op
!= TOKstructliteral
&&
4160 newval
->op
!= TOKarrayliteral
&&
4161 newval
->op
!= TOKstring
;
4162 Type
*tb
= tn
->baseElemOf();
4163 StructDeclaration
*sd
= (tb
->ty
== Tstruct
? ((TypeStruct
*)tb
)->sym
: NULL
);
4168 rb
.refCopy
= wantRef
|| cow
;
4169 rb
.needsPostblit
= sd
&& sd
->postblit
&& e
->op
!= TOKblit
&& e
->e2
->isLvalue();
4170 rb
.needsDtor
= sd
&& sd
->dtor
&& e
->op
== TOKassign
;
4172 if (Expression
*ex
= rb
.assignTo(existingAE
, lowerbound
, upperbound
))
4175 if (goal
== ctfeNeedNothing
)
4176 return NULL
; // avoid creating an unused literal
4177 SliceExp
*retslice
= new SliceExp(e
->loc
, existingAE
,
4178 new IntegerExp(e
->loc
, firstIndex
, Type::tsize_t
),
4179 new IntegerExp(e
->loc
, firstIndex
+ upperbound
- lowerbound
, Type::tsize_t
));
4180 retslice
->type
= e
->type
;
4181 return interpret(retslice
, istate
);
4184 e
->error("slice operation %s = %s cannot be evaluated at compile time",
4185 e1
->toChars(), newval
->toChars());
4186 return CTFEExp::cantexp
;
4189 void visit(AssignExp
*e
)
4191 interpretAssignCommon(e
, NULL
);
4194 void visit(BinAssignExp
*e
)
4198 case TOKaddass
: interpretAssignCommon(e
, &Add
); return;
4199 case TOKminass
: interpretAssignCommon(e
, &Min
); return;
4200 case TOKcatass
: interpretAssignCommon(e
, &ctfeCat
); return;
4201 case TOKmulass
: interpretAssignCommon(e
, &Mul
); return;
4202 case TOKdivass
: interpretAssignCommon(e
, &Div
); return;
4203 case TOKmodass
: interpretAssignCommon(e
, &Mod
); return;
4204 case TOKshlass
: interpretAssignCommon(e
, &Shl
); return;
4205 case TOKshrass
: interpretAssignCommon(e
, &Shr
); return;
4206 case TOKushrass
: interpretAssignCommon(e
, &Ushr
); return;
4207 case TOKandass
: interpretAssignCommon(e
, &And
); return;
4208 case TOKorass
: interpretAssignCommon(e
, &Or
); return;
4209 case TOKxorass
: interpretAssignCommon(e
, &Xor
); return;
4210 case TOKpowass
: interpretAssignCommon(e
, &Pow
); return;
4217 void visit(PostExp
*e
)
4219 if (e
->op
== TOKplusplus
)
4220 interpretAssignCommon(e
, &Add
, 1);
4222 interpretAssignCommon(e
, &Min
, 1);
4225 /* Return 1 if e is a p1 > p2 or p1 >= p2 pointer comparison;
4226 * -1 if e is a p1 < p2 or p1 <= p2 pointer comparison;
4229 static int isPointerCmpExp(Expression
*e
, Expression
**p1
, Expression
**p2
)
4232 while (e
->op
== TOKnot
)
4235 e
= ((NotExp
*)e
)->e1
;
4245 *p1
= ((BinExp
*)e
)->e1
;
4246 *p2
= ((BinExp
*)e
)->e2
;
4247 if (!(isPointer((*p1
)->type
) && isPointer((*p2
)->type
)))
4257 /** Negate a relational operator, eg >= becomes <
4259 static TOK
reverseRelation(TOK op
)
4263 case TOKge
: return TOKlt
;
4264 case TOKgt
: return TOKle
;
4265 case TOKle
: return TOKgt
;
4266 case TOKlt
: return TOKge
;
4268 return assert(0), TOKreserved
;
4272 /** If this is a four pointer relation, evaluate it, else return NULL.
4274 * This is an expression of the form (p1 > q1 && p2 < q2) or (p1 < q1 || p2 > q2)
4275 * where p1, p2 are expressions yielding pointers to memory block p,
4276 * and q1, q2 are expressions yielding pointers to memory block q.
4277 * This expression is valid even if p and q are independent memory
4278 * blocks and are therefore not normally comparable; the && form returns true
4279 * if [p1..p2] lies inside [q1..q2], and false otherwise; the || form returns
4280 * true if [p1..p2] lies outside [q1..q2], and false otherwise.
4282 * Within the expression, any ordering of p1, p2, q1, q2 is permissible;
4283 * the comparison operators can be any of >, <, <=, >=, provided that
4284 * both directions (p > q and p < q) are checked. Additionally the
4285 * relational sub-expressions can be negated, eg
4286 * (!(q1 < p1) && p2 <= q2) is valid.
4288 void interpretFourPointerRelation(BinExp
*e
)
4290 assert(e
->op
== TOKandand
|| e
->op
== TOKoror
);
4292 /* It can only be an isInside expression, if both e1 and e2 are
4293 * directional pointer comparisons.
4294 * Note that this check can be made statically; it does not depends on
4295 * any runtime values. This allows a JIT implementation to compile a
4296 * special AndAndPossiblyInside, keeping the normal AndAnd case efficient.
4299 // Save the pointer expressions and the comparison directions,
4300 // so we can use them later.
4301 Expression
*p1
= NULL
;
4302 Expression
*p2
= NULL
;
4303 Expression
*p3
= NULL
;
4304 Expression
*p4
= NULL
;
4305 int dir1
= isPointerCmpExp(e
->e1
, &p1
, &p2
);
4306 int dir2
= isPointerCmpExp(e
->e2
, &p3
, &p4
);
4307 if (dir1
== 0 || dir2
== 0)
4313 //printf("FourPointerRelation %s\n", toChars());
4315 // Evaluate the first two pointers
4316 p1
= interpret(p1
, istate
);
4317 if (exceptionOrCant(p1
))
4319 p2
= interpret(p2
, istate
);
4320 if (exceptionOrCant(p2
))
4322 dinteger_t ofs1
, ofs2
;
4323 Expression
*agg1
= getAggregateFromPointer(p1
, &ofs1
);
4324 Expression
*agg2
= getAggregateFromPointer(p2
, &ofs2
);
4326 if (!pointToSameMemoryBlock(agg1
, agg2
) &&
4327 agg1
->op
!= TOKnull
&&
4328 agg2
->op
!= TOKnull
)
4330 // Here it is either CANT_INTERPRET,
4331 // or an IsInside comparison returning false.
4332 p3
= interpret(p3
, istate
);
4333 if (CTFEExp::isCantExp(p3
))
4335 // Note that it is NOT legal for it to throw an exception!
4336 Expression
*except
= NULL
;
4337 if (exceptionOrCantInterpret(p3
))
4341 p4
= interpret(p4
, istate
);
4342 if (CTFEExp::isCantExp(p4
))
4347 if (exceptionOrCantInterpret(p4
))
4352 e
->error("comparison %s of pointers to unrelated memory blocks remains "
4353 "indeterminate at compile time "
4354 "because exception %s was thrown while evaluating %s",
4355 e
->e1
->toChars(), except
->toChars(), e
->e2
->toChars());
4356 result
= CTFEExp::cantexp
;
4359 dinteger_t ofs3
, ofs4
;
4360 Expression
*agg3
= getAggregateFromPointer(p3
, &ofs3
);
4361 Expression
*agg4
= getAggregateFromPointer(p4
, &ofs4
);
4362 // The valid cases are:
4363 // p1 > p2 && p3 > p4 (same direction, also for < && <)
4364 // p1 > p2 && p3 < p4 (different direction, also < && >)
4365 // Changing any > into >= doesnt affect the result
4366 if ((dir1
== dir2
&& pointToSameMemoryBlock(agg1
, agg4
) && pointToSameMemoryBlock(agg2
, agg3
)) ||
4367 (dir1
!= dir2
&& pointToSameMemoryBlock(agg1
, agg3
) && pointToSameMemoryBlock(agg2
, agg4
)))
4369 // it's a legal two-sided comparison
4370 result
= new IntegerExp(e
->loc
, (e
->op
== TOKandand
) ? 0 : 1, e
->type
);
4373 // It's an invalid four-pointer comparison. Either the second
4374 // comparison is in the same direction as the first, or else
4375 // more than two memory blocks are involved (either two independent
4376 // invalid comparisons are present, or else agg3 == agg4).
4377 e
->error("comparison %s of pointers to unrelated memory blocks is "
4378 "indeterminate at compile time, even when combined with %s.",
4379 e
->e1
->toChars(), e
->e2
->toChars());
4380 result
= CTFEExp::cantexp
;
4383 // The first pointer expression didn't need special treatment, so we
4384 // we need to interpret the entire expression exactly as a normal && or ||.
4385 // This is easy because we haven't evaluated e2 at all yet, and we already
4386 // know it will return a bool.
4387 // But we mustn't evaluate the pointer expressions in e1 again, in case
4388 // they have side-effects.
4390 Expression
*ex
= e
->e1
;
4391 while (ex
->op
== TOKnot
)
4394 ex
= ((NotExp
*)ex
)->e1
;
4398 cmpop
= reverseRelation(cmpop
);
4399 int cmp
= comparePointers(cmpop
, agg1
, ofs1
, agg2
, ofs2
);
4400 // We already know this is a valid comparison.
4402 if ((e
->op
== TOKandand
&& cmp
== 1) ||
4403 (e
->op
== TOKoror
&& cmp
== 0))
4405 result
= interpret(e
->e2
, istate
);
4408 result
= new IntegerExp(e
->loc
, (e
->op
== TOKandand
) ? 0 : 1, e
->type
);
4411 void visit(AndAndExp
*e
)
4413 // Check for an insidePointer expression, evaluate it if so
4414 interpretFourPointerRelation(e
);
4418 result
= interpret(e
->e1
, istate
);
4419 if (exceptionOrCant(result
))
4423 if (result
->isBool(false))
4425 else if (isTrueBool(result
))
4428 result
= interpret(&ue2
, e
->e2
, istate
);
4429 if (exceptionOrCant(result
))
4431 if (result
->op
== TOKvoidexp
)
4433 assert(e
->type
->ty
== Tvoid
);
4437 if (result
->isBool(false))
4439 else if (isTrueBool(result
))
4443 result
->error("%s does not evaluate to a boolean", result
->toChars());
4444 result
= CTFEExp::cantexp
;
4450 result
->error("%s cannot be interpreted as a boolean", result
->toChars());
4451 result
= CTFEExp::cantexp
;
4454 if (goal
!= ctfeNeedNothing
)
4456 new(pue
) IntegerExp(e
->loc
, res
, e
->type
);
4457 result
= pue
->exp();
4461 void visit(OrOrExp
*e
)
4463 // Check for an insidePointer expression, evaluate it if so
4464 interpretFourPointerRelation(e
);
4468 result
= interpret(e
->e1
, istate
);
4469 if (exceptionOrCant(result
))
4473 if (isTrueBool(result
))
4475 else if (result
->isBool(false))
4478 result
= interpret(&ue2
, e
->e2
, istate
);
4479 if (exceptionOrCant(result
))
4481 if (result
->op
== TOKvoidexp
)
4483 assert(e
->type
->ty
== Tvoid
);
4487 if (result
->isBool(false))
4489 else if (isTrueBool(result
))
4493 result
->error("%s cannot be interpreted as a boolean", result
->toChars());
4494 result
= CTFEExp::cantexp
;
4500 result
->error("%s cannot be interpreted as a boolean", result
->toChars());
4501 result
= CTFEExp::cantexp
;
4504 if (goal
!= ctfeNeedNothing
)
4506 new(pue
) IntegerExp(e
->loc
, res
, e
->type
);
4507 result
= pue
->exp();
4511 // Print a stack trace, starting from callingExp which called fd.
4512 // To shorten the stack trace, try to detect recursion.
4513 void showCtfeBackTrace(CallExp
* callingExp
, FuncDeclaration
*fd
)
4515 if (CtfeStatus::stackTraceCallsToSuppress
> 0)
4517 --CtfeStatus::stackTraceCallsToSuppress
;
4520 errorSupplemental(callingExp
->loc
, "called from here: %s", callingExp
->toChars());
4521 // Quit if it's not worth trying to compress the stack trace
4522 if (CtfeStatus::callDepth
< 6 || global
.params
.verbose
)
4524 // Recursion happens if the current function already exists in the call stack.
4525 int numToSuppress
= 0;
4526 int recurseCount
= 0;
4528 InterState
*lastRecurse
= istate
;
4529 for (InterState
* cur
= istate
; cur
; cur
= cur
->caller
)
4534 numToSuppress
= depthSoFar
;
4539 // We need at least three calls to the same function, to make compression worthwhile
4540 if (recurseCount
< 2)
4542 // We found a useful recursion. Print all the calls involved in the recursion
4543 errorSupplemental(fd
->loc
, "%d recursive calls to function %s", recurseCount
, fd
->toChars());
4544 for (InterState
*cur
= istate
; cur
->fd
!= fd
; cur
= cur
->caller
)
4546 errorSupplemental(cur
->fd
->loc
, "recursively called from function %s", cur
->fd
->toChars());
4548 // We probably didn't enter the recursion in this function.
4549 // Go deeper to find the real beginning.
4550 InterState
* cur
= istate
;
4551 while (lastRecurse
->caller
&& cur
->fd
== lastRecurse
->caller
->fd
)
4554 lastRecurse
= lastRecurse
->caller
;
4557 CtfeStatus::stackTraceCallsToSuppress
= numToSuppress
;
4560 void visit(CallExp
*e
)
4562 Expression
*pthis
= NULL
;
4563 FuncDeclaration
*fd
= NULL
;
4565 Expression
*ecall
= interpret(e
->e1
, istate
);
4566 if (exceptionOrCant(ecall
))
4569 if (ecall
->op
== TOKdotvar
)
4571 DotVarExp
*dve
= (DotVarExp
*)ecall
;
4573 // Calling a member function
4575 fd
= dve
->var
->isFuncDeclaration();
4578 if (pthis
->op
== TOKdottype
)
4579 pthis
= ((DotTypeExp
*)dve
->e1
)->e1
;
4581 else if (ecall
->op
== TOKvar
)
4583 fd
= ((VarExp
*)ecall
)->var
->isFuncDeclaration();
4586 if (fd
->ident
== Id::_ArrayPostblit
||
4587 fd
->ident
== Id::_ArrayDtor
)
4589 assert(e
->arguments
->dim
== 1);
4590 Expression
*ea
= (*e
->arguments
)[0];
4591 //printf("1 ea = %s %s\n", ea->type->toChars(), ea->toChars());
4592 if (ea
->op
== TOKslice
)
4593 ea
= ((SliceExp
*)ea
)->e1
;
4594 if (ea
->op
== TOKcast
)
4595 ea
= ((CastExp
*)ea
)->e1
;
4597 //printf("2 ea = %s, %s %s\n", ea->type->toChars(), Token::toChars(ea->op), ea->toChars());
4598 if (ea
->op
== TOKvar
|| ea
->op
== TOKsymoff
)
4599 result
= getVarExp(e
->loc
, istate
, ((SymbolExp
*)ea
)->var
, ctfeNeedRvalue
);
4600 else if (ea
->op
== TOKaddress
)
4601 result
= interpret(((AddrExp
*)ea
)->e1
, istate
);
4604 if (CTFEExp::isCantExp(result
))
4607 if (fd
->ident
== Id::_ArrayPostblit
)
4608 result
= evaluatePostblit(istate
, result
);
4610 result
= evaluateDtor(istate
, result
);
4612 result
= CTFEExp::voidexp
;
4616 else if (ecall
->op
== TOKsymoff
)
4618 SymOffExp
*soe
= (SymOffExp
*)ecall
;
4619 fd
= soe
->var
->isFuncDeclaration();
4620 assert(fd
&& soe
->offset
== 0);
4622 else if (ecall
->op
== TOKdelegate
)
4624 // Calling a delegate
4625 fd
= ((DelegateExp
*)ecall
)->func
;
4626 pthis
= ((DelegateExp
*)ecall
)->e1
;
4628 // Special handling for: &nestedfunc --> DelegateExp(VarExp(nestedfunc), nestedfunc)
4629 if (pthis
->op
== TOKvar
&& ((VarExp
*)pthis
)->var
== fd
)
4630 pthis
= NULL
; // context is not necessary for CTFE
4632 else if (ecall
->op
== TOKfunction
)
4634 // Calling a delegate literal
4635 fd
= ((FuncExp
*)ecall
)->fd
;
4639 // delegate.funcptr()
4641 e
->error("cannot call %s at compile time", e
->toChars());
4642 result
= CTFEExp::cantexp
;
4648 e
->error("CTFE internal error: cannot evaluate %s at compile time", e
->toChars());
4649 result
= CTFEExp::cantexp
;
4654 // Member function call
4656 // Currently this is satisfied because closure is not yet supported.
4657 assert(!fd
->isNested());
4659 if (pthis
->op
== TOKtypeid
)
4661 pthis
->error("static variable %s cannot be read at compile time", pthis
->toChars());
4662 result
= CTFEExp::cantexp
;
4667 if (pthis
->op
== TOKnull
)
4669 assert(pthis
->type
->toBasetype()->ty
== Tclass
);
4670 e
->error("function call through null class reference %s", pthis
->toChars());
4671 result
= CTFEExp::cantexp
;
4674 assert(pthis
->op
== TOKstructliteral
|| pthis
->op
== TOKclassreference
);
4676 if (fd
->isVirtual() && !e
->directcall
)
4678 // Make a virtual function call.
4679 // Get the function from the vtable of the original class
4680 assert(pthis
->op
== TOKclassreference
);
4681 ClassDeclaration
*cd
= ((ClassReferenceExp
*)pthis
)->originalClass();
4683 // We can't just use the vtable index to look it up, because
4684 // vtables for interfaces don't get populated until the glue layer.
4685 fd
= cd
->findFunc(fd
->ident
, (TypeFunction
*)fd
->type
);
4690 if (fd
&& fd
->semanticRun
>= PASSsemantic3done
&& fd
->semantic3Errors
)
4692 e
->error("CTFE failed because of previous errors in %s", fd
->toChars());
4693 result
= CTFEExp::cantexp
;
4697 // Check for built-in functions
4698 result
= evaluateIfBuiltin(istate
, e
->loc
, fd
, e
->arguments
, pthis
);
4704 e
->error("%s cannot be interpreted at compile time,"
4705 " because it has no available source code", fd
->toChars());
4706 result
= CTFEExp::cantexp
;
4710 result
= interpretFunction(fd
, istate
, e
->arguments
, pthis
);
4711 if (result
->op
== TOKvoidexp
)
4713 if (!exceptionOrCantInterpret(result
))
4715 if (goal
!= ctfeNeedLvalue
) // Peel off CTFE reference if it's unnesessary
4716 result
= interpret(result
, istate
);
4718 if (!exceptionOrCantInterpret(result
))
4720 result
= paintTypeOntoLiteral(e
->type
, result
);
4721 result
->loc
= e
->loc
;
4723 else if (CTFEExp::isCantExp(result
) && !global
.gag
)
4724 showCtfeBackTrace(e
, fd
); // Print a stack trace.
4727 void endTempStackFrame(InterState
*pistateComma
)
4729 // If we created a temporary stack frame, end it now.
4730 if (istate
== pistateComma
)
4731 ctfeStack
.endFrame();
4734 void visit(CommaExp
*e
)
4736 CommaExp
*firstComma
= e
;
4737 while (firstComma
->e1
->op
== TOKcomma
)
4738 firstComma
= (CommaExp
*)firstComma
->e1
;
4740 // If it creates a variable, and there's no context for
4741 // the variable to be created in, we need to create one now.
4742 InterState istateComma
;
4743 if (!istate
&& firstComma
->e1
->op
== TOKdeclaration
)
4745 ctfeStack
.startFrame(NULL
);
4746 istate
= &istateComma
;
4749 result
= CTFEExp::cantexp
;
4751 // If the comma returns a temporary variable, it needs to be an lvalue
4752 // (this is particularly important for struct constructors)
4753 if (e
->e1
->op
== TOKdeclaration
&& e
->e2
->op
== TOKvar
&&
4754 ((DeclarationExp
*)e
->e1
)->declaration
== ((VarExp
*)e
->e2
)->var
&&
4755 ((VarExp
*)e
->e2
)->var
->storage_class
& STCctfe
) // same as Expression::isTemp
4757 VarExp
*ve
= (VarExp
*)e
->e2
;
4758 VarDeclaration
*v
= ve
->var
->isVarDeclaration();
4760 if (!v
->_init
&& !getValue(v
))
4762 setValue(v
, copyLiteral(v
->type
->defaultInitLiteral(e
->loc
)).copy());
4766 Expression
*newval
= initializerToExpression(v
->_init
);
4767 // Bug 4027. Copy constructors are a weird case where the
4768 // initializer is a void function (the variable is modified
4769 // through a reference parameter instead).
4770 newval
= interpret(newval
, istate
);
4771 if (exceptionOrCant(newval
))
4772 return endTempStackFrame(&istateComma
);
4773 if (newval
->op
!= TOKvoidexp
)
4775 // v isn't necessarily null.
4776 setValueWithoutChecking(v
, copyLiteral(newval
).copy());
4783 Expression
*e1
= interpret(&ue
, e
->e1
, istate
, ctfeNeedNothing
);
4784 if (exceptionOrCant(e1
))
4785 return endTempStackFrame(&istateComma
);
4787 result
= interpret(pue
, e
->e2
, istate
, goal
);
4788 return endTempStackFrame(&istateComma
);
4791 void visit(CondExp
*e
)
4795 econd
= interpret(&uecond
, e
->econd
, istate
);
4796 if (exceptionOrCant(econd
))
4799 if (isPointer(e
->econd
->type
))
4801 if (econd
->op
!= TOKnull
)
4803 new(&uecond
) IntegerExp(e
->loc
, 1, Type::tbool
);
4804 econd
= uecond
.exp();
4808 if (isTrueBool(econd
))
4809 result
= interpret(pue
, e
->e1
, istate
, goal
);
4810 else if (econd
->isBool(false))
4811 result
= interpret(pue
, e
->e2
, istate
, goal
);
4814 e
->error("%s does not evaluate to boolean result at compile time", e
->econd
->toChars());
4815 result
= CTFEExp::cantexp
;
4819 void visit(ArrayLengthExp
*e
)
4822 Expression
*e1
= interpret(&ue1
, e
->e1
, istate
);
4824 if (exceptionOrCant(e1
))
4826 if (e1
->op
!= TOKstring
&&
4827 e1
->op
!= TOKarrayliteral
&&
4828 e1
->op
!= TOKslice
&&
4831 e
->error("%s cannot be evaluated at compile time", e
->toChars());
4832 result
= CTFEExp::cantexp
;
4835 new(pue
) IntegerExp(e
->loc
, resolveArrayLength(e1
), e
->type
);
4836 result
= pue
->exp();
4839 void visit(DelegatePtrExp
*e
)
4841 Expression
*e1
= interpret(pue
, e
->e1
, istate
);
4843 if (exceptionOrCant(e1
))
4845 e
->error("%s cannot be evaluated at compile time", e
->toChars());
4846 result
= CTFEExp::cantexp
;
4849 void visit(DelegateFuncptrExp
*e
)
4851 Expression
*e1
= interpret(pue
, e
->e1
, istate
);
4853 if (exceptionOrCant(e1
))
4855 e
->error("%s cannot be evaluated at compile time", e
->toChars());
4856 result
= CTFEExp::cantexp
;
4859 static bool resolveIndexing(IndexExp
*e
, InterState
*istate
, Expression
**pagg
, uinteger_t
*pidx
, bool modify
)
4861 assert(e
->e1
->type
->toBasetype()->ty
!= Taarray
);
4863 if (e
->e1
->type
->toBasetype()->ty
== Tpointer
)
4865 // Indexing a pointer. Note that there is no $ in this case.
4866 Expression
*e1
= interpret(e
->e1
, istate
);
4867 if (exceptionOrCantInterpret(e1
))
4870 Expression
*e2
= interpret(e
->e2
, istate
);
4871 if (exceptionOrCantInterpret(e2
))
4873 sinteger_t indx
= e2
->toInteger();
4876 Expression
*agg
= getAggregateFromPointer(e1
, &ofs
);
4878 if (agg
->op
== TOKnull
)
4880 e
->error("cannot index through null pointer %s", e
->e1
->toChars());
4883 if (agg
->op
== TOKint64
)
4885 e
->error("cannot index through invalid pointer %s of value %s",
4886 e
->e1
->toChars(), e1
->toChars());
4889 // Pointer to a non-array variable
4890 if (agg
->op
== TOKsymoff
)
4892 e
->error("mutable variable %s cannot be %s at compile time, even through a pointer",
4893 (modify
? "modified" : "read"), ((SymOffExp
*)agg
)->var
->toChars());
4897 if (agg
->op
== TOKarrayliteral
|| agg
->op
== TOKstring
)
4899 dinteger_t len
= resolveArrayLength(agg
);
4900 if (ofs
+ indx
>= len
)
4902 e
->error("pointer index [%lld] exceeds allocated memory block [0..%lld]",
4909 if (ofs
+ indx
!= 0)
4911 e
->error("pointer index [%lld] lies outside memory block [0..1]",
4921 Expression
*e1
= interpret(e
->e1
, istate
);
4922 if (exceptionOrCantInterpret(e1
))
4924 if (e1
->op
== TOKnull
)
4926 e
->error("cannot index null array %s", e
->e1
->toChars());
4929 if (e1
->op
== TOKvector
)
4930 e1
= ((VectorExp
*)e1
)->e1
;
4932 // Set the $ variable, and find the array literal to modify
4933 if (e1
->op
!= TOKarrayliteral
&&
4934 e1
->op
!= TOKstring
&&
4937 e
->error("cannot determine length of %s at compile time",
4942 dinteger_t len
= resolveArrayLength(e1
);
4945 Expression
*dollarExp
= new IntegerExp(e
->loc
, len
, Type::tsize_t
);
4946 ctfeStack
.push(e
->lengthVar
);
4947 setValue(e
->lengthVar
, dollarExp
);
4949 Expression
*e2
= interpret(e
->e2
, istate
);
4951 ctfeStack
.pop(e
->lengthVar
); // $ is defined only inside []
4952 if (exceptionOrCantInterpret(e2
))
4954 if (e2
->op
!= TOKint64
)
4956 e
->error("CTFE internal error: non-integral index [%s]", e
->e2
->toChars());
4960 if (e1
->op
== TOKslice
)
4962 // Simplify index of slice: agg[lwr..upr][indx] --> agg[indx']
4963 uinteger_t index
= e2
->toInteger();
4964 uinteger_t ilwr
= ((SliceExp
*)e1
)->lwr
->toInteger();
4965 uinteger_t iupr
= ((SliceExp
*)e1
)->upr
->toInteger();
4967 if (index
> iupr
- ilwr
)
4969 e
->error("index %llu exceeds array length %llu", index
, iupr
- ilwr
);
4972 *pagg
= ((SliceExp
*)e1
)->e1
;
4973 *pidx
= index
+ ilwr
;
4978 *pidx
= e2
->toInteger();
4981 e
->error("array index %lld is out of bounds [0..%lld]",
4989 void visit(IndexExp
*e
)
4991 if (e
->e1
->type
->toBasetype()->ty
== Tpointer
)
4994 uinteger_t indexToAccess
;
4995 if (!resolveIndexing(e
, istate
, &agg
, &indexToAccess
, false))
4997 result
= CTFEExp::cantexp
;
5000 if (agg
->op
== TOKarrayliteral
|| agg
->op
== TOKstring
)
5002 if (goal
== ctfeNeedLvalue
)
5004 // if we need a reference, IndexExp shouldn't be interpreting
5005 // the expression to a value, it should stay as a reference
5006 new(pue
) IndexExp(e
->loc
, agg
, new IntegerExp(e
->e2
->loc
, indexToAccess
, e
->e2
->type
));
5007 result
= pue
->exp();
5008 result
->type
= e
->type
;
5011 result
= ctfeIndex(e
->loc
, e
->type
, agg
, indexToAccess
);
5016 assert(indexToAccess
== 0);
5017 result
= interpret(agg
, istate
, goal
);
5018 if (exceptionOrCant(result
))
5020 result
= paintTypeOntoLiteral(e
->type
, result
);
5025 if (e
->e1
->type
->toBasetype()->ty
== Taarray
)
5027 Expression
*e1
= interpret(e
->e1
, istate
);
5028 if (exceptionOrCant(e1
))
5030 if (e1
->op
== TOKnull
)
5032 if (goal
== ctfeNeedLvalue
&& e1
->type
->ty
== Taarray
&& e
->modifiable
)
5034 assert(0); // does not reach here?
5037 e
->error("cannot index null array %s", e
->e1
->toChars());
5038 result
= CTFEExp::cantexp
;
5041 Expression
*e2
= interpret(e
->e2
, istate
);
5042 if (exceptionOrCant(e2
))
5045 if (goal
== ctfeNeedLvalue
)
5047 // Pointer or reference of a scalar type
5048 if (e1
== e
->e1
&& e2
== e
->e2
)
5052 new(pue
) IndexExp(e
->loc
, e1
, e2
);
5053 result
= pue
->exp();
5054 result
->type
= e
->type
;
5059 assert(e1
->op
== TOKassocarrayliteral
);
5061 e2
= resolveSlice(e2
, &e2tmp
);
5062 result
= findKeyInAA(e
->loc
, (AssocArrayLiteralExp
*)e1
, e2
);
5065 e
->error("key %s not found in associative array %s", e2
->toChars(), e
->e1
->toChars());
5066 result
= CTFEExp::cantexp
;
5072 uinteger_t indexToAccess
;
5073 if (!resolveIndexing(e
, istate
, &agg
, &indexToAccess
, false))
5075 result
= CTFEExp::cantexp
;
5079 if (goal
== ctfeNeedLvalue
)
5081 Expression
*e2
= new IntegerExp(e
->e2
->loc
, indexToAccess
, Type::tsize_t
);
5082 new(pue
) IndexExp(e
->loc
, agg
, e2
);
5083 result
= pue
->exp();
5084 result
->type
= e
->type
;
5088 result
= ctfeIndex(e
->loc
, e
->type
, agg
, indexToAccess
);
5089 if (exceptionOrCant(result
))
5091 if (result
->op
== TOKvoid
)
5093 e
->error("%s is used before initialized", e
->toChars());
5094 errorSupplemental(result
->loc
, "originally uninitialized here");
5095 result
= CTFEExp::cantexp
;
5098 result
= paintTypeOntoLiteral(e
->type
, result
);
5101 void visit(SliceExp
*e
)
5103 if (e
->e1
->type
->toBasetype()->ty
== Tpointer
)
5105 // Slicing a pointer. Note that there is no $ in this case.
5106 Expression
*e1
= interpret(e
->e1
, istate
);
5107 if (exceptionOrCant(e1
))
5109 if (e1
->op
== TOKint64
)
5111 e
->error("cannot slice invalid pointer %s of value %s", e
->e1
->toChars(), e1
->toChars());
5112 result
= CTFEExp::cantexp
;
5116 /* Evaluate lower and upper bounds of slice
5118 Expression
*lwr
= interpret(e
->lwr
, istate
);
5119 if (exceptionOrCant(lwr
))
5121 Expression
*upr
= interpret(e
->upr
, istate
);
5122 if (exceptionOrCant(upr
))
5124 uinteger_t ilwr
= lwr
->toInteger();
5125 uinteger_t iupr
= upr
->toInteger();
5128 Expression
*agg
= getAggregateFromPointer(e1
, &ofs
);
5131 if (agg
->op
== TOKnull
)
5135 result
= new NullExp(e
->loc
);
5136 result
->type
= e
->type
;
5139 e
->error("cannot slice null pointer %s", e
->e1
->toChars());
5140 result
= CTFEExp::cantexp
;
5143 if (agg
->op
== TOKsymoff
)
5145 e
->error("slicing pointers to static variables is not supported in CTFE");
5146 result
= CTFEExp::cantexp
;
5149 if (agg
->op
!= TOKarrayliteral
&& agg
->op
!= TOKstring
)
5151 e
->error("pointer %s cannot be sliced at compile time (it does not point to an array)", e
->e1
->toChars());
5152 result
= CTFEExp::cantexp
;
5155 assert(agg
->op
== TOKarrayliteral
|| agg
->op
== TOKstring
);
5156 dinteger_t len
= ArrayLength(Type::tsize_t
, agg
).exp()->toInteger();
5157 //Type *pointee = ((TypePointer *)agg->type)->next;
5158 if (iupr
> (len
+ 1) || iupr
< ilwr
)
5160 e
->error("pointer slice [%lld..%lld] exceeds allocated memory block [0..%lld]", ilwr
, iupr
, len
);
5161 result
= CTFEExp::cantexp
;
5166 lwr
= new IntegerExp(e
->loc
, ilwr
, lwr
->type
);
5167 upr
= new IntegerExp(e
->loc
, iupr
, upr
->type
);
5169 new(pue
) SliceExp(e
->loc
, agg
, lwr
, upr
);
5170 result
= pue
->exp();
5171 result
->type
= e
->type
;
5175 Expression
*e1
= interpret(e
->e1
, istate
);
5176 if (exceptionOrCant(e1
))
5181 result
= paintTypeOntoLiteral(e
->type
, e1
);
5185 /* Set the $ variable
5187 if (e1
->op
!= TOKarrayliteral
&& e1
->op
!= TOKstring
&& e1
->op
!= TOKnull
&& e1
->op
!= TOKslice
)
5189 e
->error("cannot determine length of %s at compile time", e1
->toChars());
5190 result
= CTFEExp::cantexp
;
5193 uinteger_t dollar
= resolveArrayLength(e1
);
5196 IntegerExp
*dollarExp
= new IntegerExp(e
->loc
, dollar
, Type::tsize_t
);
5197 ctfeStack
.push(e
->lengthVar
);
5198 setValue(e
->lengthVar
, dollarExp
);
5201 /* Evaluate lower and upper bounds of slice
5203 Expression
*lwr
= interpret(e
->lwr
, istate
);
5204 if (exceptionOrCant(lwr
))
5207 ctfeStack
.pop(e
->lengthVar
);
5210 Expression
*upr
= interpret(e
->upr
, istate
);
5211 if (exceptionOrCant(upr
))
5214 ctfeStack
.pop(e
->lengthVar
);
5218 ctfeStack
.pop(e
->lengthVar
); // $ is defined only inside [L..U]
5220 uinteger_t ilwr
= lwr
->toInteger();
5221 uinteger_t iupr
= upr
->toInteger();
5222 if (e1
->op
== TOKnull
)
5224 if (ilwr
== 0 && iupr
== 0)
5229 e1
->error("slice [%llu..%llu] is out of bounds", ilwr
, iupr
);
5230 result
= CTFEExp::cantexp
;
5233 if (e1
->op
== TOKslice
)
5235 SliceExp
*se
= (SliceExp
*)e1
;
5236 // Simplify slice of slice:
5237 // aggregate[lo1..up1][lwr..upr] ---> aggregate[lwr'..upr']
5238 uinteger_t lo1
= se
->lwr
->toInteger();
5239 uinteger_t up1
= se
->upr
->toInteger();
5240 if (ilwr
> iupr
|| iupr
> up1
- lo1
)
5242 e
->error("slice[%llu..%llu] exceeds array bounds[%llu..%llu]", ilwr
, iupr
, lo1
, up1
);
5243 result
= CTFEExp::cantexp
;
5248 new(pue
) SliceExp(e
->loc
, se
->e1
, new IntegerExp(e
->loc
, ilwr
, lwr
->type
), new IntegerExp(e
->loc
, iupr
, upr
->type
));
5249 result
= pue
->exp();
5250 result
->type
= e
->type
;
5253 if (e1
->op
== TOKarrayliteral
|| e1
->op
== TOKstring
)
5255 if (iupr
< ilwr
|| dollar
< iupr
)
5257 e
->error("slice [%lld..%lld] exceeds array bounds [0..%lld]", ilwr
, iupr
, dollar
);
5258 result
= CTFEExp::cantexp
;
5262 new(pue
) SliceExp(e
->loc
, e1
, lwr
, upr
);
5263 result
= pue
->exp();
5264 result
->type
= e
->type
;
5267 void visit(InExp
*e
)
5269 Expression
*e1
= interpret(e
->e1
, istate
);
5270 if (exceptionOrCant(e1
))
5272 Expression
*e2
= interpret(e
->e2
, istate
);
5273 if (exceptionOrCant(e2
))
5275 if (e2
->op
== TOKnull
)
5277 new(pue
) NullExp(e
->loc
, e
->type
);
5278 result
= pue
->exp();
5281 if (e2
->op
!= TOKassocarrayliteral
)
5283 e
->error("%s cannot be interpreted at compile time", e
->toChars());
5284 result
= CTFEExp::cantexp
;
5288 e1
= resolveSlice(e1
);
5289 result
= findKeyInAA(e
->loc
, (AssocArrayLiteralExp
*)e2
, e1
);
5290 if (exceptionOrCant(result
))
5294 new(pue
) NullExp(e
->loc
, e
->type
);
5295 result
= pue
->exp();
5299 // Create a CTFE pointer &aa[index]
5300 result
= new IndexExp(e
->loc
, e2
, e1
);
5301 result
->type
= e
->type
->nextOf();
5302 new(pue
) AddrExp(e
->loc
, result
, e
->type
);
5303 result
= pue
->exp();
5307 void visit(CatExp
*e
)
5309 Expression
*e1
= interpret(e
->e1
, istate
);
5310 if (exceptionOrCant(e1
))
5312 Expression
*e2
= interpret(e
->e2
, istate
);
5313 if (exceptionOrCant(e2
))
5316 e1
= resolveSlice(e1
, &e1tmp
);
5318 e2
= resolveSlice(e2
, &e2tmp
);
5319 result
= ctfeCat(e
->loc
, e
->type
, e1
, e2
).copy();
5320 if (CTFEExp::isCantExp(result
))
5322 e
->error("%s cannot be interpreted at compile time", e
->toChars());
5325 // We know we still own it, because we interpreted both e1 and e2
5326 if (result
->op
== TOKarrayliteral
)
5328 ArrayLiteralExp
*ale
= (ArrayLiteralExp
*)result
;
5329 ale
->ownedByCtfe
= OWNEDctfe
;
5332 for (size_t i
= 0; i
< ale
->elements
->dim
; i
++)
5334 Expression
*ex
= evaluatePostblit(istate
, (*ale
->elements
)[i
]);
5335 if (exceptionOrCant(ex
))
5339 if (result
->op
== TOKstring
)
5340 ((StringExp
*)result
)->ownedByCtfe
= OWNEDctfe
;
5343 void visit(DeleteExp
*e
)
5345 result
= interpret(e
->e1
, istate
);
5346 if (exceptionOrCant(result
))
5349 if (result
->op
== TOKnull
)
5351 result
= CTFEExp::voidexp
;
5355 Type
*tb
= e
->e1
->type
->toBasetype();
5360 if (result
->op
!= TOKclassreference
)
5362 e
->error("delete on invalid class reference '%s'", result
->toChars());
5363 result
= CTFEExp::cantexp
;
5367 ClassReferenceExp
*cre
= (ClassReferenceExp
*)result
;
5368 ClassDeclaration
*cd
= cre
->originalClass();
5371 e
->error("member deallocators not supported by CTFE");
5372 result
= CTFEExp::cantexp
;
5378 result
= interpretFunction(cd
->dtor
, istate
, NULL
, cre
);
5379 if (exceptionOrCant(result
))
5387 tb
= ((TypePointer
*)tb
)->next
->toBasetype();
5388 if (tb
->ty
== Tstruct
)
5390 if (result
->op
!= TOKaddress
||
5391 ((AddrExp
*)result
)->e1
->op
!= TOKstructliteral
)
5393 e
->error("delete on invalid struct pointer '%s'", result
->toChars());
5394 result
= CTFEExp::cantexp
;
5398 StructDeclaration
*sd
= ((TypeStruct
*)tb
)->sym
;
5399 StructLiteralExp
*sle
= (StructLiteralExp
*)((AddrExp
*)result
)->e1
;
5402 e
->error("member deallocators not supported by CTFE");
5403 result
= CTFEExp::cantexp
;
5409 result
= interpretFunction(sd
->dtor
, istate
, NULL
, sle
);
5410 if (exceptionOrCant(result
))
5419 Type
*tv
= tb
->nextOf()->baseElemOf();
5420 if (tv
->ty
== Tstruct
)
5422 if (result
->op
!= TOKarrayliteral
)
5424 e
->error("delete on invalid struct array '%s'", result
->toChars());
5425 result
= CTFEExp::cantexp
;
5429 StructDeclaration
*sd
= ((TypeStruct
*)tv
)->sym
;
5432 e
->error("member deallocators not supported by CTFE");
5433 result
= CTFEExp::cantexp
;
5439 ArrayLiteralExp
*ale
= (ArrayLiteralExp
*)result
;
5440 for (size_t i
= 0; i
< ale
->elements
->dim
; i
++)
5442 Expression
*el
= (*ale
->elements
)[i
];
5443 result
= interpretFunction(sd
->dtor
, istate
, NULL
, el
);
5444 if (exceptionOrCant(result
))
5455 result
= CTFEExp::voidexp
;
5458 void visit(CastExp
*e
)
5460 Expression
*e1
= interpret(e
->e1
, istate
, goal
);
5461 if (exceptionOrCant(e1
))
5463 // If the expression has been cast to void, do nothing.
5464 if (e
->to
->ty
== Tvoid
)
5466 result
= CTFEExp::voidexp
;
5469 if (e
->to
->ty
== Tpointer
&& e1
->op
!= TOKnull
)
5471 Type
*pointee
= ((TypePointer
*)e
->type
)->next
;
5472 // Implement special cases of normally-unsafe casts
5473 if (e1
->op
== TOKint64
)
5475 // Happens with Windows HANDLEs, for example.
5476 result
= paintTypeOntoLiteral(e
->to
, e1
);
5479 bool castToSarrayPointer
= false;
5480 bool castBackFromVoid
= false;
5481 if (e1
->type
->ty
== Tarray
|| e1
->type
->ty
== Tsarray
|| e1
->type
->ty
== Tpointer
)
5483 // Check for unsupported type painting operations
5484 // For slices, we need the type being sliced,
5485 // since it may have already been type painted
5486 Type
*elemtype
= e1
->type
->nextOf();
5487 if (e1
->op
== TOKslice
)
5488 elemtype
= ((SliceExp
*)e1
)->e1
->type
->nextOf();
5489 // Allow casts from X* to void *, and X** to void** for any X.
5490 // But don't allow cast from X* to void**.
5491 // So, we strip all matching * from source and target to find X.
5492 // Allow casts to X* from void* only if the 'void' was originally an X;
5493 // we check this later on.
5494 Type
*ultimatePointee
= pointee
;
5495 Type
*ultimateSrc
= elemtype
;
5496 while (ultimatePointee
->ty
== Tpointer
&& ultimateSrc
->ty
== Tpointer
)
5498 ultimatePointee
= ultimatePointee
->nextOf();
5499 ultimateSrc
= ultimateSrc
->nextOf();
5501 if (ultimatePointee
->ty
== Tsarray
&& ultimatePointee
->nextOf()->equivalent(ultimateSrc
))
5503 castToSarrayPointer
= true;
5505 else if (ultimatePointee
->ty
!= Tvoid
&& ultimateSrc
->ty
!= Tvoid
&&
5506 !isSafePointerCast(elemtype
, pointee
))
5508 e
->error("reinterpreting cast from %s* to %s* is not supported in CTFE",
5509 elemtype
->toChars(), pointee
->toChars());
5510 result
= CTFEExp::cantexp
;
5513 if (ultimateSrc
->ty
== Tvoid
)
5514 castBackFromVoid
= true;
5517 if (e1
->op
== TOKslice
)
5519 if (((SliceExp
*)e1
)->e1
->op
== TOKnull
)
5521 result
= paintTypeOntoLiteral(e
->type
, ((SliceExp
*)e1
)->e1
);
5524 // Create a CTFE pointer &aggregate[1..2]
5525 IndexExp
*ei
= new IndexExp(e
->loc
, ((SliceExp
*)e1
)->e1
, ((SliceExp
*)e1
)->lwr
);
5526 ei
->type
= e
->type
->nextOf();
5527 new(pue
) AddrExp(e
->loc
, ei
, e
->type
);
5528 result
= pue
->exp();
5531 if (e1
->op
== TOKarrayliteral
|| e1
->op
== TOKstring
)
5533 // Create a CTFE pointer &[1,2,3][0] or &"abc"[0]
5534 IndexExp
*ei
= new IndexExp(e
->loc
, e1
, new IntegerExp(e
->loc
, 0, Type::tsize_t
));
5535 ei
->type
= e
->type
->nextOf();
5536 new(pue
) AddrExp(e
->loc
, ei
, e
->type
);
5537 result
= pue
->exp();
5540 if (e1
->op
== TOKindex
&& !((IndexExp
*)e1
)->e1
->type
->equals(e1
->type
))
5542 // type painting operation
5543 IndexExp
*ie
= (IndexExp
*)e1
;
5544 result
= new IndexExp(e1
->loc
, ie
->e1
, ie
->e2
);
5545 if (castBackFromVoid
)
5547 // get the original type. For strings, it's just the type...
5548 Type
*origType
= ie
->e1
->type
->nextOf();
5549 // ..but for arrays of type void*, it's the type of the element
5550 if (ie
->e1
->op
== TOKarrayliteral
&& ie
->e2
->op
== TOKint64
)
5552 ArrayLiteralExp
*ale
= (ArrayLiteralExp
*)ie
->e1
;
5553 size_t indx
= (size_t)ie
->e2
->toInteger();
5554 if (indx
< ale
->elements
->dim
)
5556 Expression
*xx
= (*ale
->elements
)[indx
];
5559 if (xx
->op
== TOKindex
)
5560 origType
= ((IndexExp
*)xx
)->e1
->type
->nextOf();
5561 else if (xx
->op
== TOKaddress
)
5562 origType
= ((AddrExp
*)xx
)->e1
->type
;
5563 else if (xx
->op
== TOKvar
)
5564 origType
= ((VarExp
*)xx
)->var
->type
;
5568 if (!isSafePointerCast(origType
, pointee
))
5570 e
->error("using void* to reinterpret cast from %s* to %s* is not supported in CTFE", origType
->toChars(), pointee
->toChars());
5571 result
= CTFEExp::cantexp
;
5575 result
->type
= e
->type
;
5578 if (e1
->op
== TOKaddress
)
5580 Type
*origType
= ((AddrExp
*)e1
)->e1
->type
;
5581 if (isSafePointerCast(origType
, pointee
))
5583 new(pue
) AddrExp(e
->loc
, ((AddrExp
*)e1
)->e1
, e
->type
);
5584 result
= pue
->exp();
5587 if (castToSarrayPointer
&& pointee
->toBasetype()->ty
== Tsarray
&& ((AddrExp
*)e1
)->e1
->op
== TOKindex
)
5590 dinteger_t dim
= ((TypeSArray
*)pointee
->toBasetype())->dim
->toInteger();
5591 IndexExp
*ie
= (IndexExp
*)((AddrExp
*)e1
)->e1
;
5592 Expression
*lwr
= ie
->e2
;
5593 Expression
*upr
= new IntegerExp(ie
->e2
->loc
, ie
->e2
->toInteger() + dim
, Type::tsize_t
);
5595 // Create a CTFE pointer &val[idx..idx+dim]
5596 SliceExp
*er
= new SliceExp(e
->loc
, ie
->e1
, lwr
, upr
);
5598 new(pue
) AddrExp(e
->loc
, er
, e
->type
);
5599 result
= pue
->exp();
5603 if (e1
->op
== TOKvar
|| e1
->op
== TOKsymoff
)
5605 // type painting operation
5606 Type
*origType
= ((SymbolExp
*)e1
)->var
->type
;
5607 if (castBackFromVoid
&& !isSafePointerCast(origType
, pointee
))
5609 e
->error("using void* to reinterpret cast from %s* to %s* is not supported in CTFE", origType
->toChars(), pointee
->toChars());
5610 result
= CTFEExp::cantexp
;
5613 if (e1
->op
== TOKvar
)
5614 new(pue
) VarExp(e
->loc
, ((VarExp
*)e1
)->var
);
5616 new(pue
) SymOffExp(e
->loc
, ((SymOffExp
*)e1
)->var
, ((SymOffExp
*)e1
)->offset
);
5617 result
= pue
->exp();
5618 result
->type
= e
->to
;
5622 // Check if we have a null pointer (eg, inside a struct)
5623 e1
= interpret(e1
, istate
);
5624 if (e1
->op
!= TOKnull
)
5626 e
->error("pointer cast from %s to %s is not supported at compile time", e1
->type
->toChars(), e
->to
->toChars());
5627 result
= CTFEExp::cantexp
;
5631 if (e
->to
->ty
== Tsarray
&& e
->e1
->type
->ty
== Tvector
)
5633 // Special handling for: cast(float[4])__vector([w, x, y, z])
5634 e1
= interpret(e
->e1
, istate
);
5635 if (exceptionOrCant(e1
))
5637 assert(e1
->op
== TOKvector
);
5638 e1
= ((VectorExp
*)e1
)->e1
;
5640 if (e
->to
->ty
== Tarray
&& e1
->op
== TOKslice
)
5642 // Note that the slice may be void[], so when checking for dangerous
5643 // casts, we need to use the original type, which is se->e1.
5644 SliceExp
*se
= (SliceExp
*)e1
;
5645 if (!isSafePointerCast(se
->e1
->type
->nextOf(), e
->to
->nextOf()))
5647 e
->error("array cast from %s to %s is not supported at compile time", se
->e1
->type
->toChars(), e
->to
->toChars());
5648 result
= CTFEExp::cantexp
;
5651 new(pue
) SliceExp(e1
->loc
, se
->e1
, se
->lwr
, se
->upr
);
5652 result
= pue
->exp();
5653 result
->type
= e
->to
;
5656 // Disallow array type painting, except for conversions between built-in
5657 // types of identical size.
5658 if ((e
->to
->ty
== Tsarray
|| e
->to
->ty
== Tarray
) && (e1
->type
->ty
== Tsarray
|| e1
->type
->ty
== Tarray
) && !isSafePointerCast(e1
->type
->nextOf(), e
->to
->nextOf()))
5660 e
->error("array cast from %s to %s is not supported at compile time", e1
->type
->toChars(), e
->to
->toChars());
5661 result
= CTFEExp::cantexp
;
5664 if (e
->to
->ty
== Tsarray
)
5665 e1
= resolveSlice(e1
);
5666 if (e
->to
->toBasetype()->ty
== Tbool
&& e1
->type
->ty
== Tpointer
)
5668 new(pue
) IntegerExp(e
->loc
, e1
->op
!= TOKnull
, e
->to
);
5669 result
= pue
->exp();
5672 result
= ctfeCast(e
->loc
, e
->type
, e
->to
, e1
);
5675 void visit(AssertExp
*e
)
5677 Expression
*e1
= interpret(pue
, e
->e1
, istate
);
5678 if (exceptionOrCant(e1
))
5683 else if (e1
->isBool(false))
5688 result
= interpret(&ue
, e
->msg
, istate
);
5689 if (exceptionOrCant(result
))
5691 e
->error("%s", result
->toChars());
5694 e
->error("%s failed", e
->toChars());
5695 result
= CTFEExp::cantexp
;
5700 e
->error("%s is not a compile time boolean expression", e1
->toChars());
5701 result
= CTFEExp::cantexp
;
5708 void visit(PtrExp
*e
)
5710 // Check for int<->float and long<->double casts.
5711 if (e
->e1
->op
== TOKsymoff
&& ((SymOffExp
*)e
->e1
)->offset
== 0 && ((SymOffExp
*)e
->e1
)->var
->isVarDeclaration() && isFloatIntPaint(e
->type
, ((SymOffExp
*)e
->e1
)->var
->type
))
5713 // *(cast(int*)&v), where v is a float variable
5714 result
= paintFloatInt(getVarExp(e
->loc
, istate
, ((SymOffExp
*)e
->e1
)->var
, ctfeNeedRvalue
), e
->type
);
5717 if (e
->e1
->op
== TOKcast
&& ((CastExp
*)e
->e1
)->e1
->op
== TOKaddress
)
5719 // *(cast(int*)&x), where x is a float expression
5720 Expression
*x
= ((AddrExp
*)(((CastExp
*)e
->e1
)->e1
))->e1
;
5721 if (isFloatIntPaint(e
->type
, x
->type
))
5723 result
= paintFloatInt(interpret(x
, istate
), e
->type
);
5728 // Constant fold *(&structliteral + offset)
5729 if (e
->e1
->op
== TOKadd
)
5731 AddExp
*ae
= (AddExp
*)e
->e1
;
5732 if (ae
->e1
->op
== TOKaddress
&& ae
->e2
->op
== TOKint64
)
5734 AddrExp
*ade
= (AddrExp
*)ae
->e1
;
5735 Expression
*ex
= interpret(ade
->e1
, istate
);
5736 if (exceptionOrCant(ex
))
5738 if (ex
->op
== TOKstructliteral
)
5740 StructLiteralExp
*se
= (StructLiteralExp
*)ex
;
5741 dinteger_t offset
= ae
->e2
->toInteger();
5742 result
= se
->getField(e
->type
, (unsigned)offset
);
5749 // It's possible we have an array bounds error. We need to make sure it
5750 // errors with this line number, not the one where the pointer was set.
5751 result
= interpret(e
->e1
, istate
);
5752 if (exceptionOrCant(result
))
5755 if (result
->op
== TOKfunction
)
5757 if (result
->op
== TOKsymoff
)
5759 SymOffExp
*soe
= (SymOffExp
*)result
;
5760 if (soe
->offset
== 0 && soe
->var
->isFuncDeclaration())
5762 e
->error("cannot dereference pointer to static variable %s at compile time", soe
->var
->toChars());
5763 result
= CTFEExp::cantexp
;
5767 if (result
->op
!= TOKaddress
)
5769 if (result
->op
== TOKnull
)
5770 e
->error("dereference of null pointer '%s'", e
->e1
->toChars());
5772 e
->error("dereference of invalid pointer '%s'", result
->toChars());
5773 result
= CTFEExp::cantexp
;
5778 result
= ((AddrExp
*)result
)->e1
;
5780 if (result
->op
== TOKslice
&& e
->type
->toBasetype()->ty
== Tsarray
)
5783 * upr may exceed the upper boundary of aggr, but the check is deferred
5784 * until those out-of-bounds elements will be touched.
5788 result
= interpret(result
, istate
, goal
);
5789 if (exceptionOrCant(result
))
5793 void visit(DotVarExp
*e
)
5795 Expression
*ex
= interpret(e
->e1
, istate
);
5796 if (exceptionOrCant(ex
))
5799 if (FuncDeclaration
*f
= e
->var
->isFuncDeclaration())
5802 result
= e
; // optimize: reuse this CTFE reference
5805 new(pue
) DotVarExp(e
->loc
, ex
, f
, false);
5806 result
= pue
->exp();
5807 result
->type
= e
->type
;
5812 VarDeclaration
*v
= e
->var
->isVarDeclaration();
5815 e
->error("CTFE internal error: %s", e
->toChars());
5816 result
= CTFEExp::cantexp
;
5820 if (ex
->op
== TOKnull
)
5822 if (ex
->type
->toBasetype()->ty
== Tclass
)
5823 e
->error("class '%s' is null and cannot be dereferenced", e
->e1
->toChars());
5825 e
->error("CTFE internal error: null this '%s'", e
->e1
->toChars());
5826 result
= CTFEExp::cantexp
;
5829 if (ex
->op
!= TOKstructliteral
&& ex
->op
!= TOKclassreference
)
5831 e
->error("%s.%s is not yet implemented at compile time", e
->e1
->toChars(), e
->var
->toChars());
5832 result
= CTFEExp::cantexp
;
5836 StructLiteralExp
*se
;
5839 // We can't use getField, because it makes a copy
5840 if (ex
->op
== TOKclassreference
)
5842 se
= ((ClassReferenceExp
*)ex
)->value
;
5843 i
= ((ClassReferenceExp
*)ex
)->findFieldIndexByName(v
);
5847 se
= (StructLiteralExp
*)ex
;
5848 i
= findFieldIndexByName(se
->sd
, v
);
5852 e
->error("couldn't find field %s of type %s in %s", v
->toChars(), e
->type
->toChars(), se
->toChars());
5853 result
= CTFEExp::cantexp
;
5857 if (goal
== ctfeNeedLvalue
)
5859 Expression
*ev
= (*se
->elements
)[i
];
5860 if (!ev
|| ev
->op
== TOKvoid
)
5861 (*se
->elements
)[i
] = voidInitLiteral(e
->type
, v
).copy();
5862 // just return the (simplified) dotvar expression as a CTFE reference
5867 new(pue
) DotVarExp(e
->loc
, ex
, v
);
5868 result
= pue
->exp();
5869 result
->type
= e
->type
;
5874 result
= (*se
->elements
)[i
];
5877 e
->error("Internal Compiler Error: null field %s", v
->toChars());
5878 result
= CTFEExp::cantexp
;
5881 if (result
->op
== TOKvoid
)
5883 VoidInitExp
*ve
= (VoidInitExp
*)result
;
5884 const char *s
= ve
->var
->toChars();
5887 e
->error("reinterpretation through overlapped field %s is not allowed in CTFE", s
);
5888 result
= CTFEExp::cantexp
;
5891 e
->error("cannot read uninitialized variable %s in CTFE", s
);
5892 result
= CTFEExp::cantexp
;
5896 if (v
->type
->ty
!= result
->type
->ty
&& v
->type
->ty
== Tsarray
)
5898 // Block assignment from inside struct literals
5899 TypeSArray
*tsa
= (TypeSArray
*)v
->type
;
5900 size_t len
= (size_t)tsa
->dim
->toInteger();
5901 result
= createBlockDuplicatedArrayLiteral(ex
->loc
, v
->type
, ex
, len
);
5902 (*se
->elements
)[i
] = result
;
5906 void visit(RemoveExp
*e
)
5908 Expression
*agg
= interpret(e
->e1
, istate
);
5909 if (exceptionOrCant(agg
))
5911 Expression
*index
= interpret(e
->e2
, istate
);
5912 if (exceptionOrCant(index
))
5914 if (agg
->op
== TOKnull
)
5916 result
= CTFEExp::voidexp
;
5919 assert(agg
->op
== TOKassocarrayliteral
);
5920 AssocArrayLiteralExp
*aae
= (AssocArrayLiteralExp
*)agg
;
5921 Expressions
*keysx
= aae
->keys
;
5922 Expressions
*valuesx
= aae
->values
;
5924 for (size_t j
= 0; j
< valuesx
->dim
; ++j
)
5926 Expression
*ekey
= (*keysx
)[j
];
5927 int eq
= ctfeEqual(e
->loc
, TOKequal
, ekey
, index
);
5930 else if (removed
!= 0)
5932 (*keysx
)[j
- removed
] = ekey
;
5933 (*valuesx
)[j
- removed
] = (*valuesx
)[j
];
5936 valuesx
->dim
= valuesx
->dim
- removed
;
5937 keysx
->dim
= keysx
->dim
- removed
;
5938 new(pue
) IntegerExp(e
->loc
, removed
? 1 : 0, Type::tbool
);
5939 result
= pue
->exp();
5942 void visit(ClassReferenceExp
*e
)
5944 //printf("ClassReferenceExp::interpret() %s\n", e->value->toChars());
5948 void visit(VoidInitExp
*e
)
5950 e
->error("CTFE internal error: trying to read uninitialized variable");
5952 result
= CTFEExp::cantexp
;
5955 void visit(ThrownExceptionExp
*e
)
5957 assert(0); // This should never be interpreted
5963 /********************************************
5964 * Interpret the expression.
5966 * pue = non-null pointer to temporary storage that can be used to store the return value
5967 * e = Expression to interpret
5969 * goal = what the result will be used for
5971 * resulting expression
5974 static Expression
*interpret(UnionExp
*pue
, Expression
*e
, InterState
*istate
, CtfeGoal goal
)
5978 Interpreter
v(pue
, istate
, goal
);
5980 Expression
*ex
= v
.result
;
5981 assert(goal
== ctfeNeedNothing
|| ex
!= NULL
);
5986 Expression
*interpret(Expression
*e
, InterState
*istate
, CtfeGoal goal
)
5989 Expression
*result
= interpret(&ue
, e
, istate
, goal
);
5990 if (result
== ue
.exp())
5995 /***********************************
5996 * Interpret the statement.
5998 * pue = non-null pointer to temporary storage that can be used to store the return value
5999 * s = Statement to interpret
6002 * NULL continue to next statement
6003 * TOKcantexp cannot interpret statement at compile time
6004 * !NULL expression from return statement, or thrown exception
6007 static Expression
*interpret(UnionExp
*pue
, Statement
*s
, InterState
*istate
)
6011 Interpreter
v(pue
, istate
, ctfeNeedNothing
);
6016 Expression
*interpret(Statement
*s
, InterState
*istate
)
6019 Expression
*result
= interpret(&ue
, s
, istate
);
6020 if (result
== ue
.exp())
6025 Expression
*scrubArray(Loc loc
, Expressions
*elems
, bool structlit
= false);
6027 /* All results destined for use outside of CTFE need to have their CTFE-specific
6029 * In particular, all slices must be resolved.
6031 Expression
*scrubReturnValue(Loc loc
, Expression
*e
)
6033 if (e
->op
== TOKclassreference
)
6035 StructLiteralExp
*se
= ((ClassReferenceExp
*)e
)->value
;
6036 se
->ownedByCtfe
= OWNEDcode
;
6037 if (!(se
->stageflags
& stageScrub
))
6039 int old
= se
->stageflags
;
6040 se
->stageflags
|= stageScrub
;
6041 if (Expression
*ex
= scrubArray(loc
, se
->elements
, true))
6043 se
->stageflags
= old
;
6046 if (e
->op
== TOKvoid
)
6048 error(loc
, "uninitialized variable '%s' cannot be returned from CTFE", ((VoidInitExp
*)e
)->var
->toChars());
6049 return new ErrorExp();
6051 e
= resolveSlice(e
);
6052 if (e
->op
== TOKstructliteral
)
6054 StructLiteralExp
*se
= (StructLiteralExp
*)e
;
6055 se
->ownedByCtfe
= OWNEDcode
;
6056 if (!(se
->stageflags
& stageScrub
))
6058 int old
= se
->stageflags
;
6059 se
->stageflags
|= stageScrub
;
6060 if (Expression
*ex
= scrubArray(loc
, se
->elements
, true))
6062 se
->stageflags
= old
;
6065 if (e
->op
== TOKstring
)
6067 ((StringExp
*)e
)->ownedByCtfe
= OWNEDcode
;
6069 if (e
->op
== TOKarrayliteral
)
6071 ((ArrayLiteralExp
*)e
)->ownedByCtfe
= OWNEDcode
;
6072 if (Expression
*ex
= scrubArray(loc
, ((ArrayLiteralExp
*)e
)->elements
))
6075 if (e
->op
== TOKassocarrayliteral
)
6077 AssocArrayLiteralExp
*aae
= (AssocArrayLiteralExp
*)e
;
6078 aae
->ownedByCtfe
= OWNEDcode
;
6079 if (Expression
*ex
= scrubArray(loc
, aae
->keys
))
6081 if (Expression
*ex
= scrubArray(loc
, aae
->values
))
6083 aae
->type
= toBuiltinAAType(aae
->type
);
6088 // Return true if every element is either void,
6089 // or is an array literal or struct literal of void elements.
6090 bool isEntirelyVoid(Expressions
*elems
)
6092 for (size_t i
= 0; i
< elems
->dim
; i
++)
6094 Expression
*m
= (*elems
)[i
];
6095 // It can be NULL for performance reasons,
6096 // see StructLiteralExp::interpret().
6100 if (!(m
->op
== TOKvoid
) &&
6101 !(m
->op
== TOKarrayliteral
&& isEntirelyVoid(((ArrayLiteralExp
*)m
)->elements
)) &&
6102 !(m
->op
== TOKstructliteral
&& isEntirelyVoid(((StructLiteralExp
*)m
)->elements
)))
6110 // Scrub all members of an array. Return false if error
6111 Expression
*scrubArray(Loc loc
, Expressions
*elems
, bool structlit
)
6113 for (size_t i
= 0; i
< elems
->dim
; i
++)
6115 Expression
*m
= (*elems
)[i
];
6116 // It can be NULL for performance reasons,
6117 // see StructLiteralExp::interpret().
6121 // A struct .init may contain void members.
6122 // Static array members are a weird special case (bug 10994).
6124 ((m
->op
== TOKvoid
) ||
6125 (m
->op
== TOKarrayliteral
&& m
->type
->ty
== Tsarray
&& isEntirelyVoid(((ArrayLiteralExp
*)m
)->elements
)) ||
6126 (m
->op
== TOKstructliteral
&& isEntirelyVoid(((StructLiteralExp
*)m
)->elements
))))
6132 m
= scrubReturnValue(loc
, m
);
6133 if (CTFEExp::isCantExp(m
) || m
->op
== TOKerror
)
6141 Expression
*scrubArrayCache(Loc loc
, Expressions
*elems
);
6143 Expression
*scrubCacheValue(Loc loc
, Expression
*e
)
6145 if (e
->op
== TOKclassreference
)
6147 StructLiteralExp
*sle
= ((ClassReferenceExp
*)e
)->value
;
6148 sle
->ownedByCtfe
= OWNEDcache
;
6149 if (!(sle
->stageflags
& stageScrub
))
6151 int old
= sle
->stageflags
;
6152 sle
->stageflags
|= stageScrub
;
6153 if (Expression
*ex
= scrubArrayCache(loc
, sle
->elements
))
6155 sle
->stageflags
= old
;
6158 if (e
->op
== TOKstructliteral
)
6160 StructLiteralExp
*sle
= (StructLiteralExp
*)e
;
6161 sle
->ownedByCtfe
= OWNEDcache
;
6162 if (!(sle
->stageflags
& stageScrub
))
6164 int old
= sle
->stageflags
;
6165 sle
->stageflags
|= stageScrub
;
6166 if (Expression
*ex
= scrubArrayCache(loc
, sle
->elements
))
6168 sle
->stageflags
= old
;
6171 if (e
->op
== TOKstring
)
6173 ((StringExp
*)e
)->ownedByCtfe
= OWNEDcache
;
6175 if (e
->op
== TOKarrayliteral
)
6177 ((ArrayLiteralExp
*)e
)->ownedByCtfe
= OWNEDcache
;
6178 if (Expression
*ex
= scrubArrayCache(loc
, ((ArrayLiteralExp
*)e
)->elements
))
6181 if (e
->op
== TOKassocarrayliteral
)
6183 AssocArrayLiteralExp
*aae
= (AssocArrayLiteralExp
*)e
;
6184 aae
->ownedByCtfe
= OWNEDcache
;
6185 if (Expression
*ex
= scrubArrayCache(loc
, aae
->keys
))
6187 if (Expression
*ex
= scrubArrayCache(loc
, aae
->values
))
6193 Expression
*scrubArrayCache(Loc loc
, Expressions
*elems
)
6195 for (size_t i
= 0; i
< elems
->dim
; i
++)
6197 Expression
*m
= (*elems
)[i
];
6200 (*elems
)[i
] = scrubCacheValue(loc
, m
);
6205 /******************************* Special Functions ***************************/
6207 Expression
*interpret_length(InterState
*istate
, Expression
*earg
)
6209 //printf("interpret_length()\n");
6210 earg
= interpret(earg
, istate
);
6211 if (exceptionOrCantInterpret(earg
))
6214 if (earg
->op
== TOKassocarrayliteral
)
6215 len
= ((AssocArrayLiteralExp
*)earg
)->keys
->dim
;
6217 assert(earg
->op
== TOKnull
);
6218 Expression
*e
= new IntegerExp(earg
->loc
, len
, Type::tsize_t
);
6222 Expression
*interpret_keys(InterState
*istate
, Expression
*earg
, Type
*returnType
)
6224 earg
= interpret(earg
, istate
);
6225 if (exceptionOrCantInterpret(earg
))
6227 if (earg
->op
== TOKnull
)
6228 return new NullExp(earg
->loc
, returnType
);
6229 if (earg
->op
!= TOKassocarrayliteral
&& earg
->type
->toBasetype()->ty
!= Taarray
)
6231 assert(earg
->op
== TOKassocarrayliteral
);
6232 AssocArrayLiteralExp
*aae
= (AssocArrayLiteralExp
*)earg
;
6233 ArrayLiteralExp
*ae
= new ArrayLiteralExp(aae
->loc
, aae
->keys
);
6234 ae
->ownedByCtfe
= aae
->ownedByCtfe
;
6235 ae
->type
= returnType
;
6236 return copyLiteral(ae
).copy();
6239 Expression
*interpret_values(InterState
*istate
, Expression
*earg
, Type
*returnType
)
6241 earg
= interpret(earg
, istate
);
6242 if (exceptionOrCantInterpret(earg
))
6244 if (earg
->op
== TOKnull
)
6245 return new NullExp(earg
->loc
, returnType
);
6246 if (earg
->op
!= TOKassocarrayliteral
&& earg
->type
->toBasetype()->ty
!= Taarray
)
6248 assert(earg
->op
== TOKassocarrayliteral
);
6249 AssocArrayLiteralExp
*aae
= (AssocArrayLiteralExp
*)earg
;
6250 ArrayLiteralExp
*ae
= new ArrayLiteralExp(aae
->loc
, aae
->values
);
6251 ae
->ownedByCtfe
= aae
->ownedByCtfe
;
6252 ae
->type
= returnType
;
6253 //printf("result is %s\n", e->toChars());
6254 return copyLiteral(ae
).copy();
6257 Expression
*interpret_dup(InterState
*istate
, Expression
*earg
)
6259 earg
= interpret(earg
, istate
);
6260 if (exceptionOrCantInterpret(earg
))
6262 if (earg
->op
== TOKnull
)
6263 return new NullExp(earg
->loc
, earg
->type
);
6264 if (earg
->op
!= TOKassocarrayliteral
&& earg
->type
->toBasetype()->ty
!= Taarray
)
6266 assert(earg
->op
== TOKassocarrayliteral
);
6267 AssocArrayLiteralExp
*aae
= (AssocArrayLiteralExp
*)copyLiteral(earg
).copy();
6268 for (size_t i
= 0; i
< aae
->keys
->dim
; i
++)
6270 if (Expression
*e
= evaluatePostblit(istate
, (*aae
->keys
)[i
]))
6272 if (Expression
*e
= evaluatePostblit(istate
, (*aae
->values
)[i
]))
6275 aae
->type
= earg
->type
->mutableOf(); // repaint type from const(int[int]) to const(int)[int]
6276 //printf("result is %s\n", aae->toChars());
6280 // signature is int delegate(ref Value) OR int delegate(ref Key, ref Value)
6281 Expression
*interpret_aaApply(InterState
*istate
, Expression
*aa
, Expression
*deleg
)
6283 aa
= interpret(aa
, istate
);
6284 if (exceptionOrCantInterpret(aa
))
6286 if (aa
->op
!= TOKassocarrayliteral
)
6287 return new IntegerExp(deleg
->loc
, 0, Type::tsize_t
);
6289 FuncDeclaration
*fd
= NULL
;
6290 Expression
*pthis
= NULL
;
6291 if (deleg
->op
== TOKdelegate
)
6293 fd
= ((DelegateExp
*)deleg
)->func
;
6294 pthis
= ((DelegateExp
*)deleg
)->e1
;
6296 else if (deleg
->op
== TOKfunction
)
6297 fd
= ((FuncExp
*)deleg
)->fd
;
6299 assert(fd
&& fd
->fbody
);
6300 assert(fd
->parameters
);
6301 size_t numParams
= fd
->parameters
->dim
;
6302 assert(numParams
== 1 || numParams
== 2);
6304 Parameter
*fparam
= Parameter::getNth(((TypeFunction
*)fd
->type
)->parameters
, numParams
- 1);
6305 bool wantRefValue
= 0 != (fparam
->storageClass
& (STCout
| STCref
));
6308 args
.setDim(numParams
);
6310 AssocArrayLiteralExp
*ae
= (AssocArrayLiteralExp
*)aa
;
6311 if (!ae
->keys
|| ae
->keys
->dim
== 0)
6312 return new IntegerExp(deleg
->loc
, 0, Type::tsize_t
);
6313 Expression
*eresult
;
6315 for (size_t i
= 0; i
< ae
->keys
->dim
; ++i
)
6317 Expression
*ekey
= (*ae
->keys
)[i
];
6318 Expression
*evalue
= (*ae
->values
)[i
];
6321 Type
*t
= evalue
->type
;
6322 evalue
= new IndexExp(deleg
->loc
, ae
, ekey
);
6325 args
[numParams
- 1] = evalue
;
6326 if (numParams
== 2) args
[0] = ekey
;
6328 eresult
= interpretFunction(fd
, istate
, &args
, pthis
);
6329 if (exceptionOrCantInterpret(eresult
))
6332 assert(eresult
->op
== TOKint64
);
6333 if (((IntegerExp
*)eresult
)->getInteger() != 0)
6339 // Helper function: given a function of type A[] f(...),
6341 Type
*returnedArrayType(FuncDeclaration
*fd
)
6343 assert(fd
->type
->ty
== Tfunction
);
6344 assert(fd
->type
->nextOf()->ty
== Tarray
);
6345 return ((TypeFunction
*)fd
->type
)->nextOf();
6348 /* Decoding UTF strings for foreach loops. Duplicates the functionality of
6349 * the twelve _aApplyXXn functions in aApply.d in the runtime.
6351 Expression
*foreachApplyUtf(InterState
*istate
, Expression
*str
, Expression
*deleg
, bool rvs
)
6353 FuncDeclaration
*fd
= NULL
;
6354 Expression
*pthis
= NULL
;
6355 if (deleg
->op
== TOKdelegate
)
6357 fd
= ((DelegateExp
*)deleg
)->func
;
6358 pthis
= ((DelegateExp
*)deleg
)->e1
;
6360 else if (deleg
->op
== TOKfunction
)
6361 fd
= ((FuncExp
*)deleg
)->fd
;
6363 assert(fd
&& fd
->fbody
);
6364 assert(fd
->parameters
);
6365 size_t numParams
= fd
->parameters
->dim
;
6366 assert(numParams
== 1 || numParams
== 2);
6367 Type
*charType
= (*fd
->parameters
)[numParams
-1]->type
;
6368 Type
*indexType
= numParams
== 2 ? (*fd
->parameters
)[0]->type
6370 size_t len
= (size_t)resolveArrayLength(str
);
6372 return new IntegerExp(deleg
->loc
, 0, indexType
);
6374 str
= resolveSlice(str
);
6376 StringExp
*se
= NULL
;
6377 ArrayLiteralExp
*ale
= NULL
;
6378 if (str
->op
== TOKstring
)
6379 se
= (StringExp
*) str
;
6380 else if (str
->op
== TOKarrayliteral
)
6381 ale
= (ArrayLiteralExp
*)str
;
6384 str
->error("CTFE internal error: cannot foreach %s", str
->toChars());
6385 return CTFEExp::cantexp
;
6388 args
.setDim(numParams
);
6390 Expression
*eresult
= NULL
; // ded-store to prevent spurious warning
6392 // Buffers for encoding; also used for decoding array literals
6394 unsigned short utf16buf
[2];
6396 size_t start
= rvs
? len
: 0;
6397 size_t end
= rvs
? 0: len
;
6398 for (size_t indx
= start
; indx
!= end
;)
6400 // Step 1: Decode the next dchar from the string.
6402 const char *errmsg
= NULL
; // Used for reporting decoding errors
6403 dchar_t rawvalue
; // Holds the decoded dchar
6404 size_t currentIndex
= indx
; // The index of the decoded character
6408 // If it is an array literal, copy the code points into the buffer
6409 size_t buflen
= 1; // #code points in the buffer
6410 size_t n
= 1; // #code points in this char
6411 size_t sz
= (size_t)ale
->type
->nextOf()->size();
6418 // find the start of the string
6421 while (indx
> 0 && buflen
< 4)
6423 Expression
* r
= (*ale
->elements
)[indx
];
6424 assert(r
->op
== TOKint64
);
6425 utf8_t x
= (utf8_t
)(((IntegerExp
*)r
)->getInteger());
6426 if ((x
& 0xC0) != 0x80)
6432 buflen
= (indx
+ 4 > len
) ? len
- indx
: 4;
6433 for (size_t i
= 0; i
< buflen
; ++i
)
6435 Expression
* r
= (*ale
->elements
)[indx
+ i
];
6436 assert(r
->op
== TOKint64
);
6437 utf8buf
[i
] = (utf8_t
)(((IntegerExp
*)r
)->getInteger());
6440 errmsg
= utf_decodeChar(&utf8buf
[0], buflen
, &n
, &rawvalue
);
6445 // find the start of the string
6448 Expression
* r
= (*ale
->elements
)[indx
];
6449 assert(r
->op
== TOKint64
);
6450 unsigned short x
= (unsigned short)(((IntegerExp
*)r
)->getInteger());
6451 if (indx
> 0 && x
>= 0xDC00 && x
<= 0xDFFF)
6458 buflen
= (indx
+ 2 > len
) ? len
- indx
: 2;
6459 for (size_t i
=0; i
< buflen
; ++i
)
6461 Expression
* r
= (*ale
->elements
)[indx
+ i
];
6462 assert(r
->op
== TOKint64
);
6463 utf16buf
[i
] = (unsigned short)(((IntegerExp
*)r
)->getInteger());
6466 errmsg
= utf_decodeWchar(&utf16buf
[0], buflen
, &n
, &rawvalue
);
6473 Expression
* r
= (*ale
->elements
)[indx
];
6474 assert(r
->op
== TOKint64
);
6475 rawvalue
= (dchar_t
)((IntegerExp
*)r
)->getInteger();
6488 size_t saveindx
; // used for reverse iteration
6495 // find the start of the string
6496 utf8_t
*s
= (utf8_t
*)se
->string
;
6498 while (indx
> 0 && ((s
[indx
]&0xC0) == 0x80))
6502 errmsg
= utf_decodeChar((utf8_t
*)se
->string
, se
->len
, &indx
, &rawvalue
);
6510 unsigned short *s
= (unsigned short *)se
->string
;
6512 if (s
[indx
] >= 0xDC00 && s
[indx
]<= 0xDFFF)
6516 errmsg
= utf_decodeWchar((unsigned short *)se
->string
, se
->len
, &indx
, &rawvalue
);
6523 rawvalue
= ((unsigned *)(se
->string
))[indx
];
6533 deleg
->error("%s", errmsg
);
6534 return CTFEExp::cantexp
;
6537 // Step 2: encode the dchar in the target encoding
6539 int charlen
= 1; // How many codepoints are involved?
6540 switch (charType
->size())
6543 charlen
= utf_codeLengthChar(rawvalue
);
6544 utf_encodeChar(&utf8buf
[0], rawvalue
);
6547 charlen
= utf_codeLengthWchar(rawvalue
);
6548 utf_encodeWchar(&utf16buf
[0], rawvalue
);
6556 currentIndex
= indx
;
6558 // Step 3: call the delegate once for each code point
6560 // The index only needs to be set once
6562 args
[0] = new IntegerExp(deleg
->loc
, currentIndex
, indexType
);
6564 Expression
*val
= NULL
;
6566 for (int k
= 0; k
< charlen
; ++k
)
6569 switch (charType
->size())
6572 codepoint
= utf8buf
[k
];
6575 codepoint
= utf16buf
[k
];
6578 codepoint
= rawvalue
;
6583 val
= new IntegerExp(str
->loc
, codepoint
, charType
);
6585 args
[numParams
- 1] = val
;
6587 eresult
= interpretFunction(fd
, istate
, &args
, pthis
);
6588 if (exceptionOrCantInterpret(eresult
))
6590 assert(eresult
->op
== TOKint64
);
6591 if (((IntegerExp
*)eresult
)->getInteger() != 0)
6598 /* If this is a built-in function, return the interpreted result,
6599 * Otherwise, return NULL.
6601 Expression
*evaluateIfBuiltin(InterState
*istate
, Loc loc
,
6602 FuncDeclaration
*fd
, Expressions
*arguments
, Expression
*pthis
)
6604 Expression
*e
= NULL
;
6605 size_t nargs
= arguments
? arguments
->dim
: 0;
6608 if (isBuiltin(fd
) == BUILTINyes
)
6612 for (size_t i
= 0; i
< args
.dim
; i
++)
6614 Expression
*earg
= (*arguments
)[i
];
6615 earg
= interpret(earg
, istate
);
6616 if (exceptionOrCantInterpret(earg
))
6620 e
= eval_builtin(loc
, fd
, &args
);
6623 error(loc
, "cannot evaluate unimplemented builtin %s at compile time", fd
->toChars());
6624 e
= CTFEExp::cantexp
;
6630 Expression
*firstarg
= nargs
> 0 ? (*arguments
)[0] : NULL
;
6631 if (firstarg
&& firstarg
->type
->toBasetype()->ty
== Taarray
)
6633 TypeAArray
*firstAAtype
= (TypeAArray
*)firstarg
->type
;
6634 const char *id
= fd
->ident
->toChars();
6635 if (nargs
== 1 && fd
->ident
== Id::aaLen
)
6636 return interpret_length(istate
, firstarg
);
6637 if (nargs
== 3 && !strcmp(id
, "_aaApply"))
6638 return interpret_aaApply(istate
, firstarg
, (Expression
*)(arguments
->data
[2]));
6639 if (nargs
== 3 && !strcmp(id
, "_aaApply2"))
6640 return interpret_aaApply(istate
, firstarg
, (Expression
*)(arguments
->data
[2]));
6641 if (nargs
== 1 && !strcmp(id
, "keys") && !strcmp(fd
->toParent2()->ident
->toChars(), "object"))
6642 return interpret_keys(istate
, firstarg
, firstAAtype
->index
->arrayOf());
6643 if (nargs
== 1 && !strcmp(id
, "values") && !strcmp(fd
->toParent2()->ident
->toChars(), "object"))
6644 return interpret_values(istate
, firstarg
, firstAAtype
->nextOf()->arrayOf());
6645 if (nargs
== 1 && !strcmp(id
, "rehash") && !strcmp(fd
->toParent2()->ident
->toChars(), "object"))
6646 return interpret(firstarg
, istate
);
6647 if (nargs
== 1 && !strcmp(id
, "dup") && !strcmp(fd
->toParent2()->ident
->toChars(), "object"))
6648 return interpret_dup(istate
, firstarg
);
6651 if (pthis
&& !fd
->fbody
&& fd
->isCtorDeclaration() && fd
->parent
&& fd
->parent
->parent
&& fd
->parent
->parent
->ident
== Id::object
)
6653 if (pthis
->op
== TOKclassreference
&& fd
->parent
->ident
== Id::Throwable
)
6655 // At present, the constructors just copy their arguments into the struct.
6656 // But we might need some magic if stack tracing gets added to druntime.
6657 StructLiteralExp
*se
= ((ClassReferenceExp
*)pthis
)->value
;
6658 assert(arguments
->dim
<= se
->elements
->dim
);
6659 for (size_t i
= 0; i
< arguments
->dim
; ++i
)
6661 e
= interpret((*arguments
)[i
], istate
);
6662 if (exceptionOrCantInterpret(e
))
6664 (*se
->elements
)[i
] = e
;
6666 return CTFEExp::voidexp
;
6669 if (nargs
== 1 && !pthis
&&
6670 (fd
->ident
== Id::criticalenter
|| fd
->ident
== Id::criticalexit
))
6672 // Support synchronized{} as a no-op
6673 return CTFEExp::voidexp
;
6677 const char *id
= fd
->ident
->toChars();
6678 size_t idlen
= strlen(id
);
6679 if (nargs
== 2 && (idlen
== 10 || idlen
== 11) &&
6680 !strncmp(id
, "_aApply", 7))
6682 // Functions from aApply.d and aApplyR.d in the runtime
6683 bool rvs
= (idlen
== 11); // true if foreach_reverse
6684 char c
= id
[idlen
-3]; // char width: 'c', 'w', or 'd'
6685 char s
= id
[idlen
-2]; // string width: 'c', 'w', or 'd'
6686 char n
= id
[idlen
-1]; // numParams: 1 or 2.
6687 // There are 12 combinations
6688 if ((n
== '1' || n
== '2') &&
6689 (c
== 'c' || c
== 'w' || c
== 'd') &&
6690 (s
== 'c' || s
== 'w' || s
== 'd') && c
!= s
)
6692 Expression
*str
= (*arguments
)[0];
6693 str
= interpret(str
, istate
);
6694 if (exceptionOrCantInterpret(str
))
6696 return foreachApplyUtf(istate
, str
, (*arguments
)[1], rvs
);
6703 Expression
*evaluatePostblit(InterState
*istate
, Expression
*e
)
6705 Type
*tb
= e
->type
->baseElemOf();
6706 if (tb
->ty
!= Tstruct
)
6708 StructDeclaration
*sd
= ((TypeStruct
*)tb
)->sym
;
6712 if (e
->op
== TOKarrayliteral
)
6714 ArrayLiteralExp
*ale
= (ArrayLiteralExp
*)e
;
6715 for (size_t i
= 0; i
< ale
->elements
->dim
; i
++)
6717 e
= evaluatePostblit(istate
, (*ale
->elements
)[i
]);
6723 if (e
->op
== TOKstructliteral
)
6726 e
= interpretFunction(sd
->postblit
, istate
, NULL
, e
);
6727 if (exceptionOrCantInterpret(e
))
6735 Expression
*evaluateDtor(InterState
*istate
, Expression
*e
)
6737 Type
*tb
= e
->type
->baseElemOf();
6738 if (tb
->ty
!= Tstruct
)
6740 StructDeclaration
*sd
= ((TypeStruct
*)tb
)->sym
;
6744 if (e
->op
== TOKarrayliteral
)
6746 ArrayLiteralExp
*alex
= (ArrayLiteralExp
*)e
;
6747 for (size_t i
= alex
->elements
->dim
; 0 < i
--; )
6748 e
= evaluateDtor(istate
, (*alex
->elements
)[i
]);
6750 else if (e
->op
== TOKstructliteral
)
6753 e
= interpretFunction(sd
->dtor
, istate
, NULL
, e
);
6757 if (exceptionOrCantInterpret(e
))
6762 /*************************** CTFE Sanity Checks ***************************/
6764 /* Setter functions for CTFE variable values.
6765 * These functions exist to check for compiler CTFE bugs.
6767 bool hasValue(VarDeclaration
*vd
)
6769 if (vd
->ctfeAdrOnStack
== -1)
6771 return NULL
!= getValue(vd
);
6774 Expression
*getValue(VarDeclaration
*vd
)
6776 return ctfeStack
.getValue(vd
);
6779 void setValueNull(VarDeclaration
*vd
)
6781 ctfeStack
.setValue(vd
, NULL
);
6784 // Don't check for validity
6785 void setValueWithoutChecking(VarDeclaration
*vd
, Expression
*newval
)
6787 ctfeStack
.setValue(vd
, newval
);
6790 void setValue(VarDeclaration
*vd
, Expression
*newval
)
6792 assert((vd
->storage_class
& (STCout
| STCref
))
6793 ? isCtfeReferenceValid(newval
)
6794 : isCtfeValueValid(newval
));
6795 ctfeStack
.setValue(vd
, newval
);