semantic3.d revision 1.1.1.1 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