1 /** 2 * Performs the semantic3 stage, which deals with function bodies. 3 * 4 * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved 5 * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) 6 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 7 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/semantic3.d, _semantic3.d) 8 * Documentation: https://dlang.org/phobos/dmd_semantic3.html 9 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/semantic3.d 10 */ 11 12 module dmd.semantic3; 13 14 import core.stdc.stdio; 15 import core.stdc.string; 16 17 import dmd.aggregate; 18 import dmd.aliasthis; 19 import dmd.arraytypes; 20 import dmd.astcodegen; 21 import dmd.attrib; 22 import dmd.blockexit; 23 import dmd.clone; 24 import dmd.ctorflow; 25 import dmd.dcast; 26 import dmd.dclass; 27 import dmd.declaration; 28 import dmd.denum; 29 import dmd.dimport; 30 import dmd.dinterpret; 31 import dmd.dmodule; 32 import dmd.dscope; 33 import dmd.dstruct; 34 import dmd.dsymbol; 35 import dmd.dsymbolsem; 36 import dmd.dtemplate; 37 import dmd.dversion; 38 import dmd.errors; 39 import dmd.escape; 40 import dmd.expression; 41 import dmd.expressionsem; 42 import dmd.func; 43 import dmd.globals; 44 import dmd.id; 45 import dmd.identifier; 46 import dmd.init; 47 import dmd.initsem; 48 import dmd.hdrgen; 49 import dmd.mtype; 50 import dmd.nogc; 51 import dmd.nspace; 52 import dmd.ob; 53 import dmd.objc; 54 import dmd.opover; 55 import dmd.parse; 56 import dmd.root.filename; 57 import dmd.root.outbuffer; 58 import dmd.root.rmem; 59 import dmd.root.rootobject; 60 import dmd.sideeffect; 61 import dmd.statementsem; 62 import dmd.staticassert; 63 import dmd.tokens; 64 import dmd.utf; 65 import dmd.semantic2; 66 import dmd.statement; 67 import dmd.target; 68 import dmd.templateparamsem; 69 import dmd.typesem; 70 import dmd.visitor; 71 72 enum LOG = false; 73 74 75 /************************************* 76 * Does semantic analysis on function bodies. 77 */ 78 extern(C++) void semantic3(Dsymbol dsym, Scope* sc) 79 { 80 scope v = new Semantic3Visitor(sc); 81 dsym.accept(v); 82 } 83 84 private extern(C++) final class Semantic3Visitor : Visitor 85 { 86 alias visit = Visitor.visit; 87 88 Scope* sc; 89 this(Scope* sc) 90 { 91 this.sc = sc; 92 } 93 94 override void visit(Dsymbol) {} 95 96 override void visit(TemplateInstance tempinst) 97 { 98 static if (LOG) 99 { 100 printf("TemplateInstance.semantic3('%s'), semanticRun = %d\n", tempinst.toChars(), tempinst.semanticRun); 101 } 102 //if (toChars()[0] == 'D') *(char*)0=0; 103 if (tempinst.semanticRun >= PASS.semantic3) 104 return; 105 tempinst.semanticRun = PASS.semantic3; 106 if (!tempinst.errors && tempinst.members) 107 { 108 TemplateDeclaration tempdecl = tempinst.tempdecl.isTemplateDeclaration(); 109 assert(tempdecl); 110 111 sc = tempdecl._scope; 112 sc = sc.push(tempinst.argsym); 113 sc = sc.push(tempinst); 114 sc.tinst = tempinst; 115 sc.minst = tempinst.minst; 116 117 int needGagging = (tempinst.gagged && !global.gag); 118 uint olderrors = global.errors; 119 int oldGaggedErrors = -1; // dead-store to prevent spurious warning 120 /* If this is a gagged instantiation, gag errors. 121 * Future optimisation: If the results are actually needed, errors 122 * would already be gagged, so we don't really need to run semantic 123 * on the members. 124 */ 125 if (needGagging) 126 oldGaggedErrors = global.startGagging(); 127 128 for (size_t i = 0; i < tempinst.members.dim; i++) 129 { 130 Dsymbol s = (*tempinst.members)[i]; 131 s.semantic3(sc); 132 if (tempinst.gagged && global.errors != olderrors) 133 break; 134 } 135 136 if (global.errors != olderrors) 137 { 138 if (!tempinst.errors) 139 { 140 if (!tempdecl.literal) 141 tempinst.error(tempinst.loc, "error instantiating"); 142 if (tempinst.tinst) 143 tempinst.tinst.printInstantiationTrace(); 144 } 145 tempinst.errors = true; 146 } 147 if (needGagging) 148 global.endGagging(oldGaggedErrors); 149 150 sc = sc.pop(); 151 sc.pop(); 152 } 153 } 154 155 override void visit(TemplateMixin tmix) 156 { 157 if (tmix.semanticRun >= PASS.semantic3) 158 return; 159 tmix.semanticRun = PASS.semantic3; 160 static if (LOG) 161 { 162 printf("TemplateMixin.semantic3('%s')\n", tmix.toChars()); 163 } 164 if (tmix.members) 165 { 166 sc = sc.push(tmix.argsym); 167 sc = sc.push(tmix); 168 for (size_t i = 0; i < tmix.members.dim; i++) 169 { 170 Dsymbol s = (*tmix.members)[i]; 171 s.semantic3(sc); 172 } 173 sc = sc.pop(); 174 sc.pop(); 175 } 176 } 177 178 override void visit(Module mod) 179 { 180 //printf("Module::semantic3('%s'): parent = %p\n", toChars(), parent); 181 if (mod.semanticRun != PASS.semantic2done) 182 return; 183 mod.semanticRun = PASS.semantic3; 184 // Note that modules get their own scope, from scratch. 185 // This is so regardless of where in the syntax a module 186 // gets imported, it is unaffected by context. 187 Scope* sc = Scope.createGlobal(mod); // create root scope 188 //printf("Module = %p\n", sc.scopesym); 189 // Pass 3 semantic routines: do initializers and function bodies 190 for (size_t i = 0; i < mod.members.dim; i++) 191 { 192 Dsymbol s = (*mod.members)[i]; 193 //printf("Module %s: %s.semantic3()\n", toChars(), s.toChars()); 194 s.semantic3(sc); 195 196 mod.runDeferredSemantic2(); 197 } 198 if (mod.userAttribDecl) 199 { 200 mod.userAttribDecl.semantic3(sc); 201 } 202 sc = sc.pop(); 203 sc.pop(); 204 mod.semanticRun = PASS.semantic3done; 205 } 206 207 override void visit(FuncDeclaration funcdecl) 208 { 209 /* Determine if function should add `return 0;` 210 */ 211 bool addReturn0() 212 { 213 TypeFunction f = cast(TypeFunction)funcdecl.type; 214 215 return f.next.ty == Tvoid && 216 (funcdecl.isMain() || global.params.betterC && funcdecl.isCMain()); 217 } 218 219 VarDeclaration _arguments = null; 220 221 if (!funcdecl.parent) 222 { 223 if (global.errors) 224 return; 225 //printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc); 226 assert(0); 227 } 228 if (funcdecl.errors || isError(funcdecl.parent)) 229 { 230 funcdecl.errors = true; 231 return; 232 } 233 //printf("FuncDeclaration::semantic3('%s.%s', %p, sc = %p, loc = %s)\n", funcdecl.parent.toChars(), funcdecl.toChars(), funcdecl, sc, funcdecl.loc.toChars()); 234 //fflush(stdout); 235 //printf("storage class = x%x %x\n", sc.stc, storage_class); 236 //{ static int x; if (++x == 2) *(char*)0=0; } 237 //printf("\tlinkage = %d\n", sc.linkage); 238 239 if (funcdecl.ident == Id.assign && !funcdecl.inuse) 240 { 241 if (funcdecl.storage_class & STC.inference) 242 { 243 /* https://issues.dlang.org/show_bug.cgi?id=15044 244 * For generated opAssign function, any errors 245 * from its body need to be gagged. 246 */ 247 uint oldErrors = global.startGagging(); 248 ++funcdecl.inuse; 249 funcdecl.semantic3(sc); 250 --funcdecl.inuse; 251 if (global.endGagging(oldErrors)) // if errors happened 252 { 253 // Disable generated opAssign, because some members forbid identity assignment. 254 funcdecl.storage_class |= STC.disable; 255 funcdecl.fbody = null; // remove fbody which contains the error 256 funcdecl.semantic3Errors = false; 257 } 258 return; 259 } 260 } 261 262 //printf(" sc.incontract = %d\n", (sc.flags & SCOPE.contract)); 263 if (funcdecl.semanticRun >= PASS.semantic3) 264 return; 265 funcdecl.semanticRun = PASS.semantic3; 266 funcdecl.semantic3Errors = false; 267 268 if (!funcdecl.type || funcdecl.type.ty != Tfunction) 269 return; 270 TypeFunction f = cast(TypeFunction)funcdecl.type; 271 if (!funcdecl.inferRetType && f.next.ty == Terror) 272 return; 273 274 if (!funcdecl.fbody && funcdecl.inferRetType && !f.next) 275 { 276 funcdecl.error("has no function body with return type inference"); 277 return; 278 } 279 280 uint oldErrors = global.errors; 281 auto fds = FuncDeclSem3(funcdecl,sc); 282 283 fds.checkInContractOverrides(); 284 285 // Remember whether we need to generate an 'out' contract. 286 immutable bool needEnsure = FuncDeclaration.needsFensure(funcdecl); 287 288 if (funcdecl.fbody || funcdecl.frequires || needEnsure) 289 { 290 /* Symbol table into which we place parameters and nested functions, 291 * solely to diagnose name collisions. 292 */ 293 funcdecl.localsymtab = new DsymbolTable(); 294 295 // Establish function scope 296 auto ss = new ScopeDsymbol(funcdecl.loc, null); 297 // find enclosing scope symbol, might skip symbol-less CTFE and/or FuncExp scopes 298 for (auto scx = sc; ; scx = scx.enclosing) 299 { 300 if (scx.scopesym) 301 { 302 ss.parent = scx.scopesym; 303 break; 304 } 305 } 306 ss.endlinnum = funcdecl.endloc.linnum; 307 Scope* sc2 = sc.push(ss); 308 sc2.func = funcdecl; 309 sc2.parent = funcdecl; 310 sc2.ctorflow.callSuper = CSX.none; 311 sc2.sbreak = null; 312 sc2.scontinue = null; 313 sc2.sw = null; 314 sc2.fes = funcdecl.fes; 315 sc2.linkage = LINK.d; 316 sc2.stc &= STCFlowThruFunction; 317 sc2.protection = Prot(Prot.Kind.public_); 318 sc2.explicitProtection = 0; 319 sc2.aligndecl = null; 320 if (funcdecl.ident != Id.require && funcdecl.ident != Id.ensure) 321 sc2.flags = sc.flags & ~SCOPE.contract; 322 sc2.flags &= ~SCOPE.compile; 323 sc2.tf = null; 324 sc2.os = null; 325 sc2.inLoop = false; 326 sc2.userAttribDecl = null; 327 if (sc2.intypeof == 1) 328 sc2.intypeof = 2; 329 sc2.ctorflow.fieldinit = null; 330 331 /* Note: When a lambda is defined immediately under aggregate member 332 * scope, it should be contextless due to prevent interior pointers. 333 * e.g. 334 * // dg points 'this' - it's interior pointer 335 * class C { int x; void delegate() dg = (){ this.x = 1; }; } 336 * 337 * However, lambdas could be used inside typeof, in order to check 338 * some expressions validity at compile time. For such case the lambda 339 * body can access aggregate instance members. 340 * e.g. 341 * class C { int x; static assert(is(typeof({ this.x = 1; }))); } 342 * 343 * To properly accept it, mark these lambdas as member functions. 344 */ 345 if (auto fld = funcdecl.isFuncLiteralDeclaration()) 346 { 347 if (auto ad = funcdecl.isMember2()) 348 { 349 if (!sc.intypeof) 350 { 351 if (fld.tok == TOK.delegate_) 352 funcdecl.error("cannot be %s members", ad.kind()); 353 else 354 fld.tok = TOK.function_; 355 } 356 else 357 { 358 if (fld.tok != TOK.function_) 359 fld.tok = TOK.delegate_; 360 } 361 } 362 } 363 364 funcdecl.declareThis(sc2); 365 366 //printf("[%s] ad = %p vthis = %p\n", loc.toChars(), ad, vthis); 367 //if (vthis) printf("\tvthis.type = %s\n", vthis.type.toChars()); 368 369 // Declare hidden variable _arguments[] and _argptr 370 if (f.parameterList.varargs == VarArg.variadic) 371 { 372 if (f.linkage == LINK.d) 373 { 374 // Variadic arguments depend on Typeinfo being defined. 375 if (!global.params.useTypeInfo || !Type.dtypeinfo || !Type.typeinfotypelist) 376 { 377 if (!global.params.useTypeInfo) 378 funcdecl.error("D-style variadic functions cannot be used with -betterC"); 379 else if (!Type.typeinfotypelist) 380 funcdecl.error("`object.TypeInfo_Tuple` could not be found, but is implicitly used in D-style variadic functions"); 381 else 382 funcdecl.error("`object.TypeInfo` could not be found, but is implicitly used in D-style variadic functions"); 383 fatal(); 384 } 385 386 // Declare _arguments[] 387 funcdecl.v_arguments = new VarDeclaration(funcdecl.loc, Type.typeinfotypelist.type, Id._arguments_typeinfo, null); 388 funcdecl.v_arguments.storage_class |= STC.temp | STC.parameter; 389 funcdecl.v_arguments.dsymbolSemantic(sc2); 390 sc2.insert(funcdecl.v_arguments); 391 funcdecl.v_arguments.parent = funcdecl; 392 393 //Type t = Type.dtypeinfo.type.constOf().arrayOf(); 394 Type t = Type.dtypeinfo.type.arrayOf(); 395 _arguments = new VarDeclaration(funcdecl.loc, t, Id._arguments, null); 396 _arguments.storage_class |= STC.temp; 397 _arguments.dsymbolSemantic(sc2); 398 sc2.insert(_arguments); 399 _arguments.parent = funcdecl; 400 } 401 if (f.linkage == LINK.d || f.parameterList.length) 402 { 403 // Declare _argptr 404 Type t = Type.tvalist; 405 // Init is handled in FuncDeclaration_toObjFile 406 funcdecl.v_argptr = new VarDeclaration(funcdecl.loc, t, Id._argptr, new VoidInitializer(funcdecl.loc)); 407 funcdecl.v_argptr.storage_class |= STC.temp; 408 funcdecl.v_argptr.dsymbolSemantic(sc2); 409 sc2.insert(funcdecl.v_argptr); 410 funcdecl.v_argptr.parent = funcdecl; 411 } 412 } 413 414 /* Declare all the function parameters as variables 415 * and install them in parameters[] 416 */ 417 size_t nparams = f.parameterList.length; 418 if (nparams) 419 { 420 /* parameters[] has all the tuples removed, as the back end 421 * doesn't know about tuples 422 */ 423 funcdecl.parameters = new VarDeclarations(); 424 funcdecl.parameters.reserve(nparams); 425 for (size_t i = 0; i < nparams; i++) 426 { 427 Parameter fparam = f.parameterList[i]; 428 Identifier id = fparam.ident; 429 StorageClass stc = 0; 430 if (!id) 431 { 432 /* Generate identifier for un-named parameter, 433 * because we need it later on. 434 */ 435 fparam.ident = id = Identifier.generateId("_param_", i); 436 stc |= STC.temp; 437 } 438 Type vtype = fparam.type; 439 auto v = new VarDeclaration(funcdecl.loc, vtype, id, null); 440 //printf("declaring parameter %s of type %s\n", v.toChars(), v.type.toChars()); 441 stc |= STC.parameter; 442 if (f.parameterList.varargs == VarArg.typesafe && i + 1 == nparams) 443 { 444 stc |= STC.variadic; 445 auto vtypeb = vtype.toBasetype(); 446 if (vtypeb.ty == Tarray) 447 { 448 /* Since it'll be pointing into the stack for the array 449 * contents, it needs to be `scope` 450 */ 451 stc |= STC.scope_; 452 } 453 } 454 455 if ((funcdecl.flags & FUNCFLAG.inferScope) && !(fparam.storageClass & STC.scope_)) 456 stc |= STC.maybescope; 457 458 stc |= fparam.storageClass & (STC.in_ | STC.out_ | STC.ref_ | STC.return_ | STC.scope_ | STC.lazy_ | STC.final_ | STC.TYPECTOR | STC.nodtor); 459 v.storage_class = stc; 460 v.dsymbolSemantic(sc2); 461 if (!sc2.insert(v)) 462 { 463 funcdecl.error("parameter `%s.%s` is already defined", funcdecl.toChars(), v.toChars()); 464 funcdecl.errors = true; 465 } 466 else 467 funcdecl.parameters.push(v); 468 funcdecl.localsymtab.insert(v); 469 v.parent = funcdecl; 470 if (fparam.userAttribDecl) 471 v.userAttribDecl = fparam.userAttribDecl; 472 } 473 } 474 475 // Declare the tuple symbols and put them in the symbol table, 476 // but not in parameters[]. 477 if (f.parameterList.parameters) 478 foreach (fparam; *f.parameterList.parameters) 479 { 480 if (!fparam.ident) 481 continue; // never used, so ignore 482 // expand any tuples 483 if (fparam.type.ty != Ttuple) 484 continue; 485 486 TypeTuple t = cast(TypeTuple)fparam.type; 487 size_t dim = Parameter.dim(t.arguments); 488 auto exps = new Objects(dim); 489 foreach (j; 0 .. dim) 490 { 491 Parameter narg = Parameter.getNth(t.arguments, j); 492 assert(narg.ident); 493 VarDeclaration v = sc2.search(Loc.initial, narg.ident, null).isVarDeclaration(); 494 assert(v); 495 (*exps)[j] = new VarExp(v.loc, v); 496 } 497 assert(fparam.ident); 498 auto v = new TupleDeclaration(funcdecl.loc, fparam.ident, exps); 499 //printf("declaring tuple %s\n", v.toChars()); 500 v.isexp = true; 501 if (!sc2.insert(v)) 502 funcdecl.error("parameter `%s.%s` is already defined", funcdecl.toChars(), v.toChars()); 503 funcdecl.localsymtab.insert(v); 504 v.parent = funcdecl; 505 } 506 507 // Precondition invariant 508 Statement fpreinv = null; 509 if (funcdecl.addPreInvariant()) 510 { 511 Expression e = addInvariant(funcdecl.loc, sc, funcdecl.isThis(), funcdecl.vthis); 512 if (e) 513 fpreinv = new ExpStatement(Loc.initial, e); 514 } 515 516 // Postcondition invariant 517 Statement fpostinv = null; 518 if (funcdecl.addPostInvariant()) 519 { 520 Expression e = addInvariant(funcdecl.loc, sc, funcdecl.isThis(), funcdecl.vthis); 521 if (e) 522 fpostinv = new ExpStatement(Loc.initial, e); 523 } 524 525 // Pre/Postcondition contract 526 if (!funcdecl.fbody) 527 funcdecl.buildEnsureRequire(); 528 529 Scope* scout = null; 530 if (needEnsure || funcdecl.addPostInvariant()) 531 { 532 /* https://issues.dlang.org/show_bug.cgi?id=3657 533 * Set the correct end line number for fensure scope. 534 */ 535 uint fensure_endlin = funcdecl.endloc.linnum; 536 if (funcdecl.fensure) 537 if (auto s = funcdecl.fensure.isScopeStatement()) 538 fensure_endlin = s.endloc.linnum; 539 540 if ((needEnsure && global.params.useOut == CHECKENABLE.on) || fpostinv) 541 { 542 funcdecl.returnLabel = funcdecl.searchLabel(Id.returnLabel); 543 } 544 545 // scope of out contract (need for vresult.semantic) 546 auto sym = new ScopeDsymbol(funcdecl.loc, null); 547 sym.parent = sc2.scopesym; 548 sym.endlinnum = fensure_endlin; 549 scout = sc2.push(sym); 550 } 551 552 if (funcdecl.fbody) 553 { 554 auto sym = new ScopeDsymbol(funcdecl.loc, null); 555 sym.parent = sc2.scopesym; 556 sym.endlinnum = funcdecl.endloc.linnum; 557 sc2 = sc2.push(sym); 558 559 auto ad2 = funcdecl.isMemberLocal(); 560 561 /* If this is a class constructor 562 */ 563 if (ad2 && funcdecl.isCtorDeclaration()) 564 { 565 sc2.ctorflow.allocFieldinit(ad2.fields.dim); 566 foreach (v; ad2.fields) 567 { 568 v.ctorinit = 0; 569 } 570 } 571 572 if (!funcdecl.inferRetType && !target.isReturnOnStack(f, funcdecl.needThis())) 573 funcdecl.nrvo_can = 0; 574 575 bool inferRef = (f.isref && (funcdecl.storage_class & STC.auto_)); 576 577 funcdecl.fbody = funcdecl.fbody.statementSemantic(sc2); 578 if (!funcdecl.fbody) 579 funcdecl.fbody = new CompoundStatement(Loc.initial, new Statements()); 580 581 if (funcdecl.naked) 582 { 583 fpreinv = null; // can't accommodate with no stack frame 584 fpostinv = null; 585 } 586 587 assert(funcdecl.type == f || (funcdecl.type.ty == Tfunction && f.purity == PURE.impure && (cast(TypeFunction)funcdecl.type).purity >= PURE.fwdref)); 588 f = cast(TypeFunction)funcdecl.type; 589 590 if (funcdecl.inferRetType) 591 { 592 // If no return type inferred yet, then infer a void 593 if (!f.next) 594 f.next = Type.tvoid; 595 if (f.checkRetType(funcdecl.loc)) 596 funcdecl.fbody = new ErrorStatement(); 597 } 598 if (global.params.vcomplex && f.next !is null) 599 f.next.checkComplexTransition(funcdecl.loc, sc); 600 601 if (funcdecl.returns && !funcdecl.fbody.isErrorStatement()) 602 { 603 for (size_t i = 0; i < funcdecl.returns.dim;) 604 { 605 Expression exp = (*funcdecl.returns)[i].exp; 606 if (exp.op == TOK.variable && (cast(VarExp)exp).var == funcdecl.vresult) 607 { 608 if (addReturn0()) 609 exp.type = Type.tint32; 610 else 611 exp.type = f.next; 612 // Remove `return vresult;` from returns 613 funcdecl.returns.remove(i); 614 continue; 615 } 616 if (inferRef && f.isref && !exp.type.constConv(f.next)) // https://issues.dlang.org/show_bug.cgi?id=13336 617 f.isref = false; 618 i++; 619 } 620 } 621 if (f.isref) // Function returns a reference 622 { 623 if (funcdecl.storage_class & STC.auto_) 624 funcdecl.storage_class &= ~STC.auto_; 625 } 626 627 // handle NRVO 628 if (!target.isReturnOnStack(f, funcdecl.needThis()) || funcdecl.checkNrvo()) 629 funcdecl.nrvo_can = 0; 630 631 if (funcdecl.fbody.isErrorStatement()) 632 { 633 } 634 else if (funcdecl.isStaticCtorDeclaration()) 635 { 636 /* It's a static constructor. Ensure that all 637 * ctor consts were initialized. 638 */ 639 ScopeDsymbol pd = funcdecl.toParent().isScopeDsymbol(); 640 for (size_t i = 0; i < pd.members.dim; i++) 641 { 642 Dsymbol s = (*pd.members)[i]; 643 s.checkCtorConstInit(); 644 } 645 } 646 else if (ad2 && funcdecl.isCtorDeclaration()) 647 { 648 ClassDeclaration cd = ad2.isClassDeclaration(); 649 650 // Verify that all the ctorinit fields got initialized 651 if (!(sc2.ctorflow.callSuper & CSX.this_ctor)) 652 { 653 foreach (i, v; ad2.fields) 654 { 655 if (v.isThisDeclaration()) 656 continue; 657 if (v.ctorinit == 0) 658 { 659 /* Current bugs in the flow analysis: 660 * 1. union members should not produce error messages even if 661 * not assigned to 662 * 2. structs should recognize delegating opAssign calls as well 663 * as delegating calls to other constructors 664 */ 665 if (v.isCtorinit() && !v.type.isMutable() && cd) 666 funcdecl.error("missing initializer for %s field `%s`", MODtoChars(v.type.mod), v.toChars()); 667 else if (v.storage_class & STC.nodefaultctor) 668 error(funcdecl.loc, "field `%s` must be initialized in constructor", v.toChars()); 669 else if (v.type.needsNested()) 670 error(funcdecl.loc, "field `%s` must be initialized in constructor, because it is nested struct", v.toChars()); 671 } 672 else 673 { 674 bool mustInit = (v.storage_class & STC.nodefaultctor || v.type.needsNested()); 675 if (mustInit && !(sc2.ctorflow.fieldinit[i].csx & CSX.this_ctor)) 676 { 677 funcdecl.error("field `%s` must be initialized but skipped", v.toChars()); 678 } 679 } 680 } 681 } 682 sc2.ctorflow.freeFieldinit(); 683 684 if (cd && !(sc2.ctorflow.callSuper & CSX.any_ctor) && cd.baseClass && cd.baseClass.ctor) 685 { 686 sc2.ctorflow.callSuper = CSX.none; 687 688 // Insert implicit super() at start of fbody 689 Type tthis = ad2.type.addMod(funcdecl.vthis.type.mod); 690 FuncDeclaration fd = resolveFuncCall(Loc.initial, sc2, cd.baseClass.ctor, null, tthis, null, FuncResolveFlag.quiet); 691 if (!fd) 692 { 693 funcdecl.error("no match for implicit `super()` call in constructor"); 694 } 695 else if (fd.storage_class & STC.disable) 696 { 697 funcdecl.error("cannot call `super()` implicitly because it is annotated with `@disable`"); 698 } 699 else 700 { 701 Expression e1 = new SuperExp(Loc.initial); 702 Expression e = new CallExp(Loc.initial, e1); 703 e = e.expressionSemantic(sc2); 704 Statement s = new ExpStatement(Loc.initial, e); 705 funcdecl.fbody = new CompoundStatement(Loc.initial, s, funcdecl.fbody); 706 } 707 } 708 //printf("ctorflow.callSuper = x%x\n", sc2.ctorflow.callSuper); 709 } 710 711 /* https://issues.dlang.org/show_bug.cgi?id=17502 712 * Wait until after the return type has been inferred before 713 * generating the contracts for this function, and merging contracts 714 * from overrides. 715 * 716 * https://issues.dlang.org/show_bug.cgi?id=17893 717 * However should take care to generate this before inferered 718 * function attributes are applied, such as 'nothrow'. 719 * 720 * This was originally at the end of the first semantic pass, but 721 * required a fix-up to be done here for the '__result' variable 722 * type of __ensure() inside auto functions, but this didn't work 723 * if the out parameter was implicit. 724 */ 725 funcdecl.buildEnsureRequire(); 726 727 // Check for errors related to 'nothrow'. 728 const blockexit = funcdecl.fbody.blockExit(funcdecl, f.isnothrow); 729 if (f.isnothrow && blockexit & BE.throw_) 730 error(funcdecl.loc, "`nothrow` %s `%s` may throw", funcdecl.kind(), funcdecl.toPrettyChars()); 731 732 if (!(blockexit & (BE.throw_ | BE.halt) || funcdecl.flags & FUNCFLAG.hasCatches)) 733 { 734 /* Disable optimization on Win32 due to 735 * https://issues.dlang.org/show_bug.cgi?id=17997 736 */ 737 // if (!global.params.isWindows || global.params.is64bit) 738 funcdecl.eh_none = true; // don't generate unwind tables for this function 739 } 740 741 if (funcdecl.flags & FUNCFLAG.nothrowInprocess) 742 { 743 if (funcdecl.type == f) 744 f = cast(TypeFunction)f.copy(); 745 f.isnothrow = !(blockexit & BE.throw_); 746 } 747 748 if (funcdecl.fbody.isErrorStatement()) 749 { 750 } 751 else if (ad2 && funcdecl.isCtorDeclaration()) 752 { 753 /* Append: 754 * return this; 755 * to function body 756 */ 757 if (blockexit & BE.fallthru) 758 { 759 Statement s = new ReturnStatement(funcdecl.loc, null); 760 s = s.statementSemantic(sc2); 761 funcdecl.fbody = new CompoundStatement(funcdecl.loc, funcdecl.fbody, s); 762 funcdecl.hasReturnExp |= (funcdecl.hasReturnExp & 1 ? 16 : 1); 763 } 764 } 765 else if (funcdecl.fes) 766 { 767 // For foreach(){} body, append a return 0; 768 if (blockexit & BE.fallthru) 769 { 770 Expression e = IntegerExp.literal!0; 771 Statement s = new ReturnStatement(Loc.initial, e); 772 funcdecl.fbody = new CompoundStatement(Loc.initial, funcdecl.fbody, s); 773 funcdecl.hasReturnExp |= (funcdecl.hasReturnExp & 1 ? 16 : 1); 774 } 775 assert(!funcdecl.returnLabel); 776 } 777 else 778 { 779 const(bool) inlineAsm = (funcdecl.hasReturnExp & 8) != 0; 780 if ((blockexit & BE.fallthru) && f.next.ty != Tvoid && !inlineAsm) 781 { 782 Expression e; 783 if (!funcdecl.hasReturnExp) 784 funcdecl.error("has no `return` statement, but is expected to return a value of type `%s`", f.next.toChars()); 785 else 786 funcdecl.error("no `return exp;` or `assert(0);` at end of function"); 787 if (global.params.useAssert == CHECKENABLE.on && !global.params.useInline) 788 { 789 /* Add an assert(0, msg); where the missing return 790 * should be. 791 */ 792 e = new AssertExp(funcdecl.endloc, IntegerExp.literal!0, new StringExp(funcdecl.loc, "missing return expression")); 793 } 794 else 795 e = new HaltExp(funcdecl.endloc); 796 e = new CommaExp(Loc.initial, e, f.next.defaultInit(Loc.initial)); 797 e = e.expressionSemantic(sc2); 798 Statement s = new ExpStatement(Loc.initial, e); 799 funcdecl.fbody = new CompoundStatement(Loc.initial, funcdecl.fbody, s); 800 } 801 } 802 803 if (funcdecl.returns) 804 { 805 bool implicit0 = addReturn0(); 806 Type tret = implicit0 ? Type.tint32 : f.next; 807 assert(tret.ty != Tvoid); 808 if (funcdecl.vresult || funcdecl.returnLabel) 809 funcdecl.buildResultVar(scout ? scout : sc2, tret); 810 811 /* Cannot move this loop into NrvoWalker, because 812 * returns[i] may be in the nested delegate for foreach-body. 813 */ 814 for (size_t i = 0; i < funcdecl.returns.dim; i++) 815 { 816 ReturnStatement rs = (*funcdecl.returns)[i]; 817 Expression exp = rs.exp; 818 if (exp.op == TOK.error) 819 continue; 820 if (tret.ty == Terror) 821 { 822 // https://issues.dlang.org/show_bug.cgi?id=13702 823 exp = checkGC(sc2, exp); 824 continue; 825 } 826 827 /* If the expression in the return statement (exp) cannot be implicitly 828 * converted to the return type (tret) of the function and if the 829 * type of the expression is type isolated, then it may be possible 830 * that a promotion to `immutable` or `inout` (through a cast) will 831 * match the return type. 832 */ 833 if (!exp.implicitConvTo(tret) && funcdecl.isTypeIsolated(exp.type)) 834 { 835 /* https://issues.dlang.org/show_bug.cgi?id=20073 836 * 837 * The problem is that if the type of the returned expression (exp.type) 838 * is an aggregated declaration with an alias this, the alias this may be 839 * used for the conversion testing without it being an isolated type. 840 * 841 * To make sure this does not happen, we can test here the implicit conversion 842 * only for the aggregated declaration type by using `implicitConvToWithoutAliasThis`. 843 * The implicit conversion with alias this is taken care of later. 844 */ 845 AggregateDeclaration aggDecl = isAggregate(exp.type); 846 TypeStruct tstruct; 847 TypeClass tclass; 848 bool hasAliasThis; 849 if (aggDecl && aggDecl.aliasthis) 850 { 851 hasAliasThis = true; 852 tclass = exp.type.isTypeClass(); 853 if (!tclass) 854 tstruct = exp.type.isTypeStruct(); 855 assert(tclass || tstruct); 856 } 857 if (hasAliasThis) 858 { 859 if (tclass) 860 { 861 if ((cast(TypeClass)(exp.type.immutableOf())).implicitConvToWithoutAliasThis(tret)) 862 exp = exp.castTo(sc2, exp.type.immutableOf()); 863 else if ((cast(TypeClass)(exp.type.wildOf())).implicitConvToWithoutAliasThis(tret)) 864 exp = exp.castTo(sc2, exp.type.wildOf()); 865 } 866 else 867 { 868 if ((cast(TypeStruct)exp.type.immutableOf()).implicitConvToWithoutAliasThis(tret)) 869 exp = exp.castTo(sc2, exp.type.immutableOf()); 870 else if ((cast(TypeStruct)exp.type.immutableOf()).implicitConvToWithoutAliasThis(tret)) 871 exp = exp.castTo(sc2, exp.type.wildOf()); 872 } 873 } 874 else 875 { 876 if (exp.type.immutableOf().implicitConvTo(tret)) 877 exp = exp.castTo(sc2, exp.type.immutableOf()); 878 else if (exp.type.wildOf().implicitConvTo(tret)) 879 exp = exp.castTo(sc2, exp.type.wildOf()); 880 } 881 } 882 883 const hasCopyCtor = exp.type.ty == Tstruct && (cast(TypeStruct)exp.type).sym.hasCopyCtor; 884 // if a copy constructor is present, the return type conversion will be handled by it 885 if (!(hasCopyCtor && exp.isLvalue())) 886 exp = exp.implicitCastTo(sc2, tret); 887 888 if (f.isref) 889 { 890 // Function returns a reference 891 exp = exp.toLvalue(sc2, exp); 892 checkReturnEscapeRef(sc2, exp, false); 893 } 894 else 895 { 896 exp = exp.optimize(WANTvalue); 897 898 /* https://issues.dlang.org/show_bug.cgi?id=10789 899 * If NRVO is not possible, all returned lvalues should call their postblits. 900 */ 901 if (!funcdecl.nrvo_can) 902 exp = doCopyOrMove(sc2, exp, f.next); 903 904 if (tret.hasPointers()) 905 checkReturnEscape(sc2, exp, false); 906 } 907 908 exp = checkGC(sc2, exp); 909 910 if (funcdecl.vresult) 911 { 912 // Create: return vresult = exp; 913 exp = new BlitExp(rs.loc, funcdecl.vresult, exp); 914 exp.type = funcdecl.vresult.type; 915 916 if (rs.caseDim) 917 exp = Expression.combine(exp, new IntegerExp(rs.caseDim)); 918 } 919 else if (funcdecl.tintro && !tret.equals(funcdecl.tintro.nextOf())) 920 { 921 exp = exp.implicitCastTo(sc2, funcdecl.tintro.nextOf()); 922 } 923 rs.exp = exp; 924 } 925 } 926 if (funcdecl.nrvo_var || funcdecl.returnLabel) 927 { 928 scope NrvoWalker nw = new NrvoWalker(); 929 nw.fd = funcdecl; 930 nw.sc = sc2; 931 nw.visitStmt(funcdecl.fbody); 932 } 933 934 sc2 = sc2.pop(); 935 } 936 937 funcdecl.frequire = funcdecl.mergeFrequire(funcdecl.frequire, funcdecl.fdrequireParams); 938 funcdecl.fensure = funcdecl.mergeFensure(funcdecl.fensure, Id.result, funcdecl.fdensureParams); 939 940 Statement freq = funcdecl.frequire; 941 Statement fens = funcdecl.fensure; 942 943 /* Do the semantic analysis on the [in] preconditions and 944 * [out] postconditions. 945 */ 946 if (freq) 947 { 948 /* frequire is composed of the [in] contracts 949 */ 950 auto sym = new ScopeDsymbol(funcdecl.loc, null); 951 sym.parent = sc2.scopesym; 952 sym.endlinnum = funcdecl.endloc.linnum; 953 sc2 = sc2.push(sym); 954 sc2.flags = (sc2.flags & ~SCOPE.contract) | SCOPE.require; 955 956 // BUG: need to error if accessing out parameters 957 // BUG: need to disallow returns and throws 958 // BUG: verify that all in and ref parameters are read 959 freq = freq.statementSemantic(sc2); 960 freq.blockExit(funcdecl, false); 961 962 funcdecl.eh_none = false; 963 964 sc2 = sc2.pop(); 965 966 if (global.params.useIn == CHECKENABLE.off) 967 freq = null; 968 } 969 if (fens) 970 { 971 /* fensure is composed of the [out] contracts 972 */ 973 if (f.next.ty == Tvoid && funcdecl.fensures) 974 { 975 foreach (e; *funcdecl.fensures) 976 { 977 if (e.id) 978 { 979 funcdecl.error(e.ensure.loc, "`void` functions have no result"); 980 //fens = null; 981 } 982 } 983 } 984 985 sc2 = scout; //push 986 sc2.flags = (sc2.flags & ~SCOPE.contract) | SCOPE.ensure; 987 988 // BUG: need to disallow returns and throws 989 990 if (funcdecl.fensure && f.next.ty != Tvoid) 991 funcdecl.buildResultVar(scout, f.next); 992 993 fens = fens.statementSemantic(sc2); 994 fens.blockExit(funcdecl, false); 995 996 funcdecl.eh_none = false; 997 998 sc2 = sc2.pop(); 999 1000 if (global.params.useOut == CHECKENABLE.off) 1001 fens = null; 1002 } 1003 if (funcdecl.fbody && funcdecl.fbody.isErrorStatement()) 1004 { 1005 } 1006 else 1007 { 1008 auto a = new Statements(); 1009 // Merge in initialization of 'out' parameters 1010 if (funcdecl.parameters) 1011 { 1012 for (size_t i = 0; i < funcdecl.parameters.dim; i++) 1013 { 1014 VarDeclaration v = (*funcdecl.parameters)[i]; 1015 if (v.storage_class & STC.out_) 1016 { 1017 if (!v._init) 1018 { 1019 v.error("Zero-length `out` parameters are not allowed."); 1020 return; 1021 } 1022 ExpInitializer ie = v._init.isExpInitializer(); 1023 assert(ie); 1024 if (auto iec = ie.exp.isConstructExp()) 1025 { 1026 // construction occurred in parameter processing 1027 auto ec = new AssignExp(iec.loc, iec.e1, iec.e2); 1028 ec.type = iec.type; 1029 ie.exp = ec; 1030 } 1031 a.push(new ExpStatement(Loc.initial, ie.exp)); 1032 } 1033 } 1034 } 1035 1036 if (_arguments) 1037 { 1038 /* Advance to elements[] member of TypeInfo_Tuple with: 1039 * _arguments = v_arguments.elements; 1040 */ 1041 Expression e = new VarExp(Loc.initial, funcdecl.v_arguments); 1042 e = new DotIdExp(Loc.initial, e, Id.elements); 1043 e = new ConstructExp(Loc.initial, _arguments, e); 1044 e = e.expressionSemantic(sc2); 1045 1046 _arguments._init = new ExpInitializer(Loc.initial, e); 1047 auto de = new DeclarationExp(Loc.initial, _arguments); 1048 a.push(new ExpStatement(Loc.initial, de)); 1049 } 1050 1051 // Merge contracts together with body into one compound statement 1052 1053 if (freq || fpreinv) 1054 { 1055 if (!freq) 1056 freq = fpreinv; 1057 else if (fpreinv) 1058 freq = new CompoundStatement(Loc.initial, freq, fpreinv); 1059 1060 a.push(freq); 1061 } 1062 1063 if (funcdecl.fbody) 1064 a.push(funcdecl.fbody); 1065 1066 if (fens || fpostinv) 1067 { 1068 if (!fens) 1069 fens = fpostinv; 1070 else if (fpostinv) 1071 fens = new CompoundStatement(Loc.initial, fpostinv, fens); 1072 1073 auto ls = new LabelStatement(Loc.initial, Id.returnLabel, fens); 1074 funcdecl.returnLabel.statement = ls; 1075 a.push(funcdecl.returnLabel.statement); 1076 1077 if (f.next.ty != Tvoid && funcdecl.vresult) 1078 { 1079 // Create: return vresult; 1080 Expression e = new VarExp(Loc.initial, funcdecl.vresult); 1081 if (funcdecl.tintro) 1082 { 1083 e = e.implicitCastTo(sc, funcdecl.tintro.nextOf()); 1084 e = e.expressionSemantic(sc); 1085 } 1086 auto s = new ReturnStatement(Loc.initial, e); 1087 a.push(s); 1088 } 1089 } 1090 if (addReturn0()) 1091 { 1092 // Add a return 0; statement 1093 Statement s = new ReturnStatement(Loc.initial, IntegerExp.literal!0); 1094 a.push(s); 1095 } 1096 1097 Statement sbody = new CompoundStatement(Loc.initial, a); 1098 1099 /* Append destructor calls for parameters as finally blocks. 1100 */ 1101 if (funcdecl.parameters) 1102 { 1103 foreach (v; *funcdecl.parameters) 1104 { 1105 if (v.storage_class & (STC.ref_ | STC.out_ | STC.lazy_)) 1106 continue; 1107 if (v.needsScopeDtor()) 1108 { 1109 // same with ExpStatement.scopeCode() 1110 Statement s = new DtorExpStatement(Loc.initial, v.edtor, v); 1111 v.storage_class |= STC.nodtor; 1112 1113 s = s.statementSemantic(sc2); 1114 1115 bool isnothrow = f.isnothrow & !(funcdecl.flags & FUNCFLAG.nothrowInprocess); 1116 const blockexit = s.blockExit(funcdecl, isnothrow); 1117 if (blockexit & BE.throw_) 1118 funcdecl.eh_none = false; 1119 if (f.isnothrow && isnothrow && blockexit & BE.throw_) 1120 error(funcdecl.loc, "`nothrow` %s `%s` may throw", funcdecl.kind(), funcdecl.toPrettyChars()); 1121 if (funcdecl.flags & FUNCFLAG.nothrowInprocess && blockexit & BE.throw_) 1122 f.isnothrow = false; 1123 1124 if (sbody.blockExit(funcdecl, f.isnothrow) == BE.fallthru) 1125 sbody = new CompoundStatement(Loc.initial, sbody, s); 1126 else 1127 sbody = new TryFinallyStatement(Loc.initial, sbody, s); 1128 } 1129 } 1130 } 1131 // from this point on all possible 'throwers' are checked 1132 funcdecl.flags &= ~FUNCFLAG.nothrowInprocess; 1133 1134 if (funcdecl.isSynchronized()) 1135 { 1136 /* Wrap the entire function body in a synchronized statement 1137 */ 1138 ClassDeclaration cd = funcdecl.toParentDecl().isClassDeclaration(); 1139 if (cd) 1140 { 1141 if (!global.params.is64bit && global.params.isWindows && !funcdecl.isStatic() && !sbody.usesEH() && !global.params.trace) 1142 { 1143 /* The back end uses the "jmonitor" hack for syncing; 1144 * no need to do the sync at this level. 1145 */ 1146 } 1147 else 1148 { 1149 Expression vsync; 1150 if (funcdecl.isStatic()) 1151 { 1152 // The monitor is in the ClassInfo 1153 vsync = new DotIdExp(funcdecl.loc, symbolToExp(cd, funcdecl.loc, sc2, false), Id.classinfo); 1154 } 1155 else 1156 { 1157 // 'this' is the monitor 1158 vsync = new VarExp(funcdecl.loc, funcdecl.vthis); 1159 if (funcdecl.isThis2) 1160 { 1161 vsync = new PtrExp(funcdecl.loc, vsync); 1162 vsync = new IndexExp(funcdecl.loc, vsync, IntegerExp.literal!0); 1163 } 1164 } 1165 sbody = new PeelStatement(sbody); // don't redo semantic() 1166 sbody = new SynchronizedStatement(funcdecl.loc, vsync, sbody); 1167 sbody = sbody.statementSemantic(sc2); 1168 } 1169 } 1170 else 1171 { 1172 funcdecl.error("synchronized function `%s` must be a member of a class", funcdecl.toChars()); 1173 } 1174 } 1175 1176 // If declaration has no body, don't set sbody to prevent incorrect codegen. 1177 if (funcdecl.fbody || funcdecl.allowsContractWithoutBody()) 1178 funcdecl.fbody = sbody; 1179 } 1180 1181 // Check for undefined labels 1182 if (funcdecl.labtab) 1183 foreach (keyValue; funcdecl.labtab.tab.asRange) 1184 { 1185 //printf(" KV: %s = %s\n", keyValue.key.toChars(), keyValue.value.toChars()); 1186 LabelDsymbol label = cast(LabelDsymbol)keyValue.value; 1187 if (!label.statement && (!label.deleted || label.iasm)) 1188 { 1189 funcdecl.error("label `%s` is undefined", label.toChars()); 1190 } 1191 } 1192 1193 // Fix up forward-referenced gotos 1194 if (funcdecl.gotos) 1195 { 1196 for (size_t i = 0; i < funcdecl.gotos.dim; ++i) 1197 { 1198 (*funcdecl.gotos)[i].checkLabel(); 1199 } 1200 } 1201 1202 if (funcdecl.naked && (funcdecl.fensures || funcdecl.frequires)) 1203 funcdecl.error("naked assembly functions with contracts are not supported"); 1204 1205 sc2.ctorflow.callSuper = CSX.none; 1206 sc2.pop(); 1207 } 1208 1209 if (funcdecl.checkClosure()) 1210 { 1211 // We should be setting errors here instead of relying on the global error count. 1212 //errors = true; 1213 } 1214 1215 /* If function survived being marked as impure, then it is pure 1216 */ 1217 if (funcdecl.flags & FUNCFLAG.purityInprocess) 1218 { 1219 funcdecl.flags &= ~FUNCFLAG.purityInprocess; 1220 if (funcdecl.type == f) 1221 f = cast(TypeFunction)f.copy(); 1222 f.purity = PURE.fwdref; 1223 } 1224 1225 if (funcdecl.flags & FUNCFLAG.safetyInprocess) 1226 { 1227 funcdecl.flags &= ~FUNCFLAG.safetyInprocess; 1228 if (funcdecl.type == f) 1229 f = cast(TypeFunction)f.copy(); 1230 f.trust = TRUST.safe; 1231 } 1232 1233 if (funcdecl.flags & FUNCFLAG.nogcInprocess) 1234 { 1235 funcdecl.flags &= ~FUNCFLAG.nogcInprocess; 1236 if (funcdecl.type == f) 1237 f = cast(TypeFunction)f.copy(); 1238 f.isnogc = true; 1239 } 1240 1241 if (funcdecl.flags & FUNCFLAG.returnInprocess) 1242 { 1243 funcdecl.flags &= ~FUNCFLAG.returnInprocess; 1244 if (funcdecl.storage_class & STC.return_) 1245 { 1246 if (funcdecl.type == f) 1247 f = cast(TypeFunction)f.copy(); 1248 f.isreturn = true; 1249 if (funcdecl.storage_class & STC.returninferred) 1250 f.isreturninferred = true; 1251 } 1252 } 1253 1254 funcdecl.flags &= ~FUNCFLAG.inferScope; 1255 1256 // Eliminate maybescope's 1257 { 1258 // Create and fill array[] with maybe candidates from the `this` and the parameters 1259 VarDeclaration[] array = void; 1260 1261 VarDeclaration[10] tmp = void; 1262 size_t dim = (funcdecl.vthis !is null) + (funcdecl.parameters ? funcdecl.parameters.dim : 0); 1263 if (dim <= tmp.length) 1264 array = tmp[0 .. dim]; 1265 else 1266 { 1267 auto ptr = cast(VarDeclaration*)mem.xmalloc(dim * VarDeclaration.sizeof); 1268 array = ptr[0 .. dim]; 1269 } 1270 size_t n = 0; 1271 if (funcdecl.vthis) 1272 array[n++] = funcdecl.vthis; 1273 if (funcdecl.parameters) 1274 { 1275 foreach (v; *funcdecl.parameters) 1276 { 1277 array[n++] = v; 1278 } 1279 } 1280 1281 eliminateMaybeScopes(array[0 .. n]); 1282 1283 if (dim > tmp.length) 1284 mem.xfree(array.ptr); 1285 } 1286 1287 // Infer STC.scope_ 1288 if (funcdecl.parameters && !funcdecl.errors) 1289 { 1290 size_t nfparams = f.parameterList.length; 1291 assert(nfparams == funcdecl.parameters.dim); 1292 foreach (u, v; *funcdecl.parameters) 1293 { 1294 if (v.storage_class & STC.maybescope) 1295 { 1296 //printf("Inferring scope for %s\n", v.toChars()); 1297 Parameter p = f.parameterList[u]; 1298 notMaybeScope(v); 1299 v.storage_class |= STC.scope_ | STC.scopeinferred; 1300 p.storageClass |= STC.scope_ | STC.scopeinferred; 1301 assert(!(p.storageClass & STC.maybescope)); 1302 } 1303 } 1304 } 1305 1306 if (funcdecl.vthis && funcdecl.vthis.storage_class & STC.maybescope) 1307 { 1308 notMaybeScope(funcdecl.vthis); 1309 funcdecl.vthis.storage_class |= STC.scope_ | STC.scopeinferred; 1310 f.isscope = true; 1311 f.isscopeinferred = true; 1312 } 1313 1314 // reset deco to apply inference result to mangled name 1315 if (f != funcdecl.type) 1316 f.deco = null; 1317 1318 // Do semantic type AFTER pure/nothrow inference. 1319 if (!f.deco && funcdecl.ident != Id.xopEquals && funcdecl.ident != Id.xopCmp) 1320 { 1321 sc = sc.push(); 1322 if (funcdecl.isCtorDeclaration()) // https://issues.dlang.org/show_bug.cgi?id=#15665 1323 sc.flags |= SCOPE.ctor; 1324 sc.stc = 0; 1325 sc.linkage = funcdecl.linkage; // https://issues.dlang.org/show_bug.cgi?id=8496 1326 funcdecl.type = f.typeSemantic(funcdecl.loc, sc); 1327 sc = sc.pop(); 1328 } 1329 1330 // Do live analysis 1331 if (global.params.useDIP1021 && funcdecl.fbody && funcdecl.type.ty != Terror && 1332 funcdecl.type.isTypeFunction().islive) 1333 { 1334 oblive(funcdecl); 1335 } 1336 1337 /* If this function had instantiated with gagging, error reproduction will be 1338 * done by TemplateInstance::semantic. 1339 * Otherwise, error gagging should be temporarily ungagged by functionSemantic3. 1340 */ 1341 funcdecl.semanticRun = PASS.semantic3done; 1342 funcdecl.semantic3Errors = (global.errors != oldErrors) || (funcdecl.fbody && funcdecl.fbody.isErrorStatement()); 1343 if (funcdecl.type.ty == Terror) 1344 funcdecl.errors = true; 1345 //printf("-FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent.toChars(), toChars(), sc, loc.toChars()); 1346 //fflush(stdout); 1347 } 1348 1349 override void visit(CtorDeclaration ctor) 1350 { 1351 //printf("CtorDeclaration()\n%s\n", ctor.fbody.toChars()); 1352 if (ctor.semanticRun >= PASS.semantic3) 1353 return; 1354 1355 /* If any of the fields of the aggregate have a destructor, add 1356 * scope (failure) { this.fieldDtor(); } 1357 * as the first statement. It is not necessary to add it after 1358 * each initialization of a field, because destruction of .init constructed 1359 * structs should be benign. 1360 * https://issues.dlang.org/show_bug.cgi?id=14246 1361 */ 1362 AggregateDeclaration ad = ctor.isMemberDecl(); 1363 if (ad && ad.fieldDtor && global.params.dtorFields) 1364 { 1365 /* Generate: 1366 * this.fieldDtor() 1367 */ 1368 Expression e = new ThisExp(ctor.loc); 1369 e.type = ad.type.mutableOf(); 1370 e = new DotVarExp(ctor.loc, e, ad.fieldDtor, false); 1371 e = new CallExp(ctor.loc, e); 1372 auto sexp = new ExpStatement(ctor.loc, e); 1373 auto ss = new ScopeStatement(ctor.loc, sexp, ctor.loc); 1374 1375 version (all) 1376 { 1377 /* Generate: 1378 * try { ctor.fbody; } 1379 * catch (Exception __o) 1380 * { this.fieldDtor(); throw __o; } 1381 * This differs from the alternate scope(failure) version in that an Exception 1382 * is caught rather than a Throwable. This enables the optimization whereby 1383 * the try-catch can be removed if ctor.fbody is nothrow. (nothrow only 1384 * applies to Exception.) 1385 */ 1386 Identifier id = Identifier.generateId("__o"); 1387 auto ts = new ThrowStatement(ctor.loc, new IdentifierExp(ctor.loc, id)); 1388 auto handler = new CompoundStatement(ctor.loc, ss, ts); 1389 1390 auto catches = new Catches(); 1391 auto ctch = new Catch(ctor.loc, getException(), id, handler); 1392 catches.push(ctch); 1393 1394 ctor.fbody = new TryCatchStatement(ctor.loc, ctor.fbody, catches); 1395 } 1396 else 1397 { 1398 /* Generate: 1399 * scope (failure) { this.fieldDtor(); } 1400 * Hopefully we can use this version someday when scope(failure) catches 1401 * Exception instead of Throwable. 1402 */ 1403 auto s = new ScopeGuardStatement(ctor.loc, TOK.onScopeFailure, ss); 1404 ctor.fbody = new CompoundStatement(ctor.loc, s, ctor.fbody); 1405 } 1406 } 1407 visit(cast(FuncDeclaration)ctor); 1408 } 1409 1410 1411 override void visit(Nspace ns) 1412 { 1413 if (ns.semanticRun >= PASS.semantic3) 1414 return; 1415 ns.semanticRun = PASS.semantic3; 1416 static if (LOG) 1417 { 1418 printf("Nspace::semantic3('%s')\n", ns.toChars()); 1419 } 1420 if (ns.members) 1421 { 1422 sc = sc.push(ns); 1423 sc.linkage = LINK.cpp; 1424 foreach (s; *ns.members) 1425 { 1426 s.semantic3(sc); 1427 } 1428 sc.pop(); 1429 } 1430 } 1431 1432 override void visit(AttribDeclaration ad) 1433 { 1434 Dsymbols* d = ad.include(sc); 1435 if (d) 1436 { 1437 Scope* sc2 = ad.newScope(sc); 1438 for (size_t i = 0; i < d.dim; i++) 1439 { 1440 Dsymbol s = (*d)[i]; 1441 s.semantic3(sc2); 1442 } 1443 if (sc2 != sc) 1444 sc2.pop(); 1445 } 1446 } 1447 1448 override void visit(AggregateDeclaration ad) 1449 { 1450 //printf("AggregateDeclaration::semantic3(sc=%p, %s) type = %s, errors = %d\n", sc, toChars(), type.toChars(), errors); 1451 if (!ad.members) 1452 return; 1453 1454 StructDeclaration sd = ad.isStructDeclaration(); 1455 if (!sc) // from runDeferredSemantic3 for TypeInfo generation 1456 { 1457 assert(sd); 1458 sd.semanticTypeInfoMembers(); 1459 return; 1460 } 1461 1462 auto sc2 = ad.newScope(sc); 1463 1464 for (size_t i = 0; i < ad.members.dim; i++) 1465 { 1466 Dsymbol s = (*ad.members)[i]; 1467 s.semantic3(sc2); 1468 } 1469 1470 sc2.pop(); 1471 1472 // don't do it for unused deprecated types 1473 // or error ypes 1474 if (!ad.getRTInfo && Type.rtinfo && (!ad.isDeprecated() || global.params.useDeprecated != DiagnosticReporting.error) && (ad.type && ad.type.ty != Terror)) 1475 { 1476 // Evaluate: RTinfo!type 1477 auto tiargs = new Objects(); 1478 tiargs.push(ad.type); 1479 auto ti = new TemplateInstance(ad.loc, Type.rtinfo, tiargs); 1480 1481 Scope* sc3 = ti.tempdecl._scope.startCTFE(); 1482 sc3.tinst = sc.tinst; 1483 sc3.minst = sc.minst; 1484 if (ad.isDeprecated()) 1485 sc3.stc |= STC.deprecated_; 1486 1487 ti.dsymbolSemantic(sc3); 1488 ti.semantic2(sc3); 1489 ti.semantic3(sc3); 1490 auto e = symbolToExp(ti.toAlias(), Loc.initial, sc3, false); 1491 1492 sc3.endCTFE(); 1493 1494 e = e.ctfeInterpret(); 1495 ad.getRTInfo = e; 1496 } 1497 if (sd) 1498 sd.semanticTypeInfoMembers(); 1499 ad.semanticRun = PASS.semantic3done; 1500 } 1501 } 1502 1503 private struct FuncDeclSem3 1504 { 1505 // The FuncDeclaration subject to Semantic analysis 1506 FuncDeclaration funcdecl; 1507 1508 // Scope of analysis 1509 Scope* sc; 1510 this(FuncDeclaration fd,Scope* s) 1511 { 1512 funcdecl = fd; 1513 sc = s; 1514 } 1515 1516 /* Checks that the overriden functions (if any) have in contracts if 1517 * funcdecl has an in contract. 1518 */ 1519 void checkInContractOverrides() 1520 { 1521 if (funcdecl.frequires) 1522 { 1523 for (size_t i = 0; i < funcdecl.foverrides.dim; i++) 1524 { 1525 FuncDeclaration fdv = funcdecl.foverrides[i]; 1526 if (fdv.fbody && !fdv.frequires) 1527 { 1528 funcdecl.error("cannot have an in contract when overridden function `%s` does not have an in contract", fdv.toPrettyChars()); 1529 break; 1530 } 1531 } 1532 } 1533 } 1534 }