d: Merge dmd. druntime e770945277, phobos 6d6e0b9b9
[official-gcc.git] / gcc / d / dmd / semantic3.d
blob125a39d179fc45a193a8ff3fa7716234170dd024
1 /**
2 * Performs the semantic3 stage, which deals with function bodies.
4 * Copyright: Copyright (C) 1999-2024 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
12 module dmd.semantic3;
14 import core.stdc.stdio;
15 import core.stdc.string;
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.funcsem;
45 import dmd.globals;
46 import dmd.id;
47 import dmd.identifier;
48 import dmd.init;
49 import dmd.initsem;
50 import dmd.hdrgen;
51 import dmd.location;
52 import dmd.mtype;
53 import dmd.nogc;
54 import dmd.nspace;
55 import dmd.ob;
56 import dmd.objc;
57 import dmd.opover;
58 import dmd.optimize;
59 import dmd.parse;
60 import dmd.root.filename;
61 import dmd.common.outbuffer;
62 import dmd.root.rmem;
63 import dmd.rootobject;
64 import dmd.root.utf;
65 import dmd.sideeffect;
66 import dmd.statementsem;
67 import dmd.staticassert;
68 import dmd.tokens;
69 import dmd.semantic2;
70 import dmd.statement;
71 import dmd.target;
72 import dmd.templateparamsem;
73 import dmd.typesem;
74 import dmd.visitor;
76 enum LOG = false;
79 /*************************************
80 * Does semantic analysis on function bodies.
82 extern(C++) void semantic3(Dsymbol dsym, Scope* sc)
84 scope v = new Semantic3Visitor(sc);
85 dsym.accept(v);
88 private extern(C++) final class Semantic3Visitor : Visitor
90 alias visit = Visitor.visit;
92 Scope* sc;
93 this(Scope* sc) scope @safe
95 this.sc = sc;
98 override void visit(Dsymbol) {}
100 override void visit(TemplateInstance tempinst)
102 static if (LOG)
104 printf("TemplateInstance.semantic3('%s'), semanticRun = %d\n", tempinst.toChars(), tempinst.semanticRun);
106 //if (toChars()[0] == 'D') *(char*)0=0;
107 if (tempinst.semanticRun >= PASS.semantic3)
108 return;
109 tempinst.semanticRun = PASS.semantic3;
110 if (tempinst.errors || !tempinst.members)
111 return;
113 TemplateDeclaration tempdecl = tempinst.tempdecl.isTemplateDeclaration();
114 assert(tempdecl);
116 sc = tempdecl._scope;
117 sc = sc.push(tempinst.argsym);
118 sc = sc.push(tempinst);
119 sc.tinst = tempinst;
120 sc.minst = tempinst.minst;
122 int needGagging = (tempinst.gagged && !global.gag);
123 uint olderrors = global.errors;
124 int oldGaggedErrors = -1; // dead-store to prevent spurious warning
125 /* If this is a gagged instantiation, gag errors.
126 * Future optimisation: If the results are actually needed, errors
127 * would already be gagged, so we don't really need to run semantic
128 * on the members.
130 if (needGagging)
131 oldGaggedErrors = global.startGagging();
133 for (size_t i = 0; i < tempinst.members.length; i++)
135 Dsymbol s = (*tempinst.members)[i];
136 s.semantic3(sc);
137 if (tempinst.gagged && global.errors != olderrors)
138 break;
141 if (global.errors != olderrors)
143 if (!tempinst.errors)
145 if (!tempdecl.literal)
146 .error(tempinst.loc, "%s `%s` error instantiating", tempinst.kind, tempinst.toPrettyChars);
147 if (tempinst.tinst)
148 tempinst.tinst.printInstantiationTrace();
150 tempinst.errors = true;
152 if (needGagging)
153 global.endGagging(oldGaggedErrors);
155 sc = sc.pop();
156 sc.pop();
159 override void visit(TemplateMixin tmix)
161 if (tmix.semanticRun >= PASS.semantic3)
162 return;
163 tmix.semanticRun = PASS.semantic3;
164 static if (LOG)
166 printf("TemplateMixin.semantic3('%s')\n", tmix.toChars());
168 if (!tmix.members)
169 return;
171 sc = sc.push(tmix.argsym);
172 sc = sc.push(tmix);
174 uint olderrors = global.errors;
176 for (size_t i = 0; i < tmix.members.length; i++)
178 Dsymbol s = (*tmix.members)[i];
179 s.semantic3(sc);
182 if (global.errors != olderrors)
183 errorSupplemental(tmix.loc, "parent scope from here: `mixin %s`", tmix.toChars());
185 sc = sc.pop();
186 sc.pop();
189 override void visit(Module mod)
191 //printf("Module::semantic3('%s'): parent = %p\n", toChars(), parent);
192 if (mod.semanticRun != PASS.semantic2done)
193 return;
194 mod.semanticRun = PASS.semantic3;
195 // Note that modules get their own scope, from scratch.
196 // This is so regardless of where in the syntax a module
197 // gets imported, it is unaffected by context.
198 Scope* sc = Scope.createGlobal(mod, global.errorSink); // create root scope
199 //printf("Module = %p\n", sc.scopesym);
200 if (mod.members)
202 // Pass 3 semantic routines: do initializers and function bodies
203 for (size_t i = 0; i < mod.members.length; i++)
205 Dsymbol s = (*mod.members)[i];
206 //printf("Module %s: %s.semantic3()\n", toChars(), s.toChars());
207 s.semantic3(sc);
209 mod.runDeferredSemantic2();
212 if (mod.userAttribDecl)
214 mod.userAttribDecl.semantic3(sc);
216 sc = sc.pop();
217 sc.pop();
218 mod.semanticRun = PASS.semantic3done;
221 override void visit(FuncDeclaration funcdecl)
223 //printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", funcdecl.kind(), funcdecl.toChars(), sc);
224 /* Determine if function should add `return 0;`
226 bool addReturn0()
228 //printf("addReturn0()\n");
229 auto f = funcdecl.type.isTypeFunction();
231 // C11 5.1.2.2.3
232 if (sc.flags & SCOPE.Cfile && funcdecl.isCMain() && f.next.ty == Tint32)
233 return true;
235 return f.next.ty == Tvoid && (funcdecl.isMain() || funcdecl.isCMain());
238 VarDeclaration _arguments = null;
240 if (!funcdecl.parent)
242 if (global.errors)
243 return;
244 //printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc);
245 assert(0);
247 if (funcdecl.errors || isError(funcdecl.parent))
249 funcdecl.errors = true;
251 // Mark that the return type could not be inferred
252 if (funcdecl.inferRetType)
254 assert(funcdecl.type);
255 auto tf = funcdecl.type.isTypeFunction();
257 // Only change the return type s.t. other analysis is
258 // still possible e.g. missmatched parameter types
259 if (tf && !tf.next)
260 tf.next = Type.terror;
262 return;
264 //printf("FuncDeclaration::semantic3('%s.%s', %p, sc = %p, loc = %s)\n", funcdecl.parent.toChars(), funcdecl.toChars(), funcdecl, sc, funcdecl.loc.toChars());
265 //fflush(stdout);
266 //printf("storage class = x%x %x\n", sc.stc, storage_class);
267 //{ static int x; if (++x == 2) *(char*)0=0; }
268 //printf("\tlinkage = %d\n", sc.linkage);
270 if (funcdecl.ident == Id.assign && !funcdecl.inuse)
272 if (funcdecl.storage_class & STC.inference)
274 /* https://issues.dlang.org/show_bug.cgi?id=15044
275 * For generated opAssign function, any errors
276 * from its body need to be gagged.
278 uint oldErrors = global.startGagging();
279 ++funcdecl.inuse;
280 funcdecl.semantic3(sc);
281 --funcdecl.inuse;
282 if (global.endGagging(oldErrors)) // if errors happened
284 // Disable generated opAssign, because some members forbid identity assignment.
285 funcdecl.storage_class |= STC.disable;
286 funcdecl.fbody = null; // remove fbody which contains the error
287 funcdecl.hasSemantic3Errors = false;
289 return;
293 //printf(" sc.incontract = %d\n", (sc.flags & SCOPE.contract));
294 if (funcdecl.semanticRun >= PASS.semantic3)
295 return;
296 funcdecl.semanticRun = PASS.semantic3;
297 funcdecl.hasSemantic3Errors = false;
299 if (!funcdecl.type || funcdecl.type.ty != Tfunction)
300 return;
301 TypeFunction f = cast(TypeFunction)funcdecl.type;
302 if (!funcdecl.inferRetType && f.next.ty == Terror)
303 return;
305 if (!funcdecl.fbody && funcdecl.inferRetType && !f.next)
307 .error(funcdecl.loc, "%s `%s` has no function body with return type inference", funcdecl.kind, funcdecl.toPrettyChars);
308 return;
311 uint oldErrors = global.errors;
312 auto fds = FuncDeclSem3(funcdecl,sc);
314 fds.checkInContractOverrides();
316 // Remember whether we need to generate an 'out' contract.
317 immutable bool needEnsure = FuncDeclaration.needsFensure(funcdecl);
319 if (funcdecl.fbody || funcdecl.frequires || needEnsure)
321 /* Symbol table into which we place parameters and nested functions,
322 * solely to diagnose name collisions.
324 funcdecl.localsymtab = new DsymbolTable();
326 // Establish function scope
327 auto ss = new ScopeDsymbol(funcdecl.loc, null);
328 // find enclosing scope symbol, might skip symbol-less CTFE and/or FuncExp scopes
329 ss.parent = sc.inner().scopesym;
330 ss.endlinnum = funcdecl.endloc.linnum;
331 Scope* sc2 = sc.push(ss);
332 sc2.func = funcdecl;
333 sc2.parent = funcdecl;
334 sc2.ctorflow.callSuper = CSX.none;
335 sc2.sbreak = null;
336 sc2.scontinue = null;
337 sc2.sw = null;
338 sc2.fes = funcdecl.fes;
339 sc2.linkage = funcdecl.isCsymbol() ? LINK.c : LINK.d;
340 sc2.stc &= STC.flowThruFunction;
341 sc2.visibility = Visibility(Visibility.Kind.public_);
342 sc2.explicitVisibility = 0;
343 sc2.aligndecl = null;
344 if (funcdecl.ident != Id.require && funcdecl.ident != Id.ensure)
345 sc2.flags = sc.flags & ~SCOPE.contract;
346 sc2.tf = null;
347 sc2.os = null;
348 sc2.inLoop = false;
349 sc2.inDefaultArg = false;
350 sc2.userAttribDecl = null;
351 if (sc2.intypeof == 1)
352 sc2.intypeof = 2;
353 sc2.ctorflow.fieldinit = null;
355 /* Note: When a lambda is defined immediately under aggregate member
356 * scope, it should be contextless due to prevent interior pointers.
357 * e.g.
358 * // dg points 'this' - its interior pointer
359 * class C { int x; void delegate() dg = (){ this.x = 1; }; }
361 * However, lambdas could be used inside typeof, in order to check
362 * some expressions validity at compile time. For such case the lambda
363 * body can access aggregate instance members.
364 * e.g.
365 * class C { int x; static assert(is(typeof({ this.x = 1; }))); }
367 * To properly accept it, mark these lambdas as member functions.
369 if (auto fld = funcdecl.isFuncLiteralDeclaration())
371 if (auto ad = funcdecl.isMember2())
373 if (!sc.intypeof)
375 if (fld.tok == TOK.delegate_)
376 .error(funcdecl.loc, "%s `%s` cannot be %s members", funcdecl.kind, funcdecl.toPrettyChars, ad.kind());
377 else
378 fld.tok = TOK.function_;
380 else
382 if (fld.tok != TOK.function_)
383 fld.tok = TOK.delegate_;
388 declareThis(funcdecl, sc2);
390 // Reverts: https://issues.dlang.org/show_bug.cgi?id=5710
391 // No compiler supports this, and there was never any spec for it.
392 // @@@DEPRECATED_2.116@@@
393 // Deprecated in 2.096, can be made an error in 2.116.
394 // The deprecation period is longer than usual as dual-context
395 // functions may be widely used by dmd-compiled projects.
396 // It also gives more time for the implementation of dual-context
397 // functions to be reworked as a frontend-only feature.
398 if (funcdecl.hasDualContext())
400 .deprecation(funcdecl.loc, "%s `%s` function requires a dual-context, which is deprecated", funcdecl.kind, funcdecl.toPrettyChars);
401 if (auto ti = sc2.parent ? sc2.parent.isInstantiated() : null)
402 ti.printInstantiationTrace(Classification.deprecation);
405 //printf("[%s] ad = %p vthis = %p\n", loc.toChars(), ad, vthis);
406 //if (vthis) printf("\tvthis.type = %s\n", vthis.type.toChars());
408 // Declare hidden variable _arguments[] and _argptr
409 if (f.parameterList.varargs == VarArg.variadic)
411 if (f.linkage == LINK.d)
413 // Variadic arguments depend on Typeinfo being defined.
414 if (!global.params.useTypeInfo || !Type.dtypeinfo || !Type.typeinfotypelist)
416 if (!global.params.useTypeInfo)
418 version (IN_GCC)
419 .error(funcdecl.loc, "%s `%s` D-style variadic functions cannot be used with `-fno-rtti`", funcdecl.kind, funcdecl.toPrettyChars);
420 else
421 .error(funcdecl.loc, "%s `%s` D-style variadic functions cannot be used with -betterC", funcdecl.kind, funcdecl.toPrettyChars);
423 else if (!Type.typeinfotypelist)
424 .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);
425 else
426 .error(funcdecl.loc, "%s `%s` `object.TypeInfo` could not be found, but is implicitly used in D-style variadic functions", funcdecl.kind, funcdecl.toPrettyChars);
427 fatal();
430 // Declare _arguments[]
431 funcdecl.v_arguments = new VarDeclaration(funcdecl.loc, Type.typeinfotypelist.type, Id._arguments_typeinfo, null);
432 funcdecl.v_arguments.storage_class |= STC.temp | STC.parameter;
433 funcdecl.v_arguments.dsymbolSemantic(sc2);
434 sc2.insert(funcdecl.v_arguments);
435 funcdecl.v_arguments.parent = funcdecl;
437 //Type t = Type.dtypeinfo.type.constOf().arrayOf();
438 Type t = Type.dtypeinfo.type.arrayOf();
439 _arguments = new VarDeclaration(funcdecl.loc, t, Id._arguments, null);
440 _arguments.storage_class |= STC.temp;
441 _arguments.dsymbolSemantic(sc2);
442 sc2.insert(_arguments);
443 _arguments.parent = funcdecl;
445 if (f.linkage == LINK.d || f.parameterList.length)
447 // Declare _argptr
448 Type t = target.va_listType(funcdecl.loc, sc);
449 // Init is handled in FuncDeclaration_toObjFile
450 funcdecl.v_argptr = new VarDeclaration(funcdecl.loc, t, Id._argptr, new VoidInitializer(funcdecl.loc));
451 funcdecl.v_argptr.storage_class |= STC.temp;
452 funcdecl.v_argptr.dsymbolSemantic(sc2);
453 sc2.insert(funcdecl.v_argptr);
454 funcdecl.v_argptr.parent = funcdecl;
458 /* Declare all the function parameters as variables
459 * and install them in parameters[]
461 if (const nparams = f.parameterList.length)
463 /* parameters[] has all the tuples removed, as the back end
464 * doesn't know about tuples
466 funcdecl.parameters = new VarDeclarations();
467 funcdecl.parameters.reserve(nparams);
468 foreach (i, fparam; f.parameterList)
470 Identifier id = fparam.ident;
471 StorageClass stc = 0;
472 if (!id)
474 /* Generate identifier for un-named parameter,
475 * because we need it later on.
477 fparam.ident = id = Identifier.generateId("__param_", i);
478 stc |= STC.temp;
480 Type vtype = fparam.type;
481 auto v = new VarDeclaration(fparam.loc, vtype, id, null);
482 //printf("declaring parameter %s of type %s\n", v.toChars(), v.type.toChars());
483 stc |= STC.parameter;
484 if (f.parameterList.varargs == VarArg.typesafe && i + 1 == nparams)
486 stc |= STC.variadic;
489 stc |= fparam.storageClass & (STC.IOR | STC.return_ | STC.scope_ | STC.lazy_ | STC.final_ | STC.TYPECTOR | STC.nodtor | STC.returnScope | STC.register);
490 v.storage_class = stc;
491 v.dsymbolSemantic(sc2);
492 if (!sc2.insert(v))
494 .error(funcdecl.loc, "%s `%s` parameter `%s.%s` is already defined", funcdecl.kind, funcdecl.toPrettyChars, funcdecl.toChars(), v.toChars());
495 funcdecl.errors = true;
497 else
498 funcdecl.parameters.push(v);
499 funcdecl.localsymtab.insert(v);
500 v.parent = funcdecl;
501 if (fparam.userAttribDecl)
502 v.userAttribDecl = fparam.userAttribDecl;
506 // Declare the tuple symbols and put them in the symbol table,
507 // but not in parameters[].
508 if (f.parameterList.parameters)
509 foreach (fparam; *f.parameterList.parameters)
511 if (!fparam.ident)
512 continue; // never used, so ignore
513 // expand any tuples
514 if (fparam.type.ty != Ttuple)
515 continue;
517 TypeTuple t = cast(TypeTuple)fparam.type;
518 size_t dim = Parameter.dim(t.arguments);
519 auto exps = new Objects(dim);
520 foreach (j; 0 .. dim)
522 Parameter narg = Parameter.getNth(t.arguments, j);
523 assert(narg.ident);
524 Dsymbol pscopesym;
525 VarDeclaration v = sc2.search(Loc.initial, narg.ident, pscopesym).isVarDeclaration();
526 assert(v);
527 (*exps)[j] = new VarExp(v.loc, v);
529 assert(fparam.ident);
530 auto v = new TupleDeclaration(funcdecl.loc, fparam.ident, exps);
531 //printf("declaring tuple %s\n", v.toChars());
532 v.isexp = true;
533 if (!sc2.insert(v))
534 .error(funcdecl.loc, "%s `%s` parameter `%s.%s` is already defined", funcdecl.kind, funcdecl.toPrettyChars, funcdecl.toChars(), v.toChars());
535 funcdecl.localsymtab.insert(v);
536 v.parent = funcdecl;
539 // Precondition invariant
540 Statement fpreinv = null;
541 if (funcdecl.addPreInvariant())
543 Expression e = addInvariant(funcdecl.isThis(), funcdecl.vthis);
544 if (e)
545 fpreinv = new ExpStatement(Loc.initial, e);
548 // Postcondition invariant
549 Statement fpostinv = null;
550 if (funcdecl.addPostInvariant())
552 Expression e = addInvariant(funcdecl.isThis(), funcdecl.vthis);
553 if (e)
554 fpostinv = new ExpStatement(Loc.initial, e);
557 // Pre/Postcondition contract
558 if (!funcdecl.fbody)
559 funcdecl.buildEnsureRequire();
561 Scope* scout = null;
562 if (needEnsure || funcdecl.addPostInvariant())
564 /* https://issues.dlang.org/show_bug.cgi?id=3657
565 * Set the correct end line number for fensure scope.
567 uint fensure_endlin = funcdecl.endloc.linnum;
568 if (funcdecl.fensure)
569 if (auto s = funcdecl.fensure.isScopeStatement())
570 fensure_endlin = s.endloc.linnum;
572 if ((needEnsure && global.params.useOut == CHECKENABLE.on) || fpostinv)
574 funcdecl.returnLabel = funcdecl.searchLabel(Id.returnLabel, Loc.initial);
577 // scope of out contract (need for vresult.semantic)
578 auto sym = new ScopeDsymbol(funcdecl.loc, null);
579 sym.parent = sc2.scopesym;
580 sym.endlinnum = fensure_endlin;
581 scout = sc2.push(sym);
584 if (funcdecl.fbody)
586 auto sym = new ScopeDsymbol(funcdecl.loc, null);
587 sym.parent = sc2.scopesym;
588 sym.endlinnum = funcdecl.endloc.linnum;
589 sc2 = sc2.push(sym);
591 auto ad2 = funcdecl.isMemberLocal();
593 /* If this is a class constructor
595 if (ad2 && funcdecl.isCtorDeclaration())
597 sc2.ctorflow.allocFieldinit(ad2.fields.length);
598 foreach (v; ad2.fields)
600 v.ctorinit = 0;
604 bool inferRef = (f.isref && (funcdecl.storage_class & STC.auto_));
606 funcdecl.fbody = funcdecl.fbody.statementSemantic(sc2);
607 if (!funcdecl.fbody)
608 funcdecl.fbody = new CompoundStatement(Loc.initial, new Statements());
610 if (funcdecl.isNaked())
612 fpreinv = null; // can't accommodate with no stack frame
613 fpostinv = null;
616 assert(funcdecl.type == f || (funcdecl.type.ty == Tfunction && f.purity == PURE.impure && (cast(TypeFunction)funcdecl.type).purity >= PURE.fwdref));
617 f = cast(TypeFunction)funcdecl.type;
619 if (funcdecl.inferRetType)
621 // If no return type inferred yet, then infer a void
622 if (!f.next)
623 f.next = Type.tvoid;
624 if (f.checkRetType(funcdecl.loc))
625 funcdecl.fbody = new ErrorStatement();
626 else
627 funcdecl.checkMain(); // Check main() parameters and return type
630 if (f.next !is null)
631 f.next.checkComplexTransition(funcdecl.loc, sc);
633 if (funcdecl.returns && !funcdecl.fbody.isErrorStatement())
635 for (size_t i = 0; i < funcdecl.returns.length;)
637 Expression exp = (*funcdecl.returns)[i].exp;
638 if (exp.op == EXP.variable && (cast(VarExp)exp).var == funcdecl.vresult)
640 if (addReturn0())
641 exp.type = Type.tint32;
642 else
643 exp.type = f.next;
644 // Remove `return vresult;` from returns
645 funcdecl.returns.remove(i);
646 continue;
648 if (inferRef && f.isref && !exp.type.constConv(f.next)) // https://issues.dlang.org/show_bug.cgi?id=13336
649 f.isref = false;
650 i++;
653 if (f.isref) // Function returns a reference
655 if (funcdecl.storage_class & STC.auto_)
656 funcdecl.storage_class &= ~STC.auto_;
659 // handle NRVO
660 if (!target.isReturnOnStack(f, funcdecl.needThis()) || !funcdecl.checkNRVO())
661 funcdecl.isNRVO = false;
663 if (funcdecl.fbody.isErrorStatement())
666 else if (funcdecl.isStaticCtorDeclaration())
668 /* It's a static constructor. Ensure that all
669 * ctor consts were initialized.
671 ScopeDsymbol pd = funcdecl.toParent().isScopeDsymbol();
672 for (size_t i = 0; i < pd.members.length; i++)
674 Dsymbol s = (*pd.members)[i];
675 s.checkCtorConstInit();
678 else if (ad2 && funcdecl.isCtorDeclaration())
680 ClassDeclaration cd = ad2.isClassDeclaration();
682 // Verify that all the ctorinit fields got initialized
683 if (!(sc2.ctorflow.callSuper & CSX.this_ctor))
685 foreach (i, v; ad2.fields)
687 if (v.isThisDeclaration())
688 continue;
689 if (v.ctorinit == 0)
691 /* Current bugs in the flow analysis:
692 * 1. union members should not produce error messages even if
693 * not assigned to
694 * 2. structs should recognize delegating opAssign calls as well
695 * as delegating calls to other constructors
697 if (v.isCtorinit() && !v.type.isMutable() && cd)
698 .error(funcdecl.loc, "%s `%s` missing initializer for %s field `%s`", funcdecl.kind, funcdecl.toPrettyChars, MODtoChars(v.type.mod), v.toChars());
699 else if (v.storage_class & STC.nodefaultctor)
700 error(funcdecl.loc, "field `%s` must be initialized in constructor", v.toChars());
701 else if (v.type.needsNested())
702 error(funcdecl.loc, "field `%s` must be initialized in constructor, because it is nested struct", v.toChars());
704 else
706 bool mustInit = (v.storage_class & STC.nodefaultctor || v.type.needsNested());
707 if (mustInit && !(sc2.ctorflow.fieldinit[i].csx & CSX.this_ctor))
709 .error(funcdecl.loc, "%s `%s` field `%s` must be initialized but skipped", funcdecl.kind, funcdecl.toPrettyChars, v.toChars());
714 sc2.ctorflow.freeFieldinit();
716 if (cd && !(sc2.ctorflow.callSuper & (CSX.any_ctor | CSX.halt)) && cd.baseClass && cd.baseClass.ctor)
718 sc2.ctorflow.callSuper = CSX.none;
720 // Insert implicit super() at start of fbody
721 Type tthis = ad2.type.addMod(funcdecl.vthis.type.mod);
722 FuncDeclaration fd = resolveFuncCall(Loc.initial, sc2, cd.baseClass.ctor, null, tthis, ArgumentList(), FuncResolveFlag.quiet);
723 if (!fd)
725 .error(funcdecl.loc, "%s `%s` no match for implicit `super()` call in constructor", funcdecl.kind, funcdecl.toPrettyChars);
727 else if (fd.storage_class & STC.disable)
729 .error(funcdecl.loc, "%s `%s` cannot call `super()` implicitly because it is annotated with `@disable`", funcdecl.kind, funcdecl.toPrettyChars);
731 else
733 Expression e1 = new SuperExp(Loc.initial);
734 Expression e = new CallExp(Loc.initial, e1);
735 e = e.expressionSemantic(sc2);
736 Statement s = new ExpStatement(Loc.initial, e);
737 funcdecl.fbody = new CompoundStatement(Loc.initial, s, funcdecl.fbody);
740 //printf("ctorflow.callSuper = x%x\n", sc2.ctorflow.callSuper);
743 /* https://issues.dlang.org/show_bug.cgi?id=17502
744 * Wait until after the return type has been inferred before
745 * generating the contracts for this function, and merging contracts
746 * from overrides.
748 * https://issues.dlang.org/show_bug.cgi?id=17893
749 * However should take care to generate this before inferered
750 * function attributes are applied, such as 'nothrow'.
752 * This was originally at the end of the first semantic pass, but
753 * required a fix-up to be done here for the '__result' variable
754 * type of __ensure() inside auto functions, but this didn't work
755 * if the out parameter was implicit.
757 funcdecl.buildEnsureRequire();
759 // Check for errors related to 'nothrow'.
760 const blockexit = funcdecl.fbody.blockExit(funcdecl, f.isnothrow ? global.errorSink : null);
761 if (f.isnothrow && blockexit & BE.throw_)
762 error(funcdecl.loc, "%s `%s` may throw but is marked as `nothrow`", funcdecl.kind(), funcdecl.toPrettyChars());
764 if (!(blockexit & (BE.throw_ | BE.halt) || funcdecl.hasCatches))
766 /* Don't generate unwind tables for this function
767 * https://issues.dlang.org/show_bug.cgi?id=17997
769 funcdecl.hasNoEH = true;
772 if (funcdecl.nothrowInprocess)
774 if (funcdecl.type == f)
775 f = cast(TypeFunction)f.copy();
776 f.isnothrow = !(blockexit & BE.throw_);
779 if (funcdecl.fbody.isErrorStatement())
782 else if (ad2 && funcdecl.isCtorDeclaration())
784 /* Append:
785 * return this;
786 * to function body
788 if (blockexit & BE.fallthru)
790 Statement s = new ReturnStatement(funcdecl.loc, null);
791 s = s.statementSemantic(sc2);
792 funcdecl.fbody = new CompoundStatement(funcdecl.loc, funcdecl.fbody, s);
793 funcdecl.hasReturnExp |= (funcdecl.hasReturnExp & 1 ? 16 : 1);
796 else if (funcdecl.fes)
798 // For foreach(){} body, append a return 0;
799 if (blockexit & BE.fallthru)
801 Expression e = IntegerExp.literal!0;
802 Statement s = new ReturnStatement(Loc.initial, e);
803 funcdecl.fbody = new CompoundStatement(Loc.initial, funcdecl.fbody, s);
804 funcdecl.hasReturnExp |= (funcdecl.hasReturnExp & 1 ? 16 : 1);
806 assert(!funcdecl.returnLabel);
808 else if (f.next.toBasetype().ty == Tnoreturn)
810 // Fallthrough despite being declared as noreturn? return is already rejected when evaluating the ReturnStatement
811 if (blockexit & BE.fallthru)
813 .error(funcdecl.loc, "%s `%s` is typed as `%s` but does return", funcdecl.kind, funcdecl.toPrettyChars, f.next.toChars());
814 funcdecl.loc.errorSupplemental("`noreturn` functions must either throw, abort or loop indefinitely");
817 else
819 const(bool) inlineAsm = (funcdecl.hasReturnExp & 8) != 0;
820 if ((blockexit & BE.fallthru) && f.next.ty != Tvoid && !inlineAsm && !(sc.flags & SCOPE.Cfile))
822 if (!funcdecl.hasReturnExp)
823 .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());
824 else
825 .error(funcdecl.loc, "%s `%s` no `return exp;` or `assert(0);` at end of function", funcdecl.kind, funcdecl.toPrettyChars);
829 if (funcdecl.returns)
831 bool implicit0 = addReturn0();
832 Type tret = implicit0 ? Type.tint32 : f.next;
833 assert(tret.ty != Tvoid);
834 if (funcdecl.vresult || funcdecl.returnLabel)
835 funcdecl.buildResultVar(scout ? scout : sc2, tret);
837 /* Cannot move this loop into NrvoWalker, because
838 * returns[i] may be in the nested delegate for foreach-body.
840 for (size_t i = 0; i < funcdecl.returns.length; i++)
842 ReturnStatement rs = (*funcdecl.returns)[i];
843 Expression exp = rs.exp;
844 if (exp.op == EXP.error)
845 continue;
846 if (tret.ty == Terror)
848 // https://issues.dlang.org/show_bug.cgi?id=13702
849 exp = checkGC(sc2, exp);
850 continue;
853 /* If the expression in the return statement (exp) cannot be implicitly
854 * converted to the return type (tret) of the function and if the
855 * type of the expression is type isolated, then it may be possible
856 * that a promotion to `immutable` or `inout` (through a cast) will
857 * match the return type.
859 if (!exp.implicitConvTo(tret) && funcdecl.isTypeIsolated(exp.type))
861 /* https://issues.dlang.org/show_bug.cgi?id=20073
863 * The problem is that if the type of the returned expression (exp.type)
864 * is an aggregated declaration with an alias this, the alias this may be
865 * used for the conversion testing without it being an isolated type.
867 * To make sure this does not happen, we can test here the implicit conversion
868 * only for the aggregated declaration type by using `implicitConvToWithoutAliasThis`.
869 * The implicit conversion with alias this is taken care of later.
871 AggregateDeclaration aggDecl = isAggregate(exp.type);
872 TypeStruct tstruct;
873 TypeClass tclass;
874 bool hasAliasThis;
875 if (aggDecl && aggDecl.aliasthis)
877 hasAliasThis = true;
878 tclass = exp.type.isTypeClass();
879 if (!tclass)
880 tstruct = exp.type.isTypeStruct();
881 assert(tclass || tstruct);
883 if (hasAliasThis)
885 if (tclass)
887 if ((cast(TypeClass)(exp.type.immutableOf())).implicitConvToWithoutAliasThis(tret))
888 exp = exp.castTo(sc2, exp.type.immutableOf());
889 else if ((cast(TypeClass)(exp.type.wildOf())).implicitConvToWithoutAliasThis(tret))
890 exp = exp.castTo(sc2, exp.type.wildOf());
892 else
894 if ((cast(TypeStruct)exp.type.immutableOf()).implicitConvToWithoutAliasThis(tret))
895 exp = exp.castTo(sc2, exp.type.immutableOf());
896 else if ((cast(TypeStruct)exp.type.immutableOf()).implicitConvToWithoutAliasThis(tret))
897 exp = exp.castTo(sc2, exp.type.wildOf());
900 else
902 if (exp.type.immutableOf().implicitConvTo(tret))
903 exp = exp.castTo(sc2, exp.type.immutableOf());
904 else if (exp.type.wildOf().implicitConvTo(tret))
905 exp = exp.castTo(sc2, exp.type.wildOf());
909 const hasCopyCtor = exp.type.ty == Tstruct && (cast(TypeStruct)exp.type).sym.hasCopyCtor;
910 // if a copy constructor is present, the return type conversion will be handled by it
911 if (!(hasCopyCtor && exp.isLvalue()))
913 if (f.isref && !MODimplicitConv(exp.type.mod, tret.mod) && !tret.isTypeSArray())
914 error(exp.loc, "expression `%s` of type `%s` is not implicitly convertible to return type `ref %s`",
915 exp.toChars(), exp.type.toChars(), tret.toChars());
916 else
917 exp = exp.implicitCastTo(sc2, tret);
920 if (f.isref)
922 // Function returns a reference
923 exp = exp.toLvalue(sc2, "`ref` return");
924 checkReturnEscapeRef(sc2, exp, false);
925 exp = exp.optimize(WANTvalue, /*keepLvalue*/ true);
927 else
929 exp = exp.optimize(WANTvalue);
931 /* https://issues.dlang.org/show_bug.cgi?id=10789
932 * If NRVO is not possible, all returned lvalues should call their postblits.
934 if (!funcdecl.isNRVO())
935 exp = doCopyOrMove(sc2, exp, f.next);
937 if (tret.hasPointers())
938 checkReturnEscape(sc2, exp, false);
941 exp = checkGC(sc2, exp);
943 if (funcdecl.vresult)
945 // Create: return vresult = exp;
946 exp = new BlitExp(rs.loc, funcdecl.vresult, exp);
947 exp.type = funcdecl.vresult.type;
949 if (rs.caseDim)
950 exp = Expression.combine(exp, new IntegerExp(rs.caseDim));
952 else if (funcdecl.tintro && !tret.equals(funcdecl.tintro.nextOf()))
954 exp = exp.implicitCastTo(sc2, funcdecl.tintro.nextOf());
956 rs.exp = exp;
959 if (funcdecl.nrvo_var || funcdecl.returnLabel)
961 scope NrvoWalker nw = new NrvoWalker();
962 nw.fd = funcdecl;
963 nw.sc = sc2;
964 nw.visitStmt(funcdecl.fbody);
967 sc2 = sc2.pop();
970 if (global.params.inclusiveInContracts)
972 funcdecl.frequire = funcdecl.mergeFrequireInclusivePreview(
973 funcdecl.frequire, funcdecl.fdrequireParams);
975 else
977 funcdecl.frequire = funcdecl.mergeFrequire(funcdecl.frequire, funcdecl.fdrequireParams);
979 funcdecl.fensure = funcdecl.mergeFensure(funcdecl.fensure, Id.result, funcdecl.fdensureParams);
981 Statement freq = funcdecl.frequire;
982 Statement fens = funcdecl.fensure;
984 /* Do the semantic analysis on the [in] preconditions and
985 * [out] postconditions.
987 immutable bool isnothrow = f.isnothrow && !funcdecl.nothrowInprocess;
988 if (freq)
990 /* frequire is composed of the [in] contracts
992 auto sym = new ScopeDsymbol(funcdecl.loc, null);
993 sym.parent = sc2.scopesym;
994 sym.endlinnum = funcdecl.endloc.linnum;
995 sc2 = sc2.push(sym);
996 sc2.flags = (sc2.flags & ~SCOPE.contract) | SCOPE.require;
998 // BUG: need to error if accessing out parameters
999 // BUG: need to disallow returns
1000 // BUG: verify that all in and ref parameters are read
1001 freq = freq.statementSemantic(sc2);
1003 // @@@DEPRECATED_2.111@@@ - pass `isnothrow` instead of `false` to print a more detailed error msg`
1004 const blockExit = freq.blockExit(funcdecl, null);
1005 if (blockExit & BE.throw_)
1007 if (isnothrow)
1008 // @@@DEPRECATED_2.111@@@
1009 // Deprecated in 2.101, can be made an error in 2.111
1010 deprecation(funcdecl.loc, "`%s`: `in` contract may throw but function is marked as `nothrow`",
1011 funcdecl.toPrettyChars());
1012 else if (funcdecl.nothrowInprocess)
1013 f.isnothrow = false;
1016 funcdecl.hasNoEH = false;
1018 sc2 = sc2.pop();
1020 if (global.params.useIn == CHECKENABLE.off)
1021 freq = null;
1024 if (fens)
1026 /* fensure is composed of the [out] contracts
1028 if (f.next.ty == Tvoid && funcdecl.fensures)
1030 foreach (e; *funcdecl.fensures)
1032 if (e.id)
1034 .error(e.ensure.loc, "%s `%s` `void` functions have no result", funcdecl.kind, funcdecl.toPrettyChars);
1035 //fens = null;
1040 sc2 = scout; //push
1041 sc2.flags = (sc2.flags & ~SCOPE.contract) | SCOPE.ensure;
1043 // BUG: need to disallow returns and throws
1045 if (funcdecl.fensure && f.next.ty != Tvoid)
1046 funcdecl.buildResultVar(scout, f.next);
1048 fens = fens.statementSemantic(sc2);
1050 // @@@DEPRECATED_2.111@@@ - pass `isnothrow` instead of `false` to print a more detailed error msg`
1051 const blockExit = fens.blockExit(funcdecl, null);
1052 if (blockExit & BE.throw_)
1054 if (isnothrow)
1055 // @@@DEPRECATED_2.111@@@
1056 // Deprecated in 2.101, can be made an error in 2.111
1057 deprecation(funcdecl.loc, "`%s`: `out` contract may throw but function is marked as `nothrow`",
1058 funcdecl.toPrettyChars());
1059 else if (funcdecl.nothrowInprocess)
1060 f.isnothrow = false;
1063 funcdecl.hasNoEH = false;
1065 sc2 = sc2.pop();
1067 if (global.params.useOut == CHECKENABLE.off)
1068 fens = null;
1070 if (funcdecl.fbody && funcdecl.fbody.isErrorStatement())
1073 else
1075 auto a = new Statements();
1076 // Merge in initialization of 'out' parameters
1077 if (funcdecl.parameters)
1079 for (size_t i = 0; i < funcdecl.parameters.length; i++)
1081 VarDeclaration v = (*funcdecl.parameters)[i];
1082 if (v.storage_class & STC.out_)
1084 if (!v._init)
1086 .error(v.loc, "%s `%s` zero-length `out` parameters are not allowed.", v.kind, v.toPrettyChars);
1087 return;
1089 ExpInitializer ie = v._init.isExpInitializer();
1090 assert(ie);
1091 if (auto iec = ie.exp.isConstructExp())
1093 // construction occurred in parameter processing
1094 auto ec = new AssignExp(iec.loc, iec.e1, iec.e2);
1095 ec.type = iec.type;
1096 ie.exp = ec;
1098 a.push(new ExpStatement(Loc.initial, ie.exp));
1103 if (_arguments)
1105 /* Advance to elements[] member of TypeInfo_Tuple with:
1106 * _arguments = v_arguments.elements;
1108 Expression e = new VarExp(Loc.initial, funcdecl.v_arguments);
1109 e = new DotIdExp(Loc.initial, e, Id.elements);
1110 e = new ConstructExp(Loc.initial, _arguments, e);
1111 e = e.expressionSemantic(sc2);
1113 _arguments._init = new ExpInitializer(Loc.initial, e);
1114 auto de = new DeclarationExp(Loc.initial, _arguments);
1115 a.push(new ExpStatement(Loc.initial, de));
1118 // Merge contracts together with body into one compound statement
1120 if (freq || fpreinv)
1122 if (!freq)
1123 freq = fpreinv;
1124 else if (fpreinv)
1125 freq = new CompoundStatement(Loc.initial, freq, fpreinv);
1127 a.push(freq);
1130 if (funcdecl.fbody)
1131 a.push(funcdecl.fbody);
1133 if (fens || fpostinv)
1135 if (!fens)
1136 fens = fpostinv;
1137 else if (fpostinv)
1138 fens = new CompoundStatement(Loc.initial, fpostinv, fens);
1140 auto ls = new LabelStatement(Loc.initial, Id.returnLabel, fens);
1141 funcdecl.returnLabel.statement = ls;
1142 a.push(funcdecl.returnLabel.statement);
1144 if (f.next.ty != Tvoid && funcdecl.vresult)
1146 // Create: return vresult;
1147 Expression e = new VarExp(Loc.initial, funcdecl.vresult);
1148 if (funcdecl.tintro)
1150 e = e.implicitCastTo(sc, funcdecl.tintro.nextOf());
1151 e = e.expressionSemantic(sc);
1153 auto s = new ReturnStatement(Loc.initial, e);
1154 a.push(s);
1157 if (addReturn0())
1159 // Add a return 0; statement
1160 Statement s = new ReturnStatement(Loc.initial, IntegerExp.literal!0);
1161 a.push(s);
1164 Statement sbody = new CompoundStatement(Loc.initial, a);
1166 /* Append destructor calls for parameters as finally blocks.
1168 if (funcdecl.parameters)
1170 // check if callee destroys arguments
1171 const bool paramsNeedDtor = target.isCalleeDestroyingArgs(f);
1173 foreach (v; *funcdecl.parameters)
1175 if (v.isReference() || (v.storage_class & STC.lazy_))
1176 continue;
1177 if (v.needsScopeDtor())
1179 v.storage_class |= STC.nodtor;
1180 if (!paramsNeedDtor)
1181 continue;
1183 // same with ExpStatement.scopeCode()
1184 Statement s = new DtorExpStatement(Loc.initial, v.edtor, v);
1186 s = s.statementSemantic(sc2);
1188 const blockexit = s.blockExit(funcdecl, isnothrow ? global.errorSink : null);
1189 if (blockexit & BE.throw_)
1191 funcdecl.hasNoEH = false;
1192 if (isnothrow)
1193 error(funcdecl.loc, "%s `%s` may throw but is marked as `nothrow`", funcdecl.kind(), funcdecl.toPrettyChars());
1194 else if (funcdecl.nothrowInprocess)
1195 f.isnothrow = false;
1198 if (sbody.blockExit(funcdecl, f.isnothrow ? global.errorSink : null) == BE.fallthru)
1199 sbody = new CompoundStatement(Loc.initial, sbody, s);
1200 else
1201 sbody = new TryFinallyStatement(Loc.initial, sbody, s);
1205 // from this point on all possible 'throwers' are checked
1206 funcdecl.nothrowInprocess = false;
1208 if (funcdecl.isSynchronized())
1210 /* Wrap the entire function body in a synchronized statement
1212 ClassDeclaration cd = funcdecl.toParentDecl().isClassDeclaration();
1213 if (cd)
1215 if (target.libraryObjectMonitors(funcdecl, sbody))
1217 Expression vsync;
1218 if (funcdecl.isStatic())
1220 // The monitor is in the ClassInfo
1221 vsync = new DotIdExp(funcdecl.loc, symbolToExp(cd, funcdecl.loc, sc2, false), Id.classinfo);
1223 else
1225 // 'this' is the monitor
1226 vsync = new VarExp(funcdecl.loc, funcdecl.vthis);
1227 if (funcdecl.hasDualContext())
1229 vsync = new PtrExp(funcdecl.loc, vsync);
1230 vsync = new IndexExp(funcdecl.loc, vsync, IntegerExp.literal!0);
1233 sbody = new PeelStatement(sbody); // don't redo semantic()
1234 sbody = new SynchronizedStatement(funcdecl.loc, vsync, sbody);
1235 sbody = sbody.statementSemantic(sc2);
1238 else
1240 .error(funcdecl.loc, "%s `%s` synchronized function `%s` must be a member of a class", funcdecl.kind, funcdecl.toPrettyChars, funcdecl.toChars());
1244 // If declaration has no body, don't set sbody to prevent incorrect codegen.
1245 if (funcdecl.fbody || funcdecl.allowsContractWithoutBody())
1246 funcdecl.fbody = sbody;
1249 // Check for undefined labels
1250 if (funcdecl.labtab)
1251 foreach (keyValue; funcdecl.labtab.tab.asRange)
1253 //printf(" KV: %s = %s\n", keyValue.key.toChars(), keyValue.value.toChars());
1254 LabelDsymbol label = cast(LabelDsymbol)keyValue.value;
1255 if (!label.statement && (!label.deleted || label.iasm))
1257 .error(label.loc, "%s `%s` label `%s` is undefined", funcdecl.kind, funcdecl.toPrettyChars, label.toChars());
1261 // Fix up forward-referenced gotos
1262 if (funcdecl.gotos && !funcdecl.isCsymbol())
1264 for (size_t i = 0; i < funcdecl.gotos.length; ++i)
1266 (*funcdecl.gotos)[i].checkLabel();
1270 if (funcdecl.isNaked() && (funcdecl.fensures || funcdecl.frequires))
1271 .error(funcdecl.loc, "%s `%s` naked assembly functions with contracts are not supported", funcdecl.kind, funcdecl.toPrettyChars);
1273 sc2.ctorflow.callSuper = CSX.none;
1274 sc2.pop();
1277 if (funcdecl.checkClosure())
1279 // We should be setting errors here instead of relying on the global error count.
1280 //errors = true;
1283 /* If function survived being marked as impure, then it is pure
1285 if (funcdecl.purityInprocess)
1287 funcdecl.purityInprocess = false;
1288 if (funcdecl.type == f)
1289 f = cast(TypeFunction)f.copy();
1290 f.purity = PURE.fwdref;
1293 if (funcdecl.safetyInprocess)
1295 funcdecl.safetyInprocess = false;
1296 if (funcdecl.type == f)
1297 f = cast(TypeFunction)f.copy();
1298 f.trust = TRUST.safe;
1301 if (funcdecl.nogcInprocess)
1303 funcdecl.nogcInprocess = false;
1304 if (funcdecl.type == f)
1305 f = cast(TypeFunction)f.copy();
1306 f.isnogc = true;
1309 finishScopeParamInference(funcdecl, f);
1311 // reset deco to apply inference result to mangled name
1312 if (f != funcdecl.type)
1313 f.deco = null;
1315 // Do semantic type AFTER pure/nothrow inference.
1316 if (!f.deco && funcdecl.ident != Id.xopEquals && funcdecl.ident != Id.xopCmp)
1318 sc = sc.push();
1319 if (funcdecl.isCtorDeclaration()) // https://issues.dlang.org/show_bug.cgi?id=#15665
1320 f.isctor = true;
1321 sc.stc = 0;
1322 sc.linkage = funcdecl._linkage; // https://issues.dlang.org/show_bug.cgi?id=8496
1323 funcdecl.type = f.typeSemantic(funcdecl.loc, sc);
1324 sc = sc.pop();
1327 // Check `extern(C++)` functions for invalid the return/parameter types
1328 if (funcdecl._linkage == LINK.cpp)
1330 static bool isCppNonMappableType(Type type, Parameter param = null, Type origType = null)
1332 // Don't allow D `immutable` and `shared` types to be interfaced with C++
1333 if (type.isImmutable() || type.isShared())
1334 return true;
1335 else if (Type cpptype = target.cpp.parameterType(type))
1336 type = cpptype;
1338 if (origType is null)
1339 origType = type;
1341 // Permit types that are handled by toCppMangle. This list should be kept in sync with
1342 // each visit method in dmd.cppmangle and dmd.cppmanglewin.
1343 switch (type.ty)
1345 case Tnull:
1346 case Tnoreturn:
1347 case Tvector:
1348 case Tpointer:
1349 case Treference:
1350 case Tfunction:
1351 case Tstruct:
1352 case Tenum:
1353 case Tclass:
1354 case Tident:
1355 case Tinstance:
1356 break;
1358 case Tsarray:
1359 if (!origType.isTypePointer())
1360 return true;
1361 break;
1363 default:
1364 if (!type.isTypeBasic())
1365 return true;
1366 break;
1369 // Descend to the enclosing type
1370 if (auto tnext = type.nextOf())
1371 return isCppNonMappableType(tnext, param, origType);
1373 return false;
1375 if (isCppNonMappableType(f.next.toBasetype()))
1377 .error(funcdecl.loc, "%s `%s` cannot return type `%s` because its linkage is `extern(C++)`", funcdecl.kind, funcdecl.toPrettyChars, f.next.toChars());
1378 if (f.next.isTypeDArray())
1379 errorSupplemental(funcdecl.loc, "slices are specific to D and do not have a counterpart representation in C++", f.next.toChars());
1380 funcdecl.errors = true;
1382 foreach (i, param; f.parameterList)
1384 if (isCppNonMappableType(param.type.toBasetype(), param))
1386 .error(funcdecl.loc, "%s `%s` cannot have parameter of type `%s` because its linkage is `extern(C++)`", funcdecl.kind, funcdecl.toPrettyChars, param.type.toChars());
1387 if (param.type.toBasetype().isTypeSArray())
1388 errorSupplemental(funcdecl.loc, "perhaps use a `%s*` type instead",
1389 param.type.nextOf().mutableOf().unSharedOf().toChars());
1390 funcdecl.errors = true;
1395 // Do live analysis
1396 if (global.params.useDIP1021 && funcdecl.fbody && funcdecl.type.ty != Terror &&
1397 funcdecl.type.isTypeFunction().islive)
1399 oblive(funcdecl);
1402 /* If this function had instantiated with gagging, error reproduction will be
1403 * done by TemplateInstance::semantic.
1404 * Otherwise, error gagging should be temporarily ungagged by functionSemantic3.
1406 funcdecl.semanticRun = PASS.semantic3done;
1407 if ((global.errors != oldErrors) || (funcdecl.fbody && funcdecl.fbody.isErrorStatement()))
1408 funcdecl.hasSemantic3Errors = true;
1409 else
1410 funcdecl.hasSemantic3Errors = false;
1411 if (funcdecl.type.ty == Terror)
1412 funcdecl.errors = true;
1413 //printf("-FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", funcdecl.parent.toChars(), funcdecl.toChars(), sc, funcdecl.loc.toChars());
1414 //fflush(stdout);
1417 override void visit(CtorDeclaration ctor)
1419 //printf("CtorDeclaration()\n%s\n", ctor.fbody.toChars());
1420 if (ctor.semanticRun >= PASS.semantic3)
1421 return;
1423 /* If any of the fields of the aggregate have a destructor, add
1424 * scope (failure) { this.fieldDtor(); }
1425 * as the first statement of the constructor (unless the constructor
1426 * doesn't define a body - @disable, extern)
1427 *.It is not necessary to add it after
1428 * each initialization of a field, because destruction of .init constructed
1429 * structs should be benign.
1430 * https://issues.dlang.org/show_bug.cgi?id=14246
1432 AggregateDeclaration ad = ctor.isMemberDecl();
1433 if (!ctor.fbody || !ad || !ad.fieldDtor ||
1434 global.params.dtorFields == FeatureState.disabled || !global.params.useExceptions || ctor.type.toTypeFunction.isnothrow)
1435 return visit(cast(FuncDeclaration)ctor);
1437 /* Generate:
1438 * this.fieldDtor()
1440 Expression e = new ThisExp(ctor.loc);
1441 e.type = ad.type.mutableOf();
1442 e = new DotVarExp(ctor.loc, e, ad.fieldDtor, false);
1443 auto ce = new CallExp(ctor.loc, e);
1444 auto sexp = new ExpStatement(ctor.loc, ce);
1445 auto ss = new ScopeStatement(ctor.loc, sexp, ctor.loc);
1447 // @@@DEPRECATED_2.106@@@
1448 // Allow negligible attribute violations to allow for a smooth
1449 // transition. Remove this after the usual deprecation period
1450 // after 2.106.
1451 if (global.params.dtorFields == FeatureState.default_)
1453 auto ctf = cast(TypeFunction) ctor.type;
1454 auto dtf = cast(TypeFunction) ad.fieldDtor.type;
1456 const ngErr = ctf.isnogc && !dtf.isnogc;
1457 const puErr = ctf.purity && !dtf.purity;
1458 const saErr = ctf.trust == TRUST.safe && dtf.trust <= TRUST.system;
1460 if (ngErr || puErr || saErr)
1462 // storage_class is apparently not set for dtor & ctor
1463 OutBuffer ob;
1464 stcToBuffer(ob,
1465 (ngErr ? STC.nogc : 0) |
1466 (puErr ? STC.pure_ : 0) |
1467 (saErr ? STC.system : 0)
1469 ctor.loc.deprecation("`%s` has stricter attributes than its destructor (`%s`)", ctor.toPrettyChars(), ob.peekChars());
1470 ctor.loc.deprecationSupplemental("The destructor will be called if an exception is thrown");
1471 ctor.loc.deprecationSupplemental("Either make the constructor `nothrow` or adjust the field destructors");
1473 ce.ignoreAttributes = true;
1477 version (all)
1479 /* Generate:
1480 * try { ctor.fbody; }
1481 * catch (Exception __o)
1482 * { this.fieldDtor(); throw __o; }
1483 * This differs from the alternate scope(failure) version in that an Exception
1484 * is caught rather than a Throwable. This enables the optimization whereby
1485 * the try-catch can be removed if ctor.fbody is nothrow. (nothrow only
1486 * applies to Exception.)
1488 Identifier id = Identifier.generateId("__o");
1489 auto ts = new ThrowStatement(ctor.loc, new IdentifierExp(ctor.loc, id));
1490 auto handler = new CompoundStatement(ctor.loc, ss, ts);
1492 auto catches = new Catches();
1493 auto ctch = new Catch(ctor.loc, getException(), id, handler);
1494 catches.push(ctch);
1496 ctor.fbody = new TryCatchStatement(ctor.loc, ctor.fbody, catches);
1498 else
1500 /* Generate:
1501 * scope (failure) { this.fieldDtor(); }
1502 * Hopefully we can use this version someday when scope(failure) catches
1503 * Exception instead of Throwable.
1505 auto s = new ScopeGuardStatement(ctor.loc, TOK.onScopeFailure, ss);
1506 ctor.fbody = new CompoundStatement(ctor.loc, s, ctor.fbody);
1508 visit(cast(FuncDeclaration)ctor);
1512 override void visit(Nspace ns)
1514 if (ns.semanticRun >= PASS.semantic3)
1515 return;
1516 ns.semanticRun = PASS.semantic3;
1517 static if (LOG)
1519 printf("Nspace::semantic3('%s')\n", ns.toChars());
1521 if (!ns.members)
1522 return;
1524 sc = sc.push(ns);
1525 sc.linkage = LINK.cpp;
1526 foreach (s; *ns.members)
1528 s.semantic3(sc);
1530 sc.pop();
1533 override void visit(AttribDeclaration ad)
1535 Dsymbols* d = ad.include(sc);
1536 if (!d)
1537 return;
1539 Scope* sc2 = ad.newScope(sc);
1540 for (size_t i = 0; i < d.length; i++)
1542 Dsymbol s = (*d)[i];
1543 s.semantic3(sc2);
1545 if (sc2 != sc)
1546 sc2.pop();
1549 override void visit(AggregateDeclaration ad)
1551 //printf("AggregateDeclaration::semantic3(sc=%p, %s) type = %s, errors = %d\n", sc, toChars(), type.toChars(), errors);
1552 if (!ad.members)
1553 return;
1555 StructDeclaration sd = ad.isStructDeclaration();
1556 if (!sc) // from runDeferredSemantic3 for TypeInfo generation
1558 assert(sd);
1559 sd.semanticTypeInfoMembers();
1560 return;
1563 auto sc2 = ad.newScope(sc);
1565 for (size_t i = 0; i < ad.members.length; i++)
1567 Dsymbol s = (*ad.members)[i];
1568 s.semantic3(sc2);
1571 sc2.pop();
1573 // Instantiate RTInfo!S to provide a pointer bitmap for the GC
1574 // Don't do it in -betterC or on unused deprecated / error types
1575 if (!ad.getRTInfo && global.params.useTypeInfo && Type.rtinfo &&
1576 (!ad.isDeprecated() || global.params.useDeprecated != DiagnosticReporting.error) &&
1577 (ad.type && ad.type.ty != Terror))
1579 // Evaluate: RTinfo!type
1580 auto tiargs = new Objects();
1581 tiargs.push(ad.type);
1582 auto ti = new TemplateInstance(ad.loc, Type.rtinfo, tiargs);
1584 Scope* sc3 = ti.tempdecl._scope.startCTFE();
1585 sc3.tinst = sc.tinst;
1586 sc3.minst = sc.minst;
1587 if (ad.isDeprecated())
1588 sc3.stc |= STC.deprecated_;
1590 ti.dsymbolSemantic(sc3);
1591 ti.semantic2(sc3);
1592 ti.semantic3(sc3);
1593 auto e = symbolToExp(ti.toAlias(), Loc.initial, sc3, false);
1595 sc3.endCTFE();
1597 e = e.ctfeInterpret();
1598 ad.getRTInfo = e;
1600 if (sd)
1601 sd.semanticTypeInfoMembers();
1602 ad.semanticRun = PASS.semantic3done;
1606 private struct FuncDeclSem3
1608 // The FuncDeclaration subject to Semantic analysis
1609 FuncDeclaration funcdecl;
1611 // Scope of analysis
1612 Scope* sc;
1613 this(FuncDeclaration fd,Scope* s) scope @safe
1615 funcdecl = fd;
1616 sc = s;
1619 /* Checks that the overridden functions (if any) have in contracts if
1620 * funcdecl has an in contract.
1622 void checkInContractOverrides()
1624 if (funcdecl.frequires)
1626 for (size_t i = 0; i < funcdecl.foverrides.length; i++)
1628 FuncDeclaration fdv = funcdecl.foverrides[i];
1629 if (fdv.fbody && !fdv.frequires)
1631 .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());
1632 break;
1639 extern (C++) void semanticTypeInfoMembers(StructDeclaration sd)
1641 if (sd.xeq &&
1642 sd.xeq._scope &&
1643 sd.xeq.semanticRun < PASS.semantic3done)
1645 uint errors = global.startGagging();
1646 sd.xeq.semantic3(sd.xeq._scope);
1647 if (global.endGagging(errors))
1648 sd.xeq = sd.xerreq;
1651 if (sd.xcmp &&
1652 sd.xcmp._scope &&
1653 sd.xcmp.semanticRun < PASS.semantic3done)
1655 uint errors = global.startGagging();
1656 sd.xcmp.semantic3(sd.xcmp._scope);
1657 if (global.endGagging(errors))
1658 sd.xcmp = sd.xerrcmp;
1661 FuncDeclaration ftostr = search_toString(sd);
1662 if (ftostr &&
1663 ftostr._scope &&
1664 ftostr.semanticRun < PASS.semantic3done)
1666 ftostr.semantic3(ftostr._scope);
1669 if (sd.xhash &&
1670 sd.xhash._scope &&
1671 sd.xhash.semanticRun < PASS.semantic3done)
1673 sd.xhash.semantic3(sd.xhash._scope);
1676 if (sd.postblit &&
1677 sd.postblit._scope &&
1678 sd.postblit.semanticRun < PASS.semantic3done)
1680 sd.postblit.semantic3(sd.postblit._scope);
1683 if (sd.dtor &&
1684 sd.dtor._scope &&
1685 sd.dtor.semanticRun < PASS.semantic3done)
1687 sd.dtor.semantic3(sd.dtor._scope);