1 /** 2 * Compiler implementation of the 3 * $(LINK2 http://www.dlang.org, D programming language). 4 * 5 * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved 6 * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) 7 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 8 * Source: $(DMDSRC _init.d) 9 */ 10 11 module ddmd.init; 12 13 import core.stdc.stdio; 14 import core.checkedint; 15 16 import ddmd.aggregate; 17 import ddmd.arraytypes; 18 import ddmd.dcast; 19 import ddmd.declaration; 20 import ddmd.dscope; 21 import ddmd.dstruct; 22 import ddmd.dsymbol; 23 import ddmd.dtemplate; 24 import ddmd.errors; 25 import ddmd.expression; 26 import ddmd.func; 27 import ddmd.globals; 28 import ddmd.hdrgen; 29 import ddmd.id; 30 import ddmd.identifier; 31 import ddmd.mtype; 32 import ddmd.root.outbuffer; 33 import ddmd.root.rootobject; 34 import ddmd.statement; 35 import ddmd.tokens; 36 import ddmd.visitor; 37 38 enum NeedInterpret : int 39 { 40 INITnointerpret, 41 INITinterpret, 42 } 43 44 alias INITnointerpret = NeedInterpret.INITnointerpret; 45 alias INITinterpret = NeedInterpret.INITinterpret; 46 47 /*********************************************************** 48 */ 49 extern (C++) class Initializer : RootObject 50 { 51 Loc loc; 52 53 final extern (D) this(Loc loc) 54 { 55 this.loc = loc; 56 } 57 58 abstract Initializer syntaxCopy(); 59 60 static Initializers* arraySyntaxCopy(Initializers* ai) 61 { 62 Initializers* a = null; 63 if (ai) 64 { 65 a = new Initializers(); 66 a.setDim(ai.dim); 67 for (size_t i = 0; i < a.dim; i++) 68 (*a)[i] = (*ai)[i].syntaxCopy(); 69 } 70 return a; 71 } 72 73 /* Translates to an expression to infer type. 74 * Returns ExpInitializer or ErrorInitializer. 75 */ 76 abstract Initializer inferType(Scope* sc); 77 78 // needInterpret is INITinterpret if must be a manifest constant, 0 if not. 79 abstract Initializer semantic(Scope* sc, Type t, NeedInterpret needInterpret); 80 81 abstract Expression toExpression(Type t = null); 82 83 override final const(char)* toChars() 84 { 85 OutBuffer buf; 86 HdrGenState hgs; 87 .toCBuffer(this, &buf, &hgs); 88 return buf.extractString(); 89 } 90 91 ErrorInitializer isErrorInitializer() 92 { 93 return null; 94 } 95 96 VoidInitializer isVoidInitializer() 97 { 98 return null; 99 } 100 101 StructInitializer isStructInitializer() 102 { 103 return null; 104 } 105 106 ArrayInitializer isArrayInitializer() 107 { 108 return null; 109 } 110 111 ExpInitializer isExpInitializer() 112 { 113 return null; 114 } 115 116 void accept(Visitor v) 117 { 118 v.visit(this); 119 } 120 } 121 122 /*********************************************************** 123 */ 124 extern (C++) final class VoidInitializer : Initializer 125 { 126 Type type; // type that this will initialize to 127 128 extern (D) this(Loc loc) 129 { 130 super(loc); 131 } 132 133 override Initializer syntaxCopy() 134 { 135 return new VoidInitializer(loc); 136 } 137 138 override Initializer inferType(Scope* sc) 139 { 140 error(loc, "cannot infer type from void initializer"); 141 return new ErrorInitializer(); 142 } 143 144 override Initializer semantic(Scope* sc, Type t, NeedInterpret needInterpret) 145 { 146 //printf("VoidInitializer::semantic(t = %p)\n", t); 147 type = t; 148 return this; 149 } 150 151 override Expression toExpression(Type t = null) 152 { 153 return null; 154 } 155 156 override VoidInitializer isVoidInitializer() 157 { 158 return this; 159 } 160 161 override void accept(Visitor v) 162 { 163 v.visit(this); 164 } 165 } 166 167 /*********************************************************** 168 */ 169 extern (C++) final class ErrorInitializer : Initializer 170 { 171 extern (D) this() 172 { 173 super(Loc()); 174 } 175 176 override Initializer syntaxCopy() 177 { 178 return this; 179 } 180 181 override Initializer inferType(Scope* sc) 182 { 183 return this; 184 } 185 186 override Initializer semantic(Scope* sc, Type t, NeedInterpret needInterpret) 187 { 188 //printf("ErrorInitializer::semantic(t = %p)\n", t); 189 return this; 190 } 191 192 override Expression toExpression(Type t = null) 193 { 194 return new ErrorExp(); 195 } 196 197 override ErrorInitializer isErrorInitializer() 198 { 199 return this; 200 } 201 202 override void accept(Visitor v) 203 { 204 v.visit(this); 205 } 206 } 207 208 /*********************************************************** 209 */ 210 extern (C++) final class StructInitializer : Initializer 211 { 212 Identifiers field; // of Identifier *'s 213 Initializers value; // parallel array of Initializer *'s 214 215 extern (D) this(Loc loc) 216 { 217 super(loc); 218 } 219 220 override Initializer syntaxCopy() 221 { 222 auto ai = new StructInitializer(loc); 223 assert(field.dim == value.dim); 224 ai.field.setDim(field.dim); 225 ai.value.setDim(value.dim); 226 for (size_t i = 0; i < field.dim; i++) 227 { 228 ai.field[i] = field[i]; 229 ai.value[i] = value[i].syntaxCopy(); 230 } 231 return ai; 232 } 233 234 void addInit(Identifier field, Initializer value) 235 { 236 //printf("StructInitializer::addInit(field = %p, value = %p)\n", field, value); 237 this.field.push(field); 238 this.value.push(value); 239 } 240 241 override Initializer inferType(Scope* sc) 242 { 243 error(loc, "cannot infer type from struct initializer"); 244 return new ErrorInitializer(); 245 } 246 247 override Initializer semantic(Scope* sc, Type t, NeedInterpret needInterpret) 248 { 249 //printf("StructInitializer::semantic(t = %s) %s\n", t->toChars(), toChars()); 250 t = t.toBasetype(); 251 if (t.ty == Tsarray && t.nextOf().toBasetype().ty == Tstruct) 252 t = t.nextOf().toBasetype(); 253 if (t.ty == Tstruct) 254 { 255 StructDeclaration sd = (cast(TypeStruct)t).sym; 256 if (sd.ctor) 257 { 258 error(loc, "%s %s has constructors, cannot use { initializers }, use %s( initializers ) instead", sd.kind(), sd.toChars(), sd.toChars()); 259 return new ErrorInitializer(); 260 } 261 sd.size(loc); 262 if (sd.sizeok != SIZEOKdone) 263 return new ErrorInitializer(); 264 size_t nfields = sd.fields.dim - sd.isNested(); 265 //expandTuples for non-identity arguments? 266 auto elements = new Expressions(); 267 elements.setDim(nfields); 268 for (size_t i = 0; i < elements.dim; i++) 269 (*elements)[i] = null; 270 // Run semantic for explicitly given initializers 271 // TODO: this part is slightly different from StructLiteralExp::semantic. 272 bool errors = false; 273 for (size_t fieldi = 0, i = 0; i < field.dim; i++) 274 { 275 if (Identifier id = field[i]) 276 { 277 Dsymbol s = sd.search(loc, id); 278 if (!s) 279 { 280 s = sd.search_correct(id); 281 if (s) 282 error(loc, "'%s' is not a member of '%s', did you mean %s '%s'?", id.toChars(), sd.toChars(), s.kind(), s.toChars()); 283 else 284 error(loc, "'%s' is not a member of '%s'", id.toChars(), sd.toChars()); 285 return new ErrorInitializer(); 286 } 287 s = s.toAlias(); 288 // Find out which field index it is 289 for (fieldi = 0; 1; fieldi++) 290 { 291 if (fieldi >= nfields) 292 { 293 error(loc, "%s.%s is not a per-instance initializable field", sd.toChars(), s.toChars()); 294 return new ErrorInitializer(); 295 } 296 if (s == sd.fields[fieldi]) 297 break; 298 } 299 } 300 else if (fieldi >= nfields) 301 { 302 error(loc, "too many initializers for %s", sd.toChars()); 303 return new ErrorInitializer(); 304 } 305 VarDeclaration vd = sd.fields[fieldi]; 306 if ((*elements)[fieldi]) 307 { 308 error(loc, "duplicate initializer for field '%s'", vd.toChars()); 309 errors = true; 310 continue; 311 } 312 for (size_t j = 0; j < nfields; j++) 313 { 314 VarDeclaration v2 = sd.fields[j]; 315 if (vd.isOverlappedWith(v2) && (*elements)[j]) 316 { 317 error(loc, "overlapping initialization for field %s and %s", v2.toChars(), vd.toChars()); 318 errors = true; 319 continue; 320 } 321 } 322 assert(sc); 323 Initializer iz = value[i]; 324 iz = iz.semantic(sc, vd.type.addMod(t.mod), needInterpret); 325 Expression ex = iz.toExpression(); 326 if (ex.op == TOKerror) 327 { 328 errors = true; 329 continue; 330 } 331 value[i] = iz; 332 (*elements)[fieldi] = ex; 333 ++fieldi; 334 } 335 if (errors) 336 return new ErrorInitializer(); 337 auto sle = new StructLiteralExp(loc, sd, elements, t); 338 if (!sd.fill(loc, elements, false)) 339 return new ErrorInitializer(); 340 sle.type = t; 341 auto ie = new ExpInitializer(loc, sle); 342 return ie.semantic(sc, t, needInterpret); 343 } 344 else if ((t.ty == Tdelegate || t.ty == Tpointer && t.nextOf().ty == Tfunction) && value.dim == 0) 345 { 346 TOK tok = (t.ty == Tdelegate) ? TOKdelegate : TOKfunction; 347 /* Rewrite as empty delegate literal { } 348 */ 349 auto parameters = new Parameters(); 350 Type tf = new TypeFunction(parameters, null, 0, LINKd); 351 auto fd = new FuncLiteralDeclaration(loc, Loc(), tf, tok, null); 352 fd.fbody = new CompoundStatement(loc, new Statements()); 353 fd.endloc = loc; 354 Expression e = new FuncExp(loc, fd); 355 auto ie = new ExpInitializer(loc, e); 356 return ie.semantic(sc, t, needInterpret); 357 } 358 error(loc, "a struct is not a valid initializer for a %s", t.toChars()); 359 return new ErrorInitializer(); 360 } 361 362 /*************************************** 363 * This works by transforming a struct initializer into 364 * a struct literal. In the future, the two should be the 365 * same thing. 366 */ 367 override Expression toExpression(Type t = null) 368 { 369 // cannot convert to an expression without target 'ad' 370 return null; 371 } 372 373 override StructInitializer isStructInitializer() 374 { 375 return this; 376 } 377 378 override void accept(Visitor v) 379 { 380 v.visit(this); 381 } 382 } 383 384 /*********************************************************** 385 */ 386 extern (C++) final class ArrayInitializer : Initializer 387 { 388 Expressions index; // indices 389 Initializers value; // of Initializer *'s 390 uint dim; // length of array being initialized 391 Type type; // type that array will be used to initialize 392 bool sem; // true if semantic() is run 393 394 extern (D) this(Loc loc) 395 { 396 super(loc); 397 } 398 399 override Initializer syntaxCopy() 400 { 401 //printf("ArrayInitializer::syntaxCopy()\n"); 402 auto ai = new ArrayInitializer(loc); 403 assert(index.dim == value.dim); 404 ai.index.setDim(index.dim); 405 ai.value.setDim(value.dim); 406 for (size_t i = 0; i < ai.value.dim; i++) 407 { 408 ai.index[i] = index[i] ? index[i].syntaxCopy() : null; 409 ai.value[i] = value[i].syntaxCopy(); 410 } 411 return ai; 412 } 413 414 void addInit(Expression index, Initializer value) 415 { 416 this.index.push(index); 417 this.value.push(value); 418 dim = 0; 419 type = null; 420 } 421 422 bool isAssociativeArray() 423 { 424 for (size_t i = 0; i < value.dim; i++) 425 { 426 if (index[i]) 427 return true; 428 } 429 return false; 430 } 431 432 override Initializer inferType(Scope* sc) 433 { 434 //printf("ArrayInitializer::inferType() %s\n", toChars()); 435 Expressions* keys = null; 436 Expressions* values; 437 if (isAssociativeArray()) 438 { 439 keys = new Expressions(); 440 keys.setDim(value.dim); 441 values = new Expressions(); 442 values.setDim(value.dim); 443 for (size_t i = 0; i < value.dim; i++) 444 { 445 Expression e = index[i]; 446 if (!e) 447 goto Lno; 448 (*keys)[i] = e; 449 Initializer iz = value[i]; 450 if (!iz) 451 goto Lno; 452 iz = iz.inferType(sc); 453 if (iz.isErrorInitializer()) 454 return iz; 455 assert(iz.isExpInitializer()); 456 (*values)[i] = (cast(ExpInitializer)iz).exp; 457 assert((*values)[i].op != TOKerror); 458 } 459 Expression e = new AssocArrayLiteralExp(loc, keys, values); 460 auto ei = new ExpInitializer(loc, e); 461 return ei.inferType(sc); 462 } 463 else 464 { 465 auto elements = new Expressions(); 466 elements.setDim(value.dim); 467 elements.zero(); 468 for (size_t i = 0; i < value.dim; i++) 469 { 470 assert(!index[i]); // already asserted by isAssociativeArray() 471 Initializer iz = value[i]; 472 if (!iz) 473 goto Lno; 474 iz = iz.inferType(sc); 475 if (iz.isErrorInitializer()) 476 return iz; 477 assert(iz.isExpInitializer()); 478 (*elements)[i] = (cast(ExpInitializer)iz).exp; 479 assert((*elements)[i].op != TOKerror); 480 } 481 Expression e = new ArrayLiteralExp(loc, elements); 482 auto ei = new ExpInitializer(loc, e); 483 return ei.inferType(sc); 484 } 485 Lno: 486 if (keys) 487 { 488 error(loc, "not an associative array initializer"); 489 } 490 else 491 { 492 error(loc, "cannot infer type from array initializer"); 493 } 494 return new ErrorInitializer(); 495 } 496 497 override Initializer semantic(Scope* sc, Type t, NeedInterpret needInterpret) 498 { 499 uint length; 500 const(uint) amax = 0x80000000; 501 bool errors = false; 502 //printf("ArrayInitializer::semantic(%s)\n", t.toChars()); 503 if (sem) // if semantic() already run 504 return this; 505 sem = true; 506 t = t.toBasetype(); 507 switch (t.ty) 508 { 509 case Tsarray: 510 case Tarray: 511 break; 512 case Tvector: 513 t = (cast(TypeVector)t).basetype; 514 break; 515 case Taarray: 516 case Tstruct: // consider implicit constructor call 517 { 518 Expression e; 519 // note: MyStruct foo = [1:2, 3:4] is correct code if MyStruct has a this(int[int]) 520 if (t.ty == Taarray || isAssociativeArray()) 521 e = toAssocArrayLiteral(); 522 else 523 e = toExpression(); 524 if (!e) // Bugzilla 13987 525 { 526 error(loc, "cannot use array to initialize %s", t.toChars()); 527 goto Lerr; 528 } 529 auto ei = new ExpInitializer(e.loc, e); 530 return ei.semantic(sc, t, needInterpret); 531 } 532 case Tpointer: 533 if (t.nextOf().ty != Tfunction) 534 break; 535 goto default; 536 default: 537 error(loc, "cannot use array to initialize %s", t.toChars()); 538 goto Lerr; 539 } 540 type = t; 541 length = 0; 542 for (size_t i = 0; i < index.dim; i++) 543 { 544 Expression idx = index[i]; 545 if (idx) 546 { 547 sc = sc.startCTFE(); 548 idx = idx.semantic(sc); 549 sc = sc.endCTFE(); 550 idx = idx.ctfeInterpret(); 551 index[i] = idx; 552 const uinteger_t idxvalue = idx.toInteger(); 553 if (idxvalue >= amax) 554 { 555 error(loc, "array index %llu overflow", ulong(idxvalue)); 556 errors = true; 557 } 558 length = cast(uint)idxvalue; 559 if (idx.op == TOKerror) 560 errors = true; 561 } 562 Initializer val = value[i]; 563 ExpInitializer ei = val.isExpInitializer(); 564 if (ei && !idx) 565 ei.expandTuples = true; 566 val = val.semantic(sc, t.nextOf(), needInterpret); 567 if (val.isErrorInitializer()) 568 errors = true; 569 ei = val.isExpInitializer(); 570 // found a tuple, expand it 571 if (ei && ei.exp.op == TOKtuple) 572 { 573 TupleExp te = cast(TupleExp)ei.exp; 574 index.remove(i); 575 value.remove(i); 576 for (size_t j = 0; j < te.exps.dim; ++j) 577 { 578 Expression e = (*te.exps)[j]; 579 index.insert(i + j, cast(Expression)null); 580 value.insert(i + j, new ExpInitializer(e.loc, e)); 581 } 582 i--; 583 continue; 584 } 585 else 586 { 587 value[i] = val; 588 } 589 length++; 590 if (length == 0) 591 { 592 error(loc, "array dimension overflow"); 593 goto Lerr; 594 } 595 if (length > dim) 596 dim = length; 597 } 598 if (t.ty == Tsarray) 599 { 600 uinteger_t edim = (cast(TypeSArray)t).dim.toInteger(); 601 if (dim > edim) 602 { 603 error(loc, "array initializer has %u elements, but array length is %llu", dim, edim); 604 goto Lerr; 605 } 606 } 607 if (errors) 608 goto Lerr; 609 { 610 const sz = t.nextOf().size(); 611 bool overflow; 612 const max = mulu(dim, sz, overflow); 613 if (overflow || max >= amax) 614 { 615 error(loc, "array dimension %llu exceeds max of %llu", ulong(dim), ulong(amax / sz)); 616 goto Lerr; 617 } 618 return this; 619 } 620 Lerr: 621 return new ErrorInitializer(); 622 } 623 624 /******************************** 625 * If possible, convert array initializer to array literal. 626 * Otherwise return NULL. 627 */ 628 override Expression toExpression(Type tx = null) 629 { 630 //printf("ArrayInitializer::toExpression(), dim = %d\n", dim); 631 //static int i; if (++i == 2) assert(0); 632 Expressions* elements; 633 uint edim; 634 const(uint) amax = 0x80000000; 635 Type t = null; 636 if (type) 637 { 638 if (type == Type.terror) 639 return new ErrorExp(); 640 t = type.toBasetype(); 641 switch (t.ty) 642 { 643 case Tvector: 644 t = (cast(TypeVector)t).basetype; 645 goto case Tsarray; 646 647 case Tsarray: 648 uinteger_t adim = (cast(TypeSArray)t).dim.toInteger(); 649 if (adim >= amax) 650 goto Lno; 651 edim = cast(uint)adim; 652 break; 653 654 case Tpointer: 655 case Tarray: 656 edim = dim; 657 break; 658 659 default: 660 assert(0); 661 } 662 } 663 else 664 { 665 edim = cast(uint)value.dim; 666 for (size_t i = 0, j = 0; i < value.dim; i++, j++) 667 { 668 if (index[i]) 669 { 670 if (index[i].op == TOKint64) 671 { 672 const uinteger_t idxval = index[i].toInteger(); 673 if (idxval >= amax) 674 goto Lno; 675 j = cast(size_t)idxval; 676 } 677 else 678 goto Lno; 679 } 680 if (j >= edim) 681 edim = cast(uint)(j + 1); 682 } 683 } 684 elements = new Expressions(); 685 elements.setDim(edim); 686 elements.zero(); 687 for (size_t i = 0, j = 0; i < value.dim; i++, j++) 688 { 689 if (index[i]) 690 j = cast(size_t)index[i].toInteger(); 691 assert(j < edim); 692 Initializer iz = value[i]; 693 if (!iz) 694 goto Lno; 695 Expression ex = iz.toExpression(); 696 if (!ex) 697 { 698 goto Lno; 699 } 700 (*elements)[j] = ex; 701 } 702 { 703 /* Fill in any missing elements with the default initializer 704 */ 705 Expression _init = null; 706 for (size_t i = 0; i < edim; i++) 707 { 708 if (!(*elements)[i]) 709 { 710 if (!type) 711 goto Lno; 712 if (!_init) 713 _init = (cast(TypeNext)t).next.defaultInit(); 714 (*elements)[i] = _init; 715 } 716 } 717 718 /* Expand any static array initializers that are a single expression 719 * into an array of them 720 */ 721 if (t) 722 { 723 Type tn = t.nextOf().toBasetype(); 724 if (tn.ty == Tsarray) 725 { 726 const dim = cast(size_t)(cast(TypeSArray)tn).dim.toInteger(); 727 Type te = tn.nextOf().toBasetype(); 728 foreach (ref e; *elements) 729 { 730 if (te.equals(e.type)) 731 { 732 auto elements2 = new Expressions(); 733 elements2.setDim(dim); 734 foreach (ref e2; *elements2) 735 e2 = e; 736 e = new ArrayLiteralExp(e.loc, elements2); 737 e.type = tn; 738 } 739 } 740 } 741 } 742 743 /* If any elements are errors, then the whole thing is an error 744 */ 745 for (size_t i = 0; i < edim; i++) 746 { 747 Expression e = (*elements)[i]; 748 if (e.op == TOKerror) 749 return e; 750 } 751 752 Expression e = new ArrayLiteralExp(loc, elements); 753 e.type = type; 754 return e; 755 } 756 Lno: 757 return null; 758 } 759 760 /******************************** 761 * If possible, convert array initializer to associative array initializer. 762 */ 763 Expression toAssocArrayLiteral() 764 { 765 Expression e; 766 //printf("ArrayInitializer::toAssocArrayInitializer()\n"); 767 //static int i; if (++i == 2) assert(0); 768 auto keys = new Expressions(); 769 keys.setDim(value.dim); 770 auto values = new Expressions(); 771 values.setDim(value.dim); 772 for (size_t i = 0; i < value.dim; i++) 773 { 774 e = index[i]; 775 if (!e) 776 goto Lno; 777 (*keys)[i] = e; 778 Initializer iz = value[i]; 779 if (!iz) 780 goto Lno; 781 e = iz.toExpression(); 782 if (!e) 783 goto Lno; 784 (*values)[i] = e; 785 } 786 e = new AssocArrayLiteralExp(loc, keys, values); 787 return e; 788 Lno: 789 error(loc, "not an associative array initializer"); 790 return new ErrorExp(); 791 } 792 793 override ArrayInitializer isArrayInitializer() 794 { 795 return this; 796 } 797 798 override void accept(Visitor v) 799 { 800 v.visit(this); 801 } 802 } 803 804 /*********************************************************** 805 */ 806 extern (C++) final class ExpInitializer : Initializer 807 { 808 Expression exp; 809 bool expandTuples; 810 811 extern (D) this(Loc loc, Expression exp) 812 { 813 super(loc); 814 this.exp = exp; 815 } 816 817 override Initializer syntaxCopy() 818 { 819 return new ExpInitializer(loc, exp.syntaxCopy()); 820 } 821 822 override Initializer inferType(Scope* sc) 823 { 824 //printf("ExpInitializer::inferType() %s\n", toChars()); 825 exp = exp.semantic(sc); 826 exp = resolveProperties(sc, exp); 827 if (exp.op == TOKscope) 828 { 829 ScopeExp se = cast(ScopeExp)exp; 830 TemplateInstance ti = se.sds.isTemplateInstance(); 831 if (ti && ti.semanticRun == PASSsemantic && !ti.aliasdecl) 832 se.error("cannot infer type from %s %s, possible circular dependency", se.sds.kind(), se.toChars()); 833 else 834 se.error("cannot infer type from %s %s", se.sds.kind(), se.toChars()); 835 return new ErrorInitializer(); 836 } 837 838 // Give error for overloaded function addresses 839 bool hasOverloads; 840 if (auto f = isFuncAddress(exp, &hasOverloads)) 841 { 842 if (f.checkForwardRef(loc)) 843 return new ErrorInitializer(); 844 if (hasOverloads && !f.isUnique()) 845 { 846 exp.error("cannot infer type from overloaded function symbol %s", exp.toChars()); 847 return new ErrorInitializer(); 848 } 849 } 850 if (exp.op == TOKaddress) 851 { 852 AddrExp ae = cast(AddrExp)exp; 853 if (ae.e1.op == TOKoverloadset) 854 { 855 exp.error("cannot infer type from overloaded function symbol %s", exp.toChars()); 856 return new ErrorInitializer(); 857 } 858 } 859 if (exp.op == TOKerror) 860 return new ErrorInitializer(); 861 if (!exp.type) 862 return new ErrorInitializer(); 863 return this; 864 } 865 866 override Initializer semantic(Scope* sc, Type t, NeedInterpret needInterpret) 867 { 868 //printf("ExpInitializer::semantic(%s), type = %s\n", exp->toChars(), t->toChars()); 869 if (needInterpret) 870 sc = sc.startCTFE(); 871 exp = exp.semantic(sc); 872 exp = resolveProperties(sc, exp); 873 if (needInterpret) 874 sc = sc.endCTFE(); 875 if (exp.op == TOKerror) 876 return new ErrorInitializer(); 877 uint olderrors = global.errors; 878 if (needInterpret) 879 { 880 // If the result will be implicitly cast, move the cast into CTFE 881 // to avoid premature truncation of polysemous types. 882 // eg real [] x = [1.1, 2.2]; should use real precision. 883 if (exp.implicitConvTo(t)) 884 { 885 exp = exp.implicitCastTo(sc, t); 886 } 887 exp = exp.ctfeInterpret(); 888 } 889 else 890 { 891 exp = exp.optimize(WANTvalue); 892 } 893 if (!global.gag && olderrors != global.errors) 894 return this; // Failed, suppress duplicate error messages 895 if (exp.type.ty == Ttuple && (cast(TypeTuple)exp.type).arguments.dim == 0) 896 { 897 Type et = exp.type; 898 exp = new TupleExp(exp.loc, new Expressions()); 899 exp.type = et; 900 } 901 if (exp.op == TOKtype) 902 { 903 exp.error("initializer must be an expression, not '%s'", exp.toChars()); 904 return new ErrorInitializer(); 905 } 906 // Make sure all pointers are constants 907 if (needInterpret && hasNonConstPointers(exp)) 908 { 909 exp.error("cannot use non-constant CTFE pointer in an initializer '%s'", exp.toChars()); 910 return new ErrorInitializer(); 911 } 912 Type tb = t.toBasetype(); 913 Type ti = exp.type.toBasetype(); 914 if (exp.op == TOKtuple && expandTuples && !exp.implicitConvTo(t)) 915 return new ExpInitializer(loc, exp); 916 /* Look for case of initializing a static array with a too-short 917 * string literal, such as: 918 * char[5] foo = "abc"; 919 * Allow this by doing an explicit cast, which will lengthen the string 920 * literal. 921 */ 922 if (exp.op == TOKstring && tb.ty == Tsarray) 923 { 924 StringExp se = cast(StringExp)exp; 925 Type typeb = se.type.toBasetype(); 926 TY tynto = tb.nextOf().ty; 927 if (!se.committed && 928 (typeb.ty == Tarray || typeb.ty == Tsarray) && 929 (tynto == Tchar || tynto == Twchar || tynto == Tdchar) && 930 se.numberOfCodeUnits(tynto) < (cast(TypeSArray)tb).dim.toInteger()) 931 { 932 exp = se.castTo(sc, t); 933 goto L1; 934 } 935 } 936 // Look for implicit constructor call 937 if (tb.ty == Tstruct && !(ti.ty == Tstruct && tb.toDsymbol(sc) == ti.toDsymbol(sc)) && !exp.implicitConvTo(t)) 938 { 939 StructDeclaration sd = (cast(TypeStruct)tb).sym; 940 if (sd.ctor) 941 { 942 // Rewrite as S().ctor(exp) 943 Expression e; 944 e = new StructLiteralExp(loc, sd, null); 945 e = new DotIdExp(loc, e, Id.ctor); 946 e = new CallExp(loc, e, exp); 947 e = e.semantic(sc); 948 if (needInterpret) 949 exp = e.ctfeInterpret(); 950 else 951 exp = e.optimize(WANTvalue); 952 } 953 } 954 // Look for the case of statically initializing an array 955 // with a single member. 956 if (tb.ty == Tsarray && !tb.nextOf().equals(ti.toBasetype().nextOf()) && exp.implicitConvTo(tb.nextOf())) 957 { 958 /* If the variable is not actually used in compile time, array creation is 959 * redundant. So delay it until invocation of toExpression() or toDt(). 960 */ 961 t = tb.nextOf(); 962 } 963 if (exp.implicitConvTo(t)) 964 { 965 exp = exp.implicitCastTo(sc, t); 966 } 967 else 968 { 969 // Look for mismatch of compile-time known length to emit 970 // better diagnostic message, as same as AssignExp::semantic. 971 if (tb.ty == Tsarray && exp.implicitConvTo(tb.nextOf().arrayOf()) > MATCHnomatch) 972 { 973 uinteger_t dim1 = (cast(TypeSArray)tb).dim.toInteger(); 974 uinteger_t dim2 = dim1; 975 if (exp.op == TOKarrayliteral) 976 { 977 ArrayLiteralExp ale = cast(ArrayLiteralExp)exp; 978 dim2 = ale.elements ? ale.elements.dim : 0; 979 } 980 else if (exp.op == TOKslice) 981 { 982 Type tx = toStaticArrayType(cast(SliceExp)exp); 983 if (tx) 984 dim2 = (cast(TypeSArray)tx).dim.toInteger(); 985 } 986 if (dim1 != dim2) 987 { 988 exp.error("mismatched array lengths, %d and %d", cast(int)dim1, cast(int)dim2); 989 exp = new ErrorExp(); 990 } 991 } 992 exp = exp.implicitCastTo(sc, t); 993 } 994 L1: 995 if (exp.op == TOKerror) 996 return this; 997 if (needInterpret) 998 exp = exp.ctfeInterpret(); 999 else 1000 exp = exp.optimize(WANTvalue); 1001 //printf("-ExpInitializer::semantic(): "); exp->print(); 1002 return this; 1003 } 1004 1005 override Expression toExpression(Type t = null) 1006 { 1007 if (t) 1008 { 1009 //printf("ExpInitializer::toExpression(t = %s) exp = %s\n", t->toChars(), exp->toChars()); 1010 Type tb = t.toBasetype(); 1011 Expression e = (exp.op == TOKconstruct || exp.op == TOKblit) ? (cast(AssignExp)exp).e2 : exp; 1012 if (tb.ty == Tsarray && e.implicitConvTo(tb.nextOf())) 1013 { 1014 TypeSArray tsa = cast(TypeSArray)tb; 1015 size_t d = cast(size_t)tsa.dim.toInteger(); 1016 auto elements = new Expressions(); 1017 elements.setDim(d); 1018 for (size_t i = 0; i < d; i++) 1019 (*elements)[i] = e; 1020 auto ae = new ArrayLiteralExp(e.loc, elements); 1021 ae.type = t; 1022 return ae; 1023 } 1024 } 1025 return exp; 1026 } 1027 1028 override ExpInitializer isExpInitializer() 1029 { 1030 return this; 1031 } 1032 1033 override void accept(Visitor v) 1034 { 1035 v.visit(this); 1036 } 1037 } 1038 1039 version (all) 1040 { 1041 extern (C++) bool hasNonConstPointers(Expression e) 1042 { 1043 if (e.type.ty == Terror) 1044 return false; 1045 if (e.op == TOKnull) 1046 return false; 1047 if (e.op == TOKstructliteral) 1048 { 1049 StructLiteralExp se = cast(StructLiteralExp)e; 1050 return arrayHasNonConstPointers(se.elements); 1051 } 1052 if (e.op == TOKarrayliteral) 1053 { 1054 if (!e.type.nextOf().hasPointers()) 1055 return false; 1056 ArrayLiteralExp ae = cast(ArrayLiteralExp)e; 1057 return arrayHasNonConstPointers(ae.elements); 1058 } 1059 if (e.op == TOKassocarrayliteral) 1060 { 1061 AssocArrayLiteralExp ae = cast(AssocArrayLiteralExp)e; 1062 if (ae.type.nextOf().hasPointers() && arrayHasNonConstPointers(ae.values)) 1063 return true; 1064 if ((cast(TypeAArray)ae.type).index.hasPointers()) 1065 return arrayHasNonConstPointers(ae.keys); 1066 return false; 1067 } 1068 if (e.op == TOKaddress) 1069 { 1070 AddrExp ae = cast(AddrExp)e; 1071 if (ae.e1.op == TOKstructliteral) 1072 { 1073 StructLiteralExp se = cast(StructLiteralExp)ae.e1; 1074 if (!(se.stageflags & stageSearchPointers)) 1075 { 1076 int old = se.stageflags; 1077 se.stageflags |= stageSearchPointers; 1078 bool ret = arrayHasNonConstPointers(se.elements); 1079 se.stageflags = old; 1080 return ret; 1081 } 1082 else 1083 { 1084 return false; 1085 } 1086 } 1087 return true; 1088 } 1089 if (e.type.ty == Tpointer && e.type.nextOf().ty != Tfunction) 1090 { 1091 if (e.op == TOKsymoff) // address of a global is OK 1092 return false; 1093 if (e.op == TOKint64) // cast(void *)int is OK 1094 return false; 1095 if (e.op == TOKstring) // "abc".ptr is OK 1096 return false; 1097 return true; 1098 } 1099 return false; 1100 } 1101 1102 extern (C++) bool arrayHasNonConstPointers(Expressions* elems) 1103 { 1104 for (size_t i = 0; i < elems.dim; i++) 1105 { 1106 Expression e = (*elems)[i]; 1107 if (e && hasNonConstPointers(e)) 1108 return true; 1109 } 1110 return false; 1111 } 1112 }