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