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
16 import core
.stdc
.stdio
;
19 import dmd
.arraytypes
;
26 import dmd
.declaration
;
27 import dmd
.delegatize
;
28 import dmd
.dinterpret
;
33 import dmd
.dsymbolsem
;
37 import dmd
.expression
;
42 import dmd
.identifier
;
52 import dmd
.common
.outbuffer
;
53 import dmd
.rootobject
;
54 import dmd
.root
.filename
;
55 import dmd
.root
.string
;
56 import dmd
.root
.stringtable
;
59 import dmd
.statement_rewrite_walker
;
61 import dmd
.statementsem
;
63 import dmd
.templatesem
;
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
;
77 override void visit(ReturnStatement s
)
79 // See if all returns are instead to be replaced with a goto returnLabel;
85 * vresult = exp; goto Lresult;
87 auto gs
= new GotoStatement(s
.loc
, Id
.returnLabel
);
88 gs
.label
= fd
.returnLabel
;
92 s1
= new CompoundStatement(s
.loc
, new ExpStatement(s
.loc
, s
.exp
), gs
);
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);
113 /* Normally local variable dtors are called regardless exceptions.
114 * But for nrvo_var, its dtor should be called only when exception is thrown.
117 * try { s.body; } finally { nrvo_var.edtor; }
118 * // equivalent with:
119 * // s.body; scope(exit) nrvo_var.edtor;
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'
142 Statement s2
= new TryCatchStatement(Loc
.initial
, s
._body
, catches
);
148 StatementRewriteWalker
.visit(s
);
152 /**********************************
153 * Main semantic routine for functions.
155 void funcDeclarationSemantic(Scope
* sc
, FuncDeclaration funcdecl
)
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
171 * See test\interface2.d, test20
176 if (funcdecl
.semanticRun
>= PASS
.semanticdone
)
178 assert(funcdecl
.semanticRun
<= PASS
.semantic
);
179 funcdecl
.semanticRun
= PASS
.semantic
;
183 sc
= funcdecl
._scope
;
184 funcdecl
._scope
= null;
187 if (!sc || funcdecl
.errors
)
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_
);
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())
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_
;
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())
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
;
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
))
284 if (!funcdecl
.type
.deco
)
287 sc
.stc |
= funcdecl
.storage_class
& (STC
.disable | STC
.deprecated_
); // forward to function type
289 TypeFunction tf
= funcdecl
.type
.toTypeFunction();
292 /* If the nesting parent is pure without inference,
293 * then this function defaults to pure too.
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())
317 if ((fd
= p
.isFuncDeclaration()) !is null)
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
334 sc
.stc |
= STC
.scope_
;
336 sc
.stc |
= STC
.nothrow_
;
340 sc
.stc |
= STC
.property
;
341 if (tf
.purity
== PURE
.fwdref
)
344 if (tf
.trust
!= TRUST
.default_
)
346 sc
.stc &= ~STC
.safeGroup
;
347 if (tf
.trust
== TRUST
.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())
358 Type tret
= ad
.handleType();
360 tret
= tret
.addStorageClass(funcdecl
.storage_class | sc
.stc);
361 tret
= tret
.addMod(funcdecl
.type
.mod
);
363 if (ad
.isStructDeclaration())
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
);
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())
409 if (funcdecl
.type
.isShared() || funcdecl
.storage_class
& STC
.synchronized_
)
411 if (funcdecl
.type
.isWild())
413 funcdecl
.type
= funcdecl
.type
.addSTC(stc);
415 funcdecl
.type
= funcdecl
.type
.typeSemantic(funcdecl
.loc
, sc
);
419 auto f
= getFunctionType(funcdecl
);
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();
428 tfo
.isScopeQual
= f
.isScopeQual
;
429 tfo
.isreturninferred
= f
.isreturninferred
;
430 tfo
.isscopeinferred
= f
.isscopeinferred
;
432 tfo
.isnothrow
= f
.isnothrow
;
433 tfo
.isnogc
= f
.isnogc
;
434 tfo
.isproperty
= f
.isproperty
;
435 tfo
.purity
= f
.purity
;
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
);
482 error(funcdecl
.loc
, "top-level function `%s` has no `this` to which `return` can apply", funcdecl
.toChars());
485 if (funcdecl
.isAbstract() && !funcdecl
.isVirtual())
488 if (funcdecl
.isStatic())
490 else if (funcdecl
.visibility
.kind
== Visibility
.Kind
.private_ || funcdecl
.visibility
.kind
== Visibility
.Kind
.package_
)
491 sfunc
= visibilityToChars(funcdecl
.visibility
.kind
);
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
));
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())
537 if (ClassDeclaration cd
= parent
.isClassDeclaration())
539 parent
= cd
= objc
.getParent(funcdecl
, cd
);
541 if (funcdecl
.isCtorDeclaration())
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");
555 // Suppress further errors if the return type is an error
556 if (funcdecl
.type
.nextOf() == Type
.terror
)
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();
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
)
571 if (cbd
.parent
&& cbd
.parent
.isTemplateInstance())
573 if (!functionSemantic(f2
))
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;
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
605 Dsymbol s
= cd
.baseClass
.search(funcdecl
.loc
, funcdecl
.ident
);
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
);
636 if (funcdecl
.isFinalFunc())
638 // Don't check here, as it may override an interface function
640 // error("is marked as override, but does not override any function");
641 cd
.vtblFinal
.push(funcdecl
);
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
;
655 foreach (const i
, s
; cd
.vtbl
)
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
;
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
682 // Append to end of vtbl[]
683 vi
= cast(int)cd
.vtbl
.length
;
684 cd
.vtbl
.push(funcdecl
);
685 funcdecl
.vtblIndex
= vi
;
691 // can't determine because of forward references
692 funcdecl
.errors
= true;
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;
706 FuncDeclaration fdv
= cd
.baseClass
.vtbl
[vi
].isFuncDeclaration();
707 FuncDeclaration fdc
= cd
.vtbl
[vi
].isFuncDeclaration();
708 // This function is covariant with fdv
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
,
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
)
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())
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[]
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());
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
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
;
783 fdc
.vtblIndex
= vitmp
;
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
;
797 else // fdc overrides fdv
799 // this doesn't override any function
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.
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
832 if (fdv
.type
.nextOf().isBaseOf(tnext
, &offset
))
834 funcdecl
.tintro
= fdv
.type
;
841 /* Go through all the interface bases.
842 * If this function is covariant with any members of those interface
843 * functions, set the tintro.
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
[]);
859 // can't determine because of forward references
860 funcdecl
.errors
= true;
865 auto fdv
= cast(FuncDeclaration
)b
.sym
.vtbl
[vi
];
868 foundVtblMatch
= true;
870 /* Remember which functions this overrides
872 funcdecl
.foverrides
.push(fdv
);
876 else if (!funcdecl
.type
.equals(fdv
.type
))
878 /* Only need to have a tintro if the vptr
882 if (fdv
.type
.nextOf().isBaseOf(funcdecl
.type
.nextOf(), &offset
))
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());
898 funcdecl
.tintro
= ti
;
910 if (!doesoverride
&& funcdecl
.isOverride() && (funcdecl
.type
.nextOf() ||
!may_override
))
912 BaseClass
* bc
= 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
);
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();
936 if (fd
.ident
== funcdecl
.ident
)
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
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",
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());
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");
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
)
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();
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
1029 if (funcdecl
.isVirtual())
1031 if (auto ti
= parent
.isTemplateInstance())
1033 // Take care of nested templates
1036 TemplateInstance ti2
= ti
.tempdecl
.parent
.isTemplateInstance();
1042 // If it's a member template
1043 ClassDeclaration cd
= ti
.tempdecl
.isClassMember();
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
;
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()
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
))
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.
1125 * fd = function declaration
1127 * false if any errors exist in the signature.
1130 bool functionSemantic(FuncDeclaration fd
)
1132 //printf("functionSemantic() %p %s\n", this, toChars());
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
)
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
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;
1174 return fd
.functionSemantic3() ||
!fd
.errors
;
1177 if (fd
.storage_class
& STC
.inference
)
1178 return fd
.functionSemantic3() ||
!fd
.errors
;
1183 /****************************************************
1184 * Resolve forward reference of function body.
1185 * Returns false if any errors exist in the body.
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
)
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
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());
1226 fd
.hasDualContext
= true;
1227 auto ad
= fd
.isThis();
1228 if (!dualCtx
&& !ad
&& !fd
.isNested())
1231 fd
.objc
.selectorParameter
= null;
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
;
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())
1266 fd
.vthis
.storage_class |
= STC
.return_
;
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
))
1276 fd
.vthis
.parent
= fd
;
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
))
1290 /* No deco means the functionSemantic() call could not resolve
1291 * forward referenes in the type of this function.
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
,
1304 /*************************************************
1305 * Find index of function in vtbl[0..length] that
1306 * this function overrides.
1307 * Prefer an exact match to a covariant one.
1310 * vtbl = vtable to use
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;
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())
1337 continue; // keep looking
1339 return vi
; // no need to look further
1344 .error(fd
.loc
, "%s `%s` cannot determine overridden function", fd
.kind
, fd
.toPrettyChars
);
1352 StorageClass
stc = 0;
1353 const cov
= fd
.type
.covariant(fdv
.type
, &stc);
1354 //printf("\tbaseclass cov = %d\n", cov);
1357 case Covariant
.distinct
:
1358 // types are distinct
1362 bestvi
= vi
; // covariant, but not identical
1364 // keep looking for an exact match
1369 mismatch
= fdv
; // overrides, but is not covariant
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
);
1408 // Treat as if Covariant.no
1409 mismatchvi
= bestvi
;
1416 if (bestvi
== -1 && mismatch
)
1419 //mismatch.type.print();
1420 //printf("%s %s\n", type.deco, mismatch.type.deco);
1421 //printf("stc = %llx\n", mismatchstc);
1424 // Fix it by modifying the type to add the storage classes
1425 fd
.type
= fd
.type
.addStorageClass(mismatchstc
);
1426 bestvi
= mismatchvi
;
1432 /*********************************
1433 * If function is a function in a base class,
1434 * return that base class.
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
[]);
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.
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).
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
;
1483 return null; // no match
1487 printf("resolveFuncCall('%s')\n", s
.toChars());
1489 printf("\tthis: %s\n", tthis
.toChars());
1492 for (size_t i
= 0; i
< fargs
.length
; i
++)
1494 Expression arg
= (*fargs
)[i
];
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
))
1505 foreach (arg
; *fargs
)
1510 functionResolve(m
, s
, loc
, sc
, tiargs
, tthis
, argumentList
);
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
);
1521 if ((flags
& FuncResolveFlag
.overloadOnly
) && !tthis
&& m
.lastf
.needThis())
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
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
)
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
);
1553 fargsBuf
.writeByte('(');
1554 argExpTypesToCBuffer(fargsBuf
, fargs
);
1555 fargsBuf
.writeByte(')');
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());
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");
1585 // all of overloads are templates
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());
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());
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
1616 .error(loc
, "none of the overloads of `%s` are callable using argument types `!(%s)%s`",
1617 od
.ident
.toChars(), tiargsBuf
.peekChars(), fargsBuf
.peekChars());
1621 // remove when deprecation period of class allocators and deallocators is over
1622 if (fd
.isNewDeclaration() && fd
.checkDisabled(loc
, sc
))
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
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
);
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());
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());
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
);
1669 if (fd
.isCtorDeclaration())
1670 .error(loc
, "%s%s `%s` cannot construct a %sobject",
1671 funcBuf
.peekChars(), fd
.kind(), fd
.toPrettyChars(), thisBuf
.peekChars());
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");
1683 //printf("tf = %s, args = %s\n", tf.deco, (*fargs)[0].type.deco);
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());
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
)
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());
1723 void errorHelper2(const(char)* failMessage
) scope
1725 errorSupplemental(loc
, failMessage
);
1728 functionResolve(m
, orig_s
, loc
, sc
, tiargs
, tthis
, argumentList
, &errorHelper2
);
1733 /*******************************************
1734 * Prints template and function overload candidates as supplemental errors.
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
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
)
1758 // Don't print disabled functions, or `deprecated` outside of deprecated scope
1759 if (fd
.storage_class
& STC
.disable ||
(fd
.isDeprecated() && !showDeprecated
))
1763 auto tf
= cast(TypeFunction
) fd
.type
;
1765 buf
.writestring(fd
.toPrettyChars());
1766 buf
.writestring(parametersTypeToChars(tf
.parameterList
));
1770 buf
.MODtoBuffer(tf
.mod
);
1772 .errorSupplemental(fd
.loc
,
1774 single_candidate ?
"Candidate is: `%s`" : "Candidates are: `%s`", buf
.peekChars());
1776 else if (auto td
= s
.isTemplateDeclaration())
1778 import dmd
.staticcond
;
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: ")`
1794 .errorSupplemental(td
.loc
,
1795 printed ?
" `%s`\n%s" :
1796 single_candidate ?
"Candidate is: `%s`\n%s" : "Candidates are: `%s`\n%s",
1801 .errorSupplemental(td
.loc
,
1803 single_candidate ?
"Candidate is: `%s`" : "Candidates are: `%s`",
1809 // determine if there's > 1 candidate
1811 overloadApply(declaration
, (s
) {
1812 if (matchSymbol(s
, false))
1817 overloadApply(declaration
, (s
) {
1818 if (global
.params
.v
.verbose || printed
< DisplayLimit
)
1820 if (matchSymbol(s
, true, count
== 1))
1825 // Too many overloads to sensibly display.
1826 // Just show count of remaining overloads.
1827 if (matchSymbol(s
, false))
1833 .errorSupplemental(loc
, "... (%d more, -v to show) ...", skipped
);
1835 // Nothing was displayed, all overloads are either disabled or deprecated
1837 .errorSupplemental(loc
, "All possible candidates are marked as `deprecated` or `@disable`");
1838 // should be only in verbose mode
1840 .tip(constraintsTip
);
1843 /********************************************************
1844 * Generate Expression to call the invariant.
1846 * ad aggregate with the invariant
1847 * vthis variable with 'this'
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();
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);
1888 e
= new CallExp(Loc
.initial
, e
);
1889 e
.type
= Type
.tvoid
;
1894 /****************************************************
1895 * Declare result variable lazily.
1897 void buildResultVar(FuncDeclaration fd
, Scope
* sc
, Type tret
)
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();
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
);