1 /** 2 * Semantic analysis of initializers. 3 * 4 * Copyright: Copyright (C) 1999-2020 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 10 */ 11 12 module dmd.initsem; 13 14 import core.stdc.stdio; 15 import core.checkedint; 16 17 import dmd.aggregate; 18 import dmd.aliasthis; 19 import dmd.arraytypes; 20 import dmd.dcast; 21 import dmd.declaration; 22 import dmd.dscope; 23 import dmd.dstruct; 24 import dmd.dsymbol; 25 import dmd.dtemplate; 26 import dmd.errors; 27 import dmd.expression; 28 import dmd.expressionsem; 29 import dmd.func; 30 import dmd.globals; 31 import dmd.id; 32 import dmd.identifier; 33 import dmd.init; 34 import dmd.mtype; 35 import dmd.opover; 36 import dmd.statement; 37 import dmd.target; 38 import dmd.tokens; 39 import dmd.typesem; 40 41 /******************************** 42 * If possible, convert array initializer to associative array initializer. 43 * 44 * Params: 45 * ai = array initializer to be converted 46 * 47 * Returns: 48 * The converted associative array initializer or ErrorExp if `ai` 49 * is not an associative array initializer. 50 */ 51 Expression toAssocArrayLiteral(ArrayInitializer ai) 52 { 53 Expression e; 54 //printf("ArrayInitializer::toAssocArrayInitializer()\n"); 55 //static int i; if (++i == 2) assert(0); 56 const dim = ai.value.dim; 57 auto keys = new Expressions(dim); 58 auto values = new Expressions(dim); 59 for (size_t i = 0; i < dim; i++) 60 { 61 e = ai.index[i]; 62 if (!e) 63 goto Lno; 64 (*keys)[i] = e; 65 Initializer iz = ai.value[i]; 66 if (!iz) 67 goto Lno; 68 e = iz.initializerToExpression(); 69 if (!e) 70 goto Lno; 71 (*values)[i] = e; 72 } 73 e = new AssocArrayLiteralExp(ai.loc, keys, values); 74 return e; 75 Lno: 76 error(ai.loc, "not an associative array initializer"); 77 return new ErrorExp(); 78 } 79 80 /****************************************** 81 * Perform semantic analysis on init. 82 * Params: 83 * init = Initializer AST node 84 * sc = context 85 * t = type that the initializer needs to become 86 * needInterpret = if CTFE needs to be run on this, 87 * such as if it is the initializer for a const declaration 88 * Returns: 89 * `Initializer` with completed semantic analysis, `ErrorInitializer` if errors 90 * were encountered 91 */ 92 extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, Type t, NeedInterpret needInterpret) 93 { 94 Initializer visitVoid(VoidInitializer i) 95 { 96 i.type = t; 97 return i; 98 } 99 100 Initializer visitError(ErrorInitializer i) 101 { 102 return i; 103 } 104 105 Initializer visitStruct(StructInitializer i) 106 { 107 //printf("StructInitializer::semantic(t = %s) %s\n", t.toChars(), toChars()); 108 t = t.toBasetype(); 109 if (t.ty == Tsarray && t.nextOf().toBasetype().ty == Tstruct) 110 t = t.nextOf().toBasetype(); 111 if (t.ty == Tstruct) 112 { 113 StructDeclaration sd = (cast(TypeStruct)t).sym; 114 if (sd.ctor) 115 { 116 error(i.loc, "%s `%s` has constructors, cannot use `{ initializers }`, use `%s( initializers )` instead", sd.kind(), sd.toChars(), sd.toChars()); 117 return new ErrorInitializer(); 118 } 119 sd.size(i.loc); 120 if (sd.sizeok != Sizeok.done) 121 { 122 return new ErrorInitializer(); 123 } 124 const nfields = sd.nonHiddenFields(); 125 //expandTuples for non-identity arguments? 126 auto elements = new Expressions(nfields); 127 for (size_t j = 0; j < elements.dim; j++) 128 (*elements)[j] = null; 129 // Run semantic for explicitly given initializers 130 // TODO: this part is slightly different from StructLiteralExp::semantic. 131 bool errors = false; 132 for (size_t fieldi = 0, j = 0; j < i.field.dim; j++) 133 { 134 if (Identifier id = i.field[j]) 135 { 136 Dsymbol s = sd.search(i.loc, id); 137 if (!s) 138 { 139 s = sd.search_correct(id); 140 Loc initLoc = i.value[j].loc; 141 if (s) 142 error(initLoc, "`%s` is not a member of `%s`, did you mean %s `%s`?", id.toChars(), sd.toChars(), s.kind(), s.toChars()); 143 else 144 error(initLoc, "`%s` is not a member of `%s`", id.toChars(), sd.toChars()); 145 return new ErrorInitializer(); 146 } 147 s = s.toAlias(); 148 // Find out which field index it is 149 for (fieldi = 0; 1; fieldi++) 150 { 151 if (fieldi >= nfields) 152 { 153 error(i.loc, "`%s.%s` is not a per-instance initializable field", sd.toChars(), s.toChars()); 154 return new ErrorInitializer(); 155 } 156 if (s == sd.fields[fieldi]) 157 break; 158 } 159 } 160 else if (fieldi >= nfields) 161 { 162 error(i.loc, "too many initializers for `%s`", sd.toChars()); 163 return new ErrorInitializer(); 164 } 165 VarDeclaration vd = sd.fields[fieldi]; 166 if ((*elements)[fieldi]) 167 { 168 error(i.loc, "duplicate initializer for field `%s`", vd.toChars()); 169 errors = true; 170 continue; 171 } 172 if (vd.type.hasPointers) 173 { 174 if ((t.alignment() < target.ptrsize || 175 (vd.offset & (target.ptrsize - 1))) && 176 sc.func && sc.func.setUnsafe()) 177 { 178 error(i.loc, "field `%s.%s` cannot assign to misaligned pointers in `@safe` code", 179 sd.toChars(), vd.toChars()); 180 errors = true; 181 } 182 } 183 for (size_t k = 0; k < nfields; k++) 184 { 185 VarDeclaration v2 = sd.fields[k]; 186 if (vd.isOverlappedWith(v2) && (*elements)[k]) 187 { 188 error(i.loc, "overlapping initialization for field `%s` and `%s`", v2.toChars(), vd.toChars()); 189 errors = true; 190 continue; 191 } 192 } 193 assert(sc); 194 Initializer iz = i.value[j]; 195 iz = iz.initializerSemantic(sc, vd.type.addMod(t.mod), needInterpret); 196 Expression ex = iz.initializerToExpression(); 197 if (ex.op == TOK.error) 198 { 199 errors = true; 200 continue; 201 } 202 i.value[j] = iz; 203 (*elements)[fieldi] = doCopyOrMove(sc, ex); 204 ++fieldi; 205 } 206 if (errors) 207 { 208 return new ErrorInitializer(); 209 } 210 auto sle = new StructLiteralExp(i.loc, sd, elements, t); 211 if (!sd.fill(i.loc, elements, false)) 212 { 213 return new ErrorInitializer(); 214 } 215 sle.type = t; 216 auto ie = new ExpInitializer(i.loc, sle); 217 return ie.initializerSemantic(sc, t, needInterpret); 218 } 219 else if ((t.ty == Tdelegate || t.ty == Tpointer && t.nextOf().ty == Tfunction) && i.value.dim == 0) 220 { 221 TOK tok = (t.ty == Tdelegate) ? TOK.delegate_ : TOK.function_; 222 /* Rewrite as empty delegate literal { } 223 */ 224 Type tf = new TypeFunction(ParameterList(), null, LINK.d); 225 auto fd = new FuncLiteralDeclaration(i.loc, Loc.initial, tf, tok, null); 226 fd.fbody = new CompoundStatement(i.loc, new Statements()); 227 fd.endloc = i.loc; 228 Expression e = new FuncExp(i.loc, fd); 229 auto ie = new ExpInitializer(i.loc, e); 230 return ie.initializerSemantic(sc, t, needInterpret); 231 } 232 if (t.ty != Terror) 233 error(i.loc, "a struct is not a valid initializer for a `%s`", t.toChars()); 234 return new ErrorInitializer(); 235 } 236 237 Initializer visitArray(ArrayInitializer i) 238 { 239 uint length; 240 const(uint) amax = 0x80000000; 241 bool errors = false; 242 //printf("ArrayInitializer::semantic(%s)\n", t.toChars()); 243 if (i.sem) // if semantic() already run 244 { 245 return i; 246 } 247 i.sem = true; 248 t = t.toBasetype(); 249 switch (t.ty) 250 { 251 case Tsarray: 252 case Tarray: 253 break; 254 case Tvector: 255 t = (cast(TypeVector)t).basetype; 256 break; 257 case Taarray: 258 case Tstruct: // consider implicit constructor call 259 { 260 Expression e; 261 // note: MyStruct foo = [1:2, 3:4] is correct code if MyStruct has a this(int[int]) 262 if (t.ty == Taarray || i.isAssociativeArray()) 263 e = i.toAssocArrayLiteral(); 264 else 265 e = i.initializerToExpression(); 266 // Bugzilla 13987 267 if (!e) 268 { 269 error(i.loc, "cannot use array to initialize `%s`", t.toChars()); 270 goto Lerr; 271 } 272 auto ei = new ExpInitializer(e.loc, e); 273 return ei.initializerSemantic(sc, t, needInterpret); 274 } 275 case Tpointer: 276 if (t.nextOf().ty != Tfunction) 277 break; 278 goto default; 279 default: 280 error(i.loc, "cannot use array to initialize `%s`", t.toChars()); 281 goto Lerr; 282 } 283 i.type = t; 284 length = 0; 285 for (size_t j = 0; j < i.index.dim; j++) 286 { 287 Expression idx = i.index[j]; 288 if (idx) 289 { 290 sc = sc.startCTFE(); 291 idx = idx.expressionSemantic(sc); 292 sc = sc.endCTFE(); 293 idx = idx.ctfeInterpret(); 294 i.index[j] = idx; 295 const uinteger_t idxvalue = idx.toInteger(); 296 if (idxvalue >= amax) 297 { 298 error(i.loc, "array index %llu overflow", ulong(idxvalue)); 299 errors = true; 300 } 301 length = cast(uint)idxvalue; 302 if (idx.op == TOK.error) 303 errors = true; 304 } 305 Initializer val = i.value[j]; 306 ExpInitializer ei = val.isExpInitializer(); 307 if (ei && !idx) 308 ei.expandTuples = true; 309 val = val.initializerSemantic(sc, t.nextOf(), needInterpret); 310 if (val.isErrorInitializer()) 311 errors = true; 312 ei = val.isExpInitializer(); 313 // found a tuple, expand it 314 if (ei && ei.exp.op == TOK.tuple) 315 { 316 TupleExp te = cast(TupleExp)ei.exp; 317 i.index.remove(j); 318 i.value.remove(j); 319 for (size_t k = 0; k < te.exps.dim; ++k) 320 { 321 Expression e = (*te.exps)[k]; 322 i.index.insert(j + k, cast(Expression)null); 323 i.value.insert(j + k, new ExpInitializer(e.loc, e)); 324 } 325 j--; 326 continue; 327 } 328 else 329 { 330 i.value[j] = val; 331 } 332 length++; 333 if (length == 0) 334 { 335 error(i.loc, "array dimension overflow"); 336 goto Lerr; 337 } 338 if (length > i.dim) 339 i.dim = length; 340 } 341 if (t.ty == Tsarray) 342 { 343 uinteger_t edim = (cast(TypeSArray)t).dim.toInteger(); 344 if (i.dim > edim) 345 { 346 error(i.loc, "array initializer has %u elements, but array length is %llu", i.dim, edim); 347 goto Lerr; 348 } 349 } 350 if (errors) 351 goto Lerr; 352 { 353 const sz = t.nextOf().size(); 354 bool overflow; 355 const max = mulu(i.dim, sz, overflow); 356 if (overflow || max >= amax) 357 { 358 error(i.loc, "array dimension %llu exceeds max of %llu", ulong(i.dim), ulong(amax / sz)); 359 goto Lerr; 360 } 361 return i; 362 } 363 Lerr: 364 return new ErrorInitializer(); 365 } 366 367 Initializer visitExp(ExpInitializer i) 368 { 369 //printf("ExpInitializer::semantic(%s), type = %s\n", i.exp.toChars(), t.toChars()); 370 if (needInterpret) 371 sc = sc.startCTFE(); 372 i.exp = i.exp.expressionSemantic(sc); 373 i.exp = resolveProperties(sc, i.exp); 374 if (needInterpret) 375 sc = sc.endCTFE(); 376 if (i.exp.op == TOK.error) 377 { 378 return new ErrorInitializer(); 379 } 380 uint olderrors = global.errors; 381 if (needInterpret) 382 { 383 // If the result will be implicitly cast, move the cast into CTFE 384 // to avoid premature truncation of polysemous types. 385 // eg real [] x = [1.1, 2.2]; should use real precision. 386 if (i.exp.implicitConvTo(t)) 387 { 388 i.exp = i.exp.implicitCastTo(sc, t); 389 } 390 if (!global.gag && olderrors != global.errors) 391 { 392 return i; 393 } 394 i.exp = i.exp.ctfeInterpret(); 395 if (i.exp.op == TOK.voidExpression) 396 error(i.loc, "variables cannot be initialized with an expression of type `void`. Use `void` initialization instead."); 397 } 398 else 399 { 400 i.exp = i.exp.optimize(WANTvalue); 401 } 402 if (!global.gag && olderrors != global.errors) 403 { 404 return i; // Failed, suppress duplicate error messages 405 } 406 if (i.exp.type.ty == Ttuple && (cast(TypeTuple)i.exp.type).arguments.dim == 0) 407 { 408 Type et = i.exp.type; 409 i.exp = new TupleExp(i.exp.loc, new Expressions()); 410 i.exp.type = et; 411 } 412 if (i.exp.op == TOK.type) 413 { 414 i.exp.error("initializer must be an expression, not `%s`", i.exp.toChars()); 415 return new ErrorInitializer(); 416 } 417 // Make sure all pointers are constants 418 if (needInterpret && hasNonConstPointers(i.exp)) 419 { 420 i.exp.error("cannot use non-constant CTFE pointer in an initializer `%s`", i.exp.toChars()); 421 return new ErrorInitializer(); 422 } 423 Type tb = t.toBasetype(); 424 Type ti = i.exp.type.toBasetype(); 425 if (i.exp.op == TOK.tuple && i.expandTuples && !i.exp.implicitConvTo(t)) 426 { 427 return new ExpInitializer(i.loc, i.exp); 428 } 429 /* Look for case of initializing a static array with a too-short 430 * string literal, such as: 431 * char[5] foo = "abc"; 432 * Allow this by doing an explicit cast, which will lengthen the string 433 * literal. 434 */ 435 if (i.exp.op == TOK.string_ && tb.ty == Tsarray) 436 { 437 StringExp se = cast(StringExp)i.exp; 438 Type typeb = se.type.toBasetype(); 439 TY tynto = tb.nextOf().ty; 440 if (!se.committed && 441 (typeb.ty == Tarray || typeb.ty == Tsarray) && tynto.isSomeChar && 442 se.numberOfCodeUnits(tynto) < (cast(TypeSArray)tb).dim.toInteger()) 443 { 444 i.exp = se.castTo(sc, t); 445 goto L1; 446 } 447 } 448 // Look for implicit constructor call 449 if (tb.ty == Tstruct && !(ti.ty == Tstruct && tb.toDsymbol(sc) == ti.toDsymbol(sc)) && !i.exp.implicitConvTo(t)) 450 { 451 StructDeclaration sd = (cast(TypeStruct)tb).sym; 452 if (sd.ctor) 453 { 454 // Rewrite as S().ctor(exp) 455 Expression e; 456 e = new StructLiteralExp(i.loc, sd, null); 457 e = new DotIdExp(i.loc, e, Id.ctor); 458 e = new CallExp(i.loc, e, i.exp); 459 e = e.expressionSemantic(sc); 460 if (needInterpret) 461 i.exp = e.ctfeInterpret(); 462 else 463 i.exp = e.optimize(WANTvalue); 464 } 465 else if (search_function(sd, Id.call)) 466 { 467 /* https://issues.dlang.org/show_bug.cgi?id=1547 468 * 469 * Look for static opCall 470 * 471 * Rewrite as: 472 * i.exp = typeof(sd).opCall(arguments) 473 */ 474 475 Expression e = typeDotIdExp(i.loc, sd.type, Id.call); 476 e = new CallExp(i.loc, e, i.exp); 477 e = e.expressionSemantic(sc); 478 e = resolveProperties(sc, e); 479 if (needInterpret) 480 i.exp = e.ctfeInterpret(); 481 else 482 i.exp = e.optimize(WANTvalue); 483 } 484 } 485 // Look for the case of statically initializing an array 486 // with a single member. 487 if (tb.ty == Tsarray && !tb.nextOf().equals(ti.toBasetype().nextOf()) && i.exp.implicitConvTo(tb.nextOf())) 488 { 489 /* If the variable is not actually used in compile time, array creation is 490 * redundant. So delay it until invocation of toExpression() or toDt(). 491 */ 492 t = tb.nextOf(); 493 } 494 if (i.exp.implicitConvTo(t)) 495 { 496 i.exp = i.exp.implicitCastTo(sc, t); 497 } 498 else 499 { 500 // Look for mismatch of compile-time known length to emit 501 // better diagnostic message, as same as AssignExp::semantic. 502 if (tb.ty == Tsarray && i.exp.implicitConvTo(tb.nextOf().arrayOf()) > MATCH.nomatch) 503 { 504 uinteger_t dim1 = (cast(TypeSArray)tb).dim.toInteger(); 505 uinteger_t dim2 = dim1; 506 if (i.exp.op == TOK.arrayLiteral) 507 { 508 ArrayLiteralExp ale = cast(ArrayLiteralExp)i.exp; 509 dim2 = ale.elements ? ale.elements.dim : 0; 510 } 511 else if (i.exp.op == TOK.slice) 512 { 513 Type tx = toStaticArrayType(cast(SliceExp)i.exp); 514 if (tx) 515 dim2 = (cast(TypeSArray)tx).dim.toInteger(); 516 } 517 if (dim1 != dim2) 518 { 519 i.exp.error("mismatched array lengths, %d and %d", cast(int)dim1, cast(int)dim2); 520 i.exp = new ErrorExp(); 521 } 522 } 523 i.exp = i.exp.implicitCastTo(sc, t); 524 } 525 L1: 526 if (i.exp.op == TOK.error) 527 { 528 return i; 529 } 530 if (needInterpret) 531 i.exp = i.exp.ctfeInterpret(); 532 else 533 i.exp = i.exp.optimize(WANTvalue); 534 //printf("-ExpInitializer::semantic(): "); i.exp.print(); 535 return i; 536 } 537 538 final switch (init.kind) 539 { 540 case InitKind.void_: return visitVoid (cast( VoidInitializer)init); 541 case InitKind.error: return visitError (cast( ErrorInitializer)init); 542 case InitKind.struct_: return visitStruct(cast(StructInitializer)init); 543 case InitKind.array: return visitArray (cast( ArrayInitializer)init); 544 case InitKind.exp: return visitExp (cast( ExpInitializer)init); 545 } 546 } 547 548 /*********************** 549 * Translate init to an `Expression` in order to infer the type. 550 * Params: 551 * init = `Initializer` AST node 552 * sc = context 553 * Returns: 554 * an equivalent `ExpInitializer` if successful, or `ErrorInitializer` if it cannot be translated 555 */ 556 Initializer inferType(Initializer init, Scope* sc) 557 { 558 Initializer visitVoid(VoidInitializer i) 559 { 560 error(i.loc, "cannot infer type from void initializer"); 561 return new ErrorInitializer(); 562 } 563 564 Initializer visitError(ErrorInitializer i) 565 { 566 return i; 567 } 568 569 Initializer visitStruct(StructInitializer i) 570 { 571 error(i.loc, "cannot infer type from struct initializer"); 572 return new ErrorInitializer(); 573 } 574 575 Initializer visitArray(ArrayInitializer init) 576 { 577 //printf("ArrayInitializer::inferType() %s\n", toChars()); 578 Expressions* keys = null; 579 Expressions* values; 580 if (init.isAssociativeArray()) 581 { 582 keys = new Expressions(init.value.dim); 583 values = new Expressions(init.value.dim); 584 for (size_t i = 0; i < init.value.dim; i++) 585 { 586 Expression e = init.index[i]; 587 if (!e) 588 goto Lno; 589 (*keys)[i] = e; 590 Initializer iz = init.value[i]; 591 if (!iz) 592 goto Lno; 593 iz = iz.inferType(sc); 594 if (iz.isErrorInitializer()) 595 { 596 return iz; 597 } 598 assert(iz.isExpInitializer()); 599 (*values)[i] = (cast(ExpInitializer)iz).exp; 600 assert((*values)[i].op != TOK.error); 601 } 602 Expression e = new AssocArrayLiteralExp(init.loc, keys, values); 603 auto ei = new ExpInitializer(init.loc, e); 604 return ei.inferType(sc); 605 } 606 else 607 { 608 auto elements = new Expressions(init.value.dim); 609 elements.zero(); 610 for (size_t i = 0; i < init.value.dim; i++) 611 { 612 assert(!init.index[i]); // already asserted by isAssociativeArray() 613 Initializer iz = init.value[i]; 614 if (!iz) 615 goto Lno; 616 iz = iz.inferType(sc); 617 if (iz.isErrorInitializer()) 618 { 619 return iz; 620 } 621 assert(iz.isExpInitializer()); 622 (*elements)[i] = (cast(ExpInitializer)iz).exp; 623 assert((*elements)[i].op != TOK.error); 624 } 625 Expression e = new ArrayLiteralExp(init.loc, null, elements); 626 auto ei = new ExpInitializer(init.loc, e); 627 return ei.inferType(sc); 628 } 629 Lno: 630 if (keys) 631 { 632 error(init.loc, "not an associative array initializer"); 633 } 634 else 635 { 636 error(init.loc, "cannot infer type from array initializer"); 637 } 638 return new ErrorInitializer(); 639 } 640 641 Initializer visitExp(ExpInitializer init) 642 { 643 //printf("ExpInitializer::inferType() %s\n", init.toChars()); 644 init.exp = init.exp.expressionSemantic(sc); 645 646 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684 647 if (init.exp.op == TOK.type) 648 init.exp = resolveAliasThis(sc, init.exp); 649 650 init.exp = resolveProperties(sc, init.exp); 651 if (init.exp.op == TOK.scope_) 652 { 653 ScopeExp se = cast(ScopeExp)init.exp; 654 TemplateInstance ti = se.sds.isTemplateInstance(); 655 if (ti && ti.semanticRun == PASS.semantic && !ti.aliasdecl) 656 se.error("cannot infer type from %s `%s`, possible circular dependency", se.sds.kind(), se.toChars()); 657 else 658 se.error("cannot infer type from %s `%s`", se.sds.kind(), se.toChars()); 659 return new ErrorInitializer(); 660 } 661 662 // Give error for overloaded function addresses 663 bool hasOverloads; 664 if (auto f = isFuncAddress(init.exp, &hasOverloads)) 665 { 666 if (f.checkForwardRef(init.loc)) 667 { 668 return new ErrorInitializer(); 669 } 670 if (hasOverloads && !f.isUnique()) 671 { 672 init.exp.error("cannot infer type from overloaded function symbol `%s`", init.exp.toChars()); 673 return new ErrorInitializer(); 674 } 675 } 676 if (init.exp.op == TOK.address) 677 { 678 AddrExp ae = cast(AddrExp)init.exp; 679 if (ae.e1.op == TOK.overloadSet) 680 { 681 init.exp.error("cannot infer type from overloaded function symbol `%s`", init.exp.toChars()); 682 return new ErrorInitializer(); 683 } 684 } 685 if (init.exp.op == TOK.error) 686 { 687 return new ErrorInitializer(); 688 } 689 if (!init.exp.type) 690 { 691 return new ErrorInitializer(); 692 } 693 return init; 694 } 695 696 final switch (init.kind) 697 { 698 case InitKind.void_: return visitVoid (cast( VoidInitializer)init); 699 case InitKind.error: return visitError (cast( ErrorInitializer)init); 700 case InitKind.struct_: return visitStruct(cast(StructInitializer)init); 701 case InitKind.array: return visitArray (cast( ArrayInitializer)init); 702 case InitKind.exp: return visitExp (cast( ExpInitializer)init); 703 } 704 } 705 706 /*********************** 707 * Translate init to an `Expression`. 708 * Params: 709 * init = `Initializer` AST node 710 * itype = if not `null`, type to coerce expression to 711 * Returns: 712 * `Expression` created, `null` if cannot, `ErrorExp` for other errors 713 */ 714 extern (C++) Expression initializerToExpression(Initializer init, Type itype = null) 715 { 716 Expression visitVoid(VoidInitializer) 717 { 718 return null; 719 } 720 721 Expression visitError(ErrorInitializer) 722 { 723 return new ErrorExp(); 724 } 725 726 /*************************************** 727 * This works by transforming a struct initializer into 728 * a struct literal. In the future, the two should be the 729 * same thing. 730 */ 731 Expression visitStruct(StructInitializer) 732 { 733 // cannot convert to an expression without target 'ad' 734 return null; 735 } 736 737 /******************************** 738 * If possible, convert array initializer to array literal. 739 * Otherwise return NULL. 740 */ 741 Expression visitArray(ArrayInitializer init) 742 { 743 //printf("ArrayInitializer::toExpression(), dim = %d\n", dim); 744 //static int i; if (++i == 2) assert(0); 745 Expressions* elements; 746 uint edim; 747 const(uint) amax = 0x80000000; 748 Type t = null; 749 if (init.type) 750 { 751 if (init.type == Type.terror) 752 { 753 return new ErrorExp(); 754 } 755 t = init.type.toBasetype(); 756 switch (t.ty) 757 { 758 case Tvector: 759 t = (cast(TypeVector)t).basetype; 760 goto case Tsarray; 761 762 case Tsarray: 763 uinteger_t adim = (cast(TypeSArray)t).dim.toInteger(); 764 if (adim >= amax) 765 goto Lno; 766 edim = cast(uint)adim; 767 break; 768 769 case Tpointer: 770 case Tarray: 771 edim = init.dim; 772 break; 773 774 default: 775 assert(0); 776 } 777 } 778 else 779 { 780 edim = cast(uint)init.value.dim; 781 for (size_t i = 0, j = 0; i < init.value.dim; i++, j++) 782 { 783 if (init.index[i]) 784 { 785 if (init.index[i].op == TOK.int64) 786 { 787 const uinteger_t idxval = init.index[i].toInteger(); 788 if (idxval >= amax) 789 goto Lno; 790 j = cast(size_t)idxval; 791 } 792 else 793 goto Lno; 794 } 795 if (j >= edim) 796 edim = cast(uint)(j + 1); 797 } 798 } 799 elements = new Expressions(edim); 800 elements.zero(); 801 for (size_t i = 0, j = 0; i < init.value.dim; i++, j++) 802 { 803 if (init.index[i]) 804 j = cast(size_t)init.index[i].toInteger(); 805 assert(j < edim); 806 Initializer iz = init.value[i]; 807 if (!iz) 808 goto Lno; 809 Expression ex = iz.initializerToExpression(); 810 if (!ex) 811 { 812 goto Lno; 813 } 814 (*elements)[j] = ex; 815 } 816 { 817 /* Fill in any missing elements with the default initializer 818 */ 819 Expression _init = null; 820 for (size_t i = 0; i < edim; i++) 821 { 822 if (!(*elements)[i]) 823 { 824 if (!init.type) 825 goto Lno; 826 if (!_init) 827 _init = (cast(TypeNext)t).next.defaultInit(Loc.initial); 828 (*elements)[i] = _init; 829 } 830 } 831 832 /* Expand any static array initializers that are a single expression 833 * into an array of them 834 */ 835 if (t) 836 { 837 Type tn = t.nextOf().toBasetype(); 838 if (tn.ty == Tsarray) 839 { 840 const dim = cast(size_t)(cast(TypeSArray)tn).dim.toInteger(); 841 Type te = tn.nextOf().toBasetype(); 842 foreach (ref e; *elements) 843 { 844 if (te.equals(e.type)) 845 { 846 auto elements2 = new Expressions(dim); 847 foreach (ref e2; *elements2) 848 e2 = e; 849 e = new ArrayLiteralExp(e.loc, tn, elements2); 850 } 851 } 852 } 853 } 854 855 /* If any elements are errors, then the whole thing is an error 856 */ 857 for (size_t i = 0; i < edim; i++) 858 { 859 Expression e = (*elements)[i]; 860 if (e.op == TOK.error) 861 { 862 return e; 863 } 864 } 865 866 Expression e = new ArrayLiteralExp(init.loc, init.type, elements); 867 return e; 868 } 869 Lno: 870 return null; 871 } 872 873 Expression visitExp(ExpInitializer i) 874 { 875 if (itype) 876 { 877 //printf("ExpInitializer::toExpression(t = %s) exp = %s\n", itype.toChars(), i.exp.toChars()); 878 Type tb = itype.toBasetype(); 879 Expression e = (i.exp.op == TOK.construct || i.exp.op == TOK.blit) ? (cast(AssignExp)i.exp).e2 : i.exp; 880 if (tb.ty == Tsarray && e.implicitConvTo(tb.nextOf())) 881 { 882 TypeSArray tsa = cast(TypeSArray)tb; 883 size_t d = cast(size_t)tsa.dim.toInteger(); 884 auto elements = new Expressions(d); 885 for (size_t j = 0; j < d; j++) 886 (*elements)[j] = e; 887 auto ae = new ArrayLiteralExp(e.loc, itype, elements); 888 return ae; 889 } 890 } 891 return i.exp; 892 } 893 894 895 final switch (init.kind) 896 { 897 case InitKind.void_: return visitVoid (cast( VoidInitializer)init); 898 case InitKind.error: return visitError (cast( ErrorInitializer)init); 899 case InitKind.struct_: return visitStruct(cast(StructInitializer)init); 900 case InitKind.array: return visitArray (cast( ArrayInitializer)init); 901 case InitKind.exp: return visitExp (cast( ExpInitializer)init); 902 } 903 }