d: Merge upstream dmd, druntime f8bae04558, phobos ba2ade9dec
[official-gcc.git] / gcc / d / dmd / funcsem.d
blob2cadc4019110ddc901b31cce95dae1344c114d92
1 /**
2 * Does semantic analysis for functions.
4 * Specification: $(LINK2 https://dlang.org/spec/function.html, Functions)
6 * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved
7 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright)
8 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
9 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/funcsem.d, _funcsem.d)
10 * Documentation: https://dlang.org/phobos/dmd_funcsem.html
11 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/funcsem.d
14 module dmd.funcsem;
16 import core.stdc.stdio;
18 import dmd.aggregate;
19 import dmd.arraytypes;
20 import dmd.astenums;
21 import dmd.attrib;
22 import dmd.blockexit;
23 import dmd.gluelayer;
24 import dmd.dcast;
25 import dmd.dclass;
26 import dmd.declaration;
27 import dmd.delegatize;
28 import dmd.dinterpret;
29 import dmd.dmodule;
30 import dmd.dscope;
31 import dmd.dstruct;
32 import dmd.dsymbol;
33 import dmd.dsymbolsem;
34 import dmd.dtemplate;
35 import dmd.errors;
36 import dmd.escape;
37 import dmd.expression;
38 import dmd.func;
39 import dmd.globals;
40 import dmd.hdrgen;
41 import dmd.id;
42 import dmd.identifier;
43 import dmd.importc;
44 import dmd.init;
45 import dmd.location;
46 import dmd.mtype;
47 import dmd.mustuse;
48 import dmd.objc;
49 import dmd.opover;
50 import dmd.pragmasem;
51 import dmd.root.aav;
52 import dmd.common.outbuffer;
53 import dmd.rootobject;
54 import dmd.root.filename;
55 import dmd.root.string;
56 import dmd.root.stringtable;
57 import dmd.semantic2;
58 import dmd.semantic3;
59 import dmd.statement_rewrite_walker;
60 import dmd.statement;
61 import dmd.statementsem;
62 import dmd.target;
63 import dmd.templatesem;
64 import dmd.tokens;
65 import dmd.typesem;
66 import dmd.visitor;
68 /* Tweak all return statements and dtor call for nrvo_var, for correct NRVO.
70 extern (C++) final class NrvoWalker : StatementRewriteWalker
72 alias visit = typeof(super).visit;
73 public:
74 FuncDeclaration fd;
75 Scope* sc;
77 override void visit(ReturnStatement s)
79 // See if all returns are instead to be replaced with a goto returnLabel;
80 if (fd.returnLabel)
82 /* Rewrite:
83 * return exp;
84 * as:
85 * vresult = exp; goto Lresult;
87 auto gs = new GotoStatement(s.loc, Id.returnLabel);
88 gs.label = fd.returnLabel;
90 Statement s1 = gs;
91 if (s.exp)
92 s1 = new CompoundStatement(s.loc, new ExpStatement(s.loc, s.exp), gs);
94 replaceCurrent(s1);
98 override void visit(TryFinallyStatement s)
100 DtorExpStatement des;
101 if (fd.isNRVO() && s.finalbody && (des = s.finalbody.isDtorExpStatement()) !is null &&
102 fd.nrvo_var == des.var)
104 if (!(global.params.useExceptions && ClassDeclaration.throwable))
106 /* Don't need to call destructor at all, since it is nrvo
108 replaceCurrent(s._body);
109 s._body.accept(this);
110 return;
113 /* Normally local variable dtors are called regardless exceptions.
114 * But for nrvo_var, its dtor should be called only when exception is thrown.
116 * Rewrite:
117 * try { s.body; } finally { nrvo_var.edtor; }
118 * // equivalent with:
119 * // s.body; scope(exit) nrvo_var.edtor;
120 * as:
121 * try { s.body; } catch(Throwable __o) { nrvo_var.edtor; throw __o; }
122 * // equivalent with:
123 * // s.body; scope(failure) nrvo_var.edtor;
125 Statement sexception = new DtorExpStatement(Loc.initial, fd.nrvo_var.edtor, fd.nrvo_var);
126 Identifier id = Identifier.generateId("__o");
128 Statement handler = new PeelStatement(sexception);
129 if (sexception.blockExit(fd, null) & BE.fallthru)
131 auto ts = new ThrowStatement(Loc.initial, new IdentifierExp(Loc.initial, id));
132 ts.internalThrow = true;
133 handler = new CompoundStatement(Loc.initial, handler, ts);
136 auto catches = new Catches();
137 auto ctch = new Catch(Loc.initial, getThrowable(), id, handler);
138 ctch.internalCatch = true;
139 ctch.catchSemantic(sc); // Run semantic to resolve identifier '__o'
140 catches.push(ctch);
142 Statement s2 = new TryCatchStatement(Loc.initial, s._body, catches);
143 fd.hasNoEH = false;
144 replaceCurrent(s2);
145 s2.accept(this);
147 else
148 StatementRewriteWalker.visit(s);
152 /**********************************
153 * Main semantic routine for functions.
155 void funcDeclarationSemantic(Scope* sc, FuncDeclaration funcdecl)
157 version (none)
159 printf("FuncDeclaration::semantic(sc = %p, this = %p, '%s', linkage = %d)\n", sc, funcdecl, funcdecl.toPrettyChars(), sc.linkage);
160 if (funcdecl.isFuncLiteralDeclaration())
161 printf("\tFuncLiteralDeclaration()\n");
162 printf("sc.parent = %s, parent = %s\n", sc.parent.toChars(), funcdecl.parent ? funcdecl.parent.toChars() : "");
163 printf("type: %p, %s\n", funcdecl.type, funcdecl.type.toChars());
166 if (funcdecl.semanticRun != PASS.initial && funcdecl.isFuncLiteralDeclaration())
168 /* Member functions that have return types that are
169 * forward references can have semantic() run more than
170 * once on them.
171 * See test\interface2.d, test20
173 return;
176 if (funcdecl.semanticRun >= PASS.semanticdone)
177 return;
178 assert(funcdecl.semanticRun <= PASS.semantic);
179 funcdecl.semanticRun = PASS.semantic;
181 if (funcdecl._scope)
183 sc = funcdecl._scope;
184 funcdecl._scope = null;
187 if (!sc || funcdecl.errors)
188 return;
190 funcdecl.cppnamespace = sc.namespace;
191 funcdecl.parent = sc.parent;
192 Dsymbol parent = funcdecl.toParent();
194 funcdecl.foverrides.setDim(0); // reset in case semantic() is being retried for this function
196 funcdecl.storage_class |= sc.stc & ~STC.ref_;
197 AggregateDeclaration ad = funcdecl.isThis();
198 // Don't nest structs b/c of generated methods which should not access the outer scopes.
199 // https://issues.dlang.org/show_bug.cgi?id=16627
200 if (ad && !funcdecl.isGenerated())
202 funcdecl.storage_class |= ad.storage_class & (STC.TYPECTOR | STC.synchronized_);
203 ad.makeNested();
205 if (sc.func)
206 funcdecl.storage_class |= sc.func.storage_class & STC.disable;
207 // Remove prefix storage classes silently.
208 if ((funcdecl.storage_class & STC.TYPECTOR) && !(ad || funcdecl.isNested()))
209 funcdecl.storage_class &= ~STC.TYPECTOR;
211 //printf("function storage_class = x%llx, sc.stc = x%llx, %x\n", storage_class, sc.stc, Declaration.isFinal());
213 if (sc.flags & SCOPE.compile)
214 funcdecl.skipCodegen = true;
216 funcdecl._linkage = sc.linkage;
217 if (sc.flags & SCOPE.Cfile && funcdecl.isFuncLiteralDeclaration())
218 funcdecl._linkage = LINK.d; // so they are uniquely mangled
220 if (auto fld = funcdecl.isFuncLiteralDeclaration())
222 if (fld.treq)
224 Type treq = fld.treq;
225 assert(treq.nextOf().ty == Tfunction);
226 if (treq.ty == Tdelegate)
227 fld.tok = TOK.delegate_;
228 else if (treq.isPtrToFunction())
229 fld.tok = TOK.function_;
230 else
231 assert(0);
232 funcdecl._linkage = treq.nextOf().toTypeFunction().linkage;
236 // evaluate pragma(inline)
237 if (auto pragmadecl = sc.inlining)
238 funcdecl.inlining = evalPragmaInline(pragmadecl.loc, sc, pragmadecl.args);
240 funcdecl.visibility = sc.visibility;
241 funcdecl.userAttribDecl = sc.userAttribDecl;
242 UserAttributeDeclaration.checkGNUABITag(funcdecl, funcdecl._linkage);
243 checkMustUseReserved(funcdecl);
245 if (!funcdecl.originalType)
246 funcdecl.originalType = funcdecl.type.syntaxCopy();
248 static TypeFunction getFunctionType(FuncDeclaration fd)
250 if (auto tf = fd.type.isTypeFunction())
251 return tf;
253 if (!fd.type.isTypeError())
255 .error(fd.loc, "%s `%s` `%s` must be a function instead of `%s`", fd.kind, fd.toPrettyChars, fd.toChars(), fd.type.toChars());
256 fd.type = Type.terror;
258 fd.errors = true;
259 return null;
262 if (sc.flags & SCOPE.Cfile)
264 /* C11 allows a function to be declared with a typedef, D does not.
266 if (auto ti = funcdecl.type.isTypeIdentifier())
268 auto tj = ti.typeSemantic(funcdecl.loc, sc);
269 if (auto tjf = tj.isTypeFunction())
271 /* Copy the type instead of just pointing to it,
272 * as we don't merge function types
274 auto tjf2 = new TypeFunction(tjf.parameterList, tjf.next, tjf.linkage);
275 funcdecl.type = tjf2;
276 funcdecl.originalType = tjf2;
281 if (!getFunctionType(funcdecl))
282 return;
284 if (!funcdecl.type.deco)
286 sc = sc.push();
287 sc.stc |= funcdecl.storage_class & (STC.disable | STC.deprecated_); // forward to function type
289 TypeFunction tf = funcdecl.type.toTypeFunction();
290 if (sc.func)
292 /* If the nesting parent is pure without inference,
293 * then this function defaults to pure too.
295 * auto foo() pure {
296 * auto bar() {} // become a weak purity function
297 * class C { // nested class
298 * auto baz() {} // become a weak purity function
301 * static auto boo() {} // typed as impure
302 * // Even though, boo cannot call any impure functions.
303 * // See also Expression::checkPurity().
306 if (tf.purity == PURE.impure && (funcdecl.isNested() || funcdecl.isThis()))
308 FuncDeclaration fd = null;
309 for (Dsymbol p = funcdecl.toParent2(); p; p = p.toParent2())
311 if (AggregateDeclaration adx = p.isAggregateDeclaration())
313 if (adx.isNested())
314 continue;
315 break;
317 if ((fd = p.isFuncDeclaration()) !is null)
318 break;
321 /* If the parent's purity is inferred, then this function's purity needs
322 * to be inferred first.
324 if (fd && fd.isPureBypassingInference() >= PURE.weak && !funcdecl.isInstantiated())
326 tf.purity = PURE.fwdref; // default to pure
331 if (tf.isref)
332 sc.stc |= STC.ref_;
333 if (tf.isScopeQual)
334 sc.stc |= STC.scope_;
335 if (tf.isnothrow)
336 sc.stc |= STC.nothrow_;
337 if (tf.isnogc)
338 sc.stc |= STC.nogc;
339 if (tf.isproperty)
340 sc.stc |= STC.property;
341 if (tf.purity == PURE.fwdref)
342 sc.stc |= STC.pure_;
344 if (tf.trust != TRUST.default_)
346 sc.stc &= ~STC.safeGroup;
347 if (tf.trust == TRUST.safe)
348 sc.stc |= STC.safe;
349 else if (tf.trust == TRUST.system)
350 sc.stc |= STC.system;
351 else if (tf.trust == TRUST.trusted)
352 sc.stc |= STC.trusted;
355 if (funcdecl.isCtorDeclaration())
357 tf.isctor = true;
358 Type tret = ad.handleType();
359 assert(tret);
360 tret = tret.addStorageClass(funcdecl.storage_class | sc.stc);
361 tret = tret.addMod(funcdecl.type.mod);
362 tf.next = tret;
363 if (ad.isStructDeclaration())
364 sc.stc |= STC.ref_;
367 // 'return' on a non-static class member function implies 'scope' as well
368 if (ad && ad.isClassDeclaration() && (tf.isreturn || sc.stc & STC.return_) && !(sc.stc & STC.static_))
369 sc.stc |= STC.scope_;
371 // If 'this' has no pointers, remove 'scope' as it has no meaning
372 // Note: this is already covered by semantic of `VarDeclaration` and `TypeFunction`,
373 // but existing code relies on `hasPointers()` being called here to resolve forward references:
374 // https://github.com/dlang/dmd/pull/14232#issuecomment-1162906573
375 if (sc.stc & STC.scope_ && ad && ad.isStructDeclaration() && !ad.type.hasPointers())
377 sc.stc &= ~STC.scope_;
378 tf.isScopeQual = false;
379 if (tf.isreturnscope)
381 sc.stc &= ~(STC.return_ | STC.returnScope);
382 tf.isreturn = false;
383 tf.isreturnscope = false;
387 sc.linkage = funcdecl._linkage;
389 if (!tf.isNaked() && !(funcdecl.isThis() || funcdecl.isNested()))
391 import core.bitop : popcnt;
392 auto mods = MODtoChars(tf.mod);
393 .error(funcdecl.loc, "%s `%s` without `this` cannot be `%s`", funcdecl.kind, funcdecl.toPrettyChars, mods);
394 if (tf.next && tf.next.ty != Tvoid && popcnt(tf.mod) == 1)
395 .errorSupplemental(funcdecl.loc,
396 "did you mean to use `%s(%s)` as the return type?", mods, tf.next.toChars());
398 tf.mod = 0; // remove qualifiers
401 /* Apply const, immutable, wild and shared storage class
402 * to the function type. Do this before type semantic.
404 auto stc = funcdecl.storage_class;
405 if (funcdecl.type.isImmutable())
406 stc |= STC.immutable_;
407 if (funcdecl.type.isConst())
408 stc |= STC.const_;
409 if (funcdecl.type.isShared() || funcdecl.storage_class & STC.synchronized_)
410 stc |= STC.shared_;
411 if (funcdecl.type.isWild())
412 stc |= STC.wild;
413 funcdecl.type = funcdecl.type.addSTC(stc);
415 funcdecl.type = funcdecl.type.typeSemantic(funcdecl.loc, sc);
416 sc = sc.pop();
419 auto f = getFunctionType(funcdecl);
420 if (!f)
421 return; // funcdecl's type is not a function
424 // Merge back function attributes into 'originalType'.
425 // It's used for mangling, ddoc, and json output.
426 TypeFunction tfo = funcdecl.originalType.toTypeFunction();
427 tfo.mod = f.mod;
428 tfo.isScopeQual = f.isScopeQual;
429 tfo.isreturninferred = f.isreturninferred;
430 tfo.isscopeinferred = f.isscopeinferred;
431 tfo.isref = f.isref;
432 tfo.isnothrow = f.isnothrow;
433 tfo.isnogc = f.isnogc;
434 tfo.isproperty = f.isproperty;
435 tfo.purity = f.purity;
436 tfo.trust = f.trust;
438 funcdecl.storage_class &= ~(STC.TYPECTOR | STC.FUNCATTR);
441 // check pragma(crt_constructor) signature
442 if (funcdecl.isCrtCtor || funcdecl.isCrtDtor)
444 const idStr = funcdecl.isCrtCtor ? "crt_constructor" : "crt_destructor";
445 if (f.nextOf().ty != Tvoid)
446 .error(funcdecl.loc, "%s `%s` must return `void` for `pragma(%s)`", funcdecl.kind, funcdecl.toPrettyChars, idStr.ptr);
447 if (funcdecl._linkage != LINK.c && f.parameterList.length != 0)
448 .error(funcdecl.loc, "%s `%s` must be `extern(C)` for `pragma(%s)` when taking parameters", funcdecl.kind, funcdecl.toPrettyChars, idStr.ptr);
449 if (funcdecl.isThis())
450 .error(funcdecl.loc, "%s `%s` cannot be a non-static member function for `pragma(%s)`", funcdecl.kind, funcdecl.toPrettyChars, idStr.ptr);
453 if (funcdecl.overnext && funcdecl.isCsymbol())
455 /* C does not allow function overloading, but it does allow
456 * redeclarations of the same function. If .overnext points
457 * to a redeclaration, ok. Error if it is an overload.
459 auto fnext = funcdecl.overnext.isFuncDeclaration();
460 funcDeclarationSemantic(sc, fnext);
461 auto fn = fnext.type.isTypeFunction();
462 if (!fn || !cFuncEquivalence(f, fn))
464 .error(funcdecl.loc, "%s `%s` redeclaration with different type", funcdecl.kind, funcdecl.toPrettyChars);
465 //printf("t1: %s\n", f.toChars());
466 //printf("t2: %s\n", fn.toChars());
468 funcdecl.overnext = null; // don't overload the redeclarations
471 if ((funcdecl.storage_class & STC.auto_) && !f.isref && !funcdecl.inferRetType)
472 .error(funcdecl.loc, "%s `%s` storage class `auto` has no effect if return type is not inferred", funcdecl.kind, funcdecl.toPrettyChars);
474 if (f.isreturn && !funcdecl.needThis() && !funcdecl.isNested())
476 /* Non-static nested functions have a hidden 'this' pointer to which
477 * the 'return' applies
479 if (sc.scopesym && sc.scopesym.isAggregateDeclaration())
480 .error(funcdecl.loc, "%s `%s` `static` member has no `this` to which `return` can apply", funcdecl.kind, funcdecl.toPrettyChars);
481 else
482 error(funcdecl.loc, "top-level function `%s` has no `this` to which `return` can apply", funcdecl.toChars());
485 if (funcdecl.isAbstract() && !funcdecl.isVirtual())
487 const(char)* sfunc;
488 if (funcdecl.isStatic())
489 sfunc = "static";
490 else if (funcdecl.visibility.kind == Visibility.Kind.private_ || funcdecl.visibility.kind == Visibility.Kind.package_)
491 sfunc = visibilityToChars(funcdecl.visibility.kind);
492 else
493 sfunc = "final";
494 .error(funcdecl.loc, "%s `%s` `%s` functions cannot be `abstract`", funcdecl.kind, funcdecl.toPrettyChars, sfunc);
497 if (funcdecl.isOverride() && !funcdecl.isVirtual() && !funcdecl.isFuncLiteralDeclaration())
499 Visibility.Kind kind = funcdecl.visible().kind;
500 if ((kind == Visibility.Kind.private_ || kind == Visibility.Kind.package_) && funcdecl.isMember())
501 .error(funcdecl.loc, "%s `%s` `%s` method is not virtual and cannot override", funcdecl.kind, funcdecl.toPrettyChars, visibilityToChars(kind));
502 else
503 .error(funcdecl.loc, "%s `%s` cannot override a non-virtual function", funcdecl.kind, funcdecl.toPrettyChars);
506 if (funcdecl.isAbstract() && funcdecl.isFinalFunc())
507 .error(funcdecl.loc, "%s `%s` cannot be both `final` and `abstract`", funcdecl.kind, funcdecl.toPrettyChars);
509 if (funcdecl.printf || funcdecl.scanf)
511 checkPrintfScanfSignature(funcdecl, f, sc);
514 if (auto id = parent.isInterfaceDeclaration())
516 funcdecl.storage_class |= STC.abstract_;
517 if (funcdecl.isCtorDeclaration() || funcdecl.isPostBlitDeclaration() || funcdecl.isDtorDeclaration() || funcdecl.isInvariantDeclaration() || funcdecl.isNewDeclaration() || funcdecl.isDelete())
518 .error(funcdecl.loc, "%s `%s` constructors, destructors, postblits, invariants, new and delete functions are not allowed in interface `%s`", funcdecl.kind, funcdecl.toPrettyChars, id.toChars());
519 if (funcdecl.fbody && funcdecl.isVirtual())
520 .error(funcdecl.loc, "%s `%s` function body only allowed in `final` functions in interface `%s`", funcdecl.kind, funcdecl.toPrettyChars, id.toChars());
523 if (UnionDeclaration ud = parent.isUnionDeclaration())
525 if (funcdecl.isPostBlitDeclaration() || funcdecl.isDtorDeclaration() || funcdecl.isInvariantDeclaration())
526 .error(funcdecl.loc, "%s `%s` destructors, postblits and invariants are not allowed in union `%s`", funcdecl.kind, funcdecl.toPrettyChars, ud.toChars());
529 if (StructDeclaration sd = parent.isStructDeclaration())
531 if (funcdecl.isCtorDeclaration())
533 goto Ldone;
537 if (ClassDeclaration cd = parent.isClassDeclaration())
539 parent = cd = objc.getParent(funcdecl, cd);
541 if (funcdecl.isCtorDeclaration())
543 goto Ldone;
546 if (funcdecl.storage_class & STC.abstract_)
547 cd.isabstract = ThreeState.yes;
549 // if static function, do not put in vtbl[]
550 if (!funcdecl.isVirtual())
552 //printf("\tnot virtual\n");
553 goto Ldone;
555 // Suppress further errors if the return type is an error
556 if (funcdecl.type.nextOf() == Type.terror)
557 goto Ldone;
559 bool may_override = false;
560 for (size_t i = 0; i < cd.baseclasses.length; i++)
562 BaseClass* b = (*cd.baseclasses)[i];
563 ClassDeclaration cbd = b.type.toBasetype().isClassHandle();
564 if (!cbd)
565 continue;
566 for (size_t j = 0; j < cbd.vtbl.length; j++)
568 FuncDeclaration f2 = cbd.vtbl[j].isFuncDeclaration();
569 if (!f2 || f2.ident != funcdecl.ident)
570 continue;
571 if (cbd.parent && cbd.parent.isTemplateInstance())
573 if (!functionSemantic(f2))
574 goto Ldone;
576 may_override = true;
579 if (may_override && funcdecl.type.nextOf() is null)
581 /* If same name function exists in base class but 'this' is auto return,
582 * cannot find index of base class's vtbl[] to override.
584 .error(funcdecl.loc, "%s `%s` return type inference is not supported if may override base class function", funcdecl.kind, funcdecl.toPrettyChars);
587 /* Find index of existing function in base class's vtbl[] to override
588 * (the index will be the same as in cd's current vtbl[])
590 int vi = cd.baseClass ? findVtblIndex(funcdecl, cd.baseClass.vtbl[]) : -1;
592 bool doesoverride = false;
593 switch (vi)
595 case -1:
596 Lintro:
597 /* Didn't find one, so
598 * This is an 'introducing' function which gets a new
599 * slot in the vtbl[].
602 // Verify this doesn't override previous final function
603 if (cd.baseClass)
605 Dsymbol s = cd.baseClass.search(funcdecl.loc, funcdecl.ident);
606 if (s)
608 if (auto f2 = s.isFuncDeclaration())
610 f2 = f2.overloadExactMatch(funcdecl.type);
611 if (f2 && f2.isFinalFunc() && f2.visible().kind != Visibility.Kind.private_)
612 .error(funcdecl.loc, "%s `%s` cannot override `final` function `%s`", funcdecl.kind, funcdecl.toPrettyChars, f2.toPrettyChars());
617 /* These quirky conditions mimic what happens when virtual
618 inheritance is implemented by producing a virtual base table
619 with offsets to each of the virtual bases.
621 if (target.cpp.splitVBasetable && cd.classKind == ClassKind.cpp &&
622 cd.baseClass && cd.baseClass.vtbl.length)
624 /* if overriding an interface function, then this is not
625 * introducing and don't put it in the class vtbl[]
627 funcdecl.interfaceVirtual = overrideInterface(funcdecl);
628 if (funcdecl.interfaceVirtual)
630 //printf("\tinterface function %s\n", toChars());
631 cd.vtblFinal.push(funcdecl);
632 goto Linterfaces;
636 if (funcdecl.isFinalFunc())
638 // Don't check here, as it may override an interface function
639 //if (isOverride())
640 // error("is marked as override, but does not override any function");
641 cd.vtblFinal.push(funcdecl);
643 else
645 //printf("\tintroducing function %s\n", funcdecl.toChars());
646 funcdecl.isIntroducing = true;
647 if (cd.classKind == ClassKind.cpp && target.cpp.reverseOverloads)
649 /* Overloaded functions with same name are grouped and in reverse order.
650 * Search for first function of overload group, and insert
651 * funcdecl into vtbl[] immediately before it.
653 funcdecl.vtblIndex = cast(int)cd.vtbl.length;
654 bool found;
655 foreach (const i, s; cd.vtbl)
657 if (found)
658 // the rest get shifted forward
659 ++s.isFuncDeclaration().vtblIndex;
660 else if (s.ident == funcdecl.ident && s.parent == parent)
662 // found first function of overload group
663 funcdecl.vtblIndex = cast(int)i;
664 found = true;
665 ++s.isFuncDeclaration().vtblIndex;
668 cd.vtbl.insert(funcdecl.vtblIndex, funcdecl);
670 debug foreach (const i, s; cd.vtbl)
672 // a C++ dtor gets its vtblIndex later (and might even be added twice to the vtbl),
673 // e.g. when compiling druntime with a debug compiler, namely with core.stdcpp.exception.
674 if (auto fd = s.isFuncDeclaration())
675 assert(fd.vtblIndex == i ||
676 (cd.classKind == ClassKind.cpp && fd.isDtorDeclaration) ||
677 funcdecl.parent.isInterfaceDeclaration); // interface functions can be in multiple vtbls
680 else
682 // Append to end of vtbl[]
683 vi = cast(int)cd.vtbl.length;
684 cd.vtbl.push(funcdecl);
685 funcdecl.vtblIndex = vi;
688 break;
690 case -2:
691 // can't determine because of forward references
692 funcdecl.errors = true;
693 return;
695 default:
697 if (vi >= cd.vtbl.length)
699 /* the derived class cd doesn't have its vtbl[] allocated yet.
700 * https://issues.dlang.org/show_bug.cgi?id=21008
702 .error(funcdecl.loc, "%s `%s` circular reference to class `%s`", funcdecl.kind, funcdecl.toPrettyChars, cd.toChars());
703 funcdecl.errors = true;
704 return;
706 FuncDeclaration fdv = cd.baseClass.vtbl[vi].isFuncDeclaration();
707 FuncDeclaration fdc = cd.vtbl[vi].isFuncDeclaration();
708 // This function is covariant with fdv
710 if (fdc == funcdecl)
712 doesoverride = true;
713 break;
716 auto vtf = getFunctionType(fdv);
717 if (vtf.trust > TRUST.system && f.trust == TRUST.system)
718 .error(funcdecl.loc, "%s `%s` cannot override `@safe` method `%s` with a `@system` attribute", funcdecl.kind, funcdecl.toPrettyChars,
719 fdv.toPrettyChars);
721 if (fdc.toParent() == parent)
723 //printf("vi = %d,\tthis = %p %s %s @ [%s]\n\tfdc = %p %s %s @ [%s]\n\tfdv = %p %s %s @ [%s]\n",
724 // vi, this, this.toChars(), this.type.toChars(), this.loc.toChars(),
725 // fdc, fdc .toChars(), fdc .type.toChars(), fdc .loc.toChars(),
726 // fdv, fdv .toChars(), fdv .type.toChars(), fdv .loc.toChars());
728 // fdc overrides fdv exactly, then this introduces new function.
729 if (fdc.type.mod == fdv.type.mod && funcdecl.type.mod != fdv.type.mod)
730 goto Lintro;
733 if (fdv.isDeprecated && !funcdecl.isDeprecated)
734 deprecation(funcdecl.loc, "`%s` is overriding the deprecated method `%s`",
735 funcdecl.toPrettyChars, fdv.toPrettyChars);
737 // This function overrides fdv
738 if (fdv.isFinalFunc())
739 .error(funcdecl.loc, "%s `%s` cannot override `final` function `%s`", funcdecl.kind, funcdecl.toPrettyChars, fdv.toPrettyChars());
741 if (!funcdecl.isOverride())
743 if (fdv.isFuture())
745 deprecation(funcdecl.loc, "`@__future` base class method `%s` is being overridden by `%s`; rename the latter", fdv.toPrettyChars(), funcdecl.toPrettyChars());
746 // Treat 'this' as an introducing function, giving it a separate hierarchy in the vtbl[]
747 goto Lintro;
749 else
751 // https://issues.dlang.org/show_bug.cgi?id=17349
752 error(funcdecl.loc, "cannot implicitly override base class method `%s` with `%s`; add `override` attribute",
753 fdv.toPrettyChars(), funcdecl.toPrettyChars());
756 doesoverride = true;
757 if (fdc.toParent() == parent)
759 // If both are mixins, or both are not, then error.
760 // If either is not, the one that is not overrides the other.
761 bool thismixin = funcdecl.parent.isClassDeclaration() !is null;
762 bool fdcmixin = fdc.parent.isClassDeclaration() !is null;
763 if (thismixin == fdcmixin)
765 .error(funcdecl.loc, "%s `%s` multiple overrides of same function", funcdecl.kind, funcdecl.toPrettyChars);
768 * https://issues.dlang.org/show_bug.cgi?id=711
770 * If an overriding method is introduced through a mixin,
771 * we need to update the vtbl so that both methods are
772 * present.
774 else if (thismixin)
776 /* if the mixin introduced the overriding method, then reintroduce it
777 * in the vtbl. The initial entry for the mixined method
778 * will be updated at the end of the enclosing `if` block
779 * to point to the current (non-mixined) function.
781 auto vitmp = cast(int)cd.vtbl.length;
782 cd.vtbl.push(fdc);
783 fdc.vtblIndex = vitmp;
785 else if (fdcmixin)
787 /* if the current overriding function is coming from a
788 * mixined block, then push the current function in the
789 * vtbl, but keep the previous (non-mixined) function as
790 * the overriding one.
792 auto vitmp = cast(int)cd.vtbl.length;
793 cd.vtbl.push(funcdecl);
794 funcdecl.vtblIndex = vitmp;
795 break;
797 else // fdc overrides fdv
799 // this doesn't override any function
800 break;
803 cd.vtbl[vi] = funcdecl;
804 funcdecl.vtblIndex = vi;
806 /* Remember which functions this overrides
808 funcdecl.foverrides.push(fdv);
810 /* This works by whenever this function is called,
811 * it actually returns tintro, which gets dynamically
812 * cast to type. But we know that tintro is a base
813 * of type, so we could optimize it by not doing a
814 * dynamic cast, but just subtracting the isBaseOf()
815 * offset if the value is != null.
818 if (fdv.tintro)
819 funcdecl.tintro = fdv.tintro;
820 else if (!funcdecl.type.equals(fdv.type))
822 auto tnext = funcdecl.type.nextOf();
823 if (auto handle = tnext.isClassHandle())
825 if (handle.semanticRun < PASS.semanticdone && !handle.isBaseInfoComplete())
826 handle.dsymbolSemantic(null);
828 /* Only need to have a tintro if the vptr
829 * offsets differ
831 int offset;
832 if (fdv.type.nextOf().isBaseOf(tnext, &offset))
834 funcdecl.tintro = fdv.type;
837 break;
841 /* Go through all the interface bases.
842 * If this function is covariant with any members of those interface
843 * functions, set the tintro.
845 Linterfaces:
846 bool foundVtblMatch = false;
848 for (ClassDeclaration bcd = cd; !foundVtblMatch && bcd; bcd = bcd.baseClass)
850 foreach (b; bcd.interfaces)
852 vi = findVtblIndex(funcdecl, b.sym.vtbl[]);
853 switch (vi)
855 case -1:
856 break;
858 case -2:
859 // can't determine because of forward references
860 funcdecl.errors = true;
861 return;
863 default:
865 auto fdv = cast(FuncDeclaration)b.sym.vtbl[vi];
866 Type ti = null;
868 foundVtblMatch = true;
870 /* Remember which functions this overrides
872 funcdecl.foverrides.push(fdv);
874 if (fdv.tintro)
875 ti = fdv.tintro;
876 else if (!funcdecl.type.equals(fdv.type))
878 /* Only need to have a tintro if the vptr
879 * offsets differ
881 int offset;
882 if (fdv.type.nextOf().isBaseOf(funcdecl.type.nextOf(), &offset))
884 ti = fdv.type;
887 if (ti)
889 if (funcdecl.tintro)
891 if (!funcdecl.tintro.nextOf().equals(ti.nextOf()) && !funcdecl.tintro.nextOf().isBaseOf(ti.nextOf(), null) && !ti.nextOf().isBaseOf(funcdecl.tintro.nextOf(), null))
893 .error(funcdecl.loc, "%s `%s` incompatible covariant types `%s` and `%s`", funcdecl.kind, funcdecl.toPrettyChars, funcdecl.tintro.toChars(), ti.toChars());
896 else
898 funcdecl.tintro = ti;
905 if (foundVtblMatch)
907 goto L2;
910 if (!doesoverride && funcdecl.isOverride() && (funcdecl.type.nextOf() || !may_override))
912 BaseClass* bc = null;
913 Dsymbol s = null;
914 for (size_t i = 0; i < cd.baseclasses.length; i++)
916 bc = (*cd.baseclasses)[i];
917 s = bc.sym.search_correct(funcdecl.ident);
918 if (s)
919 break;
922 if (s)
924 HdrGenState hgs;
925 OutBuffer buf;
927 auto fd = s.isFuncDeclaration();
928 functionToBufferFull(cast(TypeFunction)(funcdecl.type), buf,
929 new Identifier(funcdecl.toPrettyChars()), hgs, null);
930 const(char)* funcdeclToChars = buf.peekChars();
932 if (fd)
934 OutBuffer buf1;
936 if (fd.ident == funcdecl.ident)
937 hgs.fullQual = true;
939 // https://issues.dlang.org/show_bug.cgi?id=23745
940 // If the potentially overridden function contains errors,
941 // inform the user to fix that one first
942 if (fd.errors)
944 error(funcdecl.loc, "function `%s` does not override any function, did you mean to override `%s`?",
945 funcdecl.toChars(), fd.toPrettyChars());
946 errorSupplemental(fd.loc, "Function `%s` contains errors in its declaration, therefore it cannot be correctly overridden",
947 fd.toPrettyChars());
949 else
951 functionToBufferFull(cast(TypeFunction)(fd.type), buf1,
952 new Identifier(fd.toPrettyChars()), hgs, null);
954 error(funcdecl.loc, "function `%s` does not override any function, did you mean to override `%s`?",
955 funcdeclToChars, buf1.peekChars());
958 else
960 error(funcdecl.loc, "function `%s` does not override any function, did you mean to override %s `%s`?",
961 funcdeclToChars, s.kind, s.toPrettyChars());
962 errorSupplemental(funcdecl.loc, "Functions are the only declarations that may be overridden");
965 else
966 .error(funcdecl.loc, "%s `%s` does not override any function", funcdecl.kind, funcdecl.toPrettyChars);
970 objc.setSelector(funcdecl, sc);
971 objc.checkLinkage(funcdecl);
972 objc.addToClassMethodList(funcdecl, cd);
973 objc.setAsOptional(funcdecl, sc);
975 /* Go through all the interface bases.
976 * Disallow overriding any final functions in the interface(s).
978 foreach (b; cd.interfaces)
980 if (b.sym)
982 if (auto s = search_function(b.sym, funcdecl.ident))
984 if (auto f2 = s.isFuncDeclaration())
986 f2 = f2.overloadExactMatch(funcdecl.type);
987 if (f2 && f2.isFinalFunc() && f2.visible().kind != Visibility.Kind.private_)
988 .error(funcdecl.loc, "%s `%s` cannot override `final` function `%s.%s`", funcdecl.kind, funcdecl.toPrettyChars, b.sym.toChars(), f2.toPrettyChars());
994 if (funcdecl.isOverride)
996 if (funcdecl.storage_class & STC.disable)
997 deprecation(funcdecl.loc,
998 "`%s` cannot be annotated with `@disable` because it is overriding a function in the base class",
999 funcdecl.toPrettyChars);
1001 if (funcdecl.isDeprecated && !(funcdecl.foverrides.length && funcdecl.foverrides[0].isDeprecated))
1002 deprecation(funcdecl.loc,
1003 "`%s` cannot be marked as `deprecated` because it is overriding a function in the base class",
1004 funcdecl.toPrettyChars);
1008 else if (funcdecl.isOverride() && !parent.isTemplateInstance())
1009 .error(funcdecl.loc, "%s `%s` `override` only applies to class member functions", funcdecl.kind, funcdecl.toPrettyChars);
1011 if (auto ti = parent.isTemplateInstance)
1013 objc.setSelector(funcdecl, sc);
1014 objc.setAsOptional(funcdecl, sc);
1017 objc.validateSelector(funcdecl);
1018 objc.validateOptional(funcdecl);
1019 // Reflect this.type to f because it could be changed by findVtblIndex
1020 f = funcdecl.type.toTypeFunction();
1022 Ldone:
1023 if (!funcdecl.fbody && !funcdecl.allowsContractWithoutBody())
1024 .error(funcdecl.loc, "%s `%s` `in` and `out` contracts can only appear without a body when they are virtual interface functions or abstract", funcdecl.kind, funcdecl.toPrettyChars);
1026 /* Do not allow template instances to add virtual functions
1027 * to a class.
1029 if (funcdecl.isVirtual())
1031 if (auto ti = parent.isTemplateInstance())
1033 // Take care of nested templates
1034 while (1)
1036 TemplateInstance ti2 = ti.tempdecl.parent.isTemplateInstance();
1037 if (!ti2)
1038 break;
1039 ti = ti2;
1042 // If it's a member template
1043 ClassDeclaration cd = ti.tempdecl.isClassMember();
1044 if (cd)
1046 .error(funcdecl.loc, "%s `%s` cannot use template to add virtual function to class `%s`", funcdecl.kind, funcdecl.toPrettyChars, cd.toChars());
1051 funcdecl.checkMain(); // Check main() parameters and return type
1053 /* Purity and safety can be inferred for some functions by examining
1054 * the function body.
1056 if (funcdecl.canInferAttributes(sc))
1057 funcdecl.initInferAttributes();
1059 funcdecl.semanticRun = PASS.semanticdone;
1061 /* Save scope for possible later use (if we need the
1062 * function internals)
1064 funcdecl._scope = sc.copy();
1065 funcdecl._scope.setNoFree();
1067 __gshared bool printedMain = false; // semantic might run more than once
1068 if (global.params.v.verbose && !printedMain)
1070 const(char)* type = funcdecl.isMain() ? "main" : funcdecl.isWinMain() ? "winmain" : funcdecl.isDllMain() ? "dllmain" : cast(const(char)*)null;
1071 Module mod = sc._module;
1073 if (type && mod)
1075 printedMain = true;
1076 auto name = mod.srcfile.toChars();
1077 auto path = FileName.searchPath(global.path, name, true);
1078 message("entry %-10s\t%s", type, path ? path : name);
1082 if (funcdecl.fbody && sc._module.isRoot() &&
1083 (funcdecl.isMain() || funcdecl.isWinMain() || funcdecl.isDllMain() || funcdecl.isCMain()))
1084 global.hasMainFunction = true;
1086 if (funcdecl.fbody && funcdecl.isMain() && sc._module.isRoot())
1088 // check if `_d_cmain` is defined
1089 bool cmainTemplateExists()
1091 Dsymbol pscopesym;
1092 auto rootSymbol = sc.search(funcdecl.loc, Id.empty, pscopesym);
1093 if (auto moduleSymbol = rootSymbol.search(funcdecl.loc, Id.object))
1094 if (moduleSymbol.search(funcdecl.loc, Id.CMain))
1095 return true;
1097 return false;
1100 // Only mixin `_d_cmain` if it is defined
1101 if (cmainTemplateExists())
1103 // add `mixin _d_cmain!();` to the declaring module
1104 auto tqual = new TypeIdentifier(funcdecl.loc, Id.CMain);
1105 auto tm = new TemplateMixin(funcdecl.loc, null, tqual, null);
1106 sc._module.members.push(tm);
1110 assert(funcdecl.type.ty != Terror || funcdecl.errors);
1112 // semantic for parameters' UDAs
1113 foreach (i, param; f.parameterList)
1115 if (param && param.userAttribDecl)
1116 param.userAttribDecl.dsymbolSemantic(sc);
1121 /****************************************************
1122 * Resolve forward reference of function signature -
1123 * parameter types, return type, and attributes.
1124 * Params:
1125 * fd = function declaration
1126 * Returns:
1127 * false if any errors exist in the signature.
1129 public
1130 bool functionSemantic(FuncDeclaration fd)
1132 //printf("functionSemantic() %p %s\n", this, toChars());
1133 if (!fd._scope)
1134 return !fd.errors;
1136 fd.cppnamespace = fd._scope.namespace;
1138 if (!fd.originalType) // semantic not yet run
1140 TemplateInstance spec = fd.isSpeculative();
1141 uint olderrs = global.errors;
1142 uint oldgag = global.gag;
1143 if (global.gag && !spec)
1144 global.gag = 0;
1145 dsymbolSemantic(fd, fd._scope);
1146 global.gag = oldgag;
1147 if (spec && global.errors != olderrs)
1148 spec.errors = (global.errors - olderrs != 0);
1149 if (olderrs != global.errors) // if errors compiling this function
1150 return false;
1153 // if inferring return type, sematic3 needs to be run
1154 // - When the function body contains any errors, we cannot assume
1155 // the inferred return type is valid.
1156 // So, the body errors should become the function signature error.
1157 if (fd.inferRetType && fd.type && !fd.type.nextOf())
1158 return fd.functionSemantic3();
1160 TemplateInstance ti;
1161 if (fd.isInstantiated() && !fd.isVirtualMethod() &&
1162 ((ti = fd.parent.isTemplateInstance()) is null || ti.isTemplateMixin() || ti.tempdecl.ident == fd.ident))
1164 AggregateDeclaration ad = fd.isMemberLocal();
1165 if (ad && ad.sizeok != Sizeok.done)
1167 /* Currently dmd cannot resolve forward references per methods,
1168 * then setting SIZOKfwd is too conservative and would break existing code.
1169 * So, just stop method attributes inference until ad.dsymbolSemantic() done.
1171 //ad.sizeok = Sizeok.fwd;
1173 else
1174 return fd.functionSemantic3() || !fd.errors;
1177 if (fd.storage_class & STC.inference)
1178 return fd.functionSemantic3() || !fd.errors;
1180 return !fd.errors;
1183 /****************************************************
1184 * Resolve forward reference of function body.
1185 * Returns false if any errors exist in the body.
1187 public
1188 bool functionSemantic3(FuncDeclaration fd)
1190 if (fd.semanticRun < PASS.semantic3 && fd._scope)
1192 /* Forward reference - we need to run semantic3 on this function.
1193 * If errors are gagged, and it's not part of a template instance,
1194 * we need to temporarily ungag errors.
1196 TemplateInstance spec = fd.isSpeculative();
1197 uint olderrs = global.errors;
1198 uint oldgag = global.gag;
1199 if (global.gag && !spec)
1200 global.gag = 0;
1201 semantic3(fd, fd._scope);
1202 global.gag = oldgag;
1204 // If it is a speculatively-instantiated template, and errors occur,
1205 // we need to mark the template as having errors.
1206 if (spec && global.errors != olderrs)
1207 spec.errors = (global.errors - olderrs != 0);
1208 if (olderrs != global.errors) // if errors compiling this function
1209 return false;
1212 return !fd.errors && !fd.hasSemantic3Errors();
1215 // called from semantic3
1217 * Creates and returns the hidden parameters for this function declaration.
1219 * Hidden parameters include the `this` parameter of a class, struct or
1220 * nested function and the selector parameter for Objective-C methods.
1222 extern (D) void declareThis(FuncDeclaration fd, Scope* sc)
1224 const bool dualCtx = (fd.toParent2() != fd.toParentLocal());
1225 if (dualCtx)
1226 fd.hasDualContext = true;
1227 auto ad = fd.isThis();
1228 if (!dualCtx && !ad && !fd.isNested())
1230 fd.vthis = null;
1231 fd.objc.selectorParameter = null;
1232 return;
1235 Type addModStc(Type t)
1237 return t.addMod(fd.type.mod).addStorageClass(fd.storage_class);
1240 if (dualCtx || fd.isNested())
1242 /* The 'this' for a nested function is the link to the
1243 * enclosing function's stack frame.
1244 * Note that nested functions and member functions are disjoint.
1246 Type tthis = addModStc(dualCtx ?
1247 Type.tvoidptr.sarrayOf(2).pointerTo() :
1248 Type.tvoid.pointerTo());
1249 fd.vthis = new VarDeclaration(fd.loc, tthis, dualCtx ? Id.this2 : Id.capture, null);
1250 fd.vthis.storage_class |= STC.parameter | STC.nodtor;
1252 else if (ad)
1254 Type thandle = addModStc(ad.handleType());
1255 fd.vthis = new ThisDeclaration(fd.loc, thandle);
1256 fd.vthis.storage_class |= STC.parameter;
1257 if (thandle.ty == Tstruct)
1259 fd.vthis.storage_class |= STC.ref_;
1263 if (auto tf = fd.type.isTypeFunction())
1265 if (tf.isreturn)
1266 fd.vthis.storage_class |= STC.return_;
1267 if (tf.isScopeQual)
1268 fd.vthis.storage_class |= STC.scope_;
1269 if (tf.isreturnscope)
1270 fd.vthis.storage_class |= STC.returnScope;
1273 fd.vthis.dsymbolSemantic(sc);
1274 if (!sc.insert(fd.vthis))
1275 assert(0);
1276 fd.vthis.parent = fd;
1277 if (ad)
1278 fd.objc.selectorParameter = .objc.createSelectorParameter(fd, sc);
1281 /****************************************************
1282 * Check that this function type is properly resolved.
1283 * If not, report "forward reference error" and return true.
1285 extern (D) bool checkForwardRef(FuncDeclaration fd, const ref Loc loc)
1287 if (!functionSemantic(fd))
1288 return true;
1290 /* No deco means the functionSemantic() call could not resolve
1291 * forward referenes in the type of this function.
1293 if (!fd.type.deco)
1295 bool inSemantic3 = (fd.inferRetType && fd.semanticRun >= PASS.semantic3);
1296 .error(loc, "forward reference to %s`%s`",
1297 (inSemantic3 ? "inferred return type of function " : "").ptr,
1298 fd.toChars());
1299 return true;
1301 return false;
1304 /*************************************************
1305 * Find index of function in vtbl[0..length] that
1306 * this function overrides.
1307 * Prefer an exact match to a covariant one.
1308 * Params:
1309 * fd = function
1310 * vtbl = vtable to use
1311 * Returns:
1312 * -1 didn't find one
1313 * -2 can't determine because of forward references
1315 int findVtblIndex(FuncDeclaration fd, Dsymbol[] vtbl)
1317 //printf("findVtblIndex() %s\n", toChars());
1318 import dmd.typesem : covariant;
1320 FuncDeclaration mismatch = null;
1321 StorageClass mismatchstc = 0;
1322 int mismatchvi = -1;
1323 int exactvi = -1;
1324 int bestvi = -1;
1325 for (int vi = 0; vi < cast(int)vtbl.length; vi++)
1327 FuncDeclaration fdv = vtbl[vi].isFuncDeclaration();
1328 if (fdv && fdv.ident == fd.ident)
1330 if (fd.type.equals(fdv.type)) // if exact match
1332 if (fdv.parent.isClassDeclaration())
1334 if (fdv.isFuture())
1336 bestvi = vi;
1337 continue; // keep looking
1339 return vi; // no need to look further
1342 if (exactvi >= 0)
1344 .error(fd.loc, "%s `%s` cannot determine overridden function", fd.kind, fd.toPrettyChars);
1345 return exactvi;
1347 exactvi = vi;
1348 bestvi = vi;
1349 continue;
1352 StorageClass stc = 0;
1353 const cov = fd.type.covariant(fdv.type, &stc);
1354 //printf("\tbaseclass cov = %d\n", cov);
1355 final switch (cov)
1357 case Covariant.distinct:
1358 // types are distinct
1359 break;
1361 case Covariant.yes:
1362 bestvi = vi; // covariant, but not identical
1363 break;
1364 // keep looking for an exact match
1366 case Covariant.no:
1367 mismatchvi = vi;
1368 mismatchstc = stc;
1369 mismatch = fdv; // overrides, but is not covariant
1370 break;
1371 // keep looking for an exact match
1373 case Covariant.fwdref:
1374 return -2; // forward references
1378 if (fd._linkage == LINK.cpp && bestvi != -1)
1380 StorageClass stc = 0;
1381 FuncDeclaration fdv = vtbl[bestvi].isFuncDeclaration();
1382 assert(fdv && fdv.ident == fd.ident);
1383 if (fd.type.covariant(fdv.type, &stc, /*cppCovariant=*/true) == Covariant.no)
1385 /* https://issues.dlang.org/show_bug.cgi?id=22351
1386 * Under D rules, `type` and `fdv.type` are covariant, but under C++ rules, they are not.
1387 * For now, continue to allow D covariant rules to apply when `override` has been used,
1388 * but issue a deprecation warning that this behaviour will change in the future.
1389 * Otherwise, follow the C++ covariant rules, which will create a new vtable entry.
1391 if (fd.isOverride())
1393 /* @@@DEPRECATED_2.110@@@
1394 * After deprecation period has ended, be sure to remove this entire `LINK.cpp` branch,
1395 * but also the `cppCovariant` parameter from Type.covariant, and update the function
1396 * so that both `LINK.cpp` covariant conditions within are always checked.
1398 .deprecation(fd.loc, "overriding `extern(C++)` function `%s%s` with `const` qualified function `%s%s%s` is deprecated",
1399 fdv.toPrettyChars(), fdv.type.toTypeFunction().parameterList.parametersTypeToChars(),
1400 fd.toPrettyChars(), fd.type.toTypeFunction().parameterList.parametersTypeToChars(), fd.type.modToChars());
1402 const char* where = fd.type.isNaked() ? "parameters" : "type";
1403 deprecationSupplemental(fd.loc, "Either remove `override`, or adjust the `const` qualifiers of the "
1404 ~ "overriding function %s", where);
1406 else
1408 // Treat as if Covariant.no
1409 mismatchvi = bestvi;
1410 mismatchstc = stc;
1411 mismatch = fdv;
1412 bestvi = -1;
1416 if (bestvi == -1 && mismatch)
1418 //type.print();
1419 //mismatch.type.print();
1420 //printf("%s %s\n", type.deco, mismatch.type.deco);
1421 //printf("stc = %llx\n", mismatchstc);
1422 if (mismatchstc)
1424 // Fix it by modifying the type to add the storage classes
1425 fd.type = fd.type.addStorageClass(mismatchstc);
1426 bestvi = mismatchvi;
1429 return bestvi;
1432 /*********************************
1433 * If function is a function in a base class,
1434 * return that base class.
1435 * Params:
1436 * fd = function
1437 * Returns:
1438 * base class if overriding, null if not
1440 BaseClass* overrideInterface(FuncDeclaration fd)
1442 for (ClassDeclaration cd = fd.toParent2().isClassDeclaration(); cd; cd = cd.baseClass)
1444 foreach (b; cd.interfaces)
1446 auto v = findVtblIndex(fd, b.sym.vtbl[]);
1447 if (v >= 0)
1448 return b;
1451 return null;
1454 /// Flag used by $(LREF resolveFuncCall).
1455 enum FuncResolveFlag : ubyte
1457 standard = 0, /// issue error messages, solve the call.
1458 quiet = 1, /// do not issue error message on no match, just return `null`.
1459 overloadOnly = 2, /// only resolve overloads, i.e. do not issue error on ambiguous
1460 /// matches and need explicit this.
1461 ufcs = 4, /// trying to resolve UFCS call
1464 /*******************************************
1465 * Given a symbol that could be either a FuncDeclaration or
1466 * a function template, resolve it to a function symbol.
1467 * Params:
1468 * loc = instantiation location
1469 * sc = instantiation scope
1470 * s = instantiation symbol
1471 * tiargs = initial list of template arguments
1472 * tthis = if !NULL, the `this` argument type
1473 * argumentList = arguments to function
1474 * flags = see $(LREF FuncResolveFlag).
1475 * Returns:
1476 * if match is found, then function symbol, else null
1478 FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
1479 Objects* tiargs, Type tthis, ArgumentList argumentList, FuncResolveFlag flags)
1481 auto fargs = argumentList.arguments;
1482 if (!s)
1483 return null; // no match
1485 version (none)
1487 printf("resolveFuncCall('%s')\n", s.toChars());
1488 if (tthis)
1489 printf("\tthis: %s\n", tthis.toChars());
1490 if (fargs)
1492 for (size_t i = 0; i < fargs.length; i++)
1494 Expression arg = (*fargs)[i];
1495 assert(arg.type);
1496 printf("\t%s: %s\n", arg.toChars(), arg.type.toChars());
1499 printf("\tfnames: %s\n", fnames ? fnames.toChars() : "null");
1502 if (tiargs && arrayObjectIsError(*tiargs))
1503 return null;
1504 if (fargs !is null)
1505 foreach (arg; *fargs)
1506 if (isError(arg))
1507 return null;
1509 MatchAccumulator m;
1510 functionResolve(m, s, loc, sc, tiargs, tthis, argumentList);
1511 auto orig_s = s;
1513 if (m.last > MATCH.nomatch && m.lastf)
1515 if (m.count == 1) // exactly one match
1517 if (!(flags & FuncResolveFlag.quiet))
1518 functionSemantic(m.lastf);
1519 return m.lastf;
1521 if ((flags & FuncResolveFlag.overloadOnly) && !tthis && m.lastf.needThis())
1523 return m.lastf;
1527 /* Failed to find a best match.
1528 * Do nothing or print error.
1530 if (m.last == MATCH.nomatch)
1532 // error was caused on matched function, not on the matching itself,
1533 // so return the function to produce a better diagnostic
1534 if (m.count == 1)
1535 return m.lastf;
1538 // We are done at this point, as the rest of this function generate
1539 // a diagnostic on invalid match
1540 if (flags & FuncResolveFlag.quiet)
1541 return null;
1543 auto fd = s.isFuncDeclaration();
1544 auto od = s.isOverDeclaration();
1545 auto td = s.isTemplateDeclaration();
1546 if (td && td.funcroot)
1547 s = fd = td.funcroot;
1549 OutBuffer tiargsBuf;
1550 arrayObjectsToBuffer(tiargsBuf, tiargs);
1552 OutBuffer fargsBuf;
1553 fargsBuf.writeByte('(');
1554 argExpTypesToCBuffer(fargsBuf, fargs);
1555 fargsBuf.writeByte(')');
1556 if (tthis)
1557 tthis.modToBuffer(fargsBuf);
1559 // The call is ambiguous
1560 if (m.lastf && m.nextf)
1562 TypeFunction tf1 = m.lastf.type.toTypeFunction();
1563 TypeFunction tf2 = m.nextf.type.toTypeFunction();
1564 const(char)* lastprms = parametersTypeToChars(tf1.parameterList);
1565 const(char)* nextprms = parametersTypeToChars(tf2.parameterList);
1567 .error(loc, "`%s.%s` called with argument types `%s` matches both:\n%s: `%s%s%s`\nand:\n%s: `%s%s%s`",
1568 s.parent.toPrettyChars(), s.ident.toChars(),
1569 fargsBuf.peekChars(),
1570 m.lastf.loc.toChars(), m.lastf.toPrettyChars(), lastprms, tf1.modToChars(),
1571 m.nextf.loc.toChars(), m.nextf.toPrettyChars(), nextprms, tf2.modToChars());
1572 return null;
1575 // no match, generate an error messages
1576 if (flags & FuncResolveFlag.ufcs)
1578 auto arg = (*fargs)[0];
1579 .error(loc, "no property `%s` for `%s` of type `%s`", s.ident.toChars(), arg.toChars(), arg.type.toChars());
1580 .errorSupplemental(loc, "the following error occured while looking for a UFCS match");
1583 if (!fd)
1585 // all of overloads are templates
1586 if (td)
1588 if (!od && !td.overnext)
1590 .error(loc, "%s `%s` is not callable using argument types `!(%s)%s`",
1591 td.kind(), td.ident.toChars(), tiargsBuf.peekChars(), fargsBuf.peekChars());
1593 else
1595 .error(loc, "none of the overloads of %s `%s.%s` are callable using argument types `!(%s)%s`",
1596 td.kind(), td.parent.toPrettyChars(), td.ident.toChars(),
1597 tiargsBuf.peekChars(), fargsBuf.peekChars());
1601 if (!global.gag || global.params.v.showGaggedErrors)
1602 printCandidates(loc, td, sc.isDeprecated());
1603 return null;
1605 /* This case used to happen when several ctors are mixed in an agregate.
1606 A (bad) error message is already generated in overloadApply().
1607 see https://issues.dlang.org/show_bug.cgi?id=19729
1608 and https://issues.dlang.org/show_bug.cgi?id=17259
1610 if (!od)
1611 return null;
1614 if (od)
1616 .error(loc, "none of the overloads of `%s` are callable using argument types `!(%s)%s`",
1617 od.ident.toChars(), tiargsBuf.peekChars(), fargsBuf.peekChars());
1618 return null;
1621 // remove when deprecation period of class allocators and deallocators is over
1622 if (fd.isNewDeclaration() && fd.checkDisabled(loc, sc))
1623 return null;
1625 bool hasOverloads = fd.overnext !is null;
1626 auto tf = fd.type.isTypeFunction();
1627 // if type is an error, the original type should be there for better diagnostics
1628 if (!tf)
1629 tf = fd.originalType.toTypeFunction();
1631 // modifier mismatch
1632 if (tthis && (fd.isCtorDeclaration() ?
1633 !MODimplicitConv(tf.mod, tthis.mod) :
1634 !MODimplicitConv(tthis.mod, tf.mod)))
1636 OutBuffer thisBuf, funcBuf;
1637 MODMatchToBuffer(&thisBuf, tthis.mod, tf.mod);
1638 auto mismatches = MODMatchToBuffer(&funcBuf, tf.mod, tthis.mod);
1639 if (hasOverloads)
1641 OutBuffer buf;
1642 buf.argExpTypesToCBuffer(fargs);
1643 if (fd.isCtorDeclaration())
1644 .error(loc, "none of the overloads of `%s` can construct a %sobject with argument types `(%s)`",
1645 fd.toChars(), thisBuf.peekChars(), buf.peekChars());
1646 else
1647 .error(loc, "none of the overloads of `%s` are callable using a %sobject with argument types `(%s)`",
1648 fd.toChars(), thisBuf.peekChars(), buf.peekChars());
1650 if (!global.gag || global.params.v.showGaggedErrors)
1651 printCandidates(loc, fd, sc.isDeprecated());
1652 return null;
1655 bool calledHelper;
1656 void errorHelper(const(char)* failMessage) scope
1658 .error(loc, "%s `%s%s%s` is not callable using argument types `%s`",
1659 fd.kind(), fd.toPrettyChars(), parametersTypeToChars(tf.parameterList),
1660 tf.modToChars(), fargsBuf.peekChars());
1661 errorSupplemental(loc, failMessage);
1662 calledHelper = true;
1665 functionResolve(m, orig_s, loc, sc, tiargs, tthis, argumentList, &errorHelper);
1666 if (calledHelper)
1667 return null;
1669 if (fd.isCtorDeclaration())
1670 .error(loc, "%s%s `%s` cannot construct a %sobject",
1671 funcBuf.peekChars(), fd.kind(), fd.toPrettyChars(), thisBuf.peekChars());
1672 else
1673 .error(loc, "%smethod `%s` is not callable using a %sobject",
1674 funcBuf.peekChars(), fd.toPrettyChars(), thisBuf.peekChars());
1676 if (mismatches.isNotShared)
1677 .errorSupplemental(fd.loc, "Consider adding `shared` here");
1678 else if (mismatches.isMutable)
1679 .errorSupplemental(fd.loc, "Consider adding `const` or `inout` here");
1680 return null;
1683 //printf("tf = %s, args = %s\n", tf.deco, (*fargs)[0].type.deco);
1684 if (hasOverloads)
1686 .error(loc, "none of the overloads of `%s` are callable using argument types `%s`",
1687 fd.toChars(), fargsBuf.peekChars());
1688 if (!global.gag || global.params.v.showGaggedErrors)
1689 printCandidates(loc, fd, sc.isDeprecated());
1690 return null;
1693 .error(loc, "%s `%s%s%s` is not callable using argument types `%s`",
1694 fd.kind(), fd.toPrettyChars(), parametersTypeToChars(tf.parameterList),
1695 tf.modToChars(), fargsBuf.peekChars());
1697 // re-resolve to check for supplemental message
1698 if (!global.gag || global.params.v.showGaggedErrors)
1700 if (tthis)
1702 if (auto classType = tthis.isTypeClass())
1704 if (auto baseClass = classType.sym.baseClass)
1706 if (auto baseFunction = baseClass.search(baseClass.loc, fd.ident))
1708 MatchAccumulator mErr;
1709 functionResolve(mErr, baseFunction, loc, sc, tiargs, baseClass.type, argumentList);
1710 if (mErr.last > MATCH.nomatch && mErr.lastf)
1712 errorSupplemental(loc, "%s `%s` hides base class function `%s`",
1713 fd.kind, fd.toPrettyChars(), mErr.lastf.toPrettyChars());
1714 errorSupplemental(loc, "add `alias %s = %s` to `%s`'s body to merge the overload sets",
1715 fd.toChars(), mErr.lastf.toPrettyChars(), tthis.toChars());
1716 return null;
1723 void errorHelper2(const(char)* failMessage) scope
1725 errorSupplemental(loc, failMessage);
1728 functionResolve(m, orig_s, loc, sc, tiargs, tthis, argumentList, &errorHelper2);
1730 return null;
1733 /*******************************************
1734 * Prints template and function overload candidates as supplemental errors.
1735 * Params:
1736 * loc = instantiation location
1737 * declaration = the declaration to print overload candidates for
1738 * showDeprecated = If `false`, `deprecated` function won't be shown
1740 private void printCandidates(Decl)(const ref Loc loc, Decl declaration, bool showDeprecated)
1741 if (is(Decl == TemplateDeclaration) || is(Decl == FuncDeclaration))
1743 // max num of overloads to print (-v or -verror-supplements overrides this).
1744 const uint DisplayLimit = global.params.v.errorSupplementCount();
1745 const(char)* constraintsTip;
1746 // determine if the first candidate was printed
1747 int printed;
1749 bool matchSymbol(Dsymbol s, bool print, bool single_candidate = false)
1751 if (auto fd = s.isFuncDeclaration())
1753 // Don't print overloads which have errors.
1754 // Not that if the whole overload set has errors, we'll never reach
1755 // this point so there's no risk of printing no candidate
1756 if (fd.errors || fd.type.ty == Terror)
1757 return false;
1758 // Don't print disabled functions, or `deprecated` outside of deprecated scope
1759 if (fd.storage_class & STC.disable || (fd.isDeprecated() && !showDeprecated))
1760 return false;
1761 if (!print)
1762 return true;
1763 auto tf = cast(TypeFunction) fd.type;
1764 OutBuffer buf;
1765 buf.writestring(fd.toPrettyChars());
1766 buf.writestring(parametersTypeToChars(tf.parameterList));
1767 if (tf.mod)
1769 buf.writeByte(' ');
1770 buf.MODtoBuffer(tf.mod);
1772 .errorSupplemental(fd.loc,
1773 printed ? " `%s`" :
1774 single_candidate ? "Candidate is: `%s`" : "Candidates are: `%s`", buf.peekChars());
1776 else if (auto td = s.isTemplateDeclaration())
1778 import dmd.staticcond;
1780 if (!print)
1781 return true;
1782 OutBuffer buf;
1783 HdrGenState hgs;
1784 hgs.skipConstraints = true;
1785 toCharsMaybeConstraints(td, buf, hgs);
1786 const tmsg = buf.peekChars();
1787 const cmsg = td.getConstraintEvalError(constraintsTip);
1789 // add blank space if there are multiple candidates
1790 // the length of the blank space is `strlen("Candidates are: ")`
1792 if (cmsg)
1794 .errorSupplemental(td.loc,
1795 printed ? " `%s`\n%s" :
1796 single_candidate ? "Candidate is: `%s`\n%s" : "Candidates are: `%s`\n%s",
1797 tmsg, cmsg);
1799 else
1801 .errorSupplemental(td.loc,
1802 printed ? " `%s`" :
1803 single_candidate ? "Candidate is: `%s`" : "Candidates are: `%s`",
1804 tmsg);
1807 return true;
1809 // determine if there's > 1 candidate
1810 int count = 0;
1811 overloadApply(declaration, (s) {
1812 if (matchSymbol(s, false))
1813 count++;
1814 return count > 1;
1816 int skipped = 0;
1817 overloadApply(declaration, (s) {
1818 if (global.params.v.verbose || printed < DisplayLimit)
1820 if (matchSymbol(s, true, count == 1))
1821 printed++;
1823 else
1825 // Too many overloads to sensibly display.
1826 // Just show count of remaining overloads.
1827 if (matchSymbol(s, false))
1828 skipped++;
1830 return 0;
1832 if (skipped > 0)
1833 .errorSupplemental(loc, "... (%d more, -v to show) ...", skipped);
1835 // Nothing was displayed, all overloads are either disabled or deprecated
1836 if (!printed)
1837 .errorSupplemental(loc, "All possible candidates are marked as `deprecated` or `@disable`");
1838 // should be only in verbose mode
1839 if (constraintsTip)
1840 .tip(constraintsTip);
1843 /********************************************************
1844 * Generate Expression to call the invariant.
1845 * Input:
1846 * ad aggregate with the invariant
1847 * vthis variable with 'this'
1848 * Returns:
1849 * void expression that calls the invariant
1851 Expression addInvariant(AggregateDeclaration ad, VarDeclaration vthis)
1853 Expression e = null;
1854 // Call invariant directly only if it exists
1855 FuncDeclaration inv = ad.inv;
1856 ClassDeclaration cd = ad.isClassDeclaration();
1858 while (!inv && cd)
1860 cd = cd.baseClass;
1861 if (!cd)
1862 break;
1863 inv = cd.inv;
1865 if (inv)
1867 version (all)
1869 // Workaround for https://issues.dlang.org/show_bug.cgi?id=13394
1870 // For the correct mangling,
1871 // run attribute inference on inv if needed.
1872 functionSemantic(inv);
1875 //e = new DsymbolExp(Loc.initial, inv);
1876 //e = new CallExp(Loc.initial, e);
1877 //e = e.semantic(sc2);
1879 /* https://issues.dlang.org/show_bug.cgi?id=13113
1880 * Currently virtual invariant calls completely
1881 * bypass attribute enforcement.
1882 * Change the behavior of pre-invariant call by following it.
1884 e = new ThisExp(Loc.initial);
1885 e.type = ad.type.addMod(vthis.type.mod);
1886 e = new DotVarExp(Loc.initial, e, inv, false);
1887 e.type = inv.type;
1888 e = new CallExp(Loc.initial, e);
1889 e.type = Type.tvoid;
1891 return e;
1894 /****************************************************
1895 * Declare result variable lazily.
1897 void buildResultVar(FuncDeclaration fd, Scope* sc, Type tret)
1899 if (!fd.vresult)
1901 Loc loc = fd.fensure ? fd.fensure.loc : fd.loc;
1902 /* If inferRetType is true, tret may not be a correct return type yet.
1903 * So, in here it may be a temporary type for vresult, and after
1904 * fbody.dsymbolSemantic() running, vresult.type might be modified.
1906 fd.vresult = new VarDeclaration(loc, tret, Id.result, null);
1907 fd.vresult.storage_class |= STC.nodtor | STC.temp;
1908 if (!fd.isVirtual())
1909 fd.vresult.storage_class |= STC.const_;
1910 fd.vresult.storage_class |= STC.result;
1911 // set before the semantic() for checkNestedReference()
1912 fd.vresult.parent = fd;
1914 if (sc && fd.vresult.semanticRun == PASS.initial)
1916 TypeFunction tf = fd.type.toTypeFunction();
1917 if (tf.isref)
1918 fd.vresult.storage_class |= STC.ref_;
1919 fd.vresult.type = tret;
1920 fd.vresult.dsymbolSemantic(sc);
1921 if (!sc.insert(fd.vresult))
1922 .error(fd.loc, "%s `%s` out result %s is already defined", fd.kind, fd.toPrettyChars, fd.vresult.toChars());
1923 assert(fd.vresult.parent == fd);