1 /** 2 * Semantic analysis of initializers. 3 * 4 * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved 5 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) 6 * License: $(LINK2 https://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.astenums; 21 import dmd.dcast; 22 import dmd.declaration; 23 import dmd.dscope; 24 import dmd.dstruct; 25 import dmd.dsymbol; 26 import dmd.dtemplate; 27 import dmd.errors; 28 import dmd.expression; 29 import dmd.expressionsem; 30 import dmd.func; 31 import dmd.globals; 32 import dmd.id; 33 import dmd.identifier; 34 import dmd.importc; 35 import dmd.init; 36 import dmd.location; 37 import dmd.mtype; 38 import dmd.opover; 39 import dmd.statement; 40 import dmd.target; 41 import dmd.tokens; 42 import dmd.typesem; 43 44 /******************************** 45 * If possible, convert array initializer to associative array initializer. 46 * 47 * Params: 48 * ai = array initializer to be converted 49 * 50 * Returns: 51 * The converted associative array initializer or ErrorExp if `ai` 52 * is not an associative array initializer. 53 */ 54 Expression toAssocArrayLiteral(ArrayInitializer ai) 55 { 56 Expression e; 57 //printf("ArrayInitializer::toAssocArrayInitializer()\n"); 58 //static int i; if (++i == 2) assert(0); 59 const dim = ai.value.length; 60 auto keys = new Expressions(dim); 61 auto values = new Expressions(dim); 62 for (size_t i = 0; i < dim; i++) 63 { 64 e = ai.index[i]; 65 if (!e) 66 goto Lno; 67 (*keys)[i] = e; 68 Initializer iz = ai.value[i]; 69 if (!iz) 70 goto Lno; 71 e = iz.initializerToExpression(); 72 if (!e) 73 goto Lno; 74 (*values)[i] = e; 75 } 76 e = new AssocArrayLiteralExp(ai.loc, keys, values); 77 return e; 78 Lno: 79 error(ai.loc, "not an associative array initializer"); 80 return ErrorExp.get(); 81 } 82 83 /****************************************** 84 * Perform semantic analysis on init. 85 * Params: 86 * init = Initializer AST node 87 * sc = context 88 * tx = type that the initializer needs to become. If tx is an incomplete 89 * type and the initializer completes it, it is updated to be the 90 * complete type. ImportC has incomplete types 91 * needInterpret = if CTFE needs to be run on this, 92 * such as if it is the initializer for a const declaration 93 * Returns: 94 * `Initializer` with completed semantic analysis, `ErrorInitializer` if errors 95 * were encountered 96 */ 97 extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedInterpret needInterpret) 98 { 99 Type t = tx; 100 101 static Initializer err() 102 { 103 return new ErrorInitializer(); 104 } 105 106 Initializer visitVoid(VoidInitializer i) 107 { 108 i.type = t; 109 return i; 110 } 111 112 Initializer visitError(ErrorInitializer i) 113 { 114 return i; 115 } 116 117 Initializer visitStruct(StructInitializer i) 118 { 119 //printf("StructInitializer::semantic(t = %s) %s\n", t.toChars(), i.toChars()); 120 /* This works by replacing the StructInitializer with an ExpInitializer. 121 */ 122 t = t.toBasetype(); 123 if (t.ty == Tsarray && t.nextOf().toBasetype().ty == Tstruct) 124 t = t.nextOf().toBasetype(); 125 if (auto ts = t.isTypeStruct()) 126 { 127 StructDeclaration sd = ts.sym; 128 // check if the sd has a regular ctor (user defined non-copy ctor) 129 // that is not disabled. 130 if (sd.hasRegularCtor(true)) 131 { 132 error(i.loc, "%s `%s` has constructors, cannot use `{ initializers }`, use `%s( initializers )` instead", sd.kind(), sd.toChars(), sd.toChars()); 133 return err(); 134 } 135 sd.size(i.loc); 136 if (sd.sizeok != Sizeok.done) 137 return err(); 138 139 Expression getExp(size_t j, Type fieldType) 140 { 141 // Convert initializer to Expression `ex` 142 auto tm = fieldType.addMod(t.mod); 143 auto iz = i.value[j].initializerSemantic(sc, tm, needInterpret); 144 auto ex = iz.initializerToExpression(null, (sc.flags & SCOPE.Cfile) != 0); 145 if (ex.op != EXP.error) 146 i.value[j] = iz; 147 return ex; 148 } 149 auto elements = resolveStructLiteralNamedArgs(sd, t, sc, i.loc, i.field[], &getExp, (size_t j) => i.value[j].loc); 150 if (!elements) 151 return err(); 152 153 // Make a StructLiteralExp out of elements[] 154 auto sle = new StructLiteralExp(i.loc, sd, elements, t); 155 if (!sd.fill(i.loc, *elements, false)) 156 return err(); 157 sle.type = t; 158 auto ie = new ExpInitializer(i.loc, sle); 159 return ie.initializerSemantic(sc, t, needInterpret); 160 } 161 else if ((t.ty == Tdelegate || t.isPtrToFunction()) && i.value.length == 0) 162 { 163 const tok = (t.ty == Tdelegate) ? TOK.delegate_ : TOK.function_; 164 /* Rewrite as empty delegate literal { } 165 */ 166 Type tf = new TypeFunction(ParameterList(), null, LINK.d); 167 auto fd = new FuncLiteralDeclaration(i.loc, Loc.initial, tf, tok, null); 168 fd.fbody = new CompoundStatement(i.loc, new Statements()); 169 fd.endloc = i.loc; 170 Expression e = new FuncExp(i.loc, fd); 171 auto ie = new ExpInitializer(i.loc, e); 172 return ie.initializerSemantic(sc, t, needInterpret); 173 } 174 if (t.ty != Terror) 175 error(i.loc, "a struct is not a valid initializer for a `%s`", t.toChars()); 176 return err(); 177 } 178 179 Initializer visitArray(ArrayInitializer i) 180 { 181 uint length; 182 const(uint) amax = 0x80000000; 183 bool errors = false; 184 //printf("ArrayInitializer::semantic(%s), ai: %s %p\n", t.toChars(), i.toChars(), i); 185 if (i.sem) // if semantic() already run 186 { 187 return i; 188 } 189 i.sem = true; 190 t = t.toBasetype(); 191 switch (t.ty) 192 { 193 case Tsarray: 194 case Tarray: 195 break; 196 case Tvector: 197 t = t.isTypeVector().basetype; 198 break; 199 case Taarray: 200 case Tstruct: // consider implicit constructor call 201 { 202 Expression e; 203 // note: MyStruct foo = [1:2, 3:4] is correct code if MyStruct has a this(int[int]) 204 if (t.ty == Taarray || i.isAssociativeArray()) 205 e = i.toAssocArrayLiteral(); 206 else 207 e = i.initializerToExpression(); 208 // Bugzilla 13987 209 if (!e) 210 { 211 error(i.loc, "cannot use array to initialize `%s`", t.toChars()); 212 return err(); 213 } 214 auto ei = new ExpInitializer(e.loc, e); 215 return ei.initializerSemantic(sc, t, needInterpret); 216 } 217 case Tpointer: 218 if (t.nextOf().ty != Tfunction) 219 break; 220 goto default; 221 default: 222 error(i.loc, "cannot use array to initialize `%s`", t.toChars()); 223 return err(); 224 } 225 i.type = t; 226 length = 0; 227 for (size_t j = 0; j < i.index.length; j++) 228 { 229 Expression idx = i.index[j]; 230 if (idx) 231 { 232 sc = sc.startCTFE(); 233 idx = idx.expressionSemantic(sc); 234 sc = sc.endCTFE(); 235 idx = idx.ctfeInterpret(); 236 i.index[j] = idx; 237 const uinteger_t idxvalue = idx.toInteger(); 238 if (idxvalue >= amax) 239 { 240 error(i.loc, "array index %llu overflow", idxvalue); 241 errors = true; 242 } 243 length = cast(uint)idxvalue; 244 if (idx.op == EXP.error) 245 errors = true; 246 } 247 Initializer val = i.value[j]; 248 ExpInitializer ei = val.isExpInitializer(); 249 if (ei && !idx) 250 ei.expandTuples = true; 251 auto tn = t.nextOf(); 252 val = val.initializerSemantic(sc, tn, needInterpret); 253 if (val.isErrorInitializer()) 254 errors = true; 255 ei = val.isExpInitializer(); 256 // found a tuple, expand it 257 if (ei && ei.exp.op == EXP.tuple) 258 { 259 TupleExp te = ei.exp.isTupleExp(); 260 i.index.remove(j); 261 i.value.remove(j); 262 for (size_t k = 0; k < te.exps.length; ++k) 263 { 264 Expression e = (*te.exps)[k]; 265 i.index.insert(j + k, cast(Expression)null); 266 i.value.insert(j + k, new ExpInitializer(e.loc, e)); 267 } 268 j--; 269 continue; 270 } 271 else 272 { 273 i.value[j] = val; 274 } 275 length++; 276 if (length == 0) 277 { 278 error(i.loc, "array dimension overflow"); 279 return err(); 280 } 281 if (length > i.dim) 282 i.dim = length; 283 } 284 if (auto tsa = t.isTypeSArray()) 285 { 286 if (sc.flags & SCOPE.Cfile && tsa.isIncomplete()) 287 { 288 // Change to array of known length 289 auto tn = tsa.next.toBasetype(); 290 tsa = new TypeSArray(tn, new IntegerExp(Loc.initial, i.dim, Type.tsize_t)); 291 tx = tsa; // rewrite caller's type 292 i.type = tsa; // remember for later passes 293 } 294 else 295 { 296 uinteger_t edim = tsa.dim.toInteger(); 297 if (i.dim > edim) 298 { 299 error(i.loc, "array initializer has %u elements, but array length is %llu", i.dim, edim); 300 return err(); 301 } 302 } 303 } 304 if (errors) 305 return err(); 306 307 const sz = t.nextOf().size(); 308 if (sz == SIZE_INVALID) 309 return err(); 310 bool overflow; 311 const max = mulu(i.dim, sz, overflow); 312 if (overflow || max >= amax) 313 { 314 error(i.loc, "array dimension %llu exceeds max of %llu", ulong(i.dim), ulong(amax / sz)); 315 return err(); 316 } 317 //printf("returns ai: %s\n", i.toChars()); 318 return i; 319 } 320 321 Initializer visitExp(ExpInitializer i) 322 { 323 //printf("ExpInitializer::semantic(%s), type = %s\n", i.exp.toChars(), t.toChars()); 324 if (needInterpret) 325 sc = sc.startCTFE(); 326 i.exp = i.exp.expressionSemantic(sc); 327 i.exp = resolveProperties(sc, i.exp); 328 if (needInterpret) 329 sc = sc.endCTFE(); 330 if (i.exp.op == EXP.error) 331 return err(); 332 uint olderrors = global.errors; 333 334 /* ImportC: convert arrays to pointers, functions to pointers to functions 335 */ 336 Type tb = t.toBasetype(); 337 if (tb.isTypePointer()) 338 i.exp = i.exp.arrayFuncConv(sc); 339 340 /* Save the expression before ctfe 341 * Otherwise the error message would contain for example "&[0][0]" instead of "new int" 342 * Regression: https://issues.dlang.org/show_bug.cgi?id=21687 343 */ 344 Expression currExp = i.exp; 345 if (needInterpret) 346 { 347 // If the result will be implicitly cast, move the cast into CTFE 348 // to avoid premature truncation of polysemous types. 349 // eg real [] x = [1.1, 2.2]; should use real precision. 350 if (i.exp.implicitConvTo(t) && !(sc.flags & SCOPE.Cfile)) 351 { 352 i.exp = i.exp.implicitCastTo(sc, t); 353 } 354 if (!global.gag && olderrors != global.errors) 355 { 356 return i; 357 } 358 if (sc.flags & SCOPE.Cfile) 359 { 360 /* the interpreter turns (char*)"string" into &"string"[0] which then 361 * it cannot interpret. Resolve that case by doing optimize() first 362 */ 363 i.exp = i.exp.optimize(WANTvalue); 364 if (i.exp.isSymOffExp()) 365 { 366 /* `static variable cannot be read at compile time` 367 * https://issues.dlang.org/show_bug.cgi?id=22513 368 * Maybe this would be better addressed in ctfeInterpret()? 369 */ 370 needInterpret = NeedInterpret.INITnointerpret; 371 } 372 } 373 if (needInterpret) 374 i.exp = i.exp.ctfeInterpret(); 375 if (i.exp.op == EXP.voidExpression) 376 error(i.loc, "variables cannot be initialized with an expression of type `void`. Use `void` initialization instead."); 377 } 378 else 379 { 380 i.exp = i.exp.optimize(WANTvalue); 381 } 382 383 if (!global.gag && olderrors != global.errors) 384 { 385 return i; // Failed, suppress duplicate error messages 386 } 387 if (i.exp.type.isTypeTuple() && i.exp.type.isTypeTuple().arguments.length == 0) 388 { 389 Type et = i.exp.type; 390 i.exp = new TupleExp(i.exp.loc, new Expressions()); 391 i.exp.type = et; 392 } 393 if (i.exp.op == EXP.type) 394 { 395 i.exp.error("initializer must be an expression, not `%s`", i.exp.toChars()); 396 return err(); 397 } 398 // Make sure all pointers are constants 399 if (needInterpret && hasNonConstPointers(i.exp)) 400 { 401 i.exp.error("cannot use non-constant CTFE pointer in an initializer `%s`", currExp.toChars()); 402 return err(); 403 } 404 Type ti = i.exp.type.toBasetype(); 405 if (i.exp.op == EXP.tuple && i.expandTuples && !i.exp.implicitConvTo(t)) 406 { 407 return new ExpInitializer(i.loc, i.exp); 408 } 409 /* Look for case of initializing a static array with a too-short 410 * string literal, such as: 411 * char[5] foo = "abc"; 412 * Allow this by doing an explicit cast, which will lengthen the string 413 * literal. 414 */ 415 if (i.exp.op == EXP.string_ && tb.ty == Tsarray) 416 { 417 StringExp se = i.exp.isStringExp(); 418 Type typeb = se.type.toBasetype(); 419 TY tynto = tb.nextOf().ty; 420 if (!se.committed && 421 (typeb.ty == Tarray || typeb.ty == Tsarray) && tynto.isSomeChar && 422 se.numberOfCodeUnits(tynto) < tb.isTypeSArray().dim.toInteger()) 423 { 424 i.exp = se.castTo(sc, t); 425 goto L1; 426 } 427 428 /* Lop off terminating 0 of initializer for: 429 * static char s[5] = "hello"; 430 */ 431 if (sc.flags & SCOPE.Cfile && 432 typeb.ty == Tsarray && 433 tynto.isSomeChar && 434 tb.isTypeSArray().dim.toInteger() + 1 == typeb.isTypeSArray().dim.toInteger()) 435 { 436 i.exp = se.castTo(sc, t); 437 goto L1; 438 } 439 } 440 /* C11 6.7.9-14..15 441 * Initialize an array of unknown size with a string. 442 * Change to static array of known size 443 */ 444 if (sc.flags & SCOPE.Cfile && i.exp.isStringExp() && 445 tb.isTypeSArray() && tb.isTypeSArray().isIncomplete()) 446 { 447 StringExp se = i.exp.isStringExp(); 448 auto ts = new TypeSArray(tb.nextOf(), new IntegerExp(Loc.initial, se.len + 1, Type.tsize_t)); 449 t = typeSemantic(ts, Loc.initial, sc); 450 i.exp.type = t; 451 tx = t; 452 } 453 454 // Look for implicit constructor call 455 if (tb.ty == Tstruct && !(ti.ty == Tstruct && tb.toDsymbol(sc) == ti.toDsymbol(sc)) && !i.exp.implicitConvTo(t)) 456 { 457 StructDeclaration sd = tb.isTypeStruct().sym; 458 if (sd.ctor) 459 { 460 // Rewrite as S().ctor(exp) 461 Expression e; 462 e = new StructLiteralExp(i.loc, sd, null); 463 e = new DotIdExp(i.loc, e, Id.ctor); 464 e = new CallExp(i.loc, e, i.exp); 465 e = e.expressionSemantic(sc); 466 if (needInterpret) 467 i.exp = e.ctfeInterpret(); 468 else 469 i.exp = e.optimize(WANTvalue); 470 } 471 else if (search_function(sd, Id.call)) 472 { 473 /* https://issues.dlang.org/show_bug.cgi?id=1547 474 * 475 * Look for static opCall 476 * 477 * Rewrite as: 478 * i.exp = typeof(sd).opCall(arguments) 479 */ 480 481 Expression e = typeDotIdExp(i.loc, sd.type, Id.call); 482 e = new CallExp(i.loc, e, i.exp); 483 e = e.expressionSemantic(sc); 484 e = resolveProperties(sc, e); 485 if (needInterpret) 486 i.exp = e.ctfeInterpret(); 487 else 488 i.exp = e.optimize(WANTvalue); 489 } 490 } 491 492 // Look for the case of statically initializing an array with a single member. 493 // Recursively strip static array / enum layers until a compatible element is found, 494 // and return an `ArrayLiteralExp` repeating the initializer, or `null` if no match found 495 // int[2][3] = 7 => [[7, 7], [7, 7], [7, 7]] 496 // int[2] = new Object => null 497 Expression sarrayRepeat(Type tb) 498 { 499 auto tsa = tb.isTypeSArray(); 500 if (!tsa) 501 return null; 502 503 // printf("i.exp = %s, tsa = %s\n", i.exp.toChars(), tsa.toChars()); 504 Expression elem = null; 505 if (i.exp.implicitConvTo(tb.nextOf())) 506 elem = i.exp.implicitCastTo(sc, tb.nextOf()); 507 else if (auto ae = sarrayRepeat(tb.nextOf().toBasetype())) 508 elem = ae; 509 else 510 return null; 511 512 auto arrayElements = new Expressions(cast(size_t) tsa.dim.toInteger()); 513 foreach (ref e; *arrayElements) 514 e = elem; 515 return new ArrayLiteralExp(i.exp.loc, tb, elem, arrayElements); 516 } 517 518 if (auto sa = sarrayRepeat(tb)) 519 { 520 // printf("sa = %s\n", sa.toChars()); 521 i.exp = sa; 522 } 523 524 { 525 auto tta = t.isTypeSArray(); 526 if (i.exp.implicitConvTo(t)) 527 { 528 i.exp = i.exp.implicitCastTo(sc, t); 529 } 530 else if (sc.flags & SCOPE.Cfile && i.exp.isStringExp() && 531 tta && (tta.next.ty == Tint8 || tta.next.ty == Tuns8) && 532 ti.ty == Tsarray && ti.nextOf().ty == Tchar) 533 { 534 /* unsigned char bbb[1] = ""; 535 * signed char ccc[1] = ""; 536 */ 537 i.exp = i.exp.castTo(sc, t); 538 } 539 else 540 { 541 auto tba = tb.isTypeSArray(); 542 // Look for mismatch of compile-time known length to emit 543 // better diagnostic message, as same as AssignExp::semantic. 544 if (tba && i.exp.implicitConvTo(tba.next.arrayOf()) > MATCH.nomatch) 545 { 546 uinteger_t dim1 = tba.dim.toInteger(); 547 uinteger_t dim2 = dim1; 548 if (auto ale = i.exp.isArrayLiteralExp()) 549 { 550 dim2 = ale.elements ? ale.elements.length : 0; 551 } 552 else if (auto se = i.exp.isSliceExp()) 553 { 554 if (Type tx = toStaticArrayType(se)) 555 dim2 = tx.isTypeSArray().dim.toInteger(); 556 } 557 if (dim1 != dim2) 558 { 559 i.exp.error("mismatched array lengths, %d and %d", cast(int)dim1, cast(int)dim2); 560 i.exp = ErrorExp.get(); 561 } 562 } 563 Type et = i.exp.type; 564 const errors = global.startGagging(); 565 i.exp = i.exp.implicitCastTo(sc, t); 566 if (global.endGagging(errors)) 567 currExp.error("cannot implicitly convert expression `%s` of type `%s` to `%s`", currExp.toChars(), et.toChars(), t.toChars()); 568 } 569 } 570 L1: 571 if (i.exp.op == EXP.error) 572 { 573 return i; 574 } 575 if (needInterpret) 576 i.exp = i.exp.ctfeInterpret(); 577 else 578 i.exp = i.exp.optimize(WANTvalue); 579 //printf("-ExpInitializer::semantic(): "); i.exp.print(); 580 return i; 581 } 582 583 Initializer visitC(CInitializer ci) 584 { 585 //printf("CInitializer::semantic() (%s) %s\n", t.toChars(), ci.toChars()); 586 /* Rewrite CInitializer into ExpInitializer, ArrayInitializer, or StructInitializer 587 */ 588 t = t.toBasetype(); 589 590 /* If `{ expression }` return the expression initializer 591 */ 592 ExpInitializer isBraceExpression() 593 { 594 auto dil = ci.initializerList[]; 595 return (dil.length == 1 && !dil[0].designatorList) 596 ? dil[0].initializer.isExpInitializer() 597 : null; 598 } 599 600 /******************************** 601 */ 602 bool overlaps(VarDeclaration field, VarDeclaration[] fields, StructInitializer si) 603 { 604 foreach (fld; fields) 605 { 606 if (field.isOverlappedWith(fld)) 607 { 608 // look for initializer corresponding with fld 609 foreach (i, ident; si.field[]) 610 { 611 if (ident == fld.ident && si.value[i]) 612 return true; // already an initializer for `field` 613 } 614 } 615 } 616 return false; 617 } 618 619 /* Run semantic on ExpInitializer, see if it represents entire struct ts 620 */ 621 bool representsStruct(ExpInitializer ei, TypeStruct ts) 622 { 623 if (needInterpret) 624 sc = sc.startCTFE(); 625 ei.exp = ei.exp.expressionSemantic(sc); 626 ei.exp = resolveProperties(sc, ei.exp); 627 if (needInterpret) 628 sc = sc.endCTFE(); 629 return ei.exp.implicitConvTo(ts) != MATCH.nomatch; // initializer represents the entire struct 630 } 631 632 /* If { } are omitted from substructs, use recursion to reconstruct where 633 * brackets go 634 * Params: 635 * ts = substruct to initialize 636 * index = index into ci.initializer, updated 637 * Returns: struct initializer for this substruct 638 */ 639 Initializer subStruct()(TypeStruct ts, ref size_t index) 640 { 641 //printf("subStruct(ts: %s, index %d)\n", ts.toChars(), cast(int)index); 642 643 auto si = new StructInitializer(ci.loc); 644 StructDeclaration sd = ts.sym; 645 sd.size(ci.loc); 646 if (sd.sizeok != Sizeok.done) 647 { 648 index = ci.initializerList.length; 649 return err(); 650 } 651 const nfields = sd.fields.length; 652 653 foreach (fieldi; 0 .. nfields) 654 { 655 if (index >= ci.initializerList.length) 656 break; // ran out of initializers 657 auto di = ci.initializerList[index]; 658 if (di.designatorList && fieldi != 0) 659 break; // back to top level 660 else 661 { 662 VarDeclaration field; 663 while (1) // skip field if it overlaps with previously seen fields 664 { 665 field = sd.fields[fieldi]; 666 ++fieldi; 667 if (!overlaps(field, sd.fields[], si)) 668 break; 669 if (fieldi == nfields) 670 break; 671 } 672 auto tn = field.type.toBasetype(); 673 auto tnsa = tn.isTypeSArray(); 674 auto tns = tn.isTypeStruct(); 675 auto ix = di.initializer; 676 if (tnsa && ix.isExpInitializer()) 677 { 678 ExpInitializer ei = ix.isExpInitializer(); 679 if (ei.exp.isStringExp() && tnsa.nextOf().isintegral()) 680 { 681 si.addInit(field.ident, ei); 682 ++index; 683 } 684 else 685 si.addInit(field.ident, subArray(tnsa, index)); // fwd ref of subArray is why subStruct is a template 686 } 687 else if (tns && ix.isExpInitializer()) 688 { 689 /* Disambiguate between an exp representing the entire 690 * struct, and an exp representing the first field of the struct 691 */ 692 if (representsStruct(ix.isExpInitializer(), tns)) // initializer represents the entire struct 693 { 694 si.addInit(field.ident, initializerSemantic(ix, sc, tn, needInterpret)); 695 ++index; 696 } 697 else // field initializers for struct 698 si.addInit(field.ident, subStruct(tns, index)); // the first field 699 } 700 else 701 { 702 si.addInit(field.ident, ix); 703 ++index; 704 } 705 } 706 } 707 //printf("subStruct() returns ai: %s, index: %d\n", si.toChars(), cast(int)index); 708 return si; 709 } 710 711 /* If { } are omitted from subarrays, use recursion to reconstruct where 712 * brackets go 713 * Params: 714 * tsa = subarray to initialize 715 * index = index into ci.initializer, updated 716 * Returns: array initializer for this subarray 717 */ 718 Initializer subArray(TypeSArray tsa, ref size_t index) 719 { 720 //printf("array(tsa: %s, index %d)\n", tsa.toChars(), cast(int)index); 721 if (tsa.isIncomplete()) 722 { 723 // C11 6.2.5-20 "element type shall be complete whenever the array type is specified" 724 assert(0); // should have been detected by parser 725 } 726 727 auto tnsa = tsa.nextOf().toBasetype().isTypeSArray(); 728 729 auto ai = new ArrayInitializer(ci.loc); 730 ai.isCarray = true; 731 732 foreach (n; 0 .. cast(size_t)tsa.dim.toInteger()) 733 { 734 if (index >= ci.initializerList.length) 735 break; // ran out of initializers 736 auto di = ci.initializerList[index]; 737 if (di.designatorList) 738 break; // back to top level 739 else if (tnsa && di.initializer.isExpInitializer()) 740 { 741 ExpInitializer ei = di.initializer.isExpInitializer(); 742 if (ei.exp.isStringExp() && tnsa.nextOf().isintegral()) 743 { 744 ai.addInit(null, ei); 745 ++index; 746 } 747 else 748 ai.addInit(null, subArray(tnsa, index)); 749 } 750 else 751 { 752 ai.addInit(null, di.initializer); 753 ++index; 754 } 755 } 756 //printf("array() returns ai: %s, index: %d\n", ai.toChars(), cast(int)index); 757 return ai; 758 } 759 760 if (auto ts = t.isTypeStruct()) 761 { 762 auto si = new StructInitializer(ci.loc); 763 StructDeclaration sd = ts.sym; 764 sd.size(ci.loc); // run semantic() on sd to get fields 765 if (sd.sizeok != Sizeok.done) 766 { 767 return err(); 768 } 769 const nfields = sd.fields.length; 770 771 size_t fieldi = 0; 772 773 for (size_t index = 0; index < ci.initializerList.length; ) 774 { 775 auto di = ci.initializerList[index]; 776 auto dlist = di.designatorList; 777 if (dlist) 778 { 779 const length = (*dlist).length; 780 if (length == 0 || !(*dlist)[0].ident) 781 { 782 error(ci.loc, "`.identifier` expected for C struct field initializer `%s`", ci.toChars()); 783 return err(); 784 } 785 if (length > 1) 786 { 787 error(ci.loc, "only 1 designator currently allowed for C struct field initializer `%s`", ci.toChars()); 788 return err(); 789 } 790 auto id = (*dlist)[0].ident; 791 foreach (k, f; sd.fields[]) // linear search for now 792 { 793 if (f.ident == id) 794 { 795 fieldi = k; 796 si.addInit(id, di.initializer); 797 ++fieldi; 798 ++index; 799 break; 800 } 801 } 802 } 803 else 804 { 805 if (fieldi == nfields) 806 break; 807 VarDeclaration field; 808 while (1) // skip field if it overlaps with previously seen fields 809 { 810 field = sd.fields[fieldi]; 811 ++fieldi; 812 if (!overlaps(field, sd.fields[], si)) 813 break; 814 if (fieldi == nfields) 815 break; 816 } 817 auto tn = field.type.toBasetype(); 818 auto tnsa = tn.isTypeSArray(); 819 auto tns = tn.isTypeStruct(); 820 auto ix = di.initializer; 821 if (tnsa && ix.isExpInitializer()) 822 { 823 ExpInitializer ei = ix.isExpInitializer(); 824 if (ei.exp.isStringExp() && tnsa.nextOf().isintegral()) 825 { 826 si.addInit(field.ident, ei); 827 ++index; 828 } 829 else 830 si.addInit(field.ident, subArray(tnsa, index)); 831 } 832 else if (tns && ix.isExpInitializer()) 833 { 834 /* Disambiguate between an exp representing the entire 835 * struct, and an exp representing the first field of the struct 836 */ 837 if (representsStruct(ix.isExpInitializer(), tns)) // initializer represents the entire struct 838 { 839 si.addInit(field.ident, initializerSemantic(ix, sc, tn, needInterpret)); 840 ++index; 841 } 842 else // field initializers for struct 843 si.addInit(field.ident, subStruct(tns, index)); // the first field 844 } 845 else 846 { 847 si.addInit(field.ident, di.initializer); 848 ++index; 849 } 850 } 851 } 852 return initializerSemantic(si, sc, t, needInterpret); 853 } 854 else if (auto ta = t.isTypeSArray()) 855 { 856 auto tn = t.nextOf().toBasetype(); // element type of array 857 858 /* If it's an array of integral being initialized by `{ string }` 859 * replace with `string` 860 */ 861 if (tn.isintegral()) 862 { 863 if (ExpInitializer ei = isBraceExpression()) 864 { 865 if (ei.exp.isStringExp()) 866 return ei.initializerSemantic(sc, t, needInterpret); 867 } 868 } 869 870 auto tnsa = tn.isTypeSArray(); // array of array 871 auto tns = tn.isTypeStruct(); // array of struct 872 873 auto ai = new ArrayInitializer(ci.loc); 874 ai.isCarray = true; 875 for (size_t index = 0; index < ci.initializerList.length; ) 876 { 877 auto di = ci.initializerList[index]; 878 if (auto dlist = di.designatorList) 879 { 880 const length = (*dlist).length; 881 if (length == 0 || !(*dlist)[0].exp) 882 { 883 error(ci.loc, "`[ constant-expression ]` expected for C array element initializer `%s`", ci.toChars()); 884 return err(); 885 } 886 if (length > 1) 887 { 888 error(ci.loc, "only 1 designator currently allowed for C array element initializer `%s`", ci.toChars()); 889 return err(); 890 } 891 //printf("tn: %s, di.initializer: %s\n", tn.toChars(), di.initializer.toChars()); 892 auto ix = di.initializer; 893 if (tnsa && ix.isExpInitializer()) 894 { 895 // Wrap initializer in [ ] 896 auto ain = new ArrayInitializer(ci.loc); 897 ain.addInit(null, di.initializer); 898 ix = ain; 899 ai.addInit((*dlist)[0].exp, initializerSemantic(ix, sc, tn, needInterpret)); 900 ++index; 901 } 902 else if (tns && ix.isExpInitializer()) 903 { 904 /* Disambiguate between an exp representing the entire 905 * struct, and an exp representing the first field of the struct 906 */ 907 if (representsStruct(ix.isExpInitializer(), tns)) // initializer represents the entire struct 908 { 909 ai.addInit((*dlist)[0].exp, initializerSemantic(ix, sc, tn, needInterpret)); 910 ++index; 911 } 912 else // field initializers for struct 913 ai.addInit((*dlist)[0].exp, subStruct(tns, index)); // the first field 914 } 915 else 916 { 917 ai.addInit((*dlist)[0].exp, initializerSemantic(ix, sc, tn, needInterpret)); 918 ++index; 919 } 920 } 921 else if (tnsa && di.initializer.isExpInitializer()) 922 { 923 ExpInitializer ei = di.initializer.isExpInitializer(); 924 if (ei.exp.isStringExp() && tnsa.nextOf().isintegral()) 925 { 926 ai.addInit(null, ei); 927 ++index; 928 } 929 else 930 ai.addInit(null, subArray(tnsa, index)); 931 } 932 else if (tns && di.initializer.isExpInitializer()) 933 { 934 /* Disambiguate between an exp representing the entire 935 * struct, and an exp representing the first field of the struct 936 */ 937 if (representsStruct(di.initializer.isExpInitializer(), tns)) // initializer represents the entire struct 938 { 939 ai.addInit(null, initializerSemantic(di.initializer, sc, tn, needInterpret)); 940 ++index; 941 } 942 else // field initializers for struct 943 ai.addInit(null, subStruct(tns, index)); // the first field 944 } 945 else 946 { 947 ai.addInit(null, initializerSemantic(di.initializer, sc, tn, needInterpret)); 948 ++index; 949 } 950 } 951 return initializerSemantic(ai, sc, tx, needInterpret); 952 } 953 else if (ExpInitializer ei = isBraceExpression()) 954 return visitExp(ei); 955 else 956 { 957 assert(0); 958 } 959 } 960 961 mixin VisitInitializer!Initializer visit; 962 auto result = visit.VisitInitializer(init); 963 return (result !is null) ? result : new ErrorInitializer(); 964 } 965 966 /*********************** 967 * Translate init to an `Expression` in order to infer the type. 968 * Params: 969 * init = `Initializer` AST node 970 * sc = context 971 * Returns: 972 * an equivalent `ExpInitializer` if successful, or `ErrorInitializer` if it cannot be translated 973 */ 974 Initializer inferType(Initializer init, Scope* sc) 975 { 976 Initializer visitVoid(VoidInitializer i) 977 { 978 error(i.loc, "cannot infer type from void initializer"); 979 return new ErrorInitializer(); 980 } 981 982 Initializer visitError(ErrorInitializer i) 983 { 984 return i; 985 } 986 987 Initializer visitStruct(StructInitializer i) 988 { 989 error(i.loc, "cannot infer type from struct initializer"); 990 return new ErrorInitializer(); 991 } 992 993 Initializer visitArray(ArrayInitializer init) 994 { 995 //printf("ArrayInitializer::inferType() %s\n", toChars()); 996 Expressions* keys = null; 997 Expressions* values; 998 if (init.isAssociativeArray()) 999 { 1000 keys = new Expressions(init.value.length); 1001 values = new Expressions(init.value.length); 1002 for (size_t i = 0; i < init.value.length; i++) 1003 { 1004 Expression e = init.index[i]; 1005 if (!e) 1006 goto Lno; 1007 (*keys)[i] = e; 1008 Initializer iz = init.value[i]; 1009 if (!iz) 1010 goto Lno; 1011 iz = iz.inferType(sc); 1012 if (iz.isErrorInitializer()) 1013 { 1014 return iz; 1015 } 1016 (*values)[i] = iz.isExpInitializer().exp; 1017 assert(!(*values)[i].isErrorExp()); 1018 } 1019 Expression e = new AssocArrayLiteralExp(init.loc, keys, values); 1020 auto ei = new ExpInitializer(init.loc, e); 1021 return ei.inferType(sc); 1022 } 1023 else 1024 { 1025 auto elements = new Expressions(init.value.length); 1026 elements.zero(); 1027 for (size_t i = 0; i < init.value.length; i++) 1028 { 1029 assert(!init.index[i]); // already asserted by isAssociativeArray() 1030 Initializer iz = init.value[i]; 1031 if (!iz) 1032 goto Lno; 1033 iz = iz.inferType(sc); 1034 if (iz.isErrorInitializer()) 1035 { 1036 return iz; 1037 } 1038 (*elements)[i] = iz.isExpInitializer().exp; 1039 assert(!(*elements)[i].isErrorExp()); 1040 } 1041 Expression e = new ArrayLiteralExp(init.loc, null, elements); 1042 auto ei = new ExpInitializer(init.loc, e); 1043 return ei.inferType(sc); 1044 } 1045 Lno: 1046 if (keys) 1047 { 1048 error(init.loc, "not an associative array initializer"); 1049 } 1050 else 1051 { 1052 error(init.loc, "cannot infer type from array initializer"); 1053 } 1054 return new ErrorInitializer(); 1055 } 1056 1057 Initializer visitExp(ExpInitializer init) 1058 { 1059 //printf("ExpInitializer::inferType() %s\n", init.toChars()); 1060 init.exp = init.exp.expressionSemantic(sc); 1061 1062 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684 1063 if (init.exp.op == EXP.type) 1064 init.exp = resolveAliasThis(sc, init.exp); 1065 1066 init.exp = resolveProperties(sc, init.exp); 1067 if (auto se = init.exp.isScopeExp()) 1068 { 1069 TemplateInstance ti = se.sds.isTemplateInstance(); 1070 if (ti && ti.semanticRun == PASS.semantic && !ti.aliasdecl) 1071 se.error("cannot infer type from %s `%s`, possible circular dependency", se.sds.kind(), se.toChars()); 1072 else 1073 se.error("cannot infer type from %s `%s`", se.sds.kind(), se.toChars()); 1074 return new ErrorInitializer(); 1075 } 1076 1077 // Give error for overloaded function addresses 1078 bool hasOverloads; 1079 if (auto f = isFuncAddress(init.exp, &hasOverloads)) 1080 { 1081 if (f.checkForwardRef(init.loc)) 1082 { 1083 return new ErrorInitializer(); 1084 } 1085 if (hasOverloads && !f.isUnique()) 1086 { 1087 init.exp.error("cannot infer type from overloaded function symbol `%s`", init.exp.toChars()); 1088 return new ErrorInitializer(); 1089 } 1090 } 1091 if (auto ae = init.exp.isAddrExp()) 1092 { 1093 if (ae.e1.op == EXP.overloadSet) 1094 { 1095 init.exp.error("cannot infer type from overloaded function symbol `%s`", init.exp.toChars()); 1096 return new ErrorInitializer(); 1097 } 1098 } 1099 if (init.exp.isErrorExp()) 1100 { 1101 return new ErrorInitializer(); 1102 } 1103 if (!init.exp.type) 1104 { 1105 return new ErrorInitializer(); 1106 } 1107 return init; 1108 } 1109 1110 Initializer visitC(CInitializer i) 1111 { 1112 //printf("CInitializer.inferType()\n"); 1113 error(i.loc, "TODO C inferType initializers not supported yet"); 1114 return new ErrorInitializer(); 1115 } 1116 1117 mixin VisitInitializer!Initializer visit; 1118 auto result = visit.VisitInitializer(init); 1119 return (result !is null) ? result : new ErrorInitializer(); 1120 } 1121 1122 /*********************** 1123 * Translate init to an `Expression`. 1124 * Params: 1125 * init = `Initializer` AST node 1126 * itype = if not `null`, type to coerce expression to 1127 * isCfile = default initializers are different with C 1128 * Returns: 1129 * `Expression` created, `null` if cannot, `ErrorExp` for other errors 1130 */ 1131 extern (C++) Expression initializerToExpression(Initializer init, Type itype = null, const bool isCfile = false) 1132 { 1133 //printf("initializerToExpression() isCfile: %d\n", isCfile); 1134 1135 Expression visitVoid(VoidInitializer) 1136 { 1137 return null; 1138 } 1139 1140 Expression visitError(ErrorInitializer) 1141 { 1142 return ErrorExp.get(); 1143 } 1144 1145 /*************************************** 1146 * This works by transforming a struct initializer into 1147 * a struct literal. In the future, the two should be the 1148 * same thing. 1149 */ 1150 Expression visitStruct(StructInitializer) 1151 { 1152 // cannot convert to an expression without target 'ad' 1153 return null; 1154 } 1155 1156 /******************************** 1157 * If possible, convert array initializer to array literal. 1158 * Otherwise return NULL. 1159 */ 1160 Expression visitArray(ArrayInitializer init) 1161 { 1162 //printf("ArrayInitializer::toExpression(), dim = %d\n", dim); 1163 //static int i; if (++i == 2) assert(0); 1164 uint edim; // the length of the resulting array literal 1165 const(uint) amax = 0x80000000; 1166 Type t = null; // type of the array literal being initialized 1167 if (init.type) 1168 { 1169 if (init.type == Type.terror) 1170 { 1171 return ErrorExp.get(); 1172 } 1173 t = init.type.toBasetype(); 1174 switch (t.ty) 1175 { 1176 case Tvector: 1177 t = t.isTypeVector().basetype; 1178 goto case Tsarray; 1179 1180 case Tsarray: 1181 uinteger_t adim = t.isTypeSArray().dim.toInteger(); 1182 if (adim >= amax) 1183 return null; 1184 edim = cast(uint)adim; 1185 break; 1186 1187 case Tpointer: 1188 case Tarray: 1189 edim = init.dim; 1190 break; 1191 1192 default: 1193 assert(0); 1194 } 1195 } 1196 else 1197 { 1198 /* Calculate the length of the array literal 1199 */ 1200 edim = cast(uint)init.value.length; 1201 size_t j = 0; 1202 foreach (i; 0 .. init.value.length) 1203 { 1204 if (auto e = init.index[i]) 1205 { 1206 if (e.op == EXP.int64) 1207 { 1208 const uinteger_t idxval = e.toInteger(); 1209 if (idxval >= amax) 1210 return null; 1211 j = cast(size_t)idxval; 1212 } 1213 else 1214 return null; 1215 } 1216 ++j; 1217 if (j > edim) 1218 edim = cast(uint)j; 1219 } 1220 } 1221 1222 auto elements = new Expressions(edim); 1223 elements.zero(); 1224 size_t j = 0; 1225 foreach (i; 0 .. init.value.length) 1226 { 1227 if (auto e = init.index[i]) 1228 j = cast(size_t)e.toInteger(); 1229 assert(j < edim); 1230 if (Initializer iz = init.value[i]) 1231 { 1232 if (Expression ex = iz.initializerToExpression(null, isCfile)) 1233 { 1234 (*elements)[j] = ex; 1235 ++j; 1236 } 1237 else 1238 return null; 1239 } 1240 else 1241 return null; 1242 } 1243 1244 /* Fill in any missing elements with the default initializer 1245 */ 1246 Expression defaultInit = null; // lazily create it 1247 foreach (ref element; (*elements)[0 .. edim]) 1248 { 1249 if (!element) 1250 { 1251 if (!init.type) // don't know what type to use 1252 return null; 1253 if (!defaultInit) 1254 defaultInit = (cast(TypeNext)t).next.defaultInit(Loc.initial, isCfile); 1255 element = defaultInit; 1256 } 1257 } 1258 1259 /* Expand any static array initializers that are a single expression 1260 * into an array of them 1261 * e => [e, e, ..., e, e] 1262 */ 1263 if (t) 1264 { 1265 Type tn = t.nextOf().toBasetype(); 1266 if (tn.ty == Tsarray) 1267 { 1268 const dim = cast(size_t)(cast(TypeSArray)tn).dim.toInteger(); 1269 Type te = tn.nextOf().toBasetype(); 1270 foreach (ref e; *elements) 1271 { 1272 if (te.equals(e.type)) 1273 { 1274 auto elements2 = new Expressions(dim); 1275 foreach (ref e2; *elements2) 1276 e2 = e; 1277 e = new ArrayLiteralExp(e.loc, tn, elements2); 1278 } 1279 } 1280 } 1281 } 1282 1283 /* If any elements are errors, then the whole thing is an error 1284 */ 1285 foreach (e; (*elements)[0 .. edim]) 1286 { 1287 if (e.op == EXP.error) 1288 { 1289 return e; 1290 } 1291 } 1292 1293 Expression e = new ArrayLiteralExp(init.loc, init.type, elements); 1294 return e; 1295 } 1296 1297 Expression visitExp(ExpInitializer i) 1298 { 1299 if (itype) 1300 { 1301 //printf("ExpInitializer::toExpression(t = %s) exp = %s\n", itype.toChars(), i.exp.toChars()); 1302 Type tb = itype.toBasetype(); 1303 Expression e = (i.exp.op == EXP.construct || i.exp.op == EXP.blit) ? (cast(AssignExp)i.exp).e2 : i.exp; 1304 if (tb.ty == Tsarray && e.implicitConvTo(tb.nextOf())) 1305 { 1306 TypeSArray tsa = cast(TypeSArray)tb; 1307 size_t d = cast(size_t)tsa.dim.toInteger(); 1308 auto elements = new Expressions(d); 1309 for (size_t j = 0; j < d; j++) 1310 (*elements)[j] = e; 1311 auto ae = new ArrayLiteralExp(e.loc, itype, elements); 1312 return ae; 1313 } 1314 } 1315 return i.exp; 1316 } 1317 1318 Expression visitC(CInitializer i) 1319 { 1320 //printf("CInitializer.initializerToExpression(null, true)\n"); 1321 return null; 1322 } 1323 1324 mixin VisitInitializer!Expression visit; 1325 return visit.VisitInitializer(init); 1326 } 1327 1328 1329 /************************************** 1330 * Determine if expression has non-constant pointers, or more precisely, 1331 * a pointer that CTFE cannot handle. 1332 * Params: 1333 * e = expression to check 1334 * Returns: 1335 * true if it has non-constant pointers 1336 */ 1337 private bool hasNonConstPointers(Expression e) 1338 { 1339 static bool checkArray(Expressions* elems) 1340 { 1341 foreach (e; *elems) 1342 { 1343 if (e && hasNonConstPointers(e)) 1344 return true; 1345 } 1346 return false; 1347 } 1348 1349 if (e.type.ty == Terror) 1350 return false; 1351 if (e.op == EXP.null_) 1352 return false; 1353 if (auto se = e.isStructLiteralExp()) 1354 { 1355 return checkArray(se.elements); 1356 } 1357 if (auto ae = e.isArrayLiteralExp()) 1358 { 1359 if (!ae.type.nextOf().hasPointers()) 1360 return false; 1361 return checkArray(ae.elements); 1362 } 1363 if (auto ae = e.isAssocArrayLiteralExp()) 1364 { 1365 if (ae.type.nextOf().hasPointers() && checkArray(ae.values)) 1366 return true; 1367 if (ae.type.isTypeAArray().index.hasPointers()) 1368 return checkArray(ae.keys); 1369 return false; 1370 } 1371 if (auto ae = e.isAddrExp()) 1372 { 1373 if (ae.type.nextOf().isImmutable() || ae.type.nextOf().isConst()) 1374 { 1375 return false; 1376 } 1377 if (auto se = ae.e1.isStructLiteralExp()) 1378 { 1379 if (!(se.stageflags & stageSearchPointers)) 1380 { 1381 const old = se.stageflags; 1382 se.stageflags |= stageSearchPointers; 1383 bool ret = checkArray(se.elements); 1384 se.stageflags = old; 1385 return ret; 1386 } 1387 else 1388 { 1389 return false; 1390 } 1391 } 1392 return true; 1393 } 1394 if (e.type.ty == Tpointer && !e.type.isPtrToFunction()) 1395 { 1396 if (e.op == EXP.symbolOffset) // address of a global is OK 1397 return false; 1398 if (e.op == EXP.int64) // cast(void *)int is OK 1399 return false; 1400 if (e.op == EXP.string_) // "abc".ptr is OK 1401 return false; 1402 return true; 1403 } 1404 return false; 1405 } 1406 1407 /** 1408 Given the names and values of a `StructInitializer` or `CallExp`, 1409 resolve it to a list of expressions to construct a `StructLiteralExp`. 1410 1411 Params: 1412 sd = struct 1413 t = type of struct (potentially including qualifiers such as `const` or `immutable`) 1414 sc = scope of the expression initializing the struct 1415 iloc = location of expression initializing the struct 1416 names = identifiers passed in argument list, `null` entries for positional arguments 1417 getExp = function that, given an index into `names` and destination type, returns the initializing expression 1418 getLoc = function that, given an index into `names`, returns a location for error messages 1419 1420 Returns: list of expressions ordered to the struct's fields, or `null` on error 1421 */ 1422 Expressions* resolveStructLiteralNamedArgs(StructDeclaration sd, Type t, Scope* sc, 1423 Loc iloc, Identifier[] names, scope Expression delegate(size_t i, Type fieldType) getExp, 1424 scope Loc delegate(size_t i) getLoc 1425 ) 1426 { 1427 //expandTuples for non-identity arguments? 1428 const nfields = sd.nonHiddenFields(); 1429 auto elements = new Expressions(nfields); 1430 auto elems = (*elements)[]; 1431 foreach (ref elem; elems) 1432 elem = null; 1433 1434 // Run semantic for explicitly given initializers 1435 // TODO: this part is slightly different from StructLiteralExp::semantic. 1436 bool errors = false; 1437 size_t fieldi = 0; 1438 foreach (j, id; names) 1439 { 1440 const argLoc = getLoc(j); 1441 if (id) 1442 { 1443 // Determine `fieldi` that `id` matches 1444 Dsymbol s = sd.search(iloc, id); 1445 if (!s) 1446 { 1447 s = sd.search_correct(id); 1448 if (s) 1449 error(argLoc, "`%s` is not a member of `%s`, did you mean %s `%s`?", id.toChars(), sd.toChars(), s.kind(), s.toChars()); 1450 else 1451 error(argLoc, "`%s` is not a member of `%s`", id.toChars(), sd.toChars()); 1452 return null; 1453 } 1454 s.checkDeprecated(iloc, sc); 1455 s = s.toAlias(); 1456 1457 // Find out which field index `s` is 1458 for (fieldi = 0; 1; fieldi++) 1459 { 1460 if (fieldi >= nfields) 1461 { 1462 error(iloc, "`%s.%s` is not a per-instance initializable field", sd.toChars(), s.toChars()); 1463 return null; 1464 } 1465 if (s == sd.fields[fieldi]) 1466 break; 1467 } 1468 } 1469 if (nfields == 0) 1470 { 1471 error(argLoc, "initializer provided for struct `%s` with no fields", sd.toChars()); 1472 return null; 1473 } 1474 if (j >= nfields) 1475 { 1476 error(argLoc, "too many initializers for `%s` with %d field%s", sd.toChars(), 1477 cast(int) nfields, nfields != 1 ? "s".ptr : "".ptr); 1478 return null; 1479 } 1480 1481 VarDeclaration vd = sd.fields[fieldi]; 1482 if (elems[fieldi]) 1483 { 1484 error(argLoc, "duplicate initializer for field `%s`", vd.toChars()); 1485 errors = true; 1486 elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors 1487 ++fieldi; 1488 continue; 1489 } 1490 1491 // Check for @safe violations 1492 if (vd.type.hasPointers) 1493 { 1494 if ((!t.alignment.isDefault() && t.alignment.get() < target.ptrsize || 1495 (vd.offset & (target.ptrsize - 1)))) 1496 { 1497 if (sc.setUnsafe(false, argLoc, 1498 "field `%s.%s` cannot assign to misaligned pointers in `@safe` code", sd, vd)) 1499 { 1500 errors = true; 1501 elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors 1502 ++fieldi; 1503 continue; 1504 } 1505 } 1506 } 1507 1508 // Check for overlapping initializations (can happen with unions) 1509 foreach (k, v2; sd.fields[0 .. nfields]) 1510 { 1511 if (vd.isOverlappedWith(v2) && elems[k]) 1512 { 1513 error(elems[k].loc, "overlapping initialization for field `%s` and `%s`", v2.toChars(), vd.toChars()); 1514 enum errorMsg = "`struct` initializers that contain anonymous unions" ~ 1515 " must initialize only the first member of a `union`. All subsequent" ~ 1516 " non-overlapping fields are default initialized"; 1517 if (!sd.isUnionDeclaration()) 1518 .errorSupplemental(elems[k].loc, errorMsg); 1519 errors = true; 1520 continue; 1521 } 1522 } 1523 1524 assert(sc); 1525 1526 auto ex = getExp(j, vd.type); 1527 1528 if (ex.op == EXP.error) 1529 { 1530 errors = true; 1531 elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors 1532 ++fieldi; 1533 continue; 1534 } 1535 1536 elems[fieldi] = doCopyOrMove(sc, ex); 1537 ++fieldi; 1538 } 1539 if (errors) 1540 return null; 1541 1542 return elements; 1543 }