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