xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/d/dmd/ctfeexpr.c (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
1 
2 /* Compiler implementation of the D programming language
3  * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved
4  * written by Walter Bright
5  * http://www.digitalmars.com
6  * Distributed under the Boost Software License, Version 1.0.
7  * http://www.boost.org/LICENSE_1_0.txt
8  * https://github.com/D-Programming-Language/dmd/blob/master/src/ctfeexpr.c
9  */
10 
11 #include "root/dsystem.h"               // mem{cpy|set}()
12 #include "root/rmem.h"
13 
14 #include "mars.h"
15 #include "expression.h"
16 #include "declaration.h"
17 #include "aggregate.h"
18 // for AssocArray
19 #include "id.h"
20 #include "utf.h"
21 #include "template.h"
22 #include "ctfe.h"
23 
24 int RealEquals(real_t x1, real_t x2);
25 
26 /************** ClassReferenceExp ********************************************/
27 
ClassReferenceExp(Loc loc,StructLiteralExp * lit,Type * type)28 ClassReferenceExp::ClassReferenceExp(Loc loc, StructLiteralExp *lit, Type *type)
29     : Expression(loc, TOKclassreference, sizeof(ClassReferenceExp))
30 {
31     assert(lit && lit->sd && lit->sd->isClassDeclaration());
32     this->value = lit;
33     this->type = type;
34 }
35 
originalClass()36 ClassDeclaration *ClassReferenceExp::originalClass()
37 {
38     return value->sd->isClassDeclaration();
39 }
40 
41 // Return index of the field, or -1 if not found
getFieldIndex(Type * fieldtype,unsigned fieldoffset)42 int ClassReferenceExp::getFieldIndex(Type *fieldtype, unsigned fieldoffset)
43 {
44     ClassDeclaration *cd = originalClass();
45     unsigned fieldsSoFar = 0;
46     for (size_t j = 0; j < value->elements->dim; j++)
47     {
48         while (j - fieldsSoFar >= cd->fields.dim)
49         {
50             fieldsSoFar += cd->fields.dim;
51             cd = cd->baseClass;
52         }
53         VarDeclaration *v2 = cd->fields[j - fieldsSoFar];
54         if (fieldoffset == v2->offset &&
55             fieldtype->size() == v2->type->size())
56         {
57             return (int)(value->elements->dim - fieldsSoFar - cd->fields.dim + (j-fieldsSoFar));
58         }
59     }
60     return -1;
61 }
62 
63 // Return index of the field, or -1 if not found
64 // Same as getFieldIndex, but checks for a direct match with the VarDeclaration
findFieldIndexByName(VarDeclaration * v)65 int ClassReferenceExp::findFieldIndexByName(VarDeclaration *v)
66 {
67     ClassDeclaration *cd = originalClass();
68     size_t fieldsSoFar = 0;
69     for (size_t j = 0; j < value->elements->dim; j++)
70     {
71         while (j - fieldsSoFar >= cd->fields.dim)
72         {
73             fieldsSoFar += cd->fields.dim;
74             cd = cd->baseClass;
75         }
76         VarDeclaration *v2 = cd->fields[j - fieldsSoFar];
77         if (v == v2)
78         {
79             return (int)(value->elements->dim - fieldsSoFar - cd->fields.dim + (j-fieldsSoFar));
80         }
81     }
82     return -1;
83 }
84 
85 /************** VoidInitExp ********************************************/
86 
VoidInitExp(VarDeclaration * var,Type *)87 VoidInitExp::VoidInitExp(VarDeclaration *var, Type *)
88     : Expression(var->loc, TOKvoid, sizeof(VoidInitExp))
89 {
90     this->var = var;
91     this->type = var->type;
92 }
93 
toChars()94 const char *VoidInitExp::toChars()
95 {
96     return "void";
97 }
98 
99 // Return index of the field, or -1 if not found
100 // Same as getFieldIndex, but checks for a direct match with the VarDeclaration
findFieldIndexByName(StructDeclaration * sd,VarDeclaration * v)101 int findFieldIndexByName(StructDeclaration *sd, VarDeclaration *v)
102 {
103     for (size_t i = 0; i < sd->fields.dim; ++i)
104     {
105         if (sd->fields[i] == v)
106             return (int)i;
107     }
108     return -1;
109 }
110 
111 /************** ThrownExceptionExp ********************************************/
112 
ThrownExceptionExp(Loc loc,ClassReferenceExp * victim)113 ThrownExceptionExp::ThrownExceptionExp(Loc loc, ClassReferenceExp *victim) : Expression(loc, TOKthrownexception, sizeof(ThrownExceptionExp))
114 {
115     this->thrown = victim;
116     this->type = victim->type;
117 }
118 
toChars()119 const char *ThrownExceptionExp::toChars()
120 {
121     return "CTFE ThrownException";
122 }
123 
124 // Generate an error message when this exception is not caught
generateUncaughtError()125 void ThrownExceptionExp::generateUncaughtError()
126 {
127     UnionExp ue;
128     Expression *e = resolveSlice((*thrown->value->elements)[0], &ue);
129     StringExp *se = e->toStringExp();
130     thrown->error("uncaught CTFE exception %s(%s)", thrown->type->toChars(), se ? se->toChars() : e->toChars());
131 
132     /* Also give the line where the throw statement was. We won't have it
133      * in the case where the ThrowStatement is generated internally
134      * (eg, in ScopeStatement)
135      */
136     if (loc.filename && !loc.equals(thrown->loc))
137         errorSupplemental(loc, "thrown from here");
138 }
139 
140 // True if 'e' is CTFEExp::cantexp, or an exception
exceptionOrCantInterpret(Expression * e)141 bool exceptionOrCantInterpret(Expression *e)
142 {
143     return e && (e->op == TOKcantexp || e->op == TOKthrownexception);
144 }
145 
146 /********************** CTFEExp ******************************************/
147 
148 CTFEExp *CTFEExp::cantexp;
149 CTFEExp *CTFEExp::voidexp;
150 CTFEExp *CTFEExp::breakexp;
151 CTFEExp *CTFEExp::continueexp;
152 CTFEExp *CTFEExp::gotoexp;
153 
CTFEExp(TOK tok)154 CTFEExp::CTFEExp(TOK tok)
155     : Expression(Loc(), tok, sizeof(CTFEExp))
156 {
157     type = Type::tvoid;
158 }
159 
toChars()160 const char *CTFEExp::toChars()
161 {
162     switch (op)
163     {
164         case TOKcantexp:    return "<cant>";
165         case TOKvoidexp:    return "<void>";
166         case TOKbreak:      return "<break>";
167         case TOKcontinue:   return "<continue>";
168         case TOKgoto:       return "<goto>";
169         default:            assert(0);  return NULL;
170     }
171 }
172 
copy()173 Expression *UnionExp::copy()
174 {
175     Expression *e = exp();
176     //if (e->size > sizeof(u)) printf("%s\n", Token::toChars(e->op));
177     assert(e->size <= sizeof(u));
178     if (e->op == TOKcantexp)    return CTFEExp::cantexp;
179     if (e->op == TOKvoidexp)    return CTFEExp::voidexp;
180     if (e->op == TOKbreak)      return CTFEExp::breakexp;
181     if (e->op == TOKcontinue)   return CTFEExp::continueexp;
182     if (e->op == TOKgoto)       return CTFEExp::gotoexp;
183     return e->copy();
184 }
185 
186 /************** Aggregate literals (AA/string/array/struct) ******************/
187 
188 // Given expr, which evaluates to an array/AA/string literal,
189 // return true if it needs to be copied
needToCopyLiteral(Expression * expr)190 bool needToCopyLiteral(Expression *expr)
191 {
192     for (;;)
193     {
194         switch (expr->op)
195         {
196             case TOKarrayliteral:
197                 return ((ArrayLiteralExp *)expr)->ownedByCtfe == OWNEDcode;
198             case TOKassocarrayliteral:
199                 return ((AssocArrayLiteralExp *)expr)->ownedByCtfe == OWNEDcode;
200             case TOKstructliteral:
201                 return ((StructLiteralExp *)expr)->ownedByCtfe == OWNEDcode;
202             case TOKstring:
203             case TOKthis:
204             case TOKvar:
205                 return false;
206             case TOKassign:
207                 return false;
208             case TOKindex:
209             case TOKdotvar:
210             case TOKslice:
211             case TOKcast:
212                 expr = ((UnaExp *)expr)->e1;
213                 continue;
214             case TOKcat:
215                 return needToCopyLiteral(((BinExp *)expr)->e1) ||
216                     needToCopyLiteral(((BinExp *)expr)->e2);
217             case TOKcatass:
218                 expr = ((BinExp *)expr)->e2;
219                 continue;
220             default:
221                 return false;
222         }
223     }
224 }
225 
226 Expressions *copyLiteralArray(Expressions *oldelems, Expression *basis = NULL)
227 {
228     if (!oldelems)
229         return oldelems;
230     CtfeStatus::numArrayAllocs++;
231     Expressions *newelems = new Expressions();
232     newelems->setDim(oldelems->dim);
233     for (size_t i = 0; i < oldelems->dim; i++)
234     {
235         Expression *el = (*oldelems)[i];
236         if (!el)
237             el = basis;
238         (*newelems)[i] = copyLiteral(el).copy();
239     }
240     return newelems;
241 }
242 
243 // Make a copy of the ArrayLiteral, AALiteral, String, or StructLiteral.
244 // This value will be used for in-place modification.
copyLiteral(Expression * e)245 UnionExp copyLiteral(Expression *e)
246 {
247     UnionExp ue;
248     if (e->op == TOKstring) // syntaxCopy doesn't make a copy for StringExp!
249     {
250         StringExp *se = (StringExp *)e;
251         utf8_t *s = (utf8_t *)mem.xcalloc(se->len + 1, se->sz);
252         memcpy(s, se->string, se->len * se->sz);
253         new(&ue) StringExp(se->loc, s, se->len);
254         StringExp *se2 = (StringExp *)ue.exp();
255         se2->committed = se->committed;
256         se2->postfix = se->postfix;
257         se2->type = se->type;
258         se2->sz = se->sz;
259         se2->ownedByCtfe = OWNEDctfe;
260         return ue;
261     }
262     if (e->op == TOKarrayliteral)
263     {
264         ArrayLiteralExp *ale = (ArrayLiteralExp *)e;
265         Expressions *elements = copyLiteralArray(ale->elements, ale->basis);
266 
267         new(&ue) ArrayLiteralExp(e->loc, e->type, elements);
268 
269         ArrayLiteralExp *r = (ArrayLiteralExp *)ue.exp();
270         r->ownedByCtfe = OWNEDctfe;
271         return ue;
272     }
273     if (e->op == TOKassocarrayliteral)
274     {
275         AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)e;
276         new(&ue) AssocArrayLiteralExp(e->loc, copyLiteralArray(aae->keys), copyLiteralArray(aae->values));
277         AssocArrayLiteralExp *r = (AssocArrayLiteralExp *)ue.exp();
278         r->type = e->type;
279         r->ownedByCtfe = OWNEDctfe;
280         return ue;
281     }
282     if (e->op == TOKstructliteral)
283     {
284         /* syntaxCopy doesn't work for struct literals, because of a nasty special
285          * case: block assignment is permitted inside struct literals, eg,
286          * an int[4] array can be initialized with a single int.
287          */
288         StructLiteralExp *sle = (StructLiteralExp *)e;
289         Expressions *oldelems = sle->elements;
290         Expressions * newelems = new Expressions();
291         newelems->setDim(oldelems->dim);
292         for (size_t i = 0; i < newelems->dim; i++)
293         {
294             // We need the struct definition to detect block assignment
295             VarDeclaration *v = sle->sd->fields[i];
296             Expression *m = (*oldelems)[i];
297 
298             // If it is a void assignment, use the default initializer
299             if (!m)
300                 m = voidInitLiteral(v->type, v).copy();
301 
302             if (v->type->ty == Tarray || v->type->ty == Taarray)
303             {
304                 // Don't have to copy array references
305             }
306             else
307             {
308                 // Buzilla 15681: Copy the source element always.
309                 m = copyLiteral(m).copy();
310 
311                 // Block assignment from inside struct literals
312                 if (v->type->ty != m->type->ty && v->type->ty == Tsarray)
313                 {
314                     TypeSArray *tsa = (TypeSArray *)v->type;
315                     size_t len = (size_t)tsa->dim->toInteger();
316                     UnionExp uex;
317                     m = createBlockDuplicatedArrayLiteral(&uex, e->loc, v->type, m, len);
318                     if (m == uex.exp())
319                         m = uex.copy();
320                 }
321             }
322             (*newelems)[i] = m;
323         }
324         new(&ue) StructLiteralExp(e->loc, sle->sd, newelems, sle->stype);
325         StructLiteralExp *r = (StructLiteralExp *)ue.exp();
326         r->type = e->type;
327         r->ownedByCtfe = OWNEDctfe;
328         r->origin = ((StructLiteralExp *)e)->origin;
329         return ue;
330     }
331     if (e->op == TOKfunction || e->op == TOKdelegate ||
332         e->op == TOKsymoff || e->op == TOKnull ||
333         e->op == TOKvar || e->op == TOKdotvar ||
334         e->op == TOKint64 || e->op == TOKfloat64 ||
335         e->op == TOKchar || e->op == TOKcomplex80 ||
336         e->op == TOKvoid || e->op == TOKvector ||
337         e->op == TOKtypeid)
338     {
339         // Simple value types
340         // Keep e1 for DelegateExp and DotVarExp
341         new(&ue) UnionExp(e);
342         Expression *r = ue.exp();
343         r->type = e->type;
344         return ue;
345     }
346     if (e->op == TOKslice)
347     {
348         SliceExp *se = (SliceExp *)e;
349         if (se->type->toBasetype()->ty == Tsarray)
350         {
351             // same with resolveSlice()
352             if (se->e1->op == TOKnull)
353             {
354                 new(&ue) NullExp(se->loc, se->type);
355                 return ue;
356             }
357             ue = Slice(se->type, se->e1, se->lwr, se->upr);
358             assert(ue.exp()->op == TOKarrayliteral);
359             ArrayLiteralExp *r = (ArrayLiteralExp *)ue.exp();
360             r->elements = copyLiteralArray(r->elements);
361             r->ownedByCtfe = OWNEDctfe;
362             return ue;
363         }
364         else
365         {
366             // Array slices only do a shallow copy
367             new(&ue) SliceExp(e->loc, se->e1, se->lwr, se->upr);
368             Expression *r = ue.exp();
369             r->type = e->type;
370             return ue;
371         }
372     }
373     if (isPointer(e->type))
374     {
375         // For pointers, we only do a shallow copy.
376         if (e->op == TOKaddress)
377             new(&ue) AddrExp(e->loc, ((AddrExp *)e)->e1);
378         else if (e->op == TOKindex)
379             new(&ue) IndexExp(e->loc, ((IndexExp *)e)->e1, ((IndexExp *)e)->e2);
380         else if (e->op == TOKdotvar)
381         {
382             new(&ue) DotVarExp(e->loc, ((DotVarExp *)e)->e1,
383                 ((DotVarExp *)e)->var, ((DotVarExp *)e)->hasOverloads);
384         }
385         else
386             assert(0);
387         Expression *r = ue.exp();
388         r->type = e->type;
389         return ue;
390     }
391     if (e->op == TOKclassreference)
392     {
393         new(&ue) ClassReferenceExp(e->loc, ((ClassReferenceExp *)e)->value, e->type);
394         return ue;
395     }
396     if (e->op == TOKerror)
397     {
398         new(&ue) UnionExp(e);
399         return ue;
400     }
401     e->error("CTFE internal error: literal %s", e->toChars());
402     assert(0);
403     return ue;
404 }
405 
406 /* Deal with type painting.
407  * Type painting is a major nuisance: we can't just set
408  * e->type = type, because that would change the original literal.
409  * But, we can't simply copy the literal either, because that would change
410  * the values of any pointers.
411  */
paintTypeOntoLiteral(Type * type,Expression * lit)412 Expression *paintTypeOntoLiteral(Type *type, Expression *lit)
413 {
414     if (lit->type->equals(type))
415         return lit;
416     return paintTypeOntoLiteralCopy(type, lit).copy();
417 }
418 
paintTypeOntoLiteral(UnionExp * pue,Type * type,Expression * lit)419 Expression *paintTypeOntoLiteral(UnionExp *pue, Type *type, Expression *lit)
420 {
421     if (lit->type->equals(type))
422         return lit;
423     *pue = paintTypeOntoLiteralCopy(type, lit);
424     return pue->exp();
425 }
426 
paintTypeOntoLiteralCopy(Type * type,Expression * lit)427 UnionExp paintTypeOntoLiteralCopy(Type *type, Expression *lit)
428 {
429     UnionExp ue;
430 
431     if (lit->type->equals(type))
432     {
433         new(&ue) UnionExp(lit);
434         return ue;
435     }
436 
437     // If it is a cast to inout, retain the original type of the referenced part.
438     if (type->hasWild() && type->hasPointers())
439     {
440         new(&ue) UnionExp(lit);
441         ue.exp()->type = type;
442         return ue;
443     }
444 
445     if (lit->op == TOKslice)
446     {
447         SliceExp *se = (SliceExp *)lit;
448         new(&ue) SliceExp(lit->loc, se->e1, se->lwr, se->upr);
449     }
450     else if (lit->op == TOKindex)
451     {
452         IndexExp *ie = (IndexExp *)lit;
453         new(&ue) IndexExp(lit->loc, ie->e1, ie->e2);
454     }
455     else if (lit->op == TOKarrayliteral)
456     {
457         new(&ue) SliceExp(lit->loc, lit,
458             new IntegerExp(Loc(), 0, Type::tsize_t), ArrayLength(Type::tsize_t, lit).copy());
459     }
460     else if (lit->op == TOKstring)
461     {
462         // For strings, we need to introduce another level of indirection
463         new(&ue) SliceExp(lit->loc, lit,
464             new IntegerExp(Loc(), 0, Type::tsize_t), ArrayLength(Type::tsize_t, lit).copy());
465     }
466     else if (lit->op == TOKassocarrayliteral)
467     {
468         AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)lit;
469         // TODO: we should be creating a reference to this AAExp, not
470         // just a ref to the keys and values.
471         OwnedBy wasOwned = aae->ownedByCtfe;
472         new(&ue) AssocArrayLiteralExp(lit->loc, aae->keys, aae->values);
473         aae = (AssocArrayLiteralExp *)ue.exp();
474         aae->ownedByCtfe = wasOwned;
475     }
476     else
477     {
478         // Can't type paint from struct to struct*; this needs another
479         // level of indirection
480         if (lit->op == TOKstructliteral && isPointer(type))
481             lit->error("CTFE internal error: painting %s", type->toChars());
482         ue = copyLiteral(lit);
483     }
484     ue.exp()->type = type;
485     return ue;
486 }
487 
488 /*************************************
489  * If e is a SliceExp, constant fold it.
490  * Params:
491  *      e = expression to resolve
492  *      pue = if not null, store resulting expression here
493  * Returns:
494  *      resulting expression
495  */
resolveSlice(Expression * e,UnionExp * pue)496 Expression *resolveSlice(Expression *e, UnionExp *pue)
497 {
498     if (e->op != TOKslice)
499         return e;
500     SliceExp *se = (SliceExp *)e;
501     if (se->e1->op == TOKnull)
502         return se->e1;
503     if (pue)
504     {
505         *pue = Slice(e->type, se->e1, se->lwr, se->upr);
506         return pue->exp();
507     }
508     else
509         return Slice(e->type, se->e1, se->lwr, se->upr).copy();
510 }
511 
512 /* Determine the array length, without interpreting it.
513  * e must be an array literal, or a slice
514  * It's very wasteful to resolve the slice when we only
515  * need the length.
516  */
resolveArrayLength(Expression * e)517 uinteger_t resolveArrayLength(Expression *e)
518 {
519     if (e->op == TOKvector)
520         return ((VectorExp *)e)->dim;
521 
522     if (e->op == TOKnull)
523         return 0;
524     if (e->op == TOKslice)
525     {
526         uinteger_t ilo = ((SliceExp *)e)->lwr->toInteger();
527         uinteger_t iup = ((SliceExp *)e)->upr->toInteger();
528         return iup - ilo;
529     }
530     if (e->op == TOKstring)
531     {
532         return ((StringExp *)e)->len;
533     }
534     if (e->op == TOKarrayliteral)
535     {
536         ArrayLiteralExp *ale = (ArrayLiteralExp *)e;
537         return ale->elements ? ale->elements->dim : 0;
538     }
539     if (e->op == TOKassocarrayliteral)
540     {
541         AssocArrayLiteralExp *ale = (AssocArrayLiteralExp *)e;
542         return ale->keys->dim;
543     }
544     assert(0);
545     return 0;
546 }
547 
548 /******************************
549  * Helper for NewExp
550  * Create an array literal consisting of 'elem' duplicated 'dim' times.
551  * Params:
552  *      pue = where to store result
553  *      loc = source location where the interpretation occurs
554  *      type = target type of the result
555  *      elem = the source of array element, it will be owned by the result
556  *      dim = element number of the result
557  * Returns:
558  *      Constructed ArrayLiteralExp
559  */
createBlockDuplicatedArrayLiteral(UnionExp * pue,Loc loc,Type * type,Expression * elem,size_t dim)560 ArrayLiteralExp *createBlockDuplicatedArrayLiteral(UnionExp *pue, Loc loc, Type *type,
561         Expression *elem, size_t dim)
562 {
563     if (type->ty == Tsarray && type->nextOf()->ty == Tsarray && elem->type->ty != Tsarray)
564     {
565         // If it is a multidimensional array literal, do it recursively
566         TypeSArray *tsa = (TypeSArray *)type->nextOf();
567         size_t len = (size_t)tsa->dim->toInteger();
568         UnionExp ue;
569         elem = createBlockDuplicatedArrayLiteral(&ue, loc, type->nextOf(), elem, len);
570         if (elem == ue.exp())
571             elem = ue.copy();
572     }
573 
574     // Buzilla 15681
575     Type *tb = elem->type->toBasetype();
576     const bool mustCopy = tb->ty == Tstruct || tb->ty == Tsarray;
577 
578     Expressions *elements = new Expressions();
579     elements->setDim(dim);
580     for (size_t i = 0; i < dim; i++)
581     {
582         (*elements)[i] = mustCopy ? copyLiteral(elem).copy() : elem;
583     }
584     new(pue) ArrayLiteralExp(loc, type, elements);
585     ArrayLiteralExp *ale = (ArrayLiteralExp *)pue->exp();
586     ale->ownedByCtfe = OWNEDctfe;
587     return ale;
588 }
589 
590 /******************************
591  * Helper for NewExp
592  * Create a string literal consisting of 'value' duplicated 'dim' times.
593  */
createBlockDuplicatedStringLiteral(UnionExp * pue,Loc loc,Type * type,unsigned value,size_t dim,unsigned char sz)594 StringExp *createBlockDuplicatedStringLiteral(UnionExp *pue, Loc loc, Type *type,
595         unsigned value, size_t dim, unsigned char sz)
596 {
597     utf8_t *s = (utf8_t *)mem.xcalloc(dim + 1, sz);
598     for (size_t elemi = 0; elemi < dim; ++elemi)
599     {
600         switch (sz)
601         {
602             case 1:     s[elemi] = (utf8_t)value; break;
603             case 2:     ((unsigned short *)s)[elemi] = (unsigned short)value; break;
604             case 4:     ((unsigned *)s)[elemi] = value; break;
605             default:    assert(0);
606         }
607     }
608     new(pue) StringExp(loc, s, dim);
609     StringExp *se = (StringExp *)pue->exp();
610     se->type = type;
611     se->sz = sz;
612     se->committed = true;
613     se->ownedByCtfe = OWNEDctfe;
614     return se;
615 }
616 
617 // Return true if t is an AA
isAssocArray(Type * t)618 bool isAssocArray(Type *t)
619 {
620     t = t->toBasetype();
621     if (t->ty == Taarray)
622         return true;
623     return false;
624 }
625 
626 // Given a template AA type, extract the corresponding built-in AA type
toBuiltinAAType(Type * t)627 TypeAArray *toBuiltinAAType(Type *t)
628 {
629     t = t->toBasetype();
630     if (t->ty == Taarray)
631         return (TypeAArray *)t;
632     assert(0);
633     return NULL;
634 }
635 
636 /************** TypeInfo operations ************************************/
637 
638 // Return true if type is TypeInfo_Class
isTypeInfo_Class(Type * type)639 bool isTypeInfo_Class(Type *type)
640 {
641     return type->ty == Tclass &&
642         (Type::dtypeinfo == ((TypeClass *)type)->sym ||
643          Type::dtypeinfo->isBaseOf(((TypeClass *)type)->sym, NULL));
644 }
645 
646 /************** Pointer operations ************************************/
647 
648 // Return true if t is a pointer (not a function pointer)
isPointer(Type * t)649 bool isPointer(Type *t)
650 {
651     Type * tb = t->toBasetype();
652     return tb->ty == Tpointer && tb->nextOf()->ty != Tfunction;
653 }
654 
655 // For CTFE only. Returns true if 'e' is true or a non-null pointer.
isTrueBool(Expression * e)656 bool isTrueBool(Expression *e)
657 {
658     return e->isBool(true) ||
659            ((e->type->ty == Tpointer || e->type->ty == Tclass) && e->op != TOKnull);
660 }
661 
662 /* Is it safe to convert from srcPointee* to destPointee* ?
663  * srcPointee is the genuine type (never void).
664  * destPointee may be void.
665  */
isSafePointerCast(Type * srcPointee,Type * destPointee)666 bool isSafePointerCast(Type *srcPointee, Type *destPointee)
667 {
668     // It's safe to cast S** to D** if it's OK to cast S* to D*
669     while (srcPointee->ty == Tpointer && destPointee->ty == Tpointer)
670     {
671         srcPointee = srcPointee->nextOf();
672         destPointee = destPointee->nextOf();
673     }
674 
675     // It's OK if both are the same (modulo const)
676     if (srcPointee->constConv(destPointee))
677         return true;
678 
679     // It's OK if function pointers differ only in safe/pure/nothrow
680     if (srcPointee->ty == Tfunction && destPointee->ty == Tfunction)
681         return srcPointee->covariant(destPointee) == 1;
682 
683     // it's OK to cast to void*
684     if (destPointee->ty == Tvoid)
685         return true;
686 
687     // It's OK to cast from V[K] to void*
688     if (srcPointee->ty == Taarray && destPointee == Type::tvoidptr)
689         return true;
690 
691     // It's OK if they are the same size (static array of) integers, eg:
692     //     int*     --> uint*
693     //     int[5][] --> uint[5][]
694     if (srcPointee->ty == Tsarray && destPointee->ty == Tsarray)
695     {
696         if (srcPointee->size() != destPointee->size())
697             return false;
698         srcPointee = srcPointee->baseElemOf();
699         destPointee = destPointee->baseElemOf();
700     }
701     return srcPointee->isintegral() &&
702            destPointee->isintegral() &&
703            srcPointee->size() == destPointee->size();
704 }
705 
getAggregateFromPointer(Expression * e,dinteger_t * ofs)706 Expression *getAggregateFromPointer(Expression *e, dinteger_t *ofs)
707 {
708     *ofs = 0;
709     if (e->op == TOKaddress)
710         e = ((AddrExp *)e)->e1;
711     if (e->op == TOKsymoff)
712         *ofs = ((SymOffExp *)e)->offset;
713     if (e->op == TOKdotvar)
714     {
715         Expression *ex = ((DotVarExp *)e)->e1;
716         VarDeclaration *v = ((DotVarExp *)e)->var->isVarDeclaration();
717         assert(v);
718         StructLiteralExp *se = ex->op == TOKclassreference ? ((ClassReferenceExp *)ex)->value : (StructLiteralExp *)ex;
719         // We can't use getField, because it makes a copy
720         unsigned i;
721         if (ex->op == TOKclassreference)
722             i = ((ClassReferenceExp *)ex)->getFieldIndex(e->type, v->offset);
723         else
724             i = se->getFieldIndex(e->type, v->offset);
725         e = (*se->elements)[i];
726     }
727     if (e->op == TOKindex)
728     {
729         IndexExp *ie = (IndexExp *)e;
730         // Note that each AA element is part of its own memory block
731         if ((ie->e1->type->ty == Tarray ||
732              ie->e1->type->ty == Tsarray ||
733              ie->e1->op == TOKstring ||
734              ie->e1->op == TOKarrayliteral) &&
735             ie->e2->op == TOKint64)
736         {
737             *ofs = ie->e2->toInteger();
738             return ie->e1;
739         }
740     }
741     if (e->op == TOKslice && e->type->toBasetype()->ty == Tsarray)
742     {
743         SliceExp *se = (SliceExp *)e;
744         if ((se->e1->type->ty == Tarray ||
745              se->e1->type->ty == Tsarray ||
746              se->e1->op == TOKstring ||
747              se->e1->op == TOKarrayliteral) &&
748             se->lwr->op == TOKint64)
749         {
750             *ofs = se->lwr->toInteger();
751             return se->e1;
752         }
753     }
754     return e;
755 }
756 
757 /** Return true if agg1 and agg2 are pointers to the same memory block
758 */
pointToSameMemoryBlock(Expression * agg1,Expression * agg2)759 bool pointToSameMemoryBlock(Expression *agg1, Expression *agg2)
760 {
761     if (agg1 == agg2)
762         return true;
763 
764     // For integers cast to pointers, we regard them as non-comparable
765     // unless they are identical. (This may be overly strict).
766     if (agg1->op == TOKint64 && agg2->op == TOKint64 &&
767         agg1->toInteger() == agg2->toInteger())
768     {
769         return true;
770     }
771 
772     // Note that type painting can occur with VarExp, so we
773     // must compare the variables being pointed to.
774     if (agg1->op == TOKvar && agg2->op == TOKvar &&
775         ((VarExp *)agg1)->var == ((VarExp *)agg2)->var)
776     {
777         return true;
778     }
779     if (agg1->op == TOKsymoff && agg2->op == TOKsymoff &&
780         ((SymOffExp *)agg1)->var == ((SymOffExp *)agg2)->var)
781     {
782         return true;
783     }
784 
785     return false;
786 }
787 
788 // return e1 - e2 as an integer, or error if not possible
pointerDifference(Loc loc,Type * type,Expression * e1,Expression * e2)789 UnionExp pointerDifference(Loc loc, Type *type, Expression *e1, Expression *e2)
790 {
791     UnionExp ue;
792     dinteger_t ofs1, ofs2;
793     Expression *agg1 = getAggregateFromPointer(e1, &ofs1);
794     Expression *agg2 = getAggregateFromPointer(e2, &ofs2);
795     if (agg1 == agg2)
796     {
797         Type *pointee = ((TypePointer *)agg1->type)->next;
798         dinteger_t sz = pointee->size();
799         new(&ue) IntegerExp(loc, (ofs1 - ofs2) * sz, type);
800     }
801     else if (agg1->op == TOKstring && agg2->op == TOKstring)
802     {
803         if (((StringExp *)agg1)->string == ((StringExp *)agg2)->string)
804         {
805             Type *pointee = ((TypePointer *)agg1->type)->next;
806             dinteger_t sz = pointee->size();
807             new(&ue) IntegerExp(loc, (ofs1 - ofs2) * sz, type);
808         }
809     }
810     else if (agg1->op == TOKsymoff && agg2->op == TOKsymoff &&
811              ((SymOffExp *)agg1)->var == ((SymOffExp *)agg2)->var)
812     {
813         new(&ue) IntegerExp(loc, ofs1 - ofs2, type);
814     }
815     else
816     {
817         error(loc, "%s - %s cannot be interpreted at compile time: cannot subtract "
818             "pointers to two different memory blocks",
819             e1->toChars(), e2->toChars());
820         new(&ue) CTFEExp(TOKcantexp);
821     }
822     return ue;
823 }
824 
825 // Return eptr op e2, where eptr is a pointer, e2 is an integer,
826 // and op is TOKadd or TOKmin
pointerArithmetic(Loc loc,TOK op,Type * type,Expression * eptr,Expression * e2)827 UnionExp pointerArithmetic(Loc loc, TOK op, Type *type,
828     Expression *eptr, Expression *e2)
829 {
830     UnionExp ue;
831 
832     if (eptr->type->nextOf()->ty == Tvoid)
833     {
834         error(loc, "cannot perform arithmetic on void* pointers at compile time");
835       Lcant:
836         new(&ue) CTFEExp(TOKcantexp);
837         return ue;
838     }
839 
840     dinteger_t ofs1;
841     if (eptr->op == TOKaddress)
842         eptr = ((AddrExp *)eptr)->e1;
843     Expression *agg1 = getAggregateFromPointer(eptr, &ofs1);
844     if (agg1->op == TOKsymoff)
845     {
846         if (((SymOffExp *)agg1)->var->type->ty != Tsarray)
847         {
848             error(loc, "cannot perform pointer arithmetic on arrays of unknown length at compile time");
849             goto Lcant;
850         }
851     }
852     else if (agg1->op != TOKstring && agg1->op != TOKarrayliteral)
853     {
854         error(loc, "cannot perform pointer arithmetic on non-arrays at compile time");
855         goto Lcant;
856     }
857     dinteger_t ofs2 = e2->toInteger();
858 
859     Type *pointee = ((TypeNext *)agg1->type->toBasetype())->next;
860     dinteger_t sz = pointee->size();
861 
862     sinteger_t indx;
863     dinteger_t len;
864     if (agg1->op == TOKsymoff)
865     {
866         indx = ofs1 / sz;
867         len = ((TypeSArray *)((SymOffExp *)agg1)->var->type)->dim->toInteger();
868     }
869     else
870     {
871         Expression *dollar = ArrayLength(Type::tsize_t, agg1).copy();
872         assert(!CTFEExp::isCantExp(dollar));
873         indx = ofs1;
874         len = dollar->toInteger();
875     }
876     if (op == TOKadd || op == TOKaddass || op == TOKplusplus)
877         indx += ofs2 / sz;
878     else if (op == TOKmin || op == TOKminass || op == TOKminusminus)
879         indx -= ofs2 / sz;
880     else
881     {
882         error(loc, "CTFE internal error: bad pointer operation");
883         goto Lcant;
884     }
885 
886     if (indx < 0 || len < (dinteger_t)indx)
887     {
888         error(loc, "cannot assign pointer to index %lld inside memory block [0..%lld]", (ulonglong)indx, (ulonglong)len);
889         goto Lcant;
890     }
891 
892     if (agg1->op == TOKsymoff)
893     {
894         new(&ue) SymOffExp(loc, ((SymOffExp *)agg1)->var, indx * sz);
895         SymOffExp *se = (SymOffExp *)ue.exp();
896         se->type = type;
897         return ue;
898     }
899 
900     if (agg1->op != TOKarrayliteral && agg1->op != TOKstring)
901     {
902         error(loc, "CTFE internal error: pointer arithmetic %s", agg1->toChars());
903         goto Lcant;
904     }
905 
906     if (eptr->type->toBasetype()->ty == Tsarray)
907     {
908         dinteger_t dim = ((TypeSArray *)eptr->type->toBasetype())->dim->toInteger();
909 
910         // Create a CTFE pointer &agg1[indx .. indx+dim]
911         SliceExp *se = new SliceExp(loc, agg1,
912             new IntegerExp(loc, indx,       Type::tsize_t),
913             new IntegerExp(loc, indx + dim, Type::tsize_t));
914         se->type = type->toBasetype()->nextOf();
915         new(&ue) AddrExp(loc, se);
916         ue.exp()->type = type;
917         return ue;
918     }
919 
920     // Create a CTFE pointer &agg1[indx]
921     IntegerExp *ofs = new IntegerExp(loc, indx, Type::tsize_t);
922     Expression *ie = new IndexExp(loc, agg1, ofs);
923     ie->type = type->toBasetype()->nextOf();    // Bugzilla 13992
924     new(&ue) AddrExp(loc, ie);
925     ue.exp()->type = type;
926     return ue;
927 }
928 
929 // Return 1 if true, 0 if false
930 // -1 if comparison is illegal because they point to non-comparable memory blocks
comparePointers(TOK op,Expression * agg1,dinteger_t ofs1,Expression * agg2,dinteger_t ofs2)931 int comparePointers(TOK op, Expression *agg1, dinteger_t ofs1, Expression *agg2, dinteger_t ofs2)
932 {
933     if (pointToSameMemoryBlock(agg1, agg2))
934     {
935         int n;
936         switch (op)
937         {
938         case TOKlt:          n = (ofs1 <  ofs2); break;
939         case TOKle:          n = (ofs1 <= ofs2); break;
940         case TOKgt:          n = (ofs1 >  ofs2); break;
941         case TOKge:          n = (ofs1 >= ofs2); break;
942         case TOKidentity:
943         case TOKequal:       n = (ofs1 == ofs2); break;
944         case TOKnotidentity:
945         case TOKnotequal:    n = (ofs1 != ofs2); break;
946         default:
947             assert(0);
948         }
949         return n;
950     }
951     bool null1 = (agg1->op == TOKnull);
952     bool null2 = (agg2->op == TOKnull);
953 
954     int cmp;
955     if (null1 || null2)
956     {
957         switch (op)
958         {
959         case TOKlt:   cmp =  null1 && !null2;   break;
960         case TOKgt:   cmp = !null1 &&  null2;   break;
961         case TOKle:   cmp = null1;              break;
962         case TOKge:   cmp = null2;              break;
963         case TOKidentity:
964         case TOKequal:
965         case TOKnotidentity: // 'cmp' gets inverted below
966         case TOKnotequal:
967             cmp = (null1 == null2);
968             break;
969         default:
970             assert(0);
971         }
972     }
973     else
974     {
975         switch (op)
976         {
977         case TOKidentity:
978         case TOKequal:
979         case TOKnotidentity: // 'cmp' gets inverted below
980         case TOKnotequal:
981             cmp = 0;
982             break;
983         default:
984             return -1; // memory blocks are different
985         }
986     }
987     if (op == TOKnotidentity || op == TOKnotequal)
988         cmp ^= 1;
989     return cmp;
990 }
991 
992 // True if conversion from type 'from' to 'to' involves a reinterpret_cast
993 // floating point -> integer or integer -> floating point
isFloatIntPaint(Type * to,Type * from)994 bool isFloatIntPaint(Type *to, Type *from)
995 {
996     return from->size() == to->size() &&
997            ((from->isintegral() && to->isfloating()) ||
998             (from->isfloating() && to->isintegral()));
999 }
1000 
1001 // Reinterpret float/int value 'fromVal' as a float/integer of type 'to'.
paintFloatInt(UnionExp * pue,Expression * fromVal,Type * to)1002 Expression *paintFloatInt(UnionExp *pue, Expression *fromVal, Type *to)
1003 {
1004     if (exceptionOrCantInterpret(fromVal))
1005         return fromVal;
1006 
1007     assert(to->size() == 4 || to->size() == 8);
1008     return Compiler::paintAsType(pue, fromVal, to);
1009 }
1010 
1011 /******** Constant folding, with support for CTFE ***************************/
1012 
1013 /// Return true if non-pointer expression e can be compared
1014 /// with >,is, ==, etc, using ctfeCmp, ctfeEqual, ctfeIdentity
isCtfeComparable(Expression * e)1015 bool isCtfeComparable(Expression *e)
1016 {
1017     if (e->op == TOKslice)
1018         e = ((SliceExp *)e)->e1;
1019 
1020     if (e->isConst() != 1)
1021     {
1022         if (e->op == TOKnull ||
1023             e->op == TOKstring ||
1024             e->op == TOKfunction ||
1025             e->op == TOKdelegate ||
1026             e->op == TOKarrayliteral ||
1027             e->op == TOKstructliteral ||
1028             e->op == TOKassocarrayliteral ||
1029             e->op == TOKclassreference)
1030         {
1031             return true;
1032         }
1033         // Bugzilla 14123: TypeInfo object is comparable in CTFE
1034         if (e->op == TOKtypeid)
1035             return true;
1036 
1037         return false;
1038     }
1039     return true;
1040 }
1041 
1042 /// Map TOK comparison ops
1043 template <typename N>
numCmp(TOK op,N n1,N n2)1044 static bool numCmp(TOK op, N n1, N n2)
1045 {
1046     switch (op)
1047     {
1048         case TOKlt:
1049             return n1 <  n2;
1050         case TOKle:
1051             return n1 <= n2;
1052         case TOKgt:
1053             return n1 >  n2;
1054         case TOKge:
1055             return n1 >= n2;
1056 
1057         default:
1058             assert(0);
1059     }
1060 }
1061 
1062 /// Returns cmp OP 0; where OP is ==, !=, <, >=, etc. Result is 0 or 1
specificCmp(TOK op,int rawCmp)1063 int specificCmp(TOK op, int rawCmp)
1064 {
1065     return numCmp<int>(op, rawCmp, 0);
1066 }
1067 
1068 /// Returns e1 OP e2; where OP is ==, !=, <, >=, etc. Result is 0 or 1
intUnsignedCmp(TOK op,dinteger_t n1,dinteger_t n2)1069 int intUnsignedCmp(TOK op, dinteger_t n1, dinteger_t n2)
1070 {
1071     return numCmp<dinteger_t>(op, n1, n2);
1072 }
1073 
1074 /// Returns e1 OP e2; where OP is ==, !=, <, >=, etc. Result is 0 or 1
intSignedCmp(TOK op,sinteger_t n1,sinteger_t n2)1075 int intSignedCmp(TOK op, sinteger_t n1, sinteger_t n2)
1076 {
1077     return numCmp<sinteger_t>(op, n1, n2);
1078 }
1079 
1080 /// Returns e1 OP e2; where OP is ==, !=, <, >=, etc. Result is 0 or 1
realCmp(TOK op,real_t r1,real_t r2)1081 int realCmp(TOK op, real_t r1, real_t r2)
1082 {
1083     // Don't rely on compiler, handle NAN arguments separately
1084     if (CTFloat::isNaN(r1) || CTFloat::isNaN(r2)) // if unordered
1085     {
1086         switch (op)
1087         {
1088             case TOKlt:
1089             case TOKle:
1090             case TOKgt:
1091             case TOKge:
1092                 return 0;
1093 
1094             default:
1095                 assert(0);
1096         }
1097     }
1098     else
1099     {
1100         return numCmp<real_t>(op, r1, r2);
1101     }
1102 }
1103 
1104 int ctfeRawCmp(Loc loc, Expression *e1, Expression *e2);
1105 
1106 /* Conceptually the same as memcmp(e1, e2).
1107  * e1 and e2 may be strings, arrayliterals, or slices.
1108  * For string types, return <0 if e1 < e2, 0 if e1==e2, >0 if e1 > e2.
1109  * For all other types, return 0 if e1 == e2, !=0 if e1 != e2.
1110  */
ctfeCmpArrays(Loc loc,Expression * e1,Expression * e2,uinteger_t len)1111 int ctfeCmpArrays(Loc loc, Expression *e1, Expression *e2, uinteger_t len)
1112 {
1113     // Resolve slices, if necessary
1114     uinteger_t lo1 = 0;
1115     uinteger_t lo2 = 0;
1116 
1117     Expression *x = e1;
1118     if (x->op == TOKslice)
1119     {
1120         lo1 = ((SliceExp *)x)->lwr->toInteger();
1121         x = ((SliceExp *)x)->e1;
1122     }
1123     StringExp *se1 = (x->op == TOKstring) ? (StringExp *)x : NULL;
1124     ArrayLiteralExp *ae1 = (x->op == TOKarrayliteral) ? (ArrayLiteralExp *)x : NULL;
1125 
1126     x = e2;
1127     if (x->op == TOKslice)
1128     {
1129         lo2 = ((SliceExp *)x)->lwr->toInteger();
1130         x = ((SliceExp *)x)->e1;
1131     }
1132     StringExp *se2 = (x->op == TOKstring) ? (StringExp *)x : NULL;
1133     ArrayLiteralExp *ae2 = (x->op == TOKarrayliteral) ? (ArrayLiteralExp *)x : NULL;
1134 
1135     // Now both must be either TOKarrayliteral or TOKstring
1136     if (se1 && se2)
1137         return sliceCmpStringWithString(se1, se2, (size_t)lo1, (size_t)lo2, (size_t)len);
1138     if (se1 && ae2)
1139         return sliceCmpStringWithArray(se1, ae2, (size_t)lo1, (size_t)lo2, (size_t)len);
1140     if (se2 && ae1)
1141         return -sliceCmpStringWithArray(se2, ae1, (size_t)lo2, (size_t)lo1, (size_t)len);
1142 
1143     assert (ae1 && ae2);
1144     // Comparing two array literals. This case is potentially recursive.
1145     // If they aren't strings, we just need an equality check rather than
1146     // a full cmp.
1147     bool needCmp = ae1->type->nextOf()->isintegral();
1148     for (size_t i = 0; i < (size_t)len; i++)
1149     {
1150         Expression *ee1 = (*ae1->elements)[(size_t)(lo1 + i)];
1151         Expression *ee2 = (*ae2->elements)[(size_t)(lo2 + i)];
1152         if (needCmp)
1153         {
1154             sinteger_t c = ee1->toInteger() - ee2->toInteger();
1155             if (c > 0)
1156                 return 1;
1157             if (c < 0)
1158                 return -1;
1159         }
1160         else
1161         {
1162             if (ctfeRawCmp(loc, ee1, ee2))
1163                 return 1;
1164         }
1165     }
1166     return 0;
1167 }
1168 
1169 /* Given a delegate expression e, return .funcptr.
1170  * If e is NullExp, return NULL.
1171  */
funcptrOf(Expression * e)1172 FuncDeclaration *funcptrOf(Expression *e)
1173 {
1174     assert(e->type->ty == Tdelegate);
1175 
1176     if (e->op == TOKdelegate)
1177         return ((DelegateExp *)e)->func;
1178     if (e->op == TOKfunction)
1179         return ((FuncExp *)e)->fd;
1180     assert(e->op == TOKnull);
1181     return NULL;
1182 }
1183 
isArray(Expression * e)1184 bool isArray(Expression *e)
1185 {
1186     return e->op == TOKarrayliteral || e->op == TOKstring ||
1187            e->op == TOKslice || e->op == TOKnull;
1188 }
1189 
1190 /* For strings, return <0 if e1 < e2, 0 if e1==e2, >0 if e1 > e2.
1191  * For all other types, return 0 if e1 == e2, !=0 if e1 != e2.
1192  */
ctfeRawCmp(Loc loc,Expression * e1,Expression * e2)1193 int ctfeRawCmp(Loc loc, Expression *e1, Expression *e2)
1194 {
1195     if (e1->op == TOKclassreference || e2->op == TOKclassreference)
1196     {
1197         if (e1->op == TOKclassreference && e2->op == TOKclassreference &&
1198             ((ClassReferenceExp *)e1)->value == ((ClassReferenceExp *)e2)->value)
1199             return 0;
1200         return 1;
1201     }
1202     if (e1->op == TOKtypeid && e2->op == TOKtypeid)
1203     {
1204         // printf("e1: %s\n", e1->toChars());
1205         // printf("e2: %s\n", e2->toChars());
1206         Type *t1 = isType(((TypeidExp *)e1)->obj);
1207         Type *t2 = isType(((TypeidExp *)e2)->obj);
1208         assert(t1);
1209         assert(t2);
1210         return t1 != t2;
1211     }
1212 
1213     // null == null, regardless of type
1214 
1215     if (e1->op == TOKnull && e2->op == TOKnull)
1216         return 0;
1217 
1218     if (e1->type->ty == Tpointer && e2->type->ty == Tpointer)
1219     {
1220         // Can only be an equality test.
1221 
1222         dinteger_t ofs1, ofs2;
1223         Expression *agg1 = getAggregateFromPointer(e1, &ofs1);
1224         Expression *agg2 = getAggregateFromPointer(e2, &ofs2);
1225         if ((agg1 == agg2) || (agg1->op == TOKvar && agg2->op == TOKvar &&
1226             ((VarExp *)agg1)->var == ((VarExp *)agg2)->var))
1227         {
1228             if (ofs1 == ofs2)
1229                 return 0;
1230         }
1231         return 1;
1232     }
1233     if (e1->type->ty == Tdelegate && e2->type->ty == Tdelegate)
1234     {
1235         // If .funcptr isn't the same, they are not equal
1236 
1237         if (funcptrOf(e1) != funcptrOf(e2))
1238             return 1;
1239 
1240         // If both are delegate literals, assume they have the
1241         // same closure pointer. TODO: We don't support closures yet!
1242         if (e1->op == TOKfunction && e2->op == TOKfunction)
1243             return 0;
1244         assert(e1->op == TOKdelegate && e2->op == TOKdelegate);
1245 
1246         // Same .funcptr. Do they have the same .ptr?
1247         Expression * ptr1 = ((DelegateExp *)e1)->e1;
1248         Expression * ptr2 = ((DelegateExp *)e2)->e1;
1249 
1250         dinteger_t ofs1, ofs2;
1251         Expression *agg1 = getAggregateFromPointer(ptr1, &ofs1);
1252         Expression *agg2 = getAggregateFromPointer(ptr2, &ofs2);
1253         // If they are TOKvar, it means they are FuncDeclarations
1254         if ((agg1 == agg2 && ofs1 == ofs2) ||
1255             (agg1->op == TOKvar && agg2->op == TOKvar &&
1256              ((VarExp *)agg1)->var == ((VarExp *)agg2)->var))
1257         {
1258             return 0;
1259         }
1260         return 1;
1261     }
1262     if (isArray(e1) && isArray(e2))
1263     {
1264         uinteger_t len1 = resolveArrayLength(e1);
1265         uinteger_t len2 = resolveArrayLength(e2);
1266         // workaround for dmc optimizer bug calculating wrong len for
1267         // uinteger_t len = (len1 < len2 ? len1 : len2);
1268         // if (len == 0) ...
1269         if (len1 > 0 && len2 > 0)
1270         {
1271             uinteger_t len = (len1 < len2 ? len1 : len2);
1272             int res = ctfeCmpArrays(loc, e1, e2, len);
1273             if (res != 0)
1274                 return res;
1275         }
1276         return (int)(len1 - len2);
1277     }
1278     if (e1->type->isintegral())
1279     {
1280         return e1->toInteger() != e2->toInteger();
1281     }
1282     real_t r1;
1283     real_t r2;
1284     if (e1->type->isreal())
1285     {
1286         r1 = e1->toReal();
1287         r2 = e2->toReal();
1288         goto L1;
1289     }
1290     else if (e1->type->isimaginary())
1291     {
1292         r1 = e1->toImaginary();
1293         r2 = e2->toImaginary();
1294      L1:
1295         if (CTFloat::isNaN(r1) || CTFloat::isNaN(r2)) // if unordered
1296         {
1297             return 1;
1298         }
1299         else
1300         {
1301             return (r1 != r2);
1302         }
1303     }
1304     else if (e1->type->iscomplex())
1305     {
1306         return e1->toComplex() != e2->toComplex();
1307     }
1308 
1309     if (e1->op == TOKstructliteral && e2->op == TOKstructliteral)
1310     {
1311         StructLiteralExp *es1 = (StructLiteralExp *)e1;
1312         StructLiteralExp *es2 = (StructLiteralExp *)e2;
1313         // For structs, we only need to return 0 or 1 (< and > aren't legal).
1314 
1315         if (es1->sd != es2->sd)
1316             return 1;
1317         else if ((!es1->elements || !es1->elements->dim) &&
1318             (!es2->elements || !es2->elements->dim))
1319             return 0;            // both arrays are empty
1320         else if (!es1->elements || !es2->elements)
1321             return 1;
1322         else if (es1->elements->dim != es2->elements->dim)
1323             return 1;
1324         else
1325         {
1326             for (size_t i = 0; i < es1->elements->dim; i++)
1327             {
1328                 Expression *ee1 = (*es1->elements)[i];
1329                 Expression *ee2 = (*es2->elements)[i];
1330 
1331                 if (ee1 == ee2)
1332                     continue;
1333                 if (!ee1 || !ee2)
1334                    return 1;
1335                 int cmp = ctfeRawCmp(loc, ee1, ee2);
1336                 if (cmp)
1337                     return 1;
1338             }
1339             return 0;   // All elements are equal
1340         }
1341     }
1342     if (e1->op == TOKassocarrayliteral && e2->op == TOKassocarrayliteral)
1343     {
1344         AssocArrayLiteralExp *es1 = (AssocArrayLiteralExp *)e1;
1345         AssocArrayLiteralExp *es2 = (AssocArrayLiteralExp *)e2;
1346 
1347         size_t dim = es1->keys->dim;
1348         if (es2->keys->dim != dim)
1349             return 1;
1350 
1351         bool *used = (bool *)mem.xmalloc(sizeof(bool) * dim);
1352         memset(used, 0, sizeof(bool) * dim);
1353 
1354         for (size_t i = 0; i < dim; ++i)
1355         {
1356             Expression *k1 = (*es1->keys)[i];
1357             Expression *v1 = (*es1->values)[i];
1358             Expression *v2 = NULL;
1359             for (size_t j = 0; j < dim; ++j)
1360             {
1361                 if (used[j])
1362                     continue;
1363                 Expression *k2 = (*es2->keys)[j];
1364 
1365                 if (ctfeRawCmp(loc, k1, k2))
1366                     continue;
1367                 used[j] = true;
1368                 v2 = (*es2->values)[j];
1369                 break;
1370             }
1371             if (!v2 || ctfeRawCmp(loc, v1, v2))
1372             {
1373                 mem.xfree(used);
1374                 return 1;
1375             }
1376         }
1377         mem.xfree(used);
1378         return 0;
1379     }
1380     error(loc, "CTFE internal error: bad compare of `%s` and `%s`", e1->toChars(), e2->toChars());
1381     assert(0);
1382     return 0;
1383 }
1384 
1385 /// Evaluate ==, !=.  Resolves slices before comparing. Returns 0 or 1
ctfeEqual(Loc loc,TOK op,Expression * e1,Expression * e2)1386 int ctfeEqual(Loc loc, TOK op, Expression *e1, Expression *e2)
1387 {
1388     int cmp = !ctfeRawCmp(loc, e1, e2);
1389     if (op == TOKnotequal)
1390         cmp ^= 1;
1391     return cmp;
1392 }
1393 
1394 /// Evaluate is, !is.  Resolves slices before comparing. Returns 0 or 1
ctfeIdentity(Loc loc,TOK op,Expression * e1,Expression * e2)1395 int ctfeIdentity(Loc loc, TOK op, Expression *e1, Expression *e2)
1396 {
1397     //printf("ctfeIdentity op = '%s', e1 = %s %s, e2 = %s %s\n", Token::toChars(op),
1398     //    Token::toChars(e1->op), e1->toChars(), Token::toChars(e2->op), e1->toChars());
1399     int cmp;
1400     if (e1->op == TOKnull)
1401     {
1402         cmp = (e2->op == TOKnull);
1403     }
1404     else if (e2->op == TOKnull)
1405     {
1406         cmp = 0;
1407     }
1408     else if (e1->op == TOKsymoff && e2->op == TOKsymoff)
1409     {
1410         SymOffExp *es1 = (SymOffExp *)e1;
1411         SymOffExp *es2 = (SymOffExp *)e2;
1412         cmp = (es1->var == es2->var && es1->offset == es2->offset);
1413     }
1414     else if (e1->type->isreal())
1415         cmp = RealEquals(e1->toReal(), e2->toReal());
1416     else if (e1->type->isimaginary())
1417         cmp = RealEquals(e1->toImaginary(), e2->toImaginary());
1418     else if (e1->type->iscomplex())
1419     {
1420         complex_t v1 = e1->toComplex();
1421         complex_t v2 = e2->toComplex();
1422         cmp = RealEquals(creall(v1), creall(v2)) &&
1423                  RealEquals(cimagl(v1), cimagl(v1));
1424     }
1425     else
1426         cmp = !ctfeRawCmp(loc, e1, e2);
1427 
1428     if (op == TOKnotidentity || op == TOKnotequal)
1429         cmp ^= 1;
1430     return cmp;
1431 }
1432 
1433 /// Evaluate >,<=, etc. Resolves slices before comparing. Returns 0 or 1
ctfeCmp(Loc loc,TOK op,Expression * e1,Expression * e2)1434 int ctfeCmp(Loc loc, TOK op, Expression *e1, Expression *e2)
1435 {
1436     Type *t1 = e1->type->toBasetype();
1437     Type *t2 = e2->type->toBasetype();
1438 
1439     if (t1->isString() && t2->isString())
1440         return specificCmp(op, ctfeRawCmp(loc, e1, e2));
1441     else if (t1->isreal())
1442         return realCmp(op, e1->toReal(), e2->toReal());
1443     else if (t1->isimaginary())
1444         return realCmp(op, e1->toImaginary(), e2->toImaginary());
1445     else if (t1->isunsigned() || t2->isunsigned())
1446         return intUnsignedCmp(op, e1->toInteger(), e2->toInteger());
1447     else
1448         return intSignedCmp(op, e1->toInteger(), e2->toInteger());
1449 }
1450 
ctfeCat(Loc loc,Type * type,Expression * e1,Expression * e2)1451 UnionExp ctfeCat(Loc loc, Type *type, Expression *e1, Expression *e2)
1452 {
1453     Type *t1 = e1->type->toBasetype();
1454     Type *t2 = e2->type->toBasetype();
1455     UnionExp ue;
1456     if (e2->op == TOKstring && e1->op == TOKarrayliteral &&
1457         t1->nextOf()->isintegral())
1458     {
1459         // [chars] ~ string => string (only valid for CTFE)
1460         StringExp *es1 = (StringExp *)e2;
1461         ArrayLiteralExp *es2 = (ArrayLiteralExp *)e1;
1462         size_t len = es1->len + es2->elements->dim;
1463         unsigned char sz = es1->sz;
1464 
1465         void *s = mem.xmalloc((len + 1) * sz);
1466         memcpy((char *)s + sz * es2->elements->dim, es1->string, es1->len * sz);
1467         for (size_t i = 0; i < es2->elements->dim; i++)
1468         {
1469             Expression *es2e = (*es2->elements)[i];
1470             if (es2e->op != TOKint64)
1471             {
1472                 new(&ue) CTFEExp(TOKcantexp);
1473                 return ue;
1474             }
1475             dinteger_t v = es2e->toInteger();
1476             Port::valcpy((utf8_t *)s + i * sz, v, sz);
1477         }
1478 
1479         // Add terminating 0
1480         memset((utf8_t *)s + len * sz, 0, sz);
1481 
1482         new(&ue) StringExp(loc, s, len);
1483         StringExp *es = (StringExp *)ue.exp();
1484         es->sz = sz;
1485         es->committed = 0;
1486         es->type = type;
1487         return ue;
1488     }
1489     if (e1->op == TOKstring && e2->op == TOKarrayliteral &&
1490         t2->nextOf()->isintegral())
1491     {
1492         // string ~ [chars] => string (only valid for CTFE)
1493         // Concatenate the strings
1494         StringExp *es1 = (StringExp *)e1;
1495         ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
1496         size_t len = es1->len + es2->elements->dim;
1497         unsigned char sz = es1->sz;
1498 
1499         void *s = mem.xmalloc((len + 1) * sz);
1500         memcpy(s, es1->string, es1->len * sz);
1501         for (size_t i = 0; i < es2->elements->dim; i++)
1502         {
1503             Expression *es2e = (*es2->elements)[i];
1504             if (es2e->op != TOKint64)
1505             {
1506                 new(&ue) CTFEExp(TOKcantexp);
1507                 return ue;
1508             }
1509             dinteger_t v = es2e->toInteger();
1510             Port::valcpy((utf8_t *)s + (es1->len + i) * sz, v, sz);
1511         }
1512 
1513         // Add terminating 0
1514         memset((utf8_t *)s + len * sz, 0, sz);
1515 
1516         new(&ue) StringExp(loc, s, len);
1517         StringExp *es = (StringExp *)ue.exp();
1518         es->sz = sz;
1519         es->committed = 0; //es1->committed;
1520         es->type = type;
1521         return ue;
1522     }
1523     if (e1->op == TOKarrayliteral && e2->op == TOKarrayliteral &&
1524         t1->nextOf()->equals(t2->nextOf()))
1525     {
1526         //  [ e1 ] ~ [ e2 ] ---> [ e1, e2 ]
1527         ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1;
1528         ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
1529 
1530         new(&ue) ArrayLiteralExp(es1->loc, type, copyLiteralArray(es1->elements));
1531         es1 = (ArrayLiteralExp *)ue.exp();
1532         es1->elements->insert(es1->elements->dim, copyLiteralArray(es2->elements));
1533         return ue;
1534     }
1535     if (e1->op == TOKarrayliteral && e2->op == TOKnull &&
1536         t1->nextOf()->equals(t2->nextOf()))
1537     {
1538         //  [ e1 ] ~ null ----> [ e1 ].dup
1539         ue = paintTypeOntoLiteralCopy(type, copyLiteral(e1).copy());
1540         return ue;
1541     }
1542     if (e1->op == TOKnull && e2->op == TOKarrayliteral &&
1543         t1->nextOf()->equals(t2->nextOf()))
1544     {
1545         //  null ~ [ e2 ] ----> [ e2 ].dup
1546         ue = paintTypeOntoLiteralCopy(type, copyLiteral(e2).copy());
1547         return ue;
1548     }
1549     ue = Cat(type, e1, e2);
1550     return ue;
1551 }
1552 
1553 /*  Given an AA literal 'ae', and a key 'e2':
1554  *  Return ae[e2] if present, or NULL if not found.
1555  */
findKeyInAA(Loc loc,AssocArrayLiteralExp * ae,Expression * e2)1556 Expression *findKeyInAA(Loc loc, AssocArrayLiteralExp *ae, Expression *e2)
1557 {
1558     /* Search the keys backwards, in case there are duplicate keys
1559      */
1560     for (size_t i = ae->keys->dim; i;)
1561     {
1562         i--;
1563         Expression *ekey = (*ae->keys)[i];
1564         int eq = ctfeEqual(loc, TOKequal, ekey, e2);
1565         if (eq)
1566         {
1567             return (*ae->values)[i];
1568         }
1569     }
1570     return NULL;
1571 }
1572 
1573 /* Same as for constfold.Index, except that it only works for static arrays,
1574  * dynamic arrays, and strings. We know that e1 is an
1575  * interpreted CTFE expression, so it cannot have side-effects.
1576  */
ctfeIndex(Loc loc,Type * type,Expression * e1,uinteger_t indx)1577 Expression *ctfeIndex(Loc loc, Type *type, Expression *e1, uinteger_t indx)
1578 {
1579     //printf("ctfeIndex(e1 = %s)\n", e1->toChars());
1580     assert(e1->type);
1581     if (e1->op == TOKstring)
1582     {
1583         StringExp *es1 = (StringExp *)e1;
1584         if (indx >= es1->len)
1585         {
1586             error(loc, "string index %llu is out of bounds [0 .. %llu]", (ulonglong)indx, (ulonglong)es1->len);
1587             return CTFEExp::cantexp;
1588         }
1589         return new IntegerExp(loc, es1->charAt(indx), type);
1590     }
1591     assert(e1->op == TOKarrayliteral);
1592     {
1593         ArrayLiteralExp *ale = (ArrayLiteralExp *)e1;
1594         if (indx >= ale->elements->dim)
1595         {
1596             error(loc, "array index %llu is out of bounds %s[0 .. %llu]", (ulonglong)indx, e1->toChars(), (ulonglong)ale->elements->dim);
1597             return CTFEExp::cantexp;
1598         }
1599         Expression *e = (*ale->elements)[(size_t)indx];
1600         return paintTypeOntoLiteral(type, e);
1601     }
1602 }
1603 
ctfeCast(UnionExp * pue,Loc loc,Type * type,Type * to,Expression * e)1604 Expression *ctfeCast(UnionExp *pue, Loc loc, Type *type, Type *to, Expression *e)
1605 {
1606     if (e->op == TOKnull)
1607         return paintTypeOntoLiteral(pue, to, e);
1608 
1609     if (e->op == TOKclassreference)
1610     {
1611         // Disallow reinterpreting class casts. Do this by ensuring that
1612         // the original class can implicitly convert to the target class
1613         ClassDeclaration *originalClass = ((ClassReferenceExp *)e)->originalClass();
1614         if (originalClass->type->implicitConvTo(to->mutableOf()))
1615             return paintTypeOntoLiteral(pue, to, e);
1616         else
1617         {
1618             new(pue) NullExp(loc, to);
1619             return pue->exp();
1620         }
1621     }
1622 
1623     // Allow TypeInfo type painting
1624     if (isTypeInfo_Class(e->type) && e->type->implicitConvTo(to))
1625         return paintTypeOntoLiteral(pue, to, e);
1626 
1627     // Allow casting away const for struct literals
1628     if (e->op == TOKstructliteral &&
1629         e->type->toBasetype()->castMod(0) == to->toBasetype()->castMod(0))
1630         return paintTypeOntoLiteral(pue, to, e);
1631 
1632     Expression *r;
1633     if (e->type->equals(type) && type->equals(to))
1634     {
1635         // necessary not to change e's address for pointer comparisons
1636         r = e;
1637     }
1638     else if (to->toBasetype()->ty == Tarray &&
1639              type->toBasetype()->ty == Tarray &&
1640              to->toBasetype()->nextOf()->size() == type->toBasetype()->nextOf()->size())
1641     {
1642         // Bugzilla 12495: Array reinterpret casts: eg. string to immutable(ubyte)[]
1643         return paintTypeOntoLiteral(pue, to, e);
1644     }
1645     else
1646     {
1647         *pue = Cast(loc, type, to, e);
1648         r = pue->exp();
1649     }
1650 
1651     if (CTFEExp::isCantExp(r))
1652         error(loc, "cannot cast %s to %s at compile time", e->toChars(), to->toChars());
1653 
1654     if (e->op == TOKarrayliteral)
1655         ((ArrayLiteralExp *)e)->ownedByCtfe = OWNEDctfe;
1656 
1657     if (e->op == TOKstring)
1658         ((StringExp *)e)->ownedByCtfe = OWNEDctfe;
1659 
1660     return r;
1661 }
1662 
1663 /******** Assignment helper functions ***************************/
1664 
1665 /* Set dest = src, where both dest and src are container value literals
1666  * (ie, struct literals, or static arrays (can be an array literal or a string))
1667  * Assignment is recursively in-place.
1668  * Purpose: any reference to a member of 'dest' will remain valid after the
1669  * assignment.
1670  */
assignInPlace(Expression * dest,Expression * src)1671 void assignInPlace(Expression *dest, Expression *src)
1672 {
1673     assert(dest->op == TOKstructliteral ||
1674            dest->op == TOKarrayliteral ||
1675            dest->op == TOKstring);
1676     Expressions *oldelems;
1677     Expressions *newelems;
1678     if (dest->op == TOKstructliteral)
1679     {
1680         assert(dest->op == src->op);
1681         oldelems = ((StructLiteralExp *)dest)->elements;
1682         newelems = ((StructLiteralExp *)src)->elements;
1683         if (((StructLiteralExp *)dest)->sd->isNested() && oldelems->dim == newelems->dim - 1)
1684             oldelems->push(NULL);
1685     }
1686     else if (dest->op == TOKarrayliteral && src->op==TOKarrayliteral)
1687     {
1688         oldelems = ((ArrayLiteralExp *)dest)->elements;
1689         newelems = ((ArrayLiteralExp *)src)->elements;
1690     }
1691     else if (dest->op == TOKstring && src->op == TOKstring)
1692     {
1693         sliceAssignStringFromString((StringExp *)dest, (StringExp *)src, 0);
1694         return;
1695     }
1696     else if (dest->op == TOKarrayliteral && src->op == TOKstring)
1697     {
1698         sliceAssignArrayLiteralFromString((ArrayLiteralExp *)dest, (StringExp *)src, 0);
1699         return;
1700     }
1701     else if (src->op == TOKarrayliteral && dest->op == TOKstring)
1702     {
1703         sliceAssignStringFromArrayLiteral((StringExp *)dest, (ArrayLiteralExp *)src, 0);
1704         return;
1705     }
1706     else
1707         assert(0);
1708 
1709     assert(oldelems->dim == newelems->dim);
1710 
1711     for (size_t i= 0; i < oldelems->dim; ++i)
1712     {
1713         Expression *e = (*newelems)[i];
1714         Expression *o = (*oldelems)[i];
1715         if (e->op == TOKstructliteral)
1716         {
1717             assert(o->op == e->op);
1718             assignInPlace(o, e);
1719         }
1720         else if (e->type->ty == Tsarray && e->op != TOKvoid &&
1721                  o->type->ty == Tsarray)
1722         {
1723             assignInPlace(o, e);
1724         }
1725         else
1726         {
1727             (*oldelems)[i] = (*newelems)[i];
1728         }
1729     }
1730 }
1731 
1732 // Duplicate the elements array, then set field 'indexToChange' = newelem.
changeOneElement(Expressions * oldelems,size_t indexToChange,Expression * newelem)1733 Expressions *changeOneElement(Expressions *oldelems, size_t indexToChange, Expression *newelem)
1734 {
1735     Expressions *expsx = new Expressions();
1736     ++CtfeStatus::numArrayAllocs;
1737     expsx->setDim(oldelems->dim);
1738     for (size_t j = 0; j < expsx->dim; j++)
1739     {
1740         if (j == indexToChange)
1741             (*expsx)[j] = newelem;
1742         else
1743             (*expsx)[j] = (*oldelems)[j];
1744     }
1745     return expsx;
1746 }
1747 
1748 // Given an AA literal aae,  set aae[index] = newval and return newval.
assignAssocArrayElement(Loc loc,AssocArrayLiteralExp * aae,Expression * index,Expression * newval)1749 Expression *assignAssocArrayElement(Loc loc, AssocArrayLiteralExp *aae,
1750     Expression *index, Expression *newval)
1751 {
1752     /* Create new associative array literal reflecting updated key/value
1753      */
1754     Expressions *keysx = aae->keys;
1755     Expressions *valuesx = aae->values;
1756     int updated = 0;
1757     for (size_t j = valuesx->dim; j; )
1758     {
1759         j--;
1760         Expression *ekey = (*aae->keys)[j];
1761         int eq = ctfeEqual(loc, TOKequal, ekey, index);
1762         if (eq)
1763         {
1764             (*valuesx)[j] = newval;
1765             updated = 1;
1766         }
1767     }
1768     if (!updated)
1769     {
1770         // Append index/newval to keysx[]/valuesx[]
1771         valuesx->push(newval);
1772         keysx->push(index);
1773     }
1774     return newval;
1775 }
1776 
1777 /// Given array literal oldval of type ArrayLiteralExp or StringExp, of length
1778 /// oldlen, change its length to newlen. If the newlen is longer than oldlen,
1779 /// all new elements will be set to the default initializer for the element type.
changeArrayLiteralLength(Loc loc,TypeArray * arrayType,Expression * oldval,size_t oldlen,size_t newlen)1780 UnionExp changeArrayLiteralLength(Loc loc, TypeArray *arrayType,
1781     Expression *oldval,  size_t oldlen, size_t newlen)
1782 {
1783     UnionExp ue;
1784     Type *elemType = arrayType->next;
1785     assert(elemType);
1786     Expression *defaultElem = elemType->defaultInitLiteral(loc);
1787     Expressions *elements = new Expressions();
1788     elements->setDim(newlen);
1789 
1790     // Resolve slices
1791     size_t indxlo = 0;
1792     if (oldval->op == TOKslice)
1793     {
1794         indxlo = (size_t)((SliceExp *)oldval)->lwr->toInteger();
1795         oldval = ((SliceExp *)oldval)->e1;
1796     }
1797     size_t copylen = oldlen < newlen ? oldlen : newlen;
1798     if (oldval->op == TOKstring)
1799     {
1800         StringExp *oldse = (StringExp *)oldval;
1801         void *s = mem.xcalloc(newlen + 1, oldse->sz);
1802         memcpy(s, oldse->string, copylen * oldse->sz);
1803         unsigned defaultValue = (unsigned)(defaultElem->toInteger());
1804         for (size_t elemi = copylen; elemi < newlen; ++elemi)
1805         {
1806             switch (oldse->sz)
1807             {
1808                 case 1:     (( utf8_t *)s)[(size_t)(indxlo + elemi)] = ( utf8_t)defaultValue;  break;
1809                 case 2:     ((utf16_t *)s)[(size_t)(indxlo + elemi)] = (utf16_t)defaultValue;  break;
1810                 case 4:     ((utf32_t *)s)[(size_t)(indxlo + elemi)] = (utf32_t)defaultValue;  break;
1811                 default:    assert(0);
1812             }
1813         }
1814         new(&ue) StringExp(loc, s, newlen);
1815         StringExp *se = (StringExp *)ue.exp();
1816         se->type = arrayType;
1817         se->sz = oldse->sz;
1818         se->committed = oldse->committed;
1819         se->ownedByCtfe = OWNEDctfe;
1820     }
1821     else
1822     {
1823         if (oldlen != 0)
1824         {
1825             assert(oldval->op == TOKarrayliteral);
1826             ArrayLiteralExp *ae = (ArrayLiteralExp *)oldval;
1827             for (size_t i = 0; i < copylen; i++)
1828                 (*elements)[i] = (*ae->elements)[indxlo + i];
1829         }
1830         if (elemType->ty == Tstruct || elemType->ty == Tsarray)
1831         {
1832             /* If it is an aggregate literal representing a value type,
1833              * we need to create a unique copy for each element
1834              */
1835             for (size_t i = copylen; i < newlen; i++)
1836                 (*elements)[i] = copyLiteral(defaultElem).copy();
1837         }
1838         else
1839         {
1840             for (size_t i = copylen; i < newlen; i++)
1841                 (*elements)[i] = defaultElem;
1842         }
1843         new(&ue) ArrayLiteralExp(loc, arrayType, elements);
1844         ArrayLiteralExp *aae = (ArrayLiteralExp *)ue.exp();
1845         aae->ownedByCtfe = OWNEDctfe;
1846     }
1847     return ue;
1848 }
1849 
1850 /*************************** CTFE Sanity Checks ***************************/
1851 
isCtfeValueValid(Expression * newval)1852 bool isCtfeValueValid(Expression *newval)
1853 {
1854     Type *tb = newval->type->toBasetype();
1855 
1856     if (newval->op == TOKint64 ||
1857         newval->op == TOKfloat64 ||
1858         newval->op == TOKchar ||
1859         newval->op == TOKcomplex80)
1860     {
1861         return tb->isscalar();
1862     }
1863     if (newval->op == TOKnull)
1864     {
1865         return tb->ty == Tnull ||
1866                tb->ty == Tpointer ||
1867                tb->ty == Tarray ||
1868                tb->ty == Taarray ||
1869                tb->ty == Tclass ||
1870                tb->ty == Tdelegate;
1871     }
1872 
1873     if (newval->op == TOKstring)
1874         return true;    // CTFE would directly use the StringExp in AST.
1875     if (newval->op == TOKarrayliteral)
1876         return true;    //((ArrayLiteralExp *)newval)->ownedByCtfe;
1877     if (newval->op == TOKassocarrayliteral)
1878         return true;    //((AssocArrayLiteralExp *)newval)->ownedByCtfe;
1879     if (newval->op == TOKstructliteral)
1880         return true;    //((StructLiteralExp *)newval)->ownedByCtfe;
1881     if (newval->op == TOKclassreference)
1882         return true;
1883 
1884     if (newval->op == TOKvector)
1885         return true;    // vector literal
1886 
1887     if (newval->op == TOKfunction)
1888         return true;    // function literal or delegate literal
1889     if (newval->op == TOKdelegate)
1890     {
1891         // &struct.func or &clasinst.func
1892         // &nestedfunc
1893         Expression *ethis = ((DelegateExp *)newval)->e1;
1894         return (ethis->op == TOKstructliteral ||
1895                 ethis->op == TOKclassreference ||
1896                 (ethis->op == TOKvar && ((VarExp *)ethis)->var == ((DelegateExp *)newval)->func));
1897     }
1898     if (newval->op == TOKsymoff)
1899     {
1900         // function pointer, or pointer to static variable
1901         Declaration *d = ((SymOffExp *)newval)->var;
1902         return d->isFuncDeclaration() || d->isDataseg();
1903     }
1904     if (newval->op == TOKtypeid)
1905     {
1906         // always valid
1907         return true;
1908     }
1909     if (newval->op == TOKaddress)
1910     {
1911         // e1 should be a CTFE reference
1912         Expression *e1 = ((AddrExp *)newval)->e1;
1913         return tb->ty == Tpointer &&
1914                (((e1->op == TOKstructliteral || e1->op == TOKarrayliteral) && isCtfeValueValid(e1)) ||
1915                 (e1->op == TOKvar) ||
1916                 (e1->op == TOKdotvar && isCtfeReferenceValid(e1)) ||
1917                 (e1->op == TOKindex && isCtfeReferenceValid(e1)) ||
1918                 (e1->op == TOKslice && e1->type->toBasetype()->ty == Tsarray));
1919     }
1920     if (newval->op == TOKslice)
1921     {
1922         // e1 should be an array aggregate
1923         SliceExp *se = (SliceExp *)newval;
1924         assert(se->lwr && se->lwr->op == TOKint64);
1925         assert(se->upr && se->upr->op == TOKint64);
1926         return (tb->ty == Tarray ||
1927                 tb->ty == Tsarray) &&
1928                (se->e1->op == TOKstring ||
1929                 se->e1->op == TOKarrayliteral);
1930     }
1931 
1932     if (newval->op == TOKvoid)
1933         return true;    // uninitialized value
1934 
1935     newval->error("CTFE internal error: illegal CTFE value %s", newval->toChars());
1936     return false;
1937 }
1938 
isCtfeReferenceValid(Expression * newval)1939 bool isCtfeReferenceValid(Expression *newval)
1940 {
1941     if (newval->op == TOKthis)
1942         return true;
1943     if (newval->op == TOKvar)
1944     {
1945         VarDeclaration *v = ((VarExp *)newval)->var->isVarDeclaration();
1946         assert(v);
1947         // Must not be a reference to a reference
1948         return true;
1949     }
1950     if (newval->op == TOKindex)
1951     {
1952         Expression *eagg = ((IndexExp *)newval)->e1;
1953         return eagg->op == TOKstring ||
1954                eagg->op == TOKarrayliteral ||
1955                eagg->op == TOKassocarrayliteral;
1956     }
1957     if (newval->op == TOKdotvar)
1958     {
1959         Expression *eagg = ((DotVarExp *)newval)->e1;
1960         return  (eagg->op == TOKstructliteral || eagg->op == TOKclassreference) &&
1961                 isCtfeValueValid(eagg);
1962     }
1963 
1964     // Internally a ref variable may directly point a stack memory.
1965     // e.g. ref int v = 1;
1966     return isCtfeValueValid(newval);
1967 }
1968 
1969 // Used for debugging only
showCtfeExpr(Expression * e,int level)1970 void showCtfeExpr(Expression *e, int level)
1971 {
1972     for (int i = level; i > 0; --i) printf(" ");
1973     Expressions *elements = NULL;
1974     // We need the struct definition to detect block assignment
1975     StructDeclaration *sd = NULL;
1976     ClassDeclaration *cd = NULL;
1977     if (e->op == TOKstructliteral)
1978     {
1979         elements = ((StructLiteralExp *)e)->elements;
1980         sd = ((StructLiteralExp *)e)->sd;
1981         printf("STRUCT type = %s %p:\n", e->type->toChars(),
1982             e);
1983     }
1984     else if (e->op == TOKclassreference)
1985     {
1986         elements = ((ClassReferenceExp *)e)->value->elements;
1987         cd = ((ClassReferenceExp *)e)->originalClass();
1988         printf("CLASS type = %s %p:\n", e->type->toChars(),
1989             ((ClassReferenceExp *)e)->value);
1990     }
1991     else if (e->op == TOKarrayliteral)
1992     {
1993         elements = ((ArrayLiteralExp *)e)->elements;
1994         printf("ARRAY LITERAL type=%s %p:\n", e->type->toChars(),
1995             e);
1996     }
1997     else if (e->op == TOKassocarrayliteral)
1998     {
1999         printf("AA LITERAL type=%s %p:\n", e->type->toChars(),
2000             e);
2001     }
2002     else if (e->op == TOKstring)
2003     {
2004         printf("STRING %s %p\n", e->toChars(),
2005             ((StringExp *)e)->string);
2006     }
2007     else if (e->op == TOKslice)
2008     {
2009         printf("SLICE %p: %s\n", e, e->toChars());
2010         showCtfeExpr(((SliceExp *)e)->e1, level + 1);
2011     }
2012     else if (e->op == TOKvar)
2013     {
2014         printf("VAR %p %s\n", e, e->toChars());
2015         VarDeclaration *v = ((VarExp *)e)->var->isVarDeclaration();
2016         if (v && getValue(v))
2017             showCtfeExpr(getValue(v), level + 1);
2018     }
2019     else if (e->op == TOKaddress)
2020     {
2021         // This is potentially recursive. We mustn't try to print the thing we're pointing to.
2022         printf("POINTER %p to %p: %s\n", e, ((AddrExp *)e)->e1, e->toChars());
2023     }
2024     else
2025         printf("VALUE %p: %s\n", e, e->toChars());
2026 
2027     if (elements)
2028     {
2029         size_t fieldsSoFar = 0;
2030         for (size_t i = 0; i < elements->dim; i++)
2031         {
2032             Expression *z = NULL;
2033             VarDeclaration *v = NULL;
2034             if (i > 15)
2035             {
2036                 printf("...(total %d elements)\n", (int)elements->dim);
2037                 return;
2038             }
2039             if (sd)
2040             {
2041                 v = sd->fields[i];
2042                 z = (*elements)[i];
2043             }
2044             else if (cd)
2045             {
2046                 while (i - fieldsSoFar >= cd->fields.dim)
2047                 {
2048                     fieldsSoFar += cd->fields.dim;
2049                     cd = cd->baseClass;
2050                     for (int j = level; j > 0; --j) printf(" ");
2051                     printf(" BASE CLASS: %s\n", cd->toChars());
2052                 }
2053                 v = cd->fields[i - fieldsSoFar];
2054                 assert((elements->dim + i) >= (fieldsSoFar + cd->fields.dim));
2055                 size_t indx = (elements->dim - fieldsSoFar)- cd->fields.dim + i;
2056                 assert(indx < elements->dim);
2057                 z = (*elements)[indx];
2058             }
2059             if (!z)
2060             {
2061                 for (int j = level; j > 0; --j) printf(" ");
2062                 printf(" void\n");
2063                 continue;
2064             }
2065 
2066             if (v)
2067             {
2068                 // If it is a void assignment, use the default initializer
2069                 if ((v->type->ty != z->type->ty) && v->type->ty == Tsarray)
2070                 {
2071                     for (int j = level; --j; ) printf(" ");
2072                     printf(" field: block initalized static array\n");
2073                     continue;
2074                 }
2075             }
2076             showCtfeExpr(z, level + 1);
2077         }
2078     }
2079 }
2080 
2081 /*************************** Void initialization ***************************/
2082 
voidInitLiteral(Type * t,VarDeclaration * var)2083 UnionExp voidInitLiteral(Type *t, VarDeclaration *var)
2084 {
2085     UnionExp ue;
2086     if (t->ty == Tsarray)
2087     {
2088         TypeSArray *tsa = (TypeSArray *)t;
2089         Expression *elem = voidInitLiteral(tsa->next, var).copy();
2090 
2091         // For aggregate value types (structs, static arrays) we must
2092         // create an a separate copy for each element.
2093         bool mustCopy = (elem->op == TOKarrayliteral || elem->op == TOKstructliteral);
2094 
2095         Expressions *elements = new Expressions();
2096         size_t d = (size_t)tsa->dim->toInteger();
2097         elements->setDim(d);
2098         for (size_t i = 0; i < d; i++)
2099         {
2100             if (mustCopy && i > 0)
2101                 elem  = copyLiteral(elem).copy();
2102             (*elements)[i] = elem;
2103         }
2104         new(&ue) ArrayLiteralExp(var->loc, tsa, elements);
2105         ArrayLiteralExp *ae = (ArrayLiteralExp *)ue.exp();
2106         ae->ownedByCtfe = OWNEDctfe;
2107     }
2108     else if (t->ty == Tstruct)
2109     {
2110         TypeStruct *ts = (TypeStruct *)t;
2111         Expressions *exps = new Expressions();
2112         exps->setDim(ts->sym->fields.dim);
2113         for (size_t i = 0; i < ts->sym->fields.dim; i++)
2114         {
2115             (*exps)[i] = voidInitLiteral(ts->sym->fields[i]->type, ts->sym->fields[i]).copy();
2116         }
2117         new(&ue) StructLiteralExp(var->loc, ts->sym, exps);
2118         StructLiteralExp *se = (StructLiteralExp *)ue.exp();
2119         se->type = ts;
2120         se->ownedByCtfe = OWNEDctfe;
2121     }
2122     else
2123         new(&ue) VoidInitExp(var, t);
2124     return ue;
2125 }
2126