2 * Semantic analysis of initializers.
4 * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
5 * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
6 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
7 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/initsem.d, _initsem.d)
8 * Documentation: https://dlang.org/phobos/dmd_initsem.html
9 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/initsem.d
14 import core.stdc.stdio;
15 import core.checkedint;
19 import dmd.arraytypes;
22 import dmd.declaration;
28 import dmd.expression;
29 import dmd.expressionsem;
33 import dmd.identifier;
42 /********************************
43 * If possible, convert array initializer to associative array initializer.
46 * ai = array initializer to be converted
49 * The converted associative array initializer or ErrorExp if `ai`
50 * is not an associative array initializer.
52 Expression toAssocArrayLiteral(ArrayInitializer ai)
55 //printf("ArrayInitializer::toAssocArrayInitializer()\n");
56 //static int i; if (++i == 2) assert(0);
57 const dim = ai.value.dim;
58 auto keys = new Expressions(dim);
59 auto values = new Expressions(dim);
60 for (size_t i = 0; i < dim; i++)
66 Initializer iz = ai.value[i];
69 e = iz.initializerToExpression();
74 e = new AssocArrayLiteralExp(ai.loc, keys, values);
77 error(ai.loc, "not an associative array initializer");
78 return ErrorExp.get();
81 /******************************************
82 * Perform semantic analysis on init.
84 * init = Initializer AST node
86 * tx = type that the initializer needs to become. If tx is an incomplete
87 * type and the initializer completes it, it is updated to be the
88 * complete type. ImportC has incomplete types
89 * needInterpret = if CTFE needs to be run on this,
90 * such as if it is the initializer for a const declaration
92 * `Initializer` with completed semantic analysis, `ErrorInitializer` if errors
95 extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedInterpret needInterpret)
99 static Initializer err()
101 return new ErrorInitializer();
104 Initializer visitVoid(VoidInitializer i)
110 Initializer visitError(ErrorInitializer i)
115 Initializer visitStruct(StructInitializer i)
117 //printf("StructInitializer::semantic(t = %s) %s\n", t.toChars(), i.toChars());
118 /* This works by replacing the StructInitializer with an ExpInitializer.
121 if (t.ty == Tsarray && t.nextOf().toBasetype().ty == Tstruct)
122 t = t.nextOf().toBasetype();
123 if (auto ts = t.isTypeStruct())
125 StructDeclaration sd = ts.sym;
126 // check if the sd has a regular ctor (user defined non-copy ctor)
127 // that is not disabled.
128 if (sd.hasRegularCtor(true))
130 error(i.loc, "%s `%s` has constructors, cannot use `{ initializers }`, use `%s( initializers )` instead", sd.kind(), sd.toChars(), sd.toChars());
134 if (sd.sizeok != Sizeok.done)
136 const nfields = sd.nonHiddenFields();
137 //expandTuples for non-identity arguments?
138 auto elements = new Expressions(nfields);
139 auto elems = (*elements)[];
140 foreach (ref elem; elems)
143 // Run semantic for explicitly given initializers
144 // TODO: this part is slightly different from StructLiteralExp::semantic.
147 foreach (j, id; i.field[])
151 /* Determine `fieldi` that `id` matches
153 Dsymbol s = sd.search(i.loc, id);
156 s = sd.search_correct(id);
157 const initLoc = i.value[j].loc;
159 error(initLoc, "`%s` is not a member of `%s`, did you mean %s `%s`?", id.toChars(), sd.toChars(), s.kind(), s.toChars());
161 error(initLoc, "`%s` is not a member of `%s`", id.toChars(), sd.toChars());
164 s.checkDeprecated(i.loc, sc);
167 // Find out which field index `s` is
168 for (fieldi = 0; 1; fieldi++)
170 if (fieldi >= nfields)
172 error(i.loc, "`%s.%s` is not a per-instance initializable field", sd.toChars(), s.toChars());
175 if (s == sd.fields[fieldi])
179 else if (fieldi >= nfields)
181 error(i.loc, "too many initializers for `%s`", sd.toChars());
185 VarDeclaration vd = sd.fields[fieldi];
188 error(i.loc, "duplicate initializer for field `%s`", vd.toChars());
193 // Check for @safe violations
194 if (vd.type.hasPointers)
196 if ((t.alignment() < target.ptrsize ||
197 (vd.offset & (target.ptrsize - 1))) &&
198 sc.func && sc.func.setUnsafe())
200 error(i.loc, "field `%s.%s` cannot assign to misaligned pointers in `@safe` code",
201 sd.toChars(), vd.toChars());
206 // Check for overlapping initializations (can happen with unions)
207 foreach (k, v2; sd.fields[0 .. nfields])
209 if (vd.isOverlappedWith(v2) && elems[k])
211 error(i.loc, "overlapping initialization for field `%s` and `%s`", v2.toChars(), vd.toChars());
217 // Convert initializer to Expression `ex`
219 auto tm = vd.type.addMod(t.mod);
220 auto iz = i.value[j].initializerSemantic(sc, tm, needInterpret);
221 auto ex = iz.initializerToExpression();
222 if (ex.op == TOK.error)
229 elems[fieldi] = doCopyOrMove(sc, ex);
235 // Make a StructLiteralExp out of elements[]
236 auto sle = new StructLiteralExp(i.loc, sd, elements, t);
237 if (!sd.fill(i.loc, elements, false))
240 auto ie = new ExpInitializer(i.loc, sle);
241 return ie.initializerSemantic(sc, t, needInterpret);
243 else if ((t.ty == Tdelegate || t.isPtrToFunction()) && i.value.dim == 0)
245 const tok = (t.ty == Tdelegate) ? TOK.delegate_ : TOK.function_;
246 /* Rewrite as empty delegate literal { }
248 Type tf = new TypeFunction(ParameterList(), null, LINK.d);
249 auto fd = new FuncLiteralDeclaration(i.loc, Loc.initial, tf, tok, null);
250 fd.fbody = new CompoundStatement(i.loc, new Statements());
252 Expression e = new FuncExp(i.loc, fd);
253 auto ie = new ExpInitializer(i.loc, e);
254 return ie.initializerSemantic(sc, t, needInterpret);
257 error(i.loc, "a struct is not a valid initializer for a `%s`", t.toChars());
261 Initializer visitArray(ArrayInitializer i)
264 const(uint) amax = 0x80000000;
266 //printf("ArrayInitializer::semantic(%s)\n", t.toChars());
267 if (i.sem) // if semantic() already run
279 t = (cast(TypeVector)t).basetype;
282 case Tstruct: // consider implicit constructor call
285 // note: MyStruct foo = [1:2, 3:4] is correct code if MyStruct has a this(int[int])
286 if (t.ty == Taarray || i.isAssociativeArray())
287 e = i.toAssocArrayLiteral();
289 e = i.initializerToExpression();
293 error(i.loc, "cannot use array to initialize `%s`", t.toChars());
296 auto ei = new ExpInitializer(e.loc, e);
297 return ei.initializerSemantic(sc, t, needInterpret);
300 if (t.nextOf().ty != Tfunction)
304 error(i.loc, "cannot use array to initialize `%s`", t.toChars());
309 for (size_t j = 0; j < i.index.dim; j++)
311 Expression idx = i.index[j];
315 idx = idx.expressionSemantic(sc);
317 idx = idx.ctfeInterpret();
319 const uinteger_t idxvalue = idx.toInteger();
320 if (idxvalue >= amax)
322 error(i.loc, "array index %llu overflow", idxvalue);
325 length = cast(uint)idxvalue;
326 if (idx.op == TOK.error)
329 Initializer val = i.value[j];
330 ExpInitializer ei = val.isExpInitializer();
332 ei.expandTuples = true;
333 auto tn = t.nextOf();
334 val = val.initializerSemantic(sc, tn, needInterpret);
335 if (val.isErrorInitializer())
337 ei = val.isExpInitializer();
338 // found a tuple, expand it
339 if (ei && ei.exp.op == TOK.tuple)
341 TupleExp te = cast(TupleExp)ei.exp;
344 for (size_t k = 0; k < te.exps.dim; ++k)
346 Expression e = (*te.exps)[k];
347 i.index.insert(j + k, cast(Expression)null);
348 i.value.insert(j + k, new ExpInitializer(e.loc, e));
360 error(i.loc, "array dimension overflow");
368 uinteger_t edim = (cast(TypeSArray)t).dim.toInteger();
371 error(i.loc, "array initializer has %u elements, but array length is %llu", i.dim, edim);
378 const sz = t.nextOf().size();
380 const max = mulu(i.dim, sz, overflow);
381 if (overflow || max >= amax)
383 error(i.loc, "array dimension %llu exceeds max of %llu", ulong(i.dim), ulong(amax / sz));
389 Initializer visitExp(ExpInitializer i)
391 //printf("ExpInitializer::semantic(%s), type = %s\n", i.exp.toChars(), t.toChars());
394 i.exp = i.exp.expressionSemantic(sc);
395 i.exp = resolveProperties(sc, i.exp);
398 if (i.exp.op == TOK.error)
400 uint olderrors = global.errors;
401 /* Save the expression before ctfe
402 * Otherwise the error message would contain for example "&[0][0]" instead of "new int"
403 * Regression: https://issues.dlang.org/show_bug.cgi?id=21687
405 Expression currExp = i.exp;
408 // If the result will be implicitly cast, move the cast into CTFE
409 // to avoid premature truncation of polysemous types.
410 // eg real [] x = [1.1, 2.2]; should use real precision.
411 if (i.exp.implicitConvTo(t))
413 i.exp = i.exp.implicitCastTo(sc, t);
415 if (!global.gag && olderrors != global.errors)
419 i.exp = i.exp.ctfeInterpret();
420 if (i.exp.op == TOK.voidExpression)
421 error(i.loc, "variables cannot be initialized with an expression of type `void`. Use `void` initialization instead.");
425 i.exp = i.exp.optimize(WANTvalue);
427 if (!global.gag && olderrors != global.errors)
429 return i; // Failed, suppress duplicate error messages
431 if (i.exp.type.ty == Ttuple && (cast(TypeTuple)i.exp.type).arguments.dim == 0)
433 Type et = i.exp.type;
434 i.exp = new TupleExp(i.exp.loc, new Expressions());
437 if (i.exp.op == TOK.type)
439 i.exp.error("initializer must be an expression, not `%s`", i.exp.toChars());
442 // Make sure all pointers are constants
443 if (needInterpret && hasNonConstPointers(i.exp))
445 i.exp.error("cannot use non-constant CTFE pointer in an initializer `%s`", currExp.toChars());
448 Type tb = t.toBasetype();
449 Type ti = i.exp.type.toBasetype();
450 if (i.exp.op == TOK.tuple && i.expandTuples && !i.exp.implicitConvTo(t))
452 return new ExpInitializer(i.loc, i.exp);
454 /* Look for case of initializing a static array with a too-short
455 * string literal, such as:
456 * char[5] foo = "abc";
457 * Allow this by doing an explicit cast, which will lengthen the string
460 if (i.exp.op == TOK.string_ && tb.ty == Tsarray)
462 StringExp se = cast(StringExp)i.exp;
463 Type typeb = se.type.toBasetype();
464 TY tynto = tb.nextOf().ty;
466 (typeb.ty == Tarray || typeb.ty == Tsarray) && tynto.isSomeChar &&
467 se.numberOfCodeUnits(tynto) < (cast(TypeSArray)tb).dim.toInteger())
469 i.exp = se.castTo(sc, t);
475 * Initialize an array of unknown size with a string.
476 * ImportC regards Tarray as an array of unknown size.
477 * Change to static array of known size
479 if (sc.flags & SCOPE.Cfile && i.exp.op == TOK.string_ && tb.ty == Tarray)
481 StringExp se = i.exp.isStringExp();
482 auto ts = new TypeSArray(tb.nextOf(), new IntegerExp(Loc.initial, se.len + 1, Type.tsize_t));
483 t = typeSemantic(ts, Loc.initial, sc);
488 // Look for implicit constructor call
489 if (tb.ty == Tstruct && !(ti.ty == Tstruct && tb.toDsymbol(sc) == ti.toDsymbol(sc)) && !i.exp.implicitConvTo(t))
491 StructDeclaration sd = (cast(TypeStruct)tb).sym;
494 // Rewrite as S().ctor(exp)
496 e = new StructLiteralExp(i.loc, sd, null);
497 e = new DotIdExp(i.loc, e, Id.ctor);
498 e = new CallExp(i.loc, e, i.exp);
499 e = e.expressionSemantic(sc);
501 i.exp = e.ctfeInterpret();
503 i.exp = e.optimize(WANTvalue);
505 else if (search_function(sd, Id.call))
507 /* https://issues.dlang.org/show_bug.cgi?id=1547
509 * Look for static opCall
512 * i.exp = typeof(sd).opCall(arguments)
515 Expression e = typeDotIdExp(i.loc, sd.type, Id.call);
516 e = new CallExp(i.loc, e, i.exp);
517 e = e.expressionSemantic(sc);
518 e = resolveProperties(sc, e);
520 i.exp = e.ctfeInterpret();
522 i.exp = e.optimize(WANTvalue);
525 // Look for the case of statically initializing an array
526 // with a single member.
527 if (tb.ty == Tsarray && !tb.nextOf().equals(ti.toBasetype().nextOf()) && i.exp.implicitConvTo(tb.nextOf()))
529 /* If the variable is not actually used in compile time, array creation is
530 * redundant. So delay it until invocation of toExpression() or toDt().
534 if (i.exp.implicitConvTo(t))
536 i.exp = i.exp.implicitCastTo(sc, t);
540 // Look for mismatch of compile-time known length to emit
541 // better diagnostic message, as same as AssignExp::semantic.
542 if (tb.ty == Tsarray && i.exp.implicitConvTo(tb.nextOf().arrayOf()) > MATCH.nomatch)
544 uinteger_t dim1 = (cast(TypeSArray)tb).dim.toInteger();
545 uinteger_t dim2 = dim1;
546 if (i.exp.op == TOK.arrayLiteral)
548 ArrayLiteralExp ale = cast(ArrayLiteralExp)i.exp;
549 dim2 = ale.elements ? ale.elements.dim : 0;
551 else if (i.exp.op == TOK.slice)
553 Type tx = toStaticArrayType(cast(SliceExp)i.exp);
555 dim2 = (cast(TypeSArray)tx).dim.toInteger();
559 i.exp.error("mismatched array lengths, %d and %d", cast(int)dim1, cast(int)dim2);
560 i.exp = ErrorExp.get();
563 i.exp = i.exp.implicitCastTo(sc, t);
566 if (i.exp.op == TOK.error)
571 i.exp = i.exp.ctfeInterpret();
573 i.exp = i.exp.optimize(WANTvalue);
574 //printf("-ExpInitializer::semantic(): "); i.exp.print();
578 Initializer visitC(CInitializer ci)
580 if (ci.sem) // if semantic() already run
582 //printf("CInitializer::semantic() (%s) %s\n", t.toChars(), ci.toChars());
585 ci.type = t; // later passes will need this
587 auto dil = ci.initializerList[];
588 size_t i = 0; // index into dil[]
589 const uint amax = 0x8000_0000;
592 /* If `{ expression }` return the expression initializer
594 ExpInitializer isBraceExpression()
596 return (dil.length == 1 && !dil[0].designatorList)
597 ? dil[0].initializer.isExpInitializer()
601 /* Convert struct initializer into ExpInitializer
603 Initializer structs(TypeStruct ts)
605 //printf("structs %s\n", ts.toChars());
606 StructDeclaration sd = ts.sym;
608 if (sd.sizeok != Sizeok.done)
613 const nfields = sd.nonHiddenFields();
614 auto elements = new Expressions(nfields);
615 auto elems = (*elements)[];
616 foreach (ref elem; elems)
620 for (size_t fieldi = 0; fieldi < nfields; ++fieldi)
626 if (di.designatorList)
628 error(ci.loc, "C designator-list not supported yet");
633 VarDeclaration vd = sd.fields[fieldi];
635 // Check for overlapping initializations (can happen with unions)
636 foreach (k, v2; sd.fields[0 .. nfields])
638 if (vd.isOverlappedWith(v2) && elems[k])
640 continue FieldLoop; // skip it
646 // Convert initializer to Expression `ex`
648 auto tm = vd.type.addMod(ts.mod);
649 auto iz = di.initializer.initializerSemantic(sc, tm, needInterpret);
650 auto ex = iz.initializerToExpression();
651 if (ex.op == TOK.error)
662 // Make a StructLiteralExp out of elements[]
664 auto sle = new StructLiteralExp(ci.loc, sd, elements, tx);
665 if (!sd.fill(ci.loc, elements, false))
668 auto ie = new ExpInitializer(ci.loc, sle);
669 return ie.initializerSemantic(sc, tx, needInterpret);
672 if (auto ts = t.isTypeStruct())
674 auto ei = structs(ts);
679 error(ci.loc, "%d extra initializer(s) for `struct %s`", cast(int)(dil.length - i), ts.toChars());
685 auto tsa = t.isTypeSArray();
686 auto ta = t.isTypeDArray();
689 /* Not an array. See if it is `{ exp }` which can be
690 * converted to an ExpInitializer
692 if (ExpInitializer ei = isBraceExpression())
694 return ei.initializerSemantic(sc, t, needInterpret);
697 error(ci.loc, "C non-array initializer (%s) %s not supported yet", t.toChars(), ci.toChars());
701 /* If it's an array of integral being initialized by `{ string }`
702 * replace with `string`
704 auto tn = t.nextOf();
707 if (ExpInitializer ei = isBraceExpression())
709 if (ei.exp.isStringExp())
710 return ei.initializerSemantic(sc, t, needInterpret);
714 /* Support recursion to handle un-braced array initializers
717 * dim = max number of elements
719 * # of elements in array
721 size_t array(Type t, size_t dim)
723 //printf(" type %s i %d dim %d dil.length = %d\n", t.toChars(), cast(int)i, cast(int)dim, cast(int)dil.length);
724 auto tn = t.nextOf().toBasetype();
725 if (auto tna = tn.isTypeDArray())
727 // C11 6.2.5-20 "element type shall be complete whenever the array type is specified"
728 error(ci.loc, "incomplete element type `%s` not allowed", tna.toChars());
735 auto tnsa = tn.isTypeSArray();
736 const nelems = tnsa ? cast(size_t)tnsa.dim.toInteger() : 0;
738 foreach (j; 0 .. dim)
741 if (di.designatorList)
743 error(ci.loc, "C designator-list not supported yet");
747 if (tnsa && di.initializer.isExpInitializer())
749 // no braces enclosing array initializer, so recurse
752 else if (auto tns = tn.isTypeStruct())
754 dil[n].initializer = structs(tns);
759 auto tnx = tn; // in case initializerSemantic tries to change it
760 di.initializer = di.initializer.initializerSemantic(sc, tnx, needInterpret);
761 if (di.initializer.isErrorInitializer())
763 assert(tnx == tn); // sub-types should not be modified
769 //printf(" n: %d i: %d\n", cast(int)n, cast(int)i);
773 size_t dim = ta ? dil.length : cast(size_t)tsa.dim.toInteger();
774 auto n = array(t, dim);
779 if (ta) // array of unknown length
781 // Change to array of known length
782 tsa = new TypeSArray(tn, new IntegerExp(Loc.initial, n, Type.tsize_t));
783 tx = tsa; // rewrite caller's type
784 ci.type = tsa; // remember for later passes
786 const uinteger_t edim = tsa.dim.toInteger();
789 error(ci.loc, "%d extra initializer(s) for static array length of %d", cast(int)(dil.length - i), cast(int)edim);
793 const sz = tn.size(); // element size
795 const max = mulu(edim, sz, overflow);
796 if (overflow || max >= amax)
798 error(ci.loc, "array dimension %llu exceeds max of %llu", ulong(edim), ulong(amax / sz));
805 final switch (init.kind)
807 case InitKind.void_: return visitVoid (cast( VoidInitializer)init);
808 case InitKind.error: return visitError (cast( ErrorInitializer)init);
809 case InitKind.struct_: return visitStruct(cast(StructInitializer)init);
810 case InitKind.array: return visitArray (cast( ArrayInitializer)init);
811 case InitKind.exp: return visitExp (cast( ExpInitializer)init);
812 case InitKind.C_: return visitC (cast( CInitializer)init);
816 /***********************
817 * Translate init to an `Expression` in order to infer the type.
819 * init = `Initializer` AST node
822 * an equivalent `ExpInitializer` if successful, or `ErrorInitializer` if it cannot be translated
824 Initializer inferType(Initializer init, Scope* sc)
826 Initializer visitVoid(VoidInitializer i)
828 error(i.loc, "cannot infer type from void initializer");
829 return new ErrorInitializer();
832 Initializer visitError(ErrorInitializer i)
837 Initializer visitStruct(StructInitializer i)
839 error(i.loc, "cannot infer type from struct initializer");
840 return new ErrorInitializer();
843 Initializer visitArray(ArrayInitializer init)
845 //printf("ArrayInitializer::inferType() %s\n", toChars());
846 Expressions* keys = null;
848 if (init.isAssociativeArray())
850 keys = new Expressions(init.value.dim);
851 values = new Expressions(init.value.dim);
852 for (size_t i = 0; i < init.value.dim; i++)
854 Expression e = init.index[i];
858 Initializer iz = init.value[i];
861 iz = iz.inferType(sc);
862 if (iz.isErrorInitializer())
866 assert(iz.isExpInitializer());
867 (*values)[i] = (cast(ExpInitializer)iz).exp;
868 assert((*values)[i].op != TOK.error);
870 Expression e = new AssocArrayLiteralExp(init.loc, keys, values);
871 auto ei = new ExpInitializer(init.loc, e);
872 return ei.inferType(sc);
876 auto elements = new Expressions(init.value.dim);
878 for (size_t i = 0; i < init.value.dim; i++)
880 assert(!init.index[i]); // already asserted by isAssociativeArray()
881 Initializer iz = init.value[i];
884 iz = iz.inferType(sc);
885 if (iz.isErrorInitializer())
889 assert(iz.isExpInitializer());
890 (*elements)[i] = (cast(ExpInitializer)iz).exp;
891 assert((*elements)[i].op != TOK.error);
893 Expression e = new ArrayLiteralExp(init.loc, null, elements);
894 auto ei = new ExpInitializer(init.loc, e);
895 return ei.inferType(sc);
900 error(init.loc, "not an associative array initializer");
904 error(init.loc, "cannot infer type from array initializer");
906 return new ErrorInitializer();
909 Initializer visitExp(ExpInitializer init)
911 //printf("ExpInitializer::inferType() %s\n", init.toChars());
912 init.exp = init.exp.expressionSemantic(sc);
914 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
915 if (init.exp.op == TOK.type)
916 init.exp = resolveAliasThis(sc, init.exp);
918 init.exp = resolveProperties(sc, init.exp);
919 if (init.exp.op == TOK.scope_)
921 ScopeExp se = cast(ScopeExp)init.exp;
922 TemplateInstance ti = se.sds.isTemplateInstance();
923 if (ti && ti.semanticRun == PASS.semantic && !ti.aliasdecl)
924 se.error("cannot infer type from %s `%s`, possible circular dependency", se.sds.kind(), se.toChars());
926 se.error("cannot infer type from %s `%s`", se.sds.kind(), se.toChars());
927 return new ErrorInitializer();
930 // Give error for overloaded function addresses
932 if (auto f = isFuncAddress(init.exp, &hasOverloads))
934 if (f.checkForwardRef(init.loc))
936 return new ErrorInitializer();
938 if (hasOverloads && !f.isUnique())
940 init.exp.error("cannot infer type from overloaded function symbol `%s`", init.exp.toChars());
941 return new ErrorInitializer();
944 if (init.exp.op == TOK.address)
946 AddrExp ae = cast(AddrExp)init.exp;
947 if (ae.e1.op == TOK.overloadSet)
949 init.exp.error("cannot infer type from overloaded function symbol `%s`", init.exp.toChars());
950 return new ErrorInitializer();
953 if (init.exp.op == TOK.error)
955 return new ErrorInitializer();
959 return new ErrorInitializer();
964 Initializer visitC(CInitializer i)
966 //printf(CInitializer::inferType()\n");
967 error(i.loc, "TODO C inferType initializers not supported yet");
968 return new ErrorInitializer();
971 final switch (init.kind)
973 case InitKind.void_: return visitVoid (cast( VoidInitializer)init);
974 case InitKind.error: return visitError (cast( ErrorInitializer)init);
975 case InitKind.struct_: return visitStruct(cast(StructInitializer)init);
976 case InitKind.array: return visitArray (cast( ArrayInitializer)init);
977 case InitKind.exp: return visitExp (cast( ExpInitializer)init);
978 case InitKind.C_: return visitC (cast( CInitializer)init);
982 /***********************
983 * Translate init to an `Expression`.
985 * init = `Initializer` AST node
986 * itype = if not `null`, type to coerce expression to
988 * `Expression` created, `null` if cannot, `ErrorExp` for other errors
990 extern (C++) Expression initializerToExpression(Initializer init, Type itype = null)
992 Expression visitVoid(VoidInitializer)
997 Expression visitError(ErrorInitializer)
999 return ErrorExp.get();
1002 /***************************************
1003 * This works by transforming a struct initializer into
1004 * a struct literal. In the future, the two should be the
1007 Expression visitStruct(StructInitializer)
1009 // cannot convert to an expression without target 'ad'
1013 /********************************
1014 * If possible, convert array initializer to array literal.
1015 * Otherwise return NULL.
1017 Expression visitArray(ArrayInitializer init)
1019 //printf("ArrayInitializer::toExpression(), dim = %d\n", dim);
1020 //static int i; if (++i == 2) assert(0);
1021 uint edim; // the length of the resulting array literal
1022 const(uint) amax = 0x80000000;
1023 Type t = null; // type of the array literal being initialized
1026 if (init.type == Type.terror)
1028 return ErrorExp.get();
1030 t = init.type.toBasetype();
1034 t = t.isTypeVector().basetype;
1038 uinteger_t adim = t.isTypeSArray().dim.toInteger();
1041 edim = cast(uint)adim;
1055 /* Calculate the length of the array literal
1057 edim = cast(uint)init.value.dim;
1059 foreach (i; 0 .. init.value.dim)
1061 if (auto e = init.index[i])
1063 if (e.op == TOK.int64)
1065 const uinteger_t idxval = e.toInteger();
1068 j = cast(size_t)idxval;
1079 auto elements = new Expressions(edim);
1082 foreach (i; 0 .. init.value.dim)
1084 if (auto e = init.index[i])
1085 j = cast(size_t)e.toInteger();
1087 if (Initializer iz = init.value[i])
1089 if (Expression ex = iz.initializerToExpression())
1091 (*elements)[j] = ex;
1101 /* Fill in any missing elements with the default initializer
1103 Expression defaultInit = null; // lazily create it
1104 foreach (ref element; (*elements)[0 .. edim])
1108 if (!init.type) // don't know what type to use
1111 defaultInit = (cast(TypeNext)t).next.defaultInit(Loc.initial);
1112 element = defaultInit;
1116 /* Expand any static array initializers that are a single expression
1117 * into an array of them
1118 * e => [e, e, ..., e, e]
1122 Type tn = t.nextOf().toBasetype();
1123 if (tn.ty == Tsarray)
1125 const dim = cast(size_t)(cast(TypeSArray)tn).dim.toInteger();
1126 Type te = tn.nextOf().toBasetype();
1127 foreach (ref e; *elements)
1129 if (te.equals(e.type))
1131 auto elements2 = new Expressions(dim);
1132 foreach (ref e2; *elements2)
1134 e = new ArrayLiteralExp(e.loc, tn, elements2);
1140 /* If any elements are errors, then the whole thing is an error
1142 foreach (e; (*elements)[0 .. edim])
1144 if (e.op == TOK.error)
1150 Expression e = new ArrayLiteralExp(init.loc, init.type, elements);
1154 Expression visitExp(ExpInitializer i)
1158 //printf("ExpInitializer::toExpression(t = %s) exp = %s\n", itype.toChars(), i.exp.toChars());
1159 Type tb = itype.toBasetype();
1160 Expression e = (i.exp.op == TOK.construct || i.exp.op == TOK.blit) ? (cast(AssignExp)i.exp).e2 : i.exp;
1161 if (tb.ty == Tsarray && e.implicitConvTo(tb.nextOf()))
1163 TypeSArray tsa = cast(TypeSArray)tb;
1164 size_t d = cast(size_t)tsa.dim.toInteger();
1165 auto elements = new Expressions(d);
1166 for (size_t j = 0; j < d; j++)
1168 auto ae = new ArrayLiteralExp(e.loc, itype, elements);
1175 Expression visitC(CInitializer i)
1177 //printf("CInitializer.initializerToExpression()\n");
1181 final switch (init.kind)
1183 case InitKind.void_: return visitVoid (cast( VoidInitializer)init);
1184 case InitKind.error: return visitError (cast( ErrorInitializer)init);
1185 case InitKind.struct_: return visitStruct(cast(StructInitializer)init);
1186 case InitKind.array: return visitArray (cast( ArrayInitializer)init);
1187 case InitKind.exp: return visitExp (cast( ExpInitializer)init);
1188 case InitKind.C_: return visitC (cast( CInitializer)init);
1193 /**************************************
1194 * Determine if expression has non-constant pointers, or more precisely,
1195 * a pointer that CTFE cannot handle.
1197 * e = expression to check
1199 * true if it has non-constant pointers
1201 private bool hasNonConstPointers(Expression e)
1203 static bool checkArray(Expressions* elems)
1207 if (e && hasNonConstPointers(e))
1213 if (e.type.ty == Terror)
1215 if (e.op == TOK.null_)
1217 if (auto se = e.isStructLiteralExp())
1219 return checkArray(se.elements);
1221 if (auto ae = e.isArrayLiteralExp())
1223 if (!ae.type.nextOf().hasPointers())
1225 return checkArray(ae.elements);
1227 if (auto ae = e.isAssocArrayLiteralExp())
1229 if (ae.type.nextOf().hasPointers() && checkArray(ae.values))
1231 if ((cast(TypeAArray)ae.type).index.hasPointers())
1232 return checkArray(ae.keys);
1235 if (auto ae = e.isAddrExp())
1237 if (auto se = ae.e1.isStructLiteralExp())
1239 if (!(se.stageflags & stageSearchPointers))
1241 const old = se.stageflags;
1242 se.stageflags |= stageSearchPointers;
1243 bool ret = checkArray(se.elements);
1244 se.stageflags = old;
1254 if (e.type.ty == Tpointer && !e.type.isPtrToFunction())
1256 if (e.op == TOK.symbolOffset) // address of a global is OK
1258 if (e.op == TOK.int64) // cast(void *)int is OK
1260 if (e.op == TOK.string_) // "abc".ptr is OK