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