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