1
2 /* Compiler implementation of the D programming language
3 * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved
4 * written by Walter Bright
5 * http://www.digitalmars.com
6 * Distributed under the Boost Software License, Version 1.0.
7 * http://www.boost.org/LICENSE_1_0.txt
8 * https://github.com/D-Programming-Language/dmd/blob/master/src/func.c
9 */
10
11 #include "root/dsystem.h"
12
13 #include "mars.h"
14 #include "init.h"
15 #include "declaration.h"
16 #include "attrib.h"
17 #include "expression.h"
18 #include "scope.h"
19 #include "mtype.h"
20 #include "aggregate.h"
21 #include "identifier.h"
22 #include "id.h"
23 #include "module.h"
24 #include "statement.h"
25 #include "template.h"
26 #include "hdrgen.h"
27 #include "target.h"
28 #include "parse.h"
29 #include "root/rmem.h"
30 #include "visitor.h"
31 #include "objc.h"
32
33 Expression *addInvariant(Loc loc, Scope *sc, AggregateDeclaration *ad, VarDeclaration *vthis, bool direct);
34 bool checkReturnEscape(Scope *sc, Expression *e, bool gag);
35 bool checkReturnEscapeRef(Scope *sc, Expression *e, bool gag);
36 bool checkNestedRef(Dsymbol *s, Dsymbol *p);
37 Statement *semantic(Statement *s, Scope *sc);
38 void semantic(Catch *c, Scope *sc);
39 Expression *resolve(Loc loc, Scope *sc, Dsymbol *s, bool hasOverloads);
40 Expression *semantic(Expression *e, Scope *sc);
41 int blockExit(Statement *s, FuncDeclaration *func, bool mustNotThrow);
42 TypeIdentifier *getThrowable();
43
44 RET retStyle(TypeFunction *tf);
45 void MODtoBuffer(OutBuffer *buf, MOD mod);
46 char *MODtoChars(MOD mod);
47 bool MODimplicitConv(MOD modfrom, MOD modto);
48 MATCH MODmethodConv(MOD modfrom, MOD modto);
49 void allocFieldinit(Scope *sc, size_t dim);
50 void freeFieldinit(Scope *sc);
51 Objc *objc();
52
53
54 /* A visitor to walk entire statements and provides ability to replace any sub-statements.
55 */
56 class StatementRewriteWalker : public Visitor
57 {
58 /* Point the currently visited statement.
59 * By using replaceCurrent() method, you can replace AST during walking.
60 */
61 Statement **ps;
62 public:
visitStmt(Statement * & s)63 void visitStmt(Statement *&s) { ps = &s; s->accept(this); }
replaceCurrent(Statement * s)64 void replaceCurrent(Statement *s) { *ps = s; }
65
visit(ErrorStatement *)66 void visit(ErrorStatement *) { }
visit(PeelStatement * s)67 void visit(PeelStatement *s)
68 {
69 if (s->s)
70 visitStmt(s->s);
71 }
visit(ExpStatement *)72 void visit(ExpStatement *) { }
visit(DtorExpStatement *)73 void visit(DtorExpStatement *) { }
visit(CompileStatement *)74 void visit(CompileStatement *) { }
visit(CompoundStatement * s)75 void visit(CompoundStatement *s)
76 {
77 if (s->statements && s->statements->dim)
78 {
79 for (size_t i = 0; i < s->statements->dim; i++)
80 {
81 if ((*s->statements)[i])
82 visitStmt((*s->statements)[i]);
83 }
84 }
85 }
visit(CompoundDeclarationStatement * s)86 void visit(CompoundDeclarationStatement *s) { visit((CompoundStatement *)s); }
visit(UnrolledLoopStatement * s)87 void visit(UnrolledLoopStatement *s)
88 {
89 if (s->statements && s->statements->dim)
90 {
91 for (size_t i = 0; i < s->statements->dim; i++)
92 {
93 if ((*s->statements)[i])
94 visitStmt((*s->statements)[i]);
95 }
96 }
97 }
visit(ScopeStatement * s)98 void visit(ScopeStatement *s)
99 {
100 if (s->statement)
101 visitStmt(s->statement);
102 }
visit(WhileStatement * s)103 void visit(WhileStatement *s)
104 {
105 if (s->_body)
106 visitStmt(s->_body);
107 }
visit(DoStatement * s)108 void visit(DoStatement *s)
109 {
110 if (s->_body)
111 visitStmt(s->_body);
112 }
visit(ForStatement * s)113 void visit(ForStatement *s)
114 {
115 if (s->_init)
116 visitStmt(s->_init);
117 if (s->_body)
118 visitStmt(s->_body);
119 }
visit(ForeachStatement * s)120 void visit(ForeachStatement *s)
121 {
122 if (s->_body)
123 visitStmt(s->_body);
124 }
visit(ForeachRangeStatement * s)125 void visit(ForeachRangeStatement *s)
126 {
127 if (s->_body)
128 visitStmt(s->_body);
129 }
visit(IfStatement * s)130 void visit(IfStatement *s)
131 {
132 if (s->ifbody)
133 visitStmt(s->ifbody);
134 if (s->elsebody)
135 visitStmt(s->elsebody);
136 }
visit(ConditionalStatement *)137 void visit(ConditionalStatement *) { }
visit(PragmaStatement *)138 void visit(PragmaStatement *) { }
visit(StaticAssertStatement *)139 void visit(StaticAssertStatement *) { }
visit(SwitchStatement * s)140 void visit(SwitchStatement *s)
141 {
142 if (s->_body)
143 visitStmt(s->_body);
144 }
visit(CaseStatement * s)145 void visit(CaseStatement *s)
146 {
147 if (s->statement)
148 visitStmt(s->statement);
149 }
visit(CaseRangeStatement * s)150 void visit(CaseRangeStatement *s)
151 {
152 if (s->statement)
153 visitStmt(s->statement);
154 }
visit(DefaultStatement * s)155 void visit(DefaultStatement *s)
156 {
157 if (s->statement)
158 visitStmt(s->statement);
159 }
visit(GotoDefaultStatement *)160 void visit(GotoDefaultStatement *) { }
visit(GotoCaseStatement *)161 void visit(GotoCaseStatement *) { }
visit(SwitchErrorStatement *)162 void visit(SwitchErrorStatement *) { }
visit(ReturnStatement *)163 void visit(ReturnStatement *) { }
visit(BreakStatement *)164 void visit(BreakStatement *) { }
visit(ContinueStatement *)165 void visit(ContinueStatement *) { }
visit(SynchronizedStatement * s)166 void visit(SynchronizedStatement *s)
167 {
168 if (s->_body)
169 visitStmt(s->_body);
170 }
visit(WithStatement * s)171 void visit(WithStatement *s)
172 {
173 if (s->_body)
174 visitStmt(s->_body);
175 }
visit(TryCatchStatement * s)176 void visit(TryCatchStatement *s)
177 {
178 if (s->_body)
179 visitStmt(s->_body);
180 if (s->catches && s->catches->dim)
181 {
182 for (size_t i = 0; i < s->catches->dim; i++)
183 {
184 Catch *c = (*s->catches)[i];
185 if (c && c->handler)
186 visitStmt(c->handler);
187 }
188 }
189 }
visit(TryFinallyStatement * s)190 void visit(TryFinallyStatement *s)
191 {
192 if (s->_body)
193 visitStmt(s->_body);
194 if (s->finalbody)
195 visitStmt(s->finalbody);
196 }
visit(OnScopeStatement *)197 void visit(OnScopeStatement *) { }
visit(ThrowStatement *)198 void visit(ThrowStatement *) { }
visit(DebugStatement * s)199 void visit(DebugStatement *s)
200 {
201 if (s->statement)
202 visitStmt(s->statement);
203 }
visit(GotoStatement *)204 void visit(GotoStatement *) { }
visit(LabelStatement * s)205 void visit(LabelStatement *s)
206 {
207 if (s->statement)
208 visitStmt(s->statement);
209 }
visit(AsmStatement *)210 void visit(AsmStatement *) { }
visit(ImportStatement *)211 void visit(ImportStatement *) { }
212 };
213
214 /* Tweak all return statements and dtor call for nrvo_var, for correct NRVO.
215 */
216 class NrvoWalker : public StatementRewriteWalker
217 {
218 public:
219 FuncDeclaration *fd;
220 Scope *sc;
221
visit(ReturnStatement * s)222 void visit(ReturnStatement *s)
223 {
224 // See if all returns are instead to be replaced with a goto returnLabel;
225 if (fd->returnLabel)
226 {
227 /* Rewrite:
228 * return exp;
229 * as:
230 * vresult = exp; goto Lresult;
231 */
232 GotoStatement *gs = new GotoStatement(s->loc, Id::returnLabel);
233 gs->label = fd->returnLabel;
234
235 Statement *s1 = gs;
236 if (s->exp)
237 s1 = new CompoundStatement(s->loc, new ExpStatement(s->loc, s->exp), gs);
238
239 replaceCurrent(s1);
240 }
241 }
visit(TryFinallyStatement * s)242 void visit(TryFinallyStatement *s)
243 {
244 DtorExpStatement *des;
245 if (fd->nrvo_can &&
246 s->finalbody && (des = s->finalbody->isDtorExpStatement()) != NULL &&
247 fd->nrvo_var == des->var)
248 {
249 if (!(global.params.useExceptions && ClassDeclaration::throwable))
250 {
251 /* Don't need to call destructor at all, since it is nrvo
252 */
253 replaceCurrent(s->_body);
254 s->_body->accept(this);
255 return;
256 }
257
258 /* Normally local variable dtors are called regardless exceptions.
259 * But for nrvo_var, its dtor should be called only when exception is thrown.
260 *
261 * Rewrite:
262 * try { s->body; } finally { nrvo_var->edtor; }
263 * // equivalent with:
264 * // s->body; scope(exit) nrvo_var->edtor;
265 * as:
266 * try { s->body; } catch(Throwable __o) { nrvo_var->edtor; throw __o; }
267 * // equivalent with:
268 * // s->body; scope(failure) nrvo_var->edtor;
269 */
270 Statement *sexception = new DtorExpStatement(Loc(), fd->nrvo_var->edtor, fd->nrvo_var);
271 Identifier *id = Identifier::generateId("__o");
272
273 Statement *handler = new PeelStatement(sexception);
274 if (blockExit(sexception, fd, false) & BEfallthru)
275 {
276 ThrowStatement *ts = new ThrowStatement(Loc(), new IdentifierExp(Loc(), id));
277 ts->internalThrow = true;
278 handler = new CompoundStatement(Loc(), handler, ts);
279 }
280
281 Catches *catches = new Catches();
282 Catch *ctch = new Catch(Loc(), getThrowable(), id, handler);
283 ctch->internalCatch = true;
284 ::semantic(ctch, sc); // Run semantic to resolve identifier '__o'
285 catches->push(ctch);
286
287 Statement *s2 = new TryCatchStatement(Loc(), s->_body, catches);
288 replaceCurrent(s2);
289 s2->accept(this);
290 }
291 else
292 StatementRewriteWalker::visit(s);
293 }
294 };
295
296 /********************************* FuncDeclaration ****************************/
297
FuncDeclaration(Loc loc,Loc endloc,Identifier * id,StorageClass storage_class,Type * type)298 FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageClass storage_class, Type *type)
299 : Declaration(id)
300 {
301 //printf("FuncDeclaration(id = '%s', type = %p)\n", id->toChars(), type);
302 //printf("storage_class = x%x\n", storage_class);
303 this->storage_class = storage_class;
304 this->type = type;
305 if (type)
306 {
307 // Normalize storage_class, because function-type related attributes
308 // are already set in the 'type' in parsing phase.
309 this->storage_class &= ~(STC_TYPECTOR | STC_FUNCATTR);
310 }
311 this->loc = loc;
312 this->endloc = endloc;
313 fthrows = NULL;
314 frequire = NULL;
315 fdrequire = NULL;
316 fdensure = NULL;
317 mangleString = NULL;
318 outId = NULL;
319 vresult = NULL;
320 returnLabel = NULL;
321 fensure = NULL;
322 fbody = NULL;
323 localsymtab = NULL;
324 vthis = NULL;
325 v_arguments = NULL;
326 v_argptr = NULL;
327 parameters = NULL;
328 labtab = NULL;
329 overnext = NULL;
330 overnext0 = NULL;
331 vtblIndex = -1;
332 hasReturnExp = 0;
333 naked = false;
334 generated = false;
335 inlineStatusExp = ILSuninitialized;
336 inlineStatusStmt = ILSuninitialized;
337 inlining = PINLINEdefault;
338 inlineNest = 0;
339 ctfeCode = NULL;
340 isArrayOp = 0;
341 semantic3Errors = false;
342 fes = NULL;
343 interfaceVirtual = NULL;
344 introducing = 0;
345 tintro = NULL;
346 /* The type given for "infer the return type" is a TypeFunction with
347 * NULL for the return type.
348 */
349 inferRetType = (type && type->nextOf() == NULL);
350 storage_class2 = 0;
351 hasReturnExp = 0;
352 nrvo_can = 1;
353 nrvo_var = NULL;
354 shidden = NULL;
355 builtin = BUILTINunknown;
356 tookAddressOf = 0;
357 requiresClosure = false;
358 inlinedNestedCallees = NULL;
359 flags = 0;
360 returns = NULL;
361 gotos = NULL;
362 selector = NULL;
363 }
364
create(Loc loc,Loc endloc,Identifier * id,StorageClass storage_class,Type * type)365 FuncDeclaration *FuncDeclaration::create(Loc loc, Loc endloc, Identifier *id, StorageClass storage_class, Type *type)
366 {
367 return new FuncDeclaration(loc, endloc, id, storage_class, type);
368 }
369
syntaxCopy(Dsymbol * s)370 Dsymbol *FuncDeclaration::syntaxCopy(Dsymbol *s)
371 {
372 //printf("FuncDeclaration::syntaxCopy('%s')\n", toChars());
373 FuncDeclaration *f =
374 s ? (FuncDeclaration *)s
375 : new FuncDeclaration(loc, endloc, ident, storage_class, type->syntaxCopy());
376 f->outId = outId;
377 f->frequire = frequire ? frequire->syntaxCopy() : NULL;
378 f->fensure = fensure ? fensure->syntaxCopy() : NULL;
379 f->fbody = fbody ? fbody->syntaxCopy() : NULL;
380 assert(!fthrows); // deprecated
381 return f;
382 }
383
384 /**********************************
385 * Decide if attributes for this function can be inferred from examining
386 * the function body.
387 * Returns:
388 * true if can
389 */
canInferAttributes(FuncDeclaration * fd,Scope * sc)390 static bool canInferAttributes(FuncDeclaration *fd, Scope *sc)
391 {
392 if (!fd->fbody)
393 return false;
394
395 if (fd->isVirtualMethod())
396 return false; // since they may be overridden
397
398 if (sc->func &&
399 /********** this is for backwards compatibility for the moment ********/
400 (!fd->isMember() || (sc->func->isSafeBypassingInference() && !fd->isInstantiated())))
401 return true;
402
403 if (fd->isFuncLiteralDeclaration() || // externs are not possible with literals
404 (fd->storage_class & STCinference) || // do attribute inference
405 (fd->inferRetType && !fd->isCtorDeclaration()))
406 return true;
407
408 if (fd->isInstantiated())
409 {
410 TemplateInstance *ti = fd->parent->isTemplateInstance();
411 if (ti == NULL || ti->isTemplateMixin() || ti->tempdecl->ident == fd->ident)
412 return true;
413 }
414
415 return false;
416 }
417
418 /*****************************************
419 * Initialize for inferring the attributes of this function.
420 */
initInferAttributes(FuncDeclaration * fd)421 static void initInferAttributes(FuncDeclaration *fd)
422 {
423 //printf("initInferAttributes() for %s\n", toPrettyChars());
424 TypeFunction *tf = fd->type->toTypeFunction();
425 if (tf->purity == PUREimpure) // purity not specified
426 fd->flags |= FUNCFLAGpurityInprocess;
427
428 if (tf->trust == TRUSTdefault)
429 fd->flags |= FUNCFLAGsafetyInprocess;
430
431 if (!tf->isnothrow)
432 fd->flags |= FUNCFLAGnothrowInprocess;
433
434 if (!tf->isnogc)
435 fd->flags |= FUNCFLAGnogcInprocess;
436
437 if (!fd->isVirtual() || fd->introducing)
438 fd->flags |= FUNCFLAGreturnInprocess;
439
440 // Initialize for inferring STCscope
441 if (global.params.vsafe)
442 fd->flags |= FUNCFLAGinferScope;
443 }
444
445 // Do the semantic analysis on the external interface to the function.
446
semantic(Scope * sc)447 void FuncDeclaration::semantic(Scope *sc)
448 {
449 TypeFunction *f;
450 AggregateDeclaration *ad;
451 InterfaceDeclaration *id;
452
453 if (semanticRun != PASSinit && isFuncLiteralDeclaration())
454 {
455 /* Member functions that have return types that are
456 * forward references can have semantic() run more than
457 * once on them.
458 * See test\interface2.d, test20
459 */
460 return;
461 }
462
463 if (semanticRun >= PASSsemanticdone)
464 return;
465 assert(semanticRun <= PASSsemantic);
466 semanticRun = PASSsemantic;
467
468 if (_scope)
469 {
470 sc = _scope;
471 _scope = NULL;
472 }
473
474 if (!sc || errors)
475 return;
476
477 parent = sc->parent;
478 Dsymbol *parent = toParent();
479
480 foverrides.setDim(0); // reset in case semantic() is being retried for this function
481
482 storage_class |= sc->stc & ~STCref;
483 ad = isThis();
484 // Don't nest structs b/c of generated methods which should not access the outer scopes.
485 // https://issues.dlang.org/show_bug.cgi?id=16627
486 if (ad && !generated)
487 {
488 storage_class |= ad->storage_class & (STC_TYPECTOR | STCsynchronized);
489 ad->makeNested();
490 }
491 if (sc->func)
492 storage_class |= sc->func->storage_class & STCdisable;
493 // Remove prefix storage classes silently.
494 if ((storage_class & STC_TYPECTOR) && !(ad || isNested()))
495 storage_class &= ~STC_TYPECTOR;
496
497 //printf("function storage_class = x%llx, sc->stc = x%llx, %x\n", storage_class, sc->stc, Declaration::isFinal());
498
499 FuncLiteralDeclaration *fld = isFuncLiteralDeclaration();
500 if (fld && fld->treq)
501 {
502 Type *treq = fld->treq;
503 assert(treq->nextOf()->ty == Tfunction);
504 if (treq->ty == Tdelegate)
505 fld->tok = TOKdelegate;
506 else if (treq->ty == Tpointer && treq->nextOf()->ty == Tfunction)
507 fld->tok = TOKfunction;
508 else
509 assert(0);
510 linkage = treq->nextOf()->toTypeFunction()->linkage;
511 }
512 else
513 linkage = sc->linkage;
514 inlining = sc->inlining;
515 protection = sc->protection;
516 userAttribDecl = sc->userAttribDecl;
517
518 if (!originalType)
519 originalType = type->syntaxCopy();
520 if (type->ty != Tfunction)
521 {
522 if (type->ty != Terror)
523 {
524 error("%s must be a function instead of %s", toChars(), type->toChars());
525 type = Type::terror;
526 }
527 errors = true;
528 return;
529 }
530 if (!type->deco)
531 {
532 sc = sc->push();
533 sc->stc |= storage_class & (STCdisable | STCdeprecated); // forward to function type
534 TypeFunction *tf = type->toTypeFunction();
535
536 if (sc->func)
537 {
538 /* If the nesting parent is pure without inference,
539 * then this function defaults to pure too.
540 *
541 * auto foo() pure {
542 * auto bar() {} // become a weak purity funciton
543 * class C { // nested class
544 * auto baz() {} // become a weak purity funciton
545 * }
546 *
547 * static auto boo() {} // typed as impure
548 * // Even though, boo cannot call any impure functions.
549 * // See also Expression::checkPurity().
550 * }
551 */
552 if (tf->purity == PUREimpure && (isNested() || isThis()))
553 {
554 FuncDeclaration *fd = NULL;
555 for (Dsymbol *p = toParent2(); p; p = p->toParent2())
556 {
557 if (AggregateDeclaration *adx = p->isAggregateDeclaration())
558 {
559 if (adx->isNested())
560 continue;
561 break;
562 }
563 if ((fd = p->isFuncDeclaration()) != NULL)
564 break;
565 }
566
567 /* If the parent's purity is inferred, then this function's purity needs
568 * to be inferred first.
569 */
570 if (fd && fd->isPureBypassingInference() >= PUREweak &&
571 !isInstantiated())
572 {
573 tf->purity = PUREfwdref; // default to pure
574 }
575 }
576 }
577
578 if (tf->isref) sc->stc |= STCref;
579 if (tf->isscope) sc->stc |= STCscope;
580 if (tf->isnothrow) sc->stc |= STCnothrow;
581 if (tf->isnogc) sc->stc |= STCnogc;
582 if (tf->isproperty) sc->stc |= STCproperty;
583 if (tf->purity == PUREfwdref) sc->stc |= STCpure;
584 if (tf->trust != TRUSTdefault)
585 sc->stc &= ~(STCsafe | STCsystem | STCtrusted);
586 if (tf->trust == TRUSTsafe) sc->stc |= STCsafe;
587 if (tf->trust == TRUSTsystem) sc->stc |= STCsystem;
588 if (tf->trust == TRUSTtrusted) sc->stc |= STCtrusted;
589
590 if (isCtorDeclaration())
591 {
592 sc->flags |= SCOPEctor;
593
594 Type *tret = ad->handleType();
595 assert(tret);
596 tret = tret->addStorageClass(storage_class | sc->stc);
597 tret = tret->addMod(type->mod);
598 tf->next = tret;
599
600 if (ad->isStructDeclaration())
601 sc->stc |= STCref;
602 }
603
604 // 'return' on a non-static class member function implies 'scope' as well
605 if (ad && ad->isClassDeclaration() && (tf->isreturn || sc->stc & STCreturn) && !(sc->stc & STCstatic))
606 sc->stc |= STCscope;
607
608 // If 'this' has no pointers, remove 'scope' as it has no meaning
609 if (sc->stc & STCscope && ad && ad->isStructDeclaration() && !ad->type->hasPointers())
610 {
611 sc->stc &= ~STCscope;
612 tf->isscope = false;
613 }
614
615 sc->linkage = linkage;
616
617 if (!tf->isNaked() && !(isThis() || isNested()))
618 {
619 OutBuffer buf;
620 MODtoBuffer(&buf, tf->mod);
621 error("without 'this' cannot be %s", buf.peekString());
622 tf->mod = 0; // remove qualifiers
623 }
624
625 /* Apply const, immutable, wild and shared storage class
626 * to the function type. Do this before type semantic.
627 */
628 StorageClass stc = storage_class;
629 if (type->isImmutable())
630 stc |= STCimmutable;
631 if (type->isConst())
632 stc |= STCconst;
633 if (type->isShared() || storage_class & STCsynchronized)
634 stc |= STCshared;
635 if (type->isWild())
636 stc |= STCwild;
637 switch (stc & STC_TYPECTOR)
638 {
639 case STCimmutable:
640 case STCimmutable | STCconst:
641 case STCimmutable | STCwild:
642 case STCimmutable | STCwild | STCconst:
643 case STCimmutable | STCshared:
644 case STCimmutable | STCshared | STCconst:
645 case STCimmutable | STCshared | STCwild:
646 case STCimmutable | STCshared | STCwild | STCconst:
647 // Don't use immutableOf(), as that will do a merge()
648 type = type->makeImmutable();
649 break;
650
651 case STCconst:
652 type = type->makeConst();
653 break;
654
655 case STCwild:
656 type = type->makeWild();
657 break;
658
659 case STCwild | STCconst:
660 type = type->makeWildConst();
661 break;
662
663 case STCshared:
664 type = type->makeShared();
665 break;
666
667 case STCshared | STCconst:
668 type = type->makeSharedConst();
669 break;
670
671 case STCshared | STCwild:
672 type = type->makeSharedWild();
673 break;
674
675 case STCshared | STCwild | STCconst:
676 type = type->makeSharedWildConst();
677 break;
678
679 case 0:
680 break;
681
682 default:
683 assert(0);
684 }
685
686 type = type->semantic(loc, sc);
687 sc = sc->pop();
688 }
689 if (type->ty != Tfunction)
690 {
691 if (type->ty != Terror)
692 {
693 error("%s must be a function instead of %s", toChars(), type->toChars());
694 type = Type::terror;
695 }
696 errors = true;
697 return;
698 }
699 else
700 {
701 // Merge back function attributes into 'originalType'.
702 // It's used for mangling, ddoc, and json output.
703 TypeFunction *tfo = originalType->toTypeFunction();
704 TypeFunction *tfx = type->toTypeFunction();
705 tfo->mod = tfx->mod;
706 tfo->isscope = tfx->isscope;
707 tfo->isscopeinferred = tfx->isscopeinferred;
708 tfo->isref = tfx->isref;
709 tfo->isnothrow = tfx->isnothrow;
710 tfo->isnogc = tfx->isnogc;
711 tfo->isproperty = tfx->isproperty;
712 tfo->purity = tfx->purity;
713 tfo->trust = tfx->trust;
714
715 storage_class &= ~(STC_TYPECTOR | STC_FUNCATTR);
716 }
717
718 f = (TypeFunction *)type;
719
720 if ((storage_class & STCauto) && !f->isref && !inferRetType)
721 error("storage class 'auto' has no effect if return type is not inferred");
722 /* Functions can only be 'scope' if they have a 'this'
723 */
724 if (f->isscope && !isNested() && !ad)
725 {
726 error("functions cannot be scope");
727 }
728
729 if (f->isreturn && !needThis() && !isNested())
730 {
731 /* Non-static nested functions have a hidden 'this' pointer to which
732 * the 'return' applies
733 */
734 error("static member has no 'this' to which 'return' can apply");
735 }
736
737 if (isAbstract() && !isVirtual())
738 {
739 const char *sfunc;
740 if (isStatic())
741 sfunc = "static";
742 else if (protection.kind == PROTprivate || protection.kind == PROTpackage)
743 sfunc = protectionToChars(protection.kind);
744 else
745 sfunc = "non-virtual";
746 error("%s functions cannot be abstract", sfunc);
747 }
748
749 if (isOverride() && !isVirtual())
750 {
751 PROTKIND kind = prot().kind;
752 if ((kind == PROTprivate || kind == PROTpackage) && isMember())
753 error("%s method is not virtual and cannot override", protectionToChars(kind));
754 else
755 error("cannot override a non-virtual function");
756 }
757
758 if (isAbstract() && isFinalFunc())
759 error("cannot be both final and abstract");
760
761 id = parent->isInterfaceDeclaration();
762 if (id)
763 {
764 storage_class |= STCabstract;
765
766 if (isCtorDeclaration() ||
767 isPostBlitDeclaration() ||
768 isDtorDeclaration() ||
769 isInvariantDeclaration() ||
770 isNewDeclaration() || isDelete())
771 error("constructors, destructors, postblits, invariants, new and delete functions are not allowed in interface %s", id->toChars());
772 if (fbody && isVirtual())
773 error("function body only allowed in final functions in interface %s", id->toChars());
774 }
775
776 if (UnionDeclaration *ud = parent->isUnionDeclaration())
777 {
778 if (isPostBlitDeclaration() ||
779 isDtorDeclaration() ||
780 isInvariantDeclaration())
781 error("destructors, postblits and invariants are not allowed in union %s", ud->toChars());
782 }
783
784 /* Contracts can only appear without a body when they are virtual interface functions
785 */
786 if (!fbody && (fensure || frequire) && !(id && isVirtual()))
787 error("in and out contracts require function body");
788
789 if (parent->isStructDeclaration())
790 {
791 if (isCtorDeclaration())
792 {
793 goto Ldone;
794 }
795 }
796
797 if (ClassDeclaration *cd = parent->isClassDeclaration())
798 {
799 if (isCtorDeclaration())
800 {
801 goto Ldone;
802 }
803
804 if (storage_class & STCabstract)
805 cd->isabstract = ABSyes;
806
807 // if static function, do not put in vtbl[]
808 if (!isVirtual())
809 {
810 //printf("\tnot virtual\n");
811 goto Ldone;
812 }
813 // Suppress further errors if the return type is an error
814 if (type->nextOf() == Type::terror)
815 goto Ldone;
816
817 bool may_override = false;
818 for (size_t i = 0; i < cd->baseclasses->dim; i++)
819 {
820 BaseClass *b = (*cd->baseclasses)[i];
821 ClassDeclaration *cbd = b->type->toBasetype()->isClassHandle();
822 if (!cbd)
823 continue;
824 for (size_t j = 0; j < cbd->vtbl.dim; j++)
825 {
826 FuncDeclaration *f2 = cbd->vtbl[j]->isFuncDeclaration();
827 if (!f2 || f2->ident != ident)
828 continue;
829 if (cbd->parent && cbd->parent->isTemplateInstance())
830 {
831 if (!f2->functionSemantic())
832 goto Ldone;
833 }
834 may_override = true;
835 }
836 }
837 if (may_override && type->nextOf() == NULL)
838 {
839 /* If same name function exists in base class but 'this' is auto return,
840 * cannot find index of base class's vtbl[] to override.
841 */
842 error("return type inference is not supported if may override base class function");
843 }
844
845 /* Find index of existing function in base class's vtbl[] to override
846 * (the index will be the same as in cd's current vtbl[])
847 */
848 int vi = cd->baseClass ? findVtblIndex((Dsymbols*)&cd->baseClass->vtbl, (int)cd->baseClass->vtbl.dim)
849 : -1;
850
851 bool doesoverride = false;
852 switch (vi)
853 {
854 case -1:
855 Lintro:
856 /* Didn't find one, so
857 * This is an 'introducing' function which gets a new
858 * slot in the vtbl[].
859 */
860
861 // Verify this doesn't override previous final function
862 if (cd->baseClass)
863 {
864 Dsymbol *s = cd->baseClass->search(loc, ident);
865 if (s)
866 {
867 FuncDeclaration *f2 = s->isFuncDeclaration();
868 if (f2)
869 {
870 f2 = f2->overloadExactMatch(type);
871 if (f2 && f2->isFinalFunc() && f2->prot().kind != PROTprivate)
872 error("cannot override final function %s", f2->toPrettyChars());
873 }
874 }
875 }
876
877 /* These quirky conditions mimic what VC++ appears to do
878 */
879 if (global.params.mscoff && cd->isCPPclass() &&
880 cd->baseClass && cd->baseClass->vtbl.dim)
881 {
882 /* if overriding an interface function, then this is not
883 * introducing and don't put it in the class vtbl[]
884 */
885 interfaceVirtual = overrideInterface();
886 if (interfaceVirtual)
887 {
888 //printf("\tinterface function %s\n", toChars());
889 cd->vtblFinal.push(this);
890 goto Linterfaces;
891 }
892 }
893
894 if (isFinalFunc())
895 {
896 // Don't check here, as it may override an interface function
897 //if (isOverride())
898 //error("is marked as override, but does not override any function");
899 cd->vtblFinal.push(this);
900 }
901 else
902 {
903 //printf("\tintroducing function %s\n", toChars());
904 introducing = 1;
905 if (cd->isCPPclass() && Target::reverseCppOverloads)
906 {
907 // with dmc, overloaded functions are grouped and in reverse order
908 vtblIndex = (int)cd->vtbl.dim;
909 for (int i = 0; i < (int)cd->vtbl.dim; i++)
910 {
911 if (cd->vtbl[i]->ident == ident && cd->vtbl[i]->parent == parent)
912 {
913 vtblIndex = (int)i;
914 break;
915 }
916 }
917 // shift all existing functions back
918 for (int i = (int)cd->vtbl.dim; i > vtblIndex; i--)
919 {
920 FuncDeclaration *fd = cd->vtbl[i-1]->isFuncDeclaration();
921 assert(fd);
922 fd->vtblIndex++;
923 }
924 cd->vtbl.insert(vtblIndex, this);
925 }
926 else
927 {
928 // Append to end of vtbl[]
929 vi = (int)cd->vtbl.dim;
930 cd->vtbl.push(this);
931 vtblIndex = vi;
932 }
933 }
934 break;
935
936 case -2:
937 // can't determine because of forward references
938 errors = true;
939 return;
940
941 default:
942 {
943 FuncDeclaration *fdv = cd->baseClass->vtbl[vi]->isFuncDeclaration();
944 FuncDeclaration *fdc = cd->vtbl[vi]->isFuncDeclaration();
945 // This function is covariant with fdv
946
947 if (fdc == this)
948 {
949 doesoverride = true;
950 break;
951 }
952
953 if (fdc->toParent() == parent)
954 {
955 //printf("vi = %d,\tthis = %p %s %s @ [%s]\n\tfdc = %p %s %s @ [%s]\n\tfdv = %p %s %s @ [%s]\n",
956 // vi, this, this->toChars(), this->type->toChars(), this->loc.toChars(),
957 // fdc, fdc ->toChars(), fdc ->type->toChars(), fdc ->loc.toChars(),
958 // fdv, fdv ->toChars(), fdv ->type->toChars(), fdv ->loc.toChars());
959
960 // fdc overrides fdv exactly, then this introduces new function.
961 if (fdc->type->mod == fdv->type->mod && this->type->mod != fdv->type->mod)
962 goto Lintro;
963 }
964
965 // This function overrides fdv
966 if (fdv->isFinalFunc())
967 error("cannot override final function %s", fdv->toPrettyChars());
968
969 if (!isOverride())
970 {
971 if (fdv->isFuture())
972 {
973 ::deprecation(loc, "@future base class method %s is being overridden by %s; rename the latter",
974 fdv->toPrettyChars(), toPrettyChars());
975 // Treat 'this' as an introducing function, giving it a separate hierarchy in the vtbl[]
976 goto Lintro;
977 }
978 else
979 {
980 int vi2 = findVtblIndex(&cd->baseClass->vtbl, (int)cd->baseClass->vtbl.dim, false);
981 if (vi2 < 0)
982 // https://issues.dlang.org/show_bug.cgi?id=17349
983 ::deprecation(loc, "cannot implicitly override base class method `%s` with `%s`; add `override` attribute",
984 fdv->toPrettyChars(), toPrettyChars());
985 else
986 ::error(loc, "implicitly overriding base class method %s with %s deprecated; add 'override' attribute",
987 fdv->toPrettyChars(), toPrettyChars());
988 }
989 }
990
991 doesoverride = true;
992 if (fdc->toParent() == parent)
993 {
994 // If both are mixins, or both are not, then error.
995 // If either is not, the one that is not overrides the other.
996 bool thismixin = this->parent->isClassDeclaration() != NULL;
997 bool fdcmixin = fdc->parent->isClassDeclaration() != NULL;
998 if (thismixin == fdcmixin)
999 {
1000 error("multiple overrides of same function");
1001 }
1002 else if (!thismixin) // fdc overrides fdv
1003 {
1004 // this doesn't override any function
1005 break;
1006 }
1007 }
1008 cd->vtbl[vi] = this;
1009 vtblIndex = vi;
1010
1011 /* Remember which functions this overrides
1012 */
1013 foverrides.push(fdv);
1014
1015 /* This works by whenever this function is called,
1016 * it actually returns tintro, which gets dynamically
1017 * cast to type. But we know that tintro is a base
1018 * of type, so we could optimize it by not doing a
1019 * dynamic cast, but just subtracting the isBaseOf()
1020 * offset if the value is != null.
1021 */
1022
1023 if (fdv->tintro)
1024 tintro = fdv->tintro;
1025 else if (!type->equals(fdv->type))
1026 {
1027 /* Only need to have a tintro if the vptr
1028 * offsets differ
1029 */
1030 int offset;
1031 if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
1032 {
1033 tintro = fdv->type;
1034 }
1035 }
1036 break;
1037 }
1038 }
1039
1040 /* Go through all the interface bases.
1041 * If this function is covariant with any members of those interface
1042 * functions, set the tintro.
1043 */
1044 Linterfaces:
1045 for (size_t i = 0; i < cd->interfaces.length; i++)
1046 {
1047 BaseClass *b = cd->interfaces.ptr[i];
1048 vi = findVtblIndex((Dsymbols *)&b->sym->vtbl, (int)b->sym->vtbl.dim);
1049 switch (vi)
1050 {
1051 case -1:
1052 break;
1053
1054 case -2:
1055 // can't determine because of forward references
1056 errors = true;
1057 return;
1058
1059 default:
1060 {
1061 FuncDeclaration *fdv = (FuncDeclaration *)b->sym->vtbl[vi];
1062 Type *ti = NULL;
1063
1064 /* Remember which functions this overrides
1065 */
1066 foverrides.push(fdv);
1067
1068 /* Should we really require 'override' when implementing
1069 * an interface function?
1070 */
1071 //if (!isOverride())
1072 //warning(loc, "overrides base class function %s, but is not marked with 'override'", fdv->toPrettyChars());
1073
1074 if (fdv->tintro)
1075 ti = fdv->tintro;
1076 else if (!type->equals(fdv->type))
1077 {
1078 /* Only need to have a tintro if the vptr
1079 * offsets differ
1080 */
1081 int offset;
1082 if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
1083 {
1084 ti = fdv->type;
1085 }
1086 }
1087 if (ti)
1088 {
1089 if (tintro)
1090 {
1091 if (!tintro->nextOf()->equals(ti->nextOf()) &&
1092 !tintro->nextOf()->isBaseOf(ti->nextOf(), NULL) &&
1093 !ti->nextOf()->isBaseOf(tintro->nextOf(), NULL))
1094 {
1095 error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars());
1096 }
1097 }
1098 tintro = ti;
1099 }
1100 goto L2;
1101 }
1102 }
1103 }
1104
1105 if (!doesoverride && isOverride() && (type->nextOf() || !may_override))
1106 {
1107 BaseClass *bc = NULL;
1108 Dsymbol *s = NULL;
1109 for (size_t i = 0; i < cd->baseclasses->dim; i++)
1110 {
1111 bc = (*cd->baseclasses)[i];
1112 s = bc->sym->search_correct(ident);
1113 if (s) break;
1114 }
1115
1116 if (s)
1117 error("does not override any function, did you mean to override '%s%s'?",
1118 bc->sym->isCPPclass() ? "extern (C++) " : "", s->toPrettyChars());
1119 else
1120 error("does not override any function");
1121 }
1122
1123 L2: ;
1124
1125 /* Go through all the interface bases.
1126 * Disallow overriding any final functions in the interface(s).
1127 */
1128 for (size_t i = 0; i < cd->interfaces.length; i++)
1129 {
1130 BaseClass *b = cd->interfaces.ptr[i];
1131 if (b->sym)
1132 {
1133 Dsymbol *s = search_function(b->sym, ident);
1134 if (s)
1135 {
1136 FuncDeclaration *f2 = s->isFuncDeclaration();
1137 if (f2)
1138 {
1139 f2 = f2->overloadExactMatch(type);
1140 if (f2 && f2->isFinalFunc() && f2->prot().kind != PROTprivate)
1141 error("cannot override final function %s.%s", b->sym->toChars(), f2->toPrettyChars());
1142 }
1143 }
1144 }
1145 }
1146
1147 if (isOverride())
1148 {
1149 if (storage_class & STCdisable)
1150 deprecation("overridden functions cannot be annotated @disable");
1151 if (isDeprecated())
1152 deprecation("deprecated functions cannot be annotated @disable");
1153 }
1154 }
1155 else if (isOverride() && !parent->isTemplateInstance())
1156 error("override only applies to class member functions");
1157
1158 // Reflect this->type to f because it could be changed by findVtblIndex
1159 f = type->toTypeFunction();
1160
1161 /* Do not allow template instances to add virtual functions
1162 * to a class.
1163 */
1164 if (isVirtual())
1165 {
1166 TemplateInstance *ti = parent->isTemplateInstance();
1167 if (ti)
1168 {
1169 // Take care of nested templates
1170 while (1)
1171 {
1172 TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance();
1173 if (!ti2)
1174 break;
1175 ti = ti2;
1176 }
1177
1178 // If it's a member template
1179 ClassDeclaration *cd = ti->tempdecl->isClassMember();
1180 if (cd)
1181 {
1182 error("cannot use template to add virtual function to class '%s'", cd->toChars());
1183 }
1184 }
1185 }
1186
1187 if (isMain())
1188 checkDmain(); // Check main() parameters and return type
1189
1190 Ldone:
1191 /* Purity and safety can be inferred for some functions by examining
1192 * the function body.
1193 */
1194 if (canInferAttributes(this, sc))
1195 initInferAttributes(this);
1196
1197 Module::dprogress++;
1198 semanticRun = PASSsemanticdone;
1199
1200 /* Save scope for possible later use (if we need the
1201 * function internals)
1202 */
1203 _scope = sc->copy();
1204 _scope->setNoFree();
1205
1206 static bool printedMain = false; // semantic might run more than once
1207 if (global.params.verbose && !printedMain)
1208 {
1209 const char *type = isMain() ? "main" : isWinMain() ? "winmain" : isDllMain() ? "dllmain" : (const char *)NULL;
1210 Module *mod = sc->_module;
1211
1212 if (type && mod)
1213 {
1214 printedMain = true;
1215 const char *name = mod->srcfile->toChars();
1216 const char *path = FileName::searchPath(global.path, name, true);
1217 message("entry %-10s\t%s", type, path ? path : name);
1218 }
1219 }
1220
1221 if (fbody && isMain() && sc->_module->isRoot())
1222 Compiler::genCmain(sc);
1223
1224 assert(type->ty != Terror || errors);
1225 }
1226
semantic2(Scope * sc)1227 void FuncDeclaration::semantic2(Scope *sc)
1228 {
1229 if (semanticRun >= PASSsemantic2done)
1230 return;
1231 assert(semanticRun <= PASSsemantic2);
1232 semanticRun = PASSsemantic2;
1233
1234 objc()->setSelector(this, sc);
1235 objc()->validateSelector(this);
1236
1237 if (parent->isClassDeclaration())
1238 {
1239 objc()->checkLinkage(this);
1240 }
1241 }
1242
1243 /****************************************************
1244 * Determine whether an 'out' contract is declared inside
1245 * the given function or any of its overrides.
1246 * Params:
1247 * fd = the function to search
1248 * Returns:
1249 * true found an 'out' contract
1250 * false didn't find one
1251 */
needsFensure(FuncDeclaration * fd)1252 static bool needsFensure(FuncDeclaration *fd)
1253 {
1254 if (fd->fensure)
1255 return true;
1256
1257 for (size_t i = 0; i < fd->foverrides.dim; i++)
1258 {
1259 FuncDeclaration *fdv = fd->foverrides[i];
1260
1261 if (fdv->fensure)
1262 return true;
1263
1264 if (needsFensure(fdv))
1265 return true;
1266 }
1267 return false;
1268 }
1269
1270 /****************************************************
1271 * Rewrite contracts as nested functions, then call them. Doing it as nested
1272 * functions means that overriding functions can call them.
1273 * Params:
1274 * fd = the function to rewrite contracts for
1275 */
buildEnsureRequire(FuncDeclaration * fdx)1276 static void buildEnsureRequire(FuncDeclaration *fdx)
1277 {
1278 if (!fdx->isVirtual())
1279 return;
1280
1281 TypeFunction *f = (TypeFunction *)fdx->type;
1282
1283 if (fdx->frequire)
1284 {
1285 /* in { ... }
1286 * becomes:
1287 * void __require() { ... }
1288 * __require();
1289 */
1290 Loc loc = fdx->frequire->loc;
1291 TypeFunction *tf = new TypeFunction(NULL, Type::tvoid, 0, LINKd);
1292 tf->isnothrow = f->isnothrow;
1293 tf->isnogc = f->isnogc;
1294 tf->purity = f->purity;
1295 tf->trust = f->trust;
1296 FuncDeclaration *fd = new FuncDeclaration(loc, loc,
1297 Id::require, STCundefined, tf);
1298 fd->fbody = fdx->frequire;
1299 Statement *s1 = new ExpStatement(loc, fd);
1300 Expression *e = new CallExp(loc, new VarExp(loc, fd, false), (Expressions *)NULL);
1301 Statement *s2 = new ExpStatement(loc, e);
1302 fdx->frequire = new CompoundStatement(loc, s1, s2);
1303 fdx->fdrequire = fd;
1304 }
1305
1306 if (!fdx->outId && f->nextOf() && f->nextOf()->toBasetype()->ty != Tvoid)
1307 fdx->outId = Id::result; // provide a default
1308
1309 if (fdx->fensure)
1310 {
1311 /* out (result) { ... }
1312 * becomes:
1313 * void __ensure(ref tret result) { ... }
1314 * __ensure(result);
1315 */
1316 Loc loc = fdx->fensure->loc;
1317 Parameters *fparams = new Parameters();
1318 Parameter *p = NULL;
1319 if (fdx->outId)
1320 {
1321 p = new Parameter(STCref | STCconst, f->nextOf(), fdx->outId, NULL);
1322 fparams->push(p);
1323 }
1324 TypeFunction *tf = new TypeFunction(fparams, Type::tvoid, 0, LINKd);
1325 tf->isnothrow = f->isnothrow;
1326 tf->isnogc = f->isnogc;
1327 tf->purity = f->purity;
1328 tf->trust = f->trust;
1329 FuncDeclaration *fd = new FuncDeclaration(loc, loc,
1330 Id::ensure, STCundefined, tf);
1331 fd->fbody = fdx->fensure;
1332 Statement *s1 = new ExpStatement(loc, fd);
1333 Expression *eresult = NULL;
1334 if (fdx->outId)
1335 eresult = new IdentifierExp(loc, fdx->outId);
1336 Expression *e = new CallExp(loc, new VarExp(loc, fd, false), eresult);
1337 Statement *s2 = new ExpStatement(loc, e);
1338 fdx->fensure = new CompoundStatement(loc, s1, s2);
1339 fdx->fdensure = fd;
1340 }
1341 }
1342
1343 /* Determine if function should add `return 0;`
1344 */
addReturn0(FuncDeclaration * funcdecl)1345 static bool addReturn0(FuncDeclaration *funcdecl)
1346 {
1347 TypeFunction *f = (TypeFunction *)funcdecl->type;
1348
1349 return f->next->ty == Tvoid &&
1350 (funcdecl->isMain() || (global.params.betterC && funcdecl->isCMain()));
1351 }
1352
1353 // Do the semantic analysis on the internals of the function.
1354
semantic3(Scope * sc)1355 void FuncDeclaration::semantic3(Scope *sc)
1356 {
1357 VarDeclaration *_arguments = NULL;
1358
1359 if (!parent)
1360 {
1361 if (global.errors)
1362 return;
1363 //printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc);
1364 assert(0);
1365 }
1366 if (errors || isError(parent))
1367 {
1368 errors = true;
1369 return;
1370 }
1371 //printf("FuncDeclaration::semantic3('%s.%s', %p, sc = %p, loc = %s)\n", parent->toChars(), toChars(), this, sc, loc.toChars());
1372 //fflush(stdout);
1373 //printf("storage class = x%x %x\n", sc->stc, storage_class);
1374 //{ static int x; if (++x == 2) *(char*)0=0; }
1375 //printf("\tlinkage = %d\n", sc->linkage);
1376
1377 if (ident == Id::assign && !inuse)
1378 {
1379 if (storage_class & STCinference)
1380 {
1381 /* Bugzilla 15044: For generated opAssign function, any errors
1382 * from its body need to be gagged.
1383 */
1384 unsigned oldErrors = global.startGagging();
1385 ++inuse;
1386 semantic3(sc);
1387 --inuse;
1388 if (global.endGagging(oldErrors)) // if errors happened
1389 {
1390 // Disable generated opAssign, because some members forbid identity assignment.
1391 storage_class |= STCdisable;
1392 fbody = NULL; // remove fbody which contains the error
1393 semantic3Errors = false;
1394 }
1395 return;
1396 }
1397 }
1398
1399 //printf(" sc->incontract = %d\n", (sc->flags & SCOPEcontract));
1400 if (semanticRun >= PASSsemantic3)
1401 return;
1402 semanticRun = PASSsemantic3;
1403 semantic3Errors = false;
1404
1405 if (!type || type->ty != Tfunction)
1406 return;
1407 TypeFunction *f = (TypeFunction *)type;
1408 if (!inferRetType && f->next->ty == Terror)
1409 return;
1410
1411 if (!fbody && inferRetType && !f->next)
1412 {
1413 error("has no function body with return type inference");
1414 return;
1415 }
1416
1417 unsigned oldErrors = global.errors;
1418
1419 if (frequire)
1420 {
1421 for (size_t i = 0; i < foverrides.dim; i++)
1422 {
1423 FuncDeclaration *fdv = foverrides[i];
1424
1425 if (fdv->fbody && !fdv->frequire)
1426 {
1427 error("cannot have an in contract when overriden function %s does not have an in contract", fdv->toPrettyChars());
1428 break;
1429 }
1430 }
1431 }
1432
1433 // Remember whether we need to generate an 'out' contract.
1434 bool needEnsure = needsFensure(this);
1435
1436 if (fbody || frequire || needEnsure)
1437 {
1438 /* Symbol table into which we place parameters and nested functions,
1439 * solely to diagnose name collisions.
1440 */
1441 localsymtab = new DsymbolTable();
1442
1443 // Establish function scope
1444 ScopeDsymbol *ss = new ScopeDsymbol();
1445 // find enclosing scope symbol, might skip symbol-less CTFE and/or FuncExp scopes
1446 for (Scope *scx = sc; ; scx = scx->enclosing)
1447 {
1448 if (scx->scopesym)
1449 {
1450 ss->parent = scx->scopesym;
1451 break;
1452 }
1453 }
1454 ss->loc = loc;
1455 ss->endlinnum = endloc.linnum;
1456 Scope *sc2 = sc->push(ss);
1457 sc2->func = this;
1458 sc2->parent = this;
1459 sc2->callSuper = 0;
1460 sc2->sbreak = NULL;
1461 sc2->scontinue = NULL;
1462 sc2->sw = NULL;
1463 sc2->fes = fes;
1464 sc2->linkage = LINKd;
1465 sc2->stc &= ~(STCauto | STCscope | STCstatic | STCextern | STCabstract |
1466 STCdeprecated | STCoverride |
1467 STC_TYPECTOR | STCfinal | STCtls | STCgshared | STCref | STCreturn |
1468 STCproperty | STCnothrow | STCpure | STCsafe | STCtrusted | STCsystem);
1469 sc2->protection = Prot(PROTpublic);
1470 sc2->explicitProtection = 0;
1471 sc2->aligndecl = NULL;
1472 if (this->ident != Id::require && this->ident != Id::ensure)
1473 sc2->flags = sc->flags & ~SCOPEcontract;
1474 sc2->flags &= ~SCOPEcompile;
1475 sc2->tf = NULL;
1476 sc2->os = NULL;
1477 sc2->noctor = 0;
1478 sc2->userAttribDecl = NULL;
1479 if (sc2->intypeof == 1) sc2->intypeof = 2;
1480 sc2->fieldinit = NULL;
1481 sc2->fieldinit_dim = 0;
1482
1483 /* Note: When a lambda is defined immediately under aggregate member
1484 * scope, it should be contextless due to prevent interior pointers.
1485 * e.g.
1486 * // dg points 'this' - it's interior pointer
1487 * class C { int x; void delegate() dg = (){ this.x = 1; }; }
1488 *
1489 * However, lambdas could be used inside typeof, in order to check
1490 * some expressions varidity at compile time. For such case the lambda
1491 * body can access aggregate instance members.
1492 * e.g.
1493 * class C { int x; static assert(is(typeof({ this.x = 1; }))); }
1494 *
1495 * To properly accept it, mark these lambdas as member functions.
1496 */
1497 if (FuncLiteralDeclaration *fld = isFuncLiteralDeclaration())
1498 {
1499 if (AggregateDeclaration *ad = isMember2())
1500 {
1501 if (!sc->intypeof)
1502 {
1503 if (fld->tok == TOKdelegate)
1504 error("cannot be %s members", ad->kind());
1505 else
1506 fld->tok = TOKfunction;
1507 }
1508 else
1509 {
1510 if (fld->tok != TOKfunction)
1511 fld->tok = TOKdelegate;
1512 }
1513 }
1514 }
1515
1516 // Declare 'this'
1517 AggregateDeclaration *ad = isThis();
1518 vthis = declareThis(sc2, ad);
1519 //printf("[%s] ad = %p vthis = %p\n", loc.toChars(), ad, vthis);
1520 //if (vthis) printf("\tvthis->type = %s\n", vthis->type->toChars());
1521
1522 // Declare hidden variable _arguments[] and _argptr
1523 if (f->varargs == 1)
1524 {
1525 if (f->linkage == LINKd)
1526 {
1527 // Variadic arguments depend on Typeinfo being defined
1528 if (!global.params.useTypeInfo || !Type::dtypeinfo || !Type::typeinfotypelist)
1529 {
1530 if (!global.params.useTypeInfo)
1531 error("D-style variadic functions cannot be used with -betterC");
1532 else if (!Type::typeinfotypelist)
1533 error("`object.TypeInfo_Tuple` could not be found, but is implicitly used in D-style variadic functions");
1534 else
1535 error("`object.TypeInfo` could not be found, but is implicitly used in D-style variadic functions");
1536 fatal();
1537 }
1538
1539 // Declare _arguments[]
1540 v_arguments = new VarDeclaration(Loc(), Type::typeinfotypelist->type, Id::_arguments_typeinfo, NULL);
1541 v_arguments->storage_class |= STCtemp | STCparameter;
1542 v_arguments->semantic(sc2);
1543 sc2->insert(v_arguments);
1544 v_arguments->parent = this;
1545
1546 //Type *t = Type::typeinfo->type->constOf()->arrayOf();
1547 Type *t = Type::dtypeinfo->type->arrayOf();
1548 _arguments = new VarDeclaration(Loc(), t, Id::_arguments, NULL);
1549 _arguments->storage_class |= STCtemp;
1550 _arguments->semantic(sc2);
1551 sc2->insert(_arguments);
1552 _arguments->parent = this;
1553 }
1554 if (f->linkage == LINKd || (f->parameters && Parameter::dim(f->parameters)))
1555 {
1556 // Declare _argptr
1557 Type *t = Type::tvalist;
1558 v_argptr = new VarDeclaration(Loc(), t, Id::_argptr, NULL);
1559 v_argptr->storage_class |= STCtemp;
1560 v_argptr->semantic(sc2);
1561 sc2->insert(v_argptr);
1562 v_argptr->parent = this;
1563 }
1564 }
1565
1566 /* Declare all the function parameters as variables
1567 * and install them in parameters[]
1568 */
1569 size_t nparams = Parameter::dim(f->parameters);
1570 if (nparams)
1571 {
1572 /* parameters[] has all the tuples removed, as the back end
1573 * doesn't know about tuples
1574 */
1575 parameters = new VarDeclarations();
1576 parameters->reserve(nparams);
1577 for (size_t i = 0; i < nparams; i++)
1578 {
1579 Parameter *fparam = Parameter::getNth(f->parameters, i);
1580 Identifier *id = fparam->ident;
1581 StorageClass stc = 0;
1582 if (!id)
1583 {
1584 /* Generate identifier for un-named parameter,
1585 * because we need it later on.
1586 */
1587 fparam->ident = id = Identifier::generateId("_param_", i);
1588 stc |= STCtemp;
1589 }
1590 Type *vtype = fparam->type;
1591 VarDeclaration *v = new VarDeclaration(loc, vtype, id, NULL);
1592 //printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars());
1593 stc |= STCparameter;
1594 if (f->varargs == 2 && i + 1 == nparams)
1595 stc |= STCvariadic;
1596 if (flags & FUNCFLAGinferScope && !(fparam->storageClass & STCscope))
1597 stc |= STCmaybescope;
1598 stc |= fparam->storageClass & (STCin | STCout | STCref | STCreturn | STCscope | STClazy | STCfinal | STC_TYPECTOR | STCnodtor);
1599 v->storage_class = stc;
1600 v->semantic(sc2);
1601 if (!sc2->insert(v))
1602 error("parameter %s.%s is already defined", toChars(), v->toChars());
1603 else
1604 parameters->push(v);
1605 localsymtab->insert(v);
1606 v->parent = this;
1607 }
1608 }
1609
1610 // Declare the tuple symbols and put them in the symbol table,
1611 // but not in parameters[].
1612 if (f->parameters)
1613 {
1614 for (size_t i = 0; i < f->parameters->dim; i++)
1615 {
1616 Parameter *fparam = (*f->parameters)[i];
1617
1618 if (!fparam->ident)
1619 continue; // never used, so ignore
1620 if (fparam->type->ty == Ttuple)
1621 {
1622 TypeTuple *t = (TypeTuple *)fparam->type;
1623 size_t dim = Parameter::dim(t->arguments);
1624 Objects *exps = new Objects();
1625 exps->setDim(dim);
1626 for (size_t j = 0; j < dim; j++)
1627 {
1628 Parameter *narg = Parameter::getNth(t->arguments, j);
1629 assert(narg->ident);
1630 VarDeclaration *v = sc2->search(Loc(), narg->ident, NULL)->isVarDeclaration();
1631 assert(v);
1632 Expression *e = new VarExp(v->loc, v);
1633 (*exps)[j] = e;
1634 }
1635 assert(fparam->ident);
1636 TupleDeclaration *v = new TupleDeclaration(loc, fparam->ident, exps);
1637 //printf("declaring tuple %s\n", v->toChars());
1638 v->isexp = true;
1639 if (!sc2->insert(v))
1640 error("parameter %s.%s is already defined", toChars(), v->toChars());
1641 localsymtab->insert(v);
1642 v->parent = this;
1643 }
1644 }
1645 }
1646
1647 // Precondition invariant
1648 Statement *fpreinv = NULL;
1649 if (addPreInvariant())
1650 {
1651 Expression *e = addInvariant(loc, sc, ad, vthis, isDtorDeclaration() != NULL);
1652 if (e)
1653 fpreinv = new ExpStatement(Loc(), e);
1654 }
1655
1656 // Postcondition invariant
1657 Statement *fpostinv = NULL;
1658 if (addPostInvariant())
1659 {
1660 Expression *e = addInvariant(loc, sc, ad, vthis, isCtorDeclaration() != NULL);
1661 if (e)
1662 fpostinv = new ExpStatement(Loc(), e);
1663 }
1664
1665 // Pre/Postcondition contract
1666 if (!fbody)
1667 buildEnsureRequire(this);
1668
1669 Scope *scout = NULL;
1670 if (needEnsure || addPostInvariant())
1671 {
1672 if ((needEnsure && global.params.useOut) || fpostinv)
1673 {
1674 returnLabel = new LabelDsymbol(Id::returnLabel);
1675 }
1676
1677 // scope of out contract (need for vresult->semantic)
1678 ScopeDsymbol *sym = new ScopeDsymbol();
1679 sym->parent = sc2->scopesym;
1680 sym->loc = loc;
1681 sym->endlinnum = endloc.linnum;
1682 scout = sc2->push(sym);
1683 }
1684
1685 if (fbody)
1686 {
1687 ScopeDsymbol *sym = new ScopeDsymbol();
1688 sym->parent = sc2->scopesym;
1689 sym->loc = loc;
1690 sym->endlinnum = endloc.linnum;
1691 sc2 = sc2->push(sym);
1692
1693 AggregateDeclaration *ad2 = isMember2();
1694
1695 /* If this is a class constructor
1696 */
1697 if (ad2 && isCtorDeclaration())
1698 {
1699 allocFieldinit(sc2, ad2->fields.dim);
1700 for (size_t i = 0; i < ad2->fields.dim; i++)
1701 {
1702 VarDeclaration *v = ad2->fields[i];
1703 v->ctorinit = 0;
1704 }
1705 }
1706
1707 if (!inferRetType && retStyle(f) != RETstack)
1708 nrvo_can = 0;
1709
1710 bool inferRef = (f->isref && (storage_class & STCauto));
1711
1712 fbody = ::semantic(fbody, sc2);
1713 if (!fbody)
1714 fbody = new CompoundStatement(Loc(), new Statements());
1715
1716 if (naked)
1717 {
1718 fpreinv = NULL; // can't accommodate with no stack frame
1719 fpostinv = NULL;
1720 }
1721
1722 assert(type == f ||
1723 (type->ty == Tfunction &&
1724 f->purity == PUREimpure &&
1725 ((TypeFunction *)type)->purity >= PUREfwdref));
1726 f = (TypeFunction *)type;
1727
1728 if (inferRetType)
1729 {
1730 // If no return type inferred yet, then infer a void
1731 if (!f->next)
1732 f->next = Type::tvoid;
1733 if (f->checkRetType(loc))
1734 fbody = new ErrorStatement();
1735 }
1736 if (global.params.vcomplex && f->next != NULL)
1737 f->next->checkComplexTransition(loc);
1738
1739 if (returns && !fbody->isErrorStatement())
1740 {
1741 for (size_t i = 0; i < returns->dim; )
1742 {
1743 Expression *exp = (*returns)[i]->exp;
1744 if (exp->op == TOKvar && ((VarExp *)exp)->var == vresult)
1745 {
1746 if (addReturn0(this))
1747 exp->type = Type::tint32;
1748 else
1749 exp->type = f->next;
1750 // Remove `return vresult;` from returns
1751 returns->remove(i);
1752 continue;
1753 }
1754 if (inferRef && f->isref && !exp->type->constConv(f->next)) // Bugzilla 13336
1755 f->isref = false;
1756 i++;
1757 }
1758 }
1759 if (f->isref) // Function returns a reference
1760 {
1761 if (storage_class & STCauto)
1762 storage_class &= ~STCauto;
1763 }
1764 if (retStyle(f) != RETstack)
1765 nrvo_can = 0;
1766
1767 if (fbody->isErrorStatement())
1768 ;
1769 else if (isStaticCtorDeclaration())
1770 {
1771 /* It's a static constructor. Ensure that all
1772 * ctor consts were initialized.
1773 */
1774 ScopeDsymbol *pd = toParent()->isScopeDsymbol();
1775 for (size_t i = 0; i < pd->members->dim; i++)
1776 {
1777 Dsymbol *s = (*pd->members)[i];
1778 s->checkCtorConstInit();
1779 }
1780 }
1781 else if (ad2 && isCtorDeclaration())
1782 {
1783 ClassDeclaration *cd = ad2->isClassDeclaration();
1784
1785 // Verify that all the ctorinit fields got initialized
1786 if (!(sc2->callSuper & CSXthis_ctor))
1787 {
1788 for (size_t i = 0; i < ad2->fields.dim; i++)
1789 {
1790 VarDeclaration *v = ad2->fields[i];
1791 if (v->isThisDeclaration())
1792 continue;
1793 if (v->ctorinit == 0)
1794 {
1795 /* Current bugs in the flow analysis:
1796 * 1. union members should not produce error messages even if
1797 * not assigned to
1798 * 2. structs should recognize delegating opAssign calls as well
1799 * as delegating calls to other constructors
1800 */
1801 if (v->isCtorinit() && !v->type->isMutable() && cd)
1802 error("missing initializer for %s field %s", MODtoChars(v->type->mod), v->toChars());
1803 else if (v->storage_class & STCnodefaultctor)
1804 ::error(loc, "field %s must be initialized in constructor", v->toChars());
1805 else if (v->type->needsNested())
1806 ::error(loc, "field %s must be initialized in constructor, because it is nested struct", v->toChars());
1807 }
1808 else
1809 {
1810 bool mustInit = (v->storage_class & STCnodefaultctor ||
1811 v->type->needsNested());
1812 if (mustInit && !(sc2->fieldinit[i] & CSXthis_ctor))
1813 {
1814 error("field %s must be initialized but skipped", v->toChars());
1815 }
1816 }
1817 }
1818 }
1819 freeFieldinit(sc2);
1820
1821 if (cd &&
1822 !(sc2->callSuper & CSXany_ctor) &&
1823 cd->baseClass && cd->baseClass->ctor)
1824 {
1825 sc2->callSuper = 0;
1826
1827 // Insert implicit super() at start of fbody
1828 FuncDeclaration *fd = resolveFuncCall(Loc(), sc2, cd->baseClass->ctor, NULL, vthis->type, NULL, 1);
1829 if (!fd)
1830 {
1831 error("no match for implicit super() call in constructor");
1832 }
1833 else if (fd->storage_class & STCdisable)
1834 {
1835 error("cannot call super() implicitly because it is annotated with @disable");
1836 }
1837 else
1838 {
1839 Expression *e1 = new SuperExp(Loc());
1840 Expression *e = new CallExp(Loc(), e1);
1841 e = ::semantic(e, sc2);
1842
1843 Statement *s = new ExpStatement(Loc(), e);
1844 fbody = new CompoundStatement(Loc(), s, fbody);
1845 }
1846 }
1847 //printf("callSuper = x%x\n", sc2->callSuper);
1848 }
1849
1850 /* https://issues.dlang.org/show_bug.cgi?id=17502
1851 * Wait until after the return type has been inferred before
1852 * generating the contracts for this function, and merging contracts
1853 * from overrides.
1854 *
1855 * https://issues.dlang.org/show_bug.cgi?id=17893
1856 * However should take care to generate this before inferered
1857 * function attributes are applied, such as 'nothrow'.
1858 *
1859 * This was originally at the end of the first semantic pass, but
1860 * required a fix-up to be done here for the '__result' variable
1861 * type of __ensure() inside auto functions, but this didn't work
1862 * if the out parameter was implicit.
1863 */
1864 buildEnsureRequire(this);
1865
1866 int blockexit = BEnone;
1867 if (!fbody->isErrorStatement())
1868 {
1869 // Check for errors related to 'nothrow'.
1870 unsigned int nothrowErrors = global.errors;
1871 blockexit = blockExit(fbody, this, f->isnothrow);
1872 if (f->isnothrow && (global.errors != nothrowErrors))
1873 ::error(loc, "nothrow %s '%s' may throw", kind(), toPrettyChars());
1874 if (flags & FUNCFLAGnothrowInprocess)
1875 {
1876 if (type == f) f = (TypeFunction *)f->copy();
1877 f->isnothrow = !(blockexit & BEthrow);
1878 }
1879 }
1880
1881 if (fbody->isErrorStatement())
1882 ;
1883 else if (ad2 && isCtorDeclaration())
1884 {
1885 /* Append:
1886 * return this;
1887 * to function body
1888 */
1889 if (blockexit & BEfallthru)
1890 {
1891 Statement *s = new ReturnStatement(loc, NULL);
1892 s = ::semantic(s, sc2);
1893 fbody = new CompoundStatement(loc, fbody, s);
1894 hasReturnExp |= (hasReturnExp & 1 ? 16 : 1);
1895 }
1896 }
1897 else if (fes)
1898 {
1899 // For foreach(){} body, append a return 0;
1900 if (blockexit & BEfallthru)
1901 {
1902 Expression *e = new IntegerExp(0);
1903 Statement *s = new ReturnStatement(Loc(), e);
1904 fbody = new CompoundStatement(Loc(), fbody, s);
1905 hasReturnExp |= (hasReturnExp & 1 ? 16 : 1);
1906 }
1907 assert(!returnLabel);
1908 }
1909 else
1910 {
1911 const bool inlineAsm = (hasReturnExp & 8) != 0;
1912 if ((blockexit & BEfallthru) && f->next->ty != Tvoid && !inlineAsm)
1913 {
1914 Expression *e;
1915 if (!hasReturnExp)
1916 error("has no return statement, but is expected to return a value of type %s", f->next->toChars());
1917 else
1918 error("no return exp; or assert(0); at end of function");
1919 if (global.params.useAssert &&
1920 !global.params.useInline)
1921 {
1922 /* Add an assert(0, msg); where the missing return
1923 * should be.
1924 */
1925 e = new AssertExp(
1926 endloc,
1927 new IntegerExp(0),
1928 new StringExp(loc, const_cast<char *>("missing return expression"))
1929 );
1930 }
1931 else
1932 e = new HaltExp(endloc);
1933 e = new CommaExp(Loc(), e, f->next->defaultInit());
1934 e = ::semantic(e, sc2);
1935 Statement *s = new ExpStatement(Loc(), e);
1936 fbody = new CompoundStatement(Loc(), fbody, s);
1937 }
1938 }
1939
1940 if (returns)
1941 {
1942 bool implicit0 = addReturn0(this);
1943 Type *tret = implicit0 ? Type::tint32 : f->next;
1944 assert(tret->ty != Tvoid);
1945 if (vresult || returnLabel)
1946 buildResultVar(scout ? scout : sc2, tret);
1947
1948 /* Cannot move this loop into NrvoWalker, because
1949 * returns[i] may be in the nested delegate for foreach-body.
1950 */
1951 for (size_t i = 0; i < returns->dim; i++)
1952 {
1953 ReturnStatement *rs = (*returns)[i];
1954 Expression *exp = rs->exp;
1955 if (exp->op == TOKerror)
1956 continue;
1957 if (tret->ty == Terror)
1958 {
1959 // Bugzilla 13702
1960 exp = checkGC(sc2, exp);
1961 continue;
1962 }
1963
1964 if (!exp->implicitConvTo(tret) &&
1965 parametersIntersect(exp->type))
1966 {
1967 if (exp->type->immutableOf()->implicitConvTo(tret))
1968 exp = exp->castTo(sc2, exp->type->immutableOf());
1969 else if (exp->type->wildOf()->implicitConvTo(tret))
1970 exp = exp->castTo(sc2, exp->type->wildOf());
1971 }
1972 exp = exp->implicitCastTo(sc2, tret);
1973
1974 if (f->isref)
1975 {
1976 // Function returns a reference
1977 exp = exp->toLvalue(sc2, exp);
1978 checkReturnEscapeRef(sc2, exp, false);
1979 }
1980 else
1981 {
1982 exp = exp->optimize(WANTvalue);
1983
1984 /* Bugzilla 10789:
1985 * If NRVO is not possible, all returned lvalues should call their postblits.
1986 */
1987 if (!nrvo_can)
1988 exp = doCopyOrMove(sc2, exp);
1989
1990 if (tret->hasPointers())
1991 checkReturnEscape(sc2, exp, false);
1992 }
1993
1994 exp = checkGC(sc2, exp);
1995
1996 if (vresult)
1997 {
1998 // Create: return vresult = exp;
1999 exp = new BlitExp(rs->loc, vresult, exp);
2000 exp->type = vresult->type;
2001
2002 if (rs->caseDim)
2003 exp = Expression::combine(exp, new IntegerExp(rs->caseDim));
2004 }
2005 else if (tintro && !tret->equals(tintro->nextOf()))
2006 {
2007 exp = exp->implicitCastTo(sc2, tintro->nextOf());
2008 }
2009 rs->exp = exp;
2010 }
2011 }
2012 if (nrvo_var || returnLabel)
2013 {
2014 NrvoWalker nw;
2015 nw.fd = this;
2016 nw.sc = sc2;
2017 nw.visitStmt(fbody);
2018 }
2019
2020 sc2 = sc2->pop();
2021 }
2022
2023 frequire = mergeFrequire(frequire);
2024 fensure = mergeFensure(fensure, outId);
2025
2026 Statement *freq = frequire;
2027 Statement *fens = fensure;
2028
2029 /* Do the semantic analysis on the [in] preconditions and
2030 * [out] postconditions.
2031 */
2032 if (freq)
2033 {
2034 /* frequire is composed of the [in] contracts
2035 */
2036 ScopeDsymbol *sym = new ScopeDsymbol();
2037 sym->parent = sc2->scopesym;
2038 sym->loc = loc;
2039 sym->endlinnum = endloc.linnum;
2040 sc2 = sc2->push(sym);
2041 sc2->flags = (sc2->flags & ~SCOPEcontract) | SCOPErequire;
2042
2043 // BUG: need to error if accessing out parameters
2044 // BUG: need to treat parameters as const
2045 // BUG: need to disallow returns and throws
2046 // BUG: verify that all in and ref parameters are read
2047 freq = ::semantic(freq, sc2);
2048 blockExit(freq, this, false);
2049
2050 sc2 = sc2->pop();
2051
2052 if (!global.params.useIn)
2053 freq = NULL;
2054 }
2055
2056 if (fens)
2057 {
2058 /* fensure is composed of the [out] contracts
2059 */
2060 if (f->next->ty == Tvoid && outId)
2061 error("void functions have no result");
2062
2063 sc2 = scout; //push
2064 sc2->flags = (sc2->flags & ~SCOPEcontract) | SCOPEensure;
2065
2066 // BUG: need to treat parameters as const
2067 // BUG: need to disallow returns and throws
2068 if (fensure && f->next->ty != Tvoid)
2069 buildResultVar(scout, f->next);
2070
2071 fens = ::semantic(fens, sc2);
2072 blockExit(fens, this, false);
2073
2074 sc2 = sc2->pop();
2075
2076 if (!global.params.useOut)
2077 fens = NULL;
2078 }
2079
2080 if (fbody && fbody->isErrorStatement())
2081 ;
2082 else
2083 {
2084 Statements *a = new Statements();
2085
2086 // Merge in initialization of 'out' parameters
2087 if (parameters)
2088 {
2089 for (size_t i = 0; i < parameters->dim; i++)
2090 {
2091 VarDeclaration *v = (*parameters)[i];
2092 if (v->storage_class & STCout)
2093 {
2094 assert(v->_init);
2095 ExpInitializer *ie = v->_init->isExpInitializer();
2096 assert(ie);
2097 if (ie->exp->op == TOKconstruct)
2098 ie->exp->op = TOKassign; // construction occured in parameter processing
2099 a->push(new ExpStatement(Loc(), ie->exp));
2100 }
2101 }
2102 }
2103
2104 if (v_argptr)
2105 {
2106 // Handled in FuncDeclaration::toObjFile
2107 v_argptr->_init = new VoidInitializer(loc);
2108 }
2109
2110 if (_arguments)
2111 {
2112 /* Advance to elements[] member of TypeInfo_Tuple with:
2113 * _arguments = v_arguments.elements;
2114 */
2115 Expression *e = new VarExp(Loc(), v_arguments);
2116 e = new DotIdExp(Loc(), e, Id::elements);
2117 e = new ConstructExp(Loc(), _arguments, e);
2118 e = ::semantic(e, sc2);
2119
2120 _arguments->_init = new ExpInitializer(Loc(), e);
2121 DeclarationExp *de = new DeclarationExp(Loc(), _arguments);
2122 a->push(new ExpStatement(Loc(), de));
2123 }
2124
2125 // Merge contracts together with body into one compound statement
2126
2127 if (freq || fpreinv)
2128 {
2129 if (!freq)
2130 freq = fpreinv;
2131 else if (fpreinv)
2132 freq = new CompoundStatement(Loc(), freq, fpreinv);
2133
2134 a->push(freq);
2135 }
2136
2137 if (fbody)
2138 a->push(fbody);
2139
2140 if (fens || fpostinv)
2141 {
2142 if (!fens)
2143 fens = fpostinv;
2144 else if (fpostinv)
2145 fens = new CompoundStatement(Loc(), fpostinv, fens);
2146
2147 LabelStatement *ls = new LabelStatement(Loc(), Id::returnLabel, fens);
2148 returnLabel->statement = ls;
2149 a->push(returnLabel->statement);
2150
2151 if (f->next->ty != Tvoid && vresult)
2152 {
2153 // Create: return vresult;
2154 Expression *e = new VarExp(Loc(), vresult);
2155 if (tintro)
2156 {
2157 e = e->implicitCastTo(sc, tintro->nextOf());
2158 e = ::semantic(e, sc);
2159 }
2160 ReturnStatement *s = new ReturnStatement(Loc(), e);
2161 a->push(s);
2162 }
2163 }
2164 if (addReturn0(this))
2165 {
2166 // Add a return 0; statement
2167 Statement *s = new ReturnStatement(Loc(), new IntegerExp(0));
2168 a->push(s);
2169 }
2170
2171 Statement *sbody = new CompoundStatement(Loc(), a);
2172 /* Append destructor calls for parameters as finally blocks.
2173 */
2174 if (parameters)
2175 {
2176 for (size_t i = 0; i < parameters->dim; i++)
2177 {
2178 VarDeclaration *v = (*parameters)[i];
2179
2180 if (v->storage_class & (STCref | STCout | STClazy))
2181 continue;
2182
2183 if (v->needsScopeDtor())
2184 {
2185 // same with ExpStatement.scopeCode()
2186 Statement *s = new DtorExpStatement(Loc(), v->edtor, v);
2187 v->storage_class |= STCnodtor;
2188
2189 s = ::semantic(s, sc2);
2190
2191 bool isnothrow = f->isnothrow & !(flags & FUNCFLAGnothrowInprocess);
2192 int blockexit = blockExit(s, this, isnothrow);
2193 if (f->isnothrow && isnothrow && blockexit & BEthrow)
2194 ::error(loc, "nothrow %s '%s' may throw", kind(), toPrettyChars());
2195 if (flags & FUNCFLAGnothrowInprocess && blockexit & BEthrow)
2196 f->isnothrow = false;
2197 if (blockExit(sbody, this, f->isnothrow) == BEfallthru)
2198 sbody = new CompoundStatement(Loc(), sbody, s);
2199 else
2200 sbody = new TryFinallyStatement(Loc(), sbody, s);
2201 }
2202 }
2203 }
2204 // from this point on all possible 'throwers' are checked
2205 flags &= ~FUNCFLAGnothrowInprocess;
2206
2207 if (isSynchronized())
2208 {
2209 /* Wrap the entire function body in a synchronized statement
2210 */
2211 ClassDeclaration *cd = isThis() ? isThis()->isClassDeclaration() : parent->isClassDeclaration();
2212
2213 if (cd)
2214 {
2215 if (!global.params.is64bit &&
2216 global.params.isWindows &&
2217 !isStatic() && !sbody->usesEH() && !global.params.trace)
2218 {
2219 /* The back end uses the "jmonitor" hack for syncing;
2220 * no need to do the sync at this level.
2221 */
2222 }
2223 else
2224 {
2225 Expression *vsync;
2226 if (isStatic())
2227 {
2228 // The monitor is in the ClassInfo
2229 vsync = new DotIdExp(loc, resolve(loc, sc2, cd, false), Id::classinfo);
2230 }
2231 else
2232 {
2233 // 'this' is the monitor
2234 vsync = new VarExp(loc, vthis);
2235 }
2236 sbody = new PeelStatement(sbody); // don't redo semantic()
2237 sbody = new SynchronizedStatement(loc, vsync, sbody);
2238 sbody = ::semantic(sbody, sc2);
2239 }
2240 }
2241 else
2242 {
2243 error("synchronized function %s must be a member of a class", toChars());
2244 }
2245 }
2246
2247 // If declaration has no body, don't set sbody to prevent incorrect codegen.
2248 InterfaceDeclaration *id = parent->isInterfaceDeclaration();
2249 if (fbody || (id && (fdensure || fdrequire) && isVirtual()))
2250 fbody = sbody;
2251 }
2252
2253 // Fix up forward-referenced gotos
2254 if (gotos)
2255 {
2256 for (size_t i = 0; i < gotos->dim; ++i)
2257 {
2258 (*gotos)[i]->checkLabel();
2259 }
2260 }
2261
2262 if (naked && (fensure || frequire))
2263 error("naked assembly functions with contracts are not supported");
2264
2265 sc2->callSuper = 0;
2266 sc2->pop();
2267 }
2268
2269 if (checkClosure())
2270 {
2271 // We should be setting errors here instead of relying on the global error count.
2272 //errors = true;
2273 }
2274
2275 /* If function survived being marked as impure, then it is pure
2276 */
2277 if (flags & FUNCFLAGpurityInprocess)
2278 {
2279 flags &= ~FUNCFLAGpurityInprocess;
2280 if (type == f)
2281 f = (TypeFunction *)f->copy();
2282 f->purity = PUREfwdref;
2283 }
2284
2285 if (flags & FUNCFLAGsafetyInprocess)
2286 {
2287 flags &= ~FUNCFLAGsafetyInprocess;
2288 if (type == f)
2289 f = (TypeFunction *)f->copy();
2290 f->trust = TRUSTsafe;
2291 }
2292
2293 if (flags & FUNCFLAGnogcInprocess)
2294 {
2295 flags &= ~FUNCFLAGnogcInprocess;
2296 if (type == f)
2297 f = (TypeFunction *)f->copy();
2298 f->isnogc = true;
2299 }
2300
2301 if (flags & FUNCFLAGreturnInprocess)
2302 {
2303 flags &= ~FUNCFLAGreturnInprocess;
2304 if (storage_class & STCreturn)
2305 {
2306 if (type == f)
2307 f = (TypeFunction *)f->copy();
2308 f->isreturn = true;
2309 }
2310 }
2311
2312 flags &= ~FUNCFLAGinferScope;
2313
2314 // Infer STCscope
2315 if (parameters)
2316 {
2317 size_t nfparams = Parameter::dim(f->parameters);
2318 assert(nfparams == parameters->dim);
2319 for (size_t u = 0; u < parameters->dim; u++)
2320 {
2321 VarDeclaration *v = (*parameters)[u];
2322 if (v->storage_class & STCmaybescope)
2323 {
2324 //printf("Inferring scope for %s\n", v->toChars());
2325 Parameter *p = Parameter::getNth(f->parameters, u);
2326 v->storage_class &= ~STCmaybescope;
2327 v->storage_class |= STCscope | STCscopeinferred;
2328 p->storageClass |= STCscope | STCscopeinferred;
2329 assert(!(p->storageClass & STCmaybescope));
2330 }
2331 }
2332 }
2333
2334 if (vthis && vthis->storage_class & STCmaybescope)
2335 {
2336 vthis->storage_class &= ~STCmaybescope;
2337 vthis->storage_class |= STCscope | STCscopeinferred;
2338 f->isscope = true;
2339 f->isscopeinferred = true;
2340 }
2341
2342 // reset deco to apply inference result to mangled name
2343 if (f != type)
2344 f->deco = NULL;
2345
2346 // Do semantic type AFTER pure/nothrow inference.
2347 if (!f->deco && ident != Id::xopEquals && ident != Id::xopCmp)
2348 {
2349 sc = sc->push();
2350 if (isCtorDeclaration()) // Bugzilla #15665
2351 sc->flags |= SCOPEctor;
2352 sc->stc = 0;
2353 sc->linkage = linkage; // Bugzilla 8496
2354 type = f->semantic(loc, sc);
2355 sc = sc->pop();
2356 }
2357
2358 /* If this function had instantiated with gagging, error reproduction will be
2359 * done by TemplateInstance::semantic.
2360 * Otherwise, error gagging should be temporarily ungagged by functionSemantic3.
2361 */
2362 semanticRun = PASSsemantic3done;
2363 semantic3Errors = (global.errors != oldErrors) || (fbody && fbody->isErrorStatement());
2364 if (type->ty == Terror)
2365 errors = true;
2366 //printf("-FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars());
2367 //fflush(stdout);
2368 }
2369
2370 /****************************************************
2371 * Resolve forward reference of function signature -
2372 * parameter types, return type, and attributes.
2373 * Returns false if any errors exist in the signature.
2374 */
functionSemantic()2375 bool FuncDeclaration::functionSemantic()
2376 {
2377 if (!_scope)
2378 return !errors;
2379
2380 if (!originalType) // semantic not yet run
2381 {
2382 TemplateInstance *spec = isSpeculative();
2383 unsigned olderrs = global.errors;
2384 unsigned oldgag = global.gag;
2385 if (global.gag && !spec)
2386 global.gag = 0;
2387 semantic(_scope);
2388 global.gag = oldgag;
2389 if (spec && global.errors != olderrs)
2390 spec->errors = (global.errors - olderrs != 0);
2391 if (olderrs != global.errors) // if errors compiling this function
2392 return false;
2393 }
2394
2395 // if inferring return type, sematic3 needs to be run
2396 // - When the function body contains any errors, we cannot assume
2397 // the inferred return type is valid.
2398 // So, the body errors should become the function signature error.
2399 if (inferRetType && type && !type->nextOf())
2400 return functionSemantic3();
2401
2402 TemplateInstance *ti;
2403 if (isInstantiated() && !isVirtualMethod() &&
2404 ((ti = parent->isTemplateInstance()) == NULL || ti->isTemplateMixin() || ti->tempdecl->ident == ident))
2405 {
2406 AggregateDeclaration *ad = isMember2();
2407 if (ad && ad->sizeok != SIZEOKdone)
2408 {
2409 /* Currently dmd cannot resolve forward references per methods,
2410 * then setting SIZOKfwd is too conservative and would break existing code.
2411 * So, just stop method attributes inference until ad->semantic() done.
2412 */
2413 //ad->sizeok = SIZEOKfwd;
2414 }
2415 else
2416 return functionSemantic3() || !errors;
2417 }
2418
2419 if (storage_class & STCinference)
2420 return functionSemantic3() || !errors;
2421
2422 return !errors;
2423 }
2424
2425 /****************************************************
2426 * Resolve forward reference of function body.
2427 * Returns false if any errors exist in the body.
2428 */
functionSemantic3()2429 bool FuncDeclaration::functionSemantic3()
2430 {
2431 if (semanticRun < PASSsemantic3 && _scope)
2432 {
2433 /* Forward reference - we need to run semantic3 on this function.
2434 * If errors are gagged, and it's not part of a template instance,
2435 * we need to temporarily ungag errors.
2436 */
2437 TemplateInstance *spec = isSpeculative();
2438 unsigned olderrs = global.errors;
2439 unsigned oldgag = global.gag;
2440 if (global.gag && !spec)
2441 global.gag = 0;
2442 semantic3(_scope);
2443 global.gag = oldgag;
2444
2445 // If it is a speculatively-instantiated template, and errors occur,
2446 // we need to mark the template as having errors.
2447 if (spec && global.errors != olderrs)
2448 spec->errors = (global.errors - olderrs != 0);
2449 if (olderrs != global.errors) // if errors compiling this function
2450 return false;
2451 }
2452
2453 return !errors && !semantic3Errors;
2454 }
2455
2456 /****************************************************
2457 * Check that this function type is properly resolved.
2458 * If not, report "forward reference error" and return true.
2459 */
checkForwardRef(Loc loc)2460 bool FuncDeclaration::checkForwardRef(Loc loc)
2461 {
2462 if (!functionSemantic())
2463 return true;
2464
2465 /* No deco means the functionSemantic() call could not resolve
2466 * forward referenes in the type of this function.
2467 */
2468 if (!type->deco)
2469 {
2470 bool inSemantic3 = (inferRetType && semanticRun >= PASSsemantic3);
2471 ::error(loc, "forward reference to %s'%s'",
2472 (inSemantic3 ? "inferred return type of function " : ""),
2473 toChars());
2474 return true;
2475 }
2476 return false;
2477 }
2478
declareThis(Scope * sc,AggregateDeclaration * ad)2479 VarDeclaration *FuncDeclaration::declareThis(Scope *sc, AggregateDeclaration *ad)
2480 {
2481 if (ad)
2482 {
2483 VarDeclaration *v;
2484 {
2485 //printf("declareThis() %s\n", toChars());
2486 Type *thandle = ad->handleType();
2487 assert(thandle);
2488 thandle = thandle->addMod(type->mod);
2489 thandle = thandle->addStorageClass(storage_class);
2490 v = new ThisDeclaration(loc, thandle);
2491 v->storage_class |= STCparameter;
2492 if (thandle->ty == Tstruct)
2493 {
2494 v->storage_class |= STCref;
2495
2496 // if member function is marked 'inout', then 'this' is 'return ref'
2497 if (type->ty == Tfunction && ((TypeFunction *)type)->iswild & 2)
2498 v->storage_class |= STCreturn;
2499 }
2500 if (type->ty == Tfunction)
2501 {
2502 TypeFunction *tf = (TypeFunction *)type;
2503 if (tf->isreturn)
2504 v->storage_class |= STCreturn;
2505 if (tf->isscope)
2506 v->storage_class |= STCscope;
2507 }
2508 if (flags & FUNCFLAGinferScope && !(v->storage_class & STCscope))
2509 v->storage_class |= STCmaybescope;
2510
2511 v->semantic(sc);
2512 if (!sc->insert(v))
2513 assert(0);
2514 v->parent = this;
2515 return v;
2516 }
2517 }
2518 else if (isNested())
2519 {
2520 /* The 'this' for a nested function is the link to the
2521 * enclosing function's stack frame.
2522 * Note that nested functions and member functions are disjoint.
2523 */
2524 VarDeclaration *v = new ThisDeclaration(loc, Type::tvoid->pointerTo());
2525 v->storage_class |= STCparameter;
2526 if (type->ty == Tfunction)
2527 {
2528 TypeFunction *tf = (TypeFunction *)type;
2529 if (tf->isreturn)
2530 v->storage_class |= STCreturn;
2531 if (tf->isscope)
2532 v->storage_class |= STCscope;
2533 }
2534 if (flags & FUNCFLAGinferScope && !(v->storage_class & STCscope))
2535 v->storage_class |= STCmaybescope;
2536
2537 v->semantic(sc);
2538 if (!sc->insert(v))
2539 assert(0);
2540 v->parent = this;
2541 return v;
2542 }
2543
2544 return NULL;
2545 }
2546
equals(RootObject * o)2547 bool FuncDeclaration::equals(RootObject *o)
2548 {
2549 if (this == o)
2550 return true;
2551
2552 Dsymbol *s = isDsymbol(o);
2553 if (s)
2554 {
2555 FuncDeclaration *fd1 = this;
2556 FuncDeclaration *fd2 = s->isFuncDeclaration();
2557 if (!fd2)
2558 return false;
2559
2560 FuncAliasDeclaration *fa1 = fd1->isFuncAliasDeclaration();
2561 FuncAliasDeclaration *fa2 = fd2->isFuncAliasDeclaration();
2562 if (fa1 && fa2)
2563 {
2564 return fa1->toAliasFunc()->equals(fa2->toAliasFunc()) &&
2565 fa1->hasOverloads == fa2->hasOverloads;
2566 }
2567
2568 if (fa1 && (fd1 = fa1->toAliasFunc())->isUnique() && !fa1->hasOverloads)
2569 fa1 = NULL;
2570 if (fa2 && (fd2 = fa2->toAliasFunc())->isUnique() && !fa2->hasOverloads)
2571 fa2 = NULL;
2572 if ((fa1 != NULL) != (fa2 != NULL))
2573 return false;
2574
2575 return fd1->toParent()->equals(fd2->toParent()) &&
2576 fd1->ident->equals(fd2->ident) && fd1->type->equals(fd2->type);
2577 }
2578 return false;
2579 }
2580
2581 /****************************************************
2582 * Declare result variable lazily.
2583 */
2584
buildResultVar(Scope * sc,Type * tret)2585 void FuncDeclaration::buildResultVar(Scope *sc, Type *tret)
2586 {
2587 if (!vresult)
2588 {
2589 Loc loc = fensure ? fensure->loc : this->loc;
2590
2591 /* If inferRetType is true, tret may not be a correct return type yet.
2592 * So, in here it may be a temporary type for vresult, and after
2593 * fbody->semantic() running, vresult->type might be modified.
2594 */
2595 vresult = new VarDeclaration(loc, tret, outId ? outId : Id::result, NULL);
2596 vresult->storage_class |= STCnodtor;
2597
2598 if (outId == Id::result)
2599 vresult->storage_class |= STCtemp;
2600 if (!isVirtual())
2601 vresult->storage_class |= STCconst;
2602 vresult->storage_class |= STCresult;
2603
2604 // set before the semantic() for checkNestedReference()
2605 vresult->parent = this;
2606 }
2607
2608 if (sc && vresult->semanticRun == PASSinit)
2609 {
2610 TypeFunction *tf = type->toTypeFunction();
2611 if (tf->isref)
2612 vresult->storage_class |= STCref;
2613 vresult->type = tret;
2614
2615 vresult->semantic(sc);
2616
2617 if (!sc->insert(vresult))
2618 error("out result %s is already defined", vresult->toChars());
2619 assert(vresult->parent == this);
2620 }
2621 }
2622
2623 /****************************************************
2624 * Merge into this function the 'in' contracts of all it overrides.
2625 * 'in's are OR'd together, i.e. only one of them needs to pass.
2626 */
2627
mergeFrequire(Statement * sf)2628 Statement *FuncDeclaration::mergeFrequire(Statement *sf)
2629 {
2630 /* If a base function and its override both have an IN contract, then
2631 * only one of them needs to succeed. This is done by generating:
2632 *
2633 * void derived.in() {
2634 * try {
2635 * base.in();
2636 * }
2637 * catch () {
2638 * ... body of derived.in() ...
2639 * }
2640 * }
2641 *
2642 * So if base.in() doesn't throw, derived.in() need not be executed, and the contract is valid.
2643 * If base.in() throws, then derived.in()'s body is executed.
2644 */
2645
2646 /* Implementing this is done by having the overriding function call
2647 * nested functions (the fdrequire functions) nested inside the overridden
2648 * function. This requires that the stack layout of the calling function's
2649 * parameters and 'this' pointer be in the same place (as the nested
2650 * function refers to them).
2651 * This is easy for the parameters, as they are all on the stack in the same
2652 * place by definition, since it's an overriding function. The problem is
2653 * getting the 'this' pointer in the same place, since it is a local variable.
2654 * We did some hacks in the code generator to make this happen:
2655 * 1. always generate exception handler frame, or at least leave space for it
2656 * in the frame (Windows 32 SEH only)
2657 * 2. always generate an EBP style frame
2658 * 3. since 'this' is passed in a register that is subsequently copied into
2659 * a stack local, allocate that local immediately following the exception
2660 * handler block, so it is always at the same offset from EBP.
2661 */
2662 for (size_t i = 0; i < foverrides.dim; i++)
2663 {
2664 FuncDeclaration *fdv = foverrides[i];
2665
2666 /* The semantic pass on the contracts of the overridden functions must
2667 * be completed before code generation occurs.
2668 * https://issues.dlang.org/show_bug.cgi?id=3602
2669 */
2670 if (fdv->frequire && fdv->semanticRun != PASSsemantic3done)
2671 {
2672 assert(fdv->_scope);
2673 Scope *sc = fdv->_scope->push();
2674 sc->stc &= ~STCoverride;
2675 fdv->semantic3(sc);
2676 sc->pop();
2677 }
2678
2679 sf = fdv->mergeFrequire(sf);
2680 if (sf && fdv->fdrequire)
2681 {
2682 //printf("fdv->frequire: %s\n", fdv->frequire->toChars());
2683 /* Make the call:
2684 * try { __require(); }
2685 * catch (Throwable) { frequire; }
2686 */
2687 Expression *eresult = NULL;
2688 Expression *e = new CallExp(loc, new VarExp(loc, fdv->fdrequire, false), eresult);
2689 Statement *s2 = new ExpStatement(loc, e);
2690
2691 Catch *c = new Catch(loc, getThrowable(), NULL, sf);
2692 c->internalCatch = true;
2693 Catches *catches = new Catches();
2694 catches->push(c);
2695 sf = new TryCatchStatement(loc, s2, catches);
2696 }
2697 else
2698 return NULL;
2699 }
2700 return sf;
2701 }
2702
2703 /****************************************************
2704 * Merge into this function the 'out' contracts of all it overrides.
2705 * 'out's are AND'd together, i.e. all of them need to pass.
2706 */
2707
mergeFensure(Statement * sf,Identifier * oid)2708 Statement *FuncDeclaration::mergeFensure(Statement *sf, Identifier *oid)
2709 {
2710 /* Same comments as for mergeFrequire(), except that we take care
2711 * of generating a consistent reference to the 'result' local by
2712 * explicitly passing 'result' to the nested function as a reference
2713 * argument.
2714 * This won't work for the 'this' parameter as it would require changing
2715 * the semantic code for the nested function so that it looks on the parameter
2716 * list for the 'this' pointer, something that would need an unknown amount
2717 * of tweaking of various parts of the compiler that I'd rather leave alone.
2718 */
2719 for (size_t i = 0; i < foverrides.dim; i++)
2720 {
2721 FuncDeclaration *fdv = foverrides[i];
2722
2723 /* The semantic pass on the contracts of the overridden functions must
2724 * be completed before code generation occurs.
2725 * https://issues.dlang.org/show_bug.cgi?id=3602 and
2726 * https://issues.dlang.org/show_bug.cgi?id=5230
2727 */
2728 if (needsFensure(fdv) && fdv->semanticRun != PASSsemantic3done)
2729 {
2730 assert(fdv->_scope);
2731 Scope *sc = fdv->_scope->push();
2732 sc->stc &= ~STCoverride;
2733 fdv->semantic3(sc);
2734 sc->pop();
2735 }
2736
2737 sf = fdv->mergeFensure(sf, oid);
2738 if (fdv->fdensure)
2739 {
2740 //printf("fdv->fensure: %s\n", fdv->fensure->toChars());
2741 // Make the call: __ensure(result)
2742 Expression *eresult = NULL;
2743 if (outId)
2744 {
2745 eresult = new IdentifierExp(loc, oid);
2746
2747 Type *t1 = fdv->type->nextOf()->toBasetype();
2748 Type *t2 = this->type->nextOf()->toBasetype();
2749 if (t1->isBaseOf(t2, NULL))
2750 {
2751 /* Making temporary reference variable is necessary
2752 * in covariant return.
2753 * See bugzilla 5204 and 10479.
2754 */
2755 ExpInitializer *ei = new ExpInitializer(Loc(), eresult);
2756 VarDeclaration *v = new VarDeclaration(Loc(), t1, Identifier::generateId("__covres"), ei);
2757 v->storage_class |= STCtemp;
2758 DeclarationExp *de = new DeclarationExp(Loc(), v);
2759 VarExp *ve = new VarExp(Loc(), v);
2760 eresult = new CommaExp(Loc(), de, ve);
2761 }
2762 }
2763 Expression *e = new CallExp(loc, new VarExp(loc, fdv->fdensure, false), eresult);
2764 Statement *s2 = new ExpStatement(loc, e);
2765
2766 if (sf)
2767 {
2768 sf = new CompoundStatement(sf->loc, s2, sf);
2769 }
2770 else
2771 sf = s2;
2772 }
2773 }
2774 return sf;
2775 }
2776
2777 /****************************************************
2778 * Determine if 'this' overrides fd.
2779 * Return !=0 if it does.
2780 */
2781
overrides(FuncDeclaration * fd)2782 int FuncDeclaration::overrides(FuncDeclaration *fd)
2783 { int result = 0;
2784
2785 if (fd->ident == ident)
2786 {
2787 int cov = type->covariant(fd->type);
2788 if (cov)
2789 { ClassDeclaration *cd1 = toParent()->isClassDeclaration();
2790 ClassDeclaration *cd2 = fd->toParent()->isClassDeclaration();
2791
2792 if (cd1 && cd2 && cd2->isBaseOf(cd1, NULL))
2793 result = 1;
2794 }
2795 }
2796 return result;
2797 }
2798
2799 /*************************************************
2800 * Find index of function in vtbl[0..dim] that
2801 * this function overrides.
2802 * Prefer an exact match to a covariant one.
2803 * Params:
2804 * fix17349 = enable fix https://issues.dlang.org/show_bug.cgi?id=17349
2805 * Returns:
2806 * -1 didn't find one
2807 * -2 can't determine because of forward references
2808 */
2809
findVtblIndex(Dsymbols * vtbl,int dim,bool fix17349)2810 int FuncDeclaration::findVtblIndex(Dsymbols *vtbl, int dim, bool fix17349)
2811 {
2812 //printf("findVtblIndex() %s\n", toChars());
2813 FuncDeclaration *mismatch = NULL;
2814 StorageClass mismatchstc = 0;
2815 int mismatchvi = -1;
2816 int exactvi = -1;
2817 int bestvi = -1;
2818 for (int vi = 0; vi < dim; vi++)
2819 {
2820 FuncDeclaration *fdv = (*vtbl)[vi]->isFuncDeclaration();
2821 if (fdv && fdv->ident == ident)
2822 {
2823 if (type->equals(fdv->type)) // if exact match
2824 {
2825 if (fdv->parent->isClassDeclaration())
2826 {
2827 if (fdv->isFuture())
2828 {
2829 bestvi = vi;
2830 continue; // keep looking
2831 }
2832 return vi; // no need to look further
2833 }
2834
2835 if (exactvi >= 0)
2836 {
2837 error("cannot determine overridden function");
2838 return exactvi;
2839 }
2840 exactvi = vi;
2841
2842 bestvi = vi;
2843 continue;
2844 }
2845
2846 StorageClass stc = 0;
2847 int cov = type->covariant(fdv->type, &stc, fix17349);
2848 //printf("\tbaseclass cov = %d\n", cov);
2849 switch (cov)
2850 {
2851 case 0: // types are distinct
2852 break;
2853
2854 case 1:
2855 bestvi = vi; // covariant, but not identical
2856 break; // keep looking for an exact match
2857
2858 case 2:
2859 mismatchvi = vi;
2860 mismatchstc = stc;
2861 mismatch = fdv; // overrides, but is not covariant
2862 break; // keep looking for an exact match
2863
2864 case 3:
2865 return -2; // forward references
2866
2867 default:
2868 assert(0);
2869 }
2870 }
2871 }
2872 if (bestvi == -1 && mismatch)
2873 {
2874 //type->print();
2875 //mismatch->type->print();
2876 //printf("%s %s\n", type->deco, mismatch->type->deco);
2877 //printf("stc = %llx\n", mismatchstc);
2878 if (mismatchstc)
2879 { // Fix it by modifying the type to add the storage classes
2880 type = type->addStorageClass(mismatchstc);
2881 bestvi = mismatchvi;
2882 }
2883 }
2884 return bestvi;
2885 }
2886
2887 /*********************************
2888 * If function a function in a base class,
2889 * return that base class.
2890 * Params:
2891 * cd = class that function is in
2892 * Returns:
2893 * base class if overriding, NULL if not
2894 */
overrideInterface()2895 BaseClass *FuncDeclaration::overrideInterface()
2896 {
2897 ClassDeclaration *cd = parent->isClassDeclaration();
2898 for (size_t i = 0; i < cd->interfaces.length; i++)
2899 {
2900 BaseClass *b = cd->interfaces.ptr[i];
2901 int v = findVtblIndex((Dsymbols *)&b->sym->vtbl, (int)b->sym->vtbl.dim);
2902 if (v >= 0)
2903 return b;
2904 }
2905 return NULL;
2906 }
2907
2908 /****************************************************
2909 * Overload this FuncDeclaration with the new one f.
2910 * Return true if successful; i.e. no conflict.
2911 */
2912
overloadInsert(Dsymbol * s)2913 bool FuncDeclaration::overloadInsert(Dsymbol *s)
2914 {
2915 //printf("FuncDeclaration::overloadInsert(s = %s) this = %s\n", s->toChars(), toChars());
2916 assert(s != this);
2917
2918 AliasDeclaration *ad = s->isAliasDeclaration();
2919 if (ad)
2920 {
2921 if (overnext)
2922 return overnext->overloadInsert(ad);
2923 if (!ad->aliassym && ad->type->ty != Tident && ad->type->ty != Tinstance)
2924 {
2925 //printf("\tad = '%s'\n", ad->type->toChars());
2926 return false;
2927 }
2928 overnext = ad;
2929 //printf("\ttrue: no conflict\n");
2930 return true;
2931 }
2932 TemplateDeclaration *td = s->isTemplateDeclaration();
2933 if (td)
2934 {
2935 if (!td->funcroot)
2936 td->funcroot = this;
2937 if (overnext)
2938 return overnext->overloadInsert(td);
2939 overnext = td;
2940 return true;
2941 }
2942 FuncDeclaration *fd = s->isFuncDeclaration();
2943 if (!fd)
2944 return false;
2945
2946 if (overnext)
2947 {
2948 td = overnext->isTemplateDeclaration();
2949 if (td)
2950 fd->overloadInsert(td);
2951 else
2952 return overnext->overloadInsert(fd);
2953 }
2954 overnext = fd;
2955 //printf("\ttrue: no conflict\n");
2956 return true;
2957 }
2958
2959 /***************************************************
2960 * Visit each overloaded function/template in turn, and call
2961 * (*fp)(param, s) on it.
2962 * Exit when no more, or (*fp)(param, f) returns nonzero.
2963 * Returns:
2964 * ==0 continue
2965 * !=0 done
2966 */
2967
overloadApply(Dsymbol * fstart,void * param,int (* fp)(void *,Dsymbol *))2968 int overloadApply(Dsymbol *fstart, void *param, int (*fp)(void *, Dsymbol *))
2969 {
2970 Dsymbol *d;
2971 Dsymbol *next;
2972 for (d = fstart; d; d = next)
2973 {
2974 if (OverDeclaration *od = d->isOverDeclaration())
2975 {
2976 if (od->hasOverloads)
2977 {
2978 if (int r = overloadApply(od->aliassym, param, fp))
2979 return r;
2980 }
2981 else
2982 {
2983 if (int r = (*fp)(param, od->aliassym))
2984 return r;
2985 }
2986 next = od->overnext;
2987 }
2988 else if (FuncAliasDeclaration *fa = d->isFuncAliasDeclaration())
2989 {
2990 if (fa->hasOverloads)
2991 {
2992 if (int r = overloadApply(fa->funcalias, param, fp))
2993 return r;
2994 }
2995 else
2996 {
2997 FuncDeclaration *fd = fa->toAliasFunc();
2998 if (!fd)
2999 {
3000 d->error("is aliased to a function");
3001 break;
3002 }
3003 if (int r = (*fp)(param, fd))
3004 return r;
3005 }
3006 next = fa->overnext;
3007 }
3008 else if (AliasDeclaration *ad = d->isAliasDeclaration())
3009 {
3010 next = ad->toAlias();
3011 if (next == ad)
3012 break;
3013 if (next == fstart)
3014 break;
3015 }
3016 else if (TemplateDeclaration *td = d->isTemplateDeclaration())
3017 {
3018 if (int r = (*fp)(param, td))
3019 return r;
3020 next = td->overnext;
3021 }
3022 else
3023 {
3024 FuncDeclaration *fd = d->isFuncDeclaration();
3025 if (!fd)
3026 {
3027 d->error("is aliased to a function");
3028 break; // BUG: should print error message?
3029 }
3030 if (int r = (*fp)(param, fd))
3031 return r;
3032 next = fd->overnext;
3033 }
3034 }
3035 return 0;
3036 }
3037
3038 /********************************************
3039 * If there are no overloads of function f, return that function,
3040 * otherwise return NULL.
3041 */
3042
isUnique()3043 FuncDeclaration *FuncDeclaration::isUnique()
3044 {
3045 struct ParamUnique
3046 {
3047 static int fp(void *param, Dsymbol *s)
3048 {
3049 FuncDeclaration *f = s->isFuncDeclaration();
3050 if (!f)
3051 return 0;
3052 FuncDeclaration **pf = (FuncDeclaration **)param;
3053
3054 if (*pf)
3055 {
3056 *pf = NULL;
3057 return 1; // ambiguous, done
3058 }
3059 else
3060 {
3061 *pf = f;
3062 return 0;
3063 }
3064 }
3065 };
3066 FuncDeclaration *result = NULL;
3067 overloadApply(this, &result, &ParamUnique::fp);
3068 return result;
3069 }
3070
3071 /********************************************
3072 * Find function in overload list that exactly matches t.
3073 */
3074
overloadExactMatch(Type * t)3075 FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t)
3076 {
3077 struct ParamExact
3078 {
3079 Type *t; // type to match
3080 FuncDeclaration *f; // return value
3081
3082 static int fp(void *param, Dsymbol *s)
3083 {
3084 FuncDeclaration *f = s->isFuncDeclaration();
3085 if (!f)
3086 return 0;
3087 ParamExact *p = (ParamExact *)param;
3088 Type *t = p->t;
3089
3090 if (t->equals(f->type))
3091 {
3092 p->f = f;
3093 return 1;
3094 }
3095
3096 /* Allow covariant matches, as long as the return type
3097 * is just a const conversion.
3098 * This allows things like pure functions to match with an impure function type.
3099 */
3100 if (t->ty == Tfunction)
3101 { TypeFunction *tf = (TypeFunction *)f->type;
3102 if (tf->covariant(t) == 1 &&
3103 tf->nextOf()->implicitConvTo(t->nextOf()) >= MATCHconst)
3104 {
3105 p->f = f;
3106 return 1;
3107 }
3108 }
3109 return 0;
3110 }
3111 };
3112 ParamExact p;
3113 p.t = t;
3114 p.f = NULL;
3115 overloadApply(this, &p, &ParamExact::fp);
3116 return p.f;
3117 }
3118
MODMatchToBuffer(OutBuffer * buf,unsigned char lhsMod,unsigned char rhsMod)3119 void MODMatchToBuffer(OutBuffer *buf, unsigned char lhsMod, unsigned char rhsMod)
3120 {
3121 bool bothMutable = ((lhsMod & rhsMod) == 0);
3122 bool sharedMismatch = ((lhsMod ^ rhsMod) & MODshared) != 0;
3123 bool sharedMismatchOnly = ((lhsMod ^ rhsMod) == MODshared);
3124
3125 if (lhsMod & MODshared)
3126 buf->writestring("shared ");
3127 else if (sharedMismatch && !(lhsMod & MODimmutable))
3128 buf->writestring("non-shared ");
3129
3130 if (bothMutable && sharedMismatchOnly)
3131 { }
3132 else if (lhsMod & MODimmutable)
3133 buf->writestring("immutable ");
3134 else if (lhsMod & MODconst)
3135 buf->writestring("const ");
3136 else if (lhsMod & MODwild)
3137 buf->writestring("inout ");
3138 else
3139 buf->writestring("mutable ");
3140 }
3141
3142 /********************************************
3143 * Find function in overload list that matches to the 'this' modifier.
3144 * There's four result types.
3145 *
3146 * 1. If the 'tthis' matches only one candidate, it's an "exact match".
3147 * Returns the function and 'hasOverloads' is set to false.
3148 * eg. If 'tthis" is mutable and there's only one mutable method.
3149 * 2. If there's two or more match candidates, but a candidate function will be
3150 * a "better match".
3151 * Returns the better match function but 'hasOverloads' is set to true.
3152 * eg. If 'tthis' is mutable, and there's both mutable and const methods,
3153 * the mutable method will be a better match.
3154 * 3. If there's two or more match candidates, but there's no better match,
3155 * Returns NULL and 'hasOverloads' is set to true to represent "ambiguous match".
3156 * eg. If 'tthis' is mutable, and there's two or more mutable methods.
3157 * 4. If there's no candidates, it's "no match" and returns NULL with error report.
3158 * e.g. If 'tthis' is const but there's no const methods.
3159 */
overloadModMatch(Loc loc,Type * tthis,bool & hasOverloads)3160 FuncDeclaration *FuncDeclaration::overloadModMatch(Loc loc, Type *tthis, bool &hasOverloads)
3161 {
3162 //printf("FuncDeclaration::overloadModMatch('%s')\n", toChars());
3163 Match m;
3164 memset(&m, 0, sizeof(m));
3165 m.last = MATCHnomatch;
3166
3167 struct ParamMod
3168 {
3169 Match *m;
3170 Type *tthis;
3171
3172 static int fp(void *param, Dsymbol *s)
3173 {
3174 if (FuncDeclaration *fd = s->isFuncDeclaration())
3175 return ((ParamMod *)param)->fp(fd);
3176 return 0;
3177 }
3178 int fp(FuncDeclaration *f)
3179 {
3180 if (f == m->lastf) // skip duplicates
3181 return 0;
3182
3183 m->anyf = f;
3184 TypeFunction *tf = f->type->toTypeFunction();
3185 //printf("tf = %s\n", tf->toChars());
3186
3187 MATCH match;
3188 if (tthis) // non-static functions are preferred than static ones
3189 {
3190 if (f->needThis())
3191 match = f->isCtorDeclaration() ? MATCHexact : MODmethodConv(tthis->mod, tf->mod);
3192 else
3193 match = MATCHconst; // keep static funciton in overload candidates
3194 }
3195 else // static functions are preferred than non-static ones
3196 {
3197 if (f->needThis())
3198 match = MATCHconvert;
3199 else
3200 match = MATCHexact;
3201 }
3202 if (match != MATCHnomatch)
3203 {
3204 if (match > m->last) goto LfIsBetter;
3205 if (match < m->last) goto LlastIsBetter;
3206
3207 /* See if one of the matches overrides the other.
3208 */
3209 if (m->lastf->overrides(f)) goto LlastIsBetter;
3210 if (f->overrides(m->lastf)) goto LfIsBetter;
3211
3212 //printf("\tambiguous\n");
3213 m->nextf = f;
3214 m->count++;
3215 return 0;
3216
3217 LlastIsBetter:
3218 //printf("\tlastbetter\n");
3219 m->count++; // count up
3220 return 0;
3221
3222 LfIsBetter:
3223 //printf("\tisbetter\n");
3224 if (m->last <= MATCHconvert)
3225 {
3226 // clear last secondary matching
3227 m->nextf = NULL;
3228 m->count = 0;
3229 }
3230 m->last = match;
3231 m->lastf = f;
3232 m->count++; // count up
3233 return 0;
3234 }
3235 return 0;
3236 }
3237 };
3238 ParamMod p;
3239 p.m = &m;
3240 p.tthis = tthis;
3241 overloadApply(this, &p, &ParamMod::fp);
3242
3243 if (m.count == 1) // exact match
3244 {
3245 hasOverloads = false;
3246 }
3247 else if (m.count > 1) // better or ambiguous match
3248 {
3249 hasOverloads = true;
3250 }
3251 else // no match
3252 {
3253 hasOverloads = true;
3254 TypeFunction *tf = this->type->toTypeFunction();
3255 assert(tthis);
3256 assert(!MODimplicitConv(tthis->mod, tf->mod)); // modifier mismatch
3257 {
3258 OutBuffer thisBuf, funcBuf;
3259 MODMatchToBuffer(&thisBuf, tthis->mod, tf->mod);
3260 MODMatchToBuffer(&funcBuf, tf->mod, tthis->mod);
3261 ::error(loc, "%smethod %s is not callable using a %sobject",
3262 funcBuf.peekString(), this->toPrettyChars(), thisBuf.peekString());
3263 }
3264 }
3265
3266 return m.lastf;
3267 }
3268
3269 /********************************************
3270 * Returns true if function was declared
3271 * directly or indirectly in a unittest block
3272 */
inUnittest()3273 bool FuncDeclaration::inUnittest()
3274 {
3275 Dsymbol *f = this;
3276 do
3277 {
3278 if (f->isUnitTestDeclaration())
3279 return true;
3280 f = f->toParent();
3281 } while (f);
3282
3283 return false;
3284 }
3285
3286 /********************************************
3287 * find function template root in overload list
3288 */
3289
findTemplateDeclRoot()3290 TemplateDeclaration *FuncDeclaration::findTemplateDeclRoot()
3291 {
3292 FuncDeclaration *f = this;
3293 while (f && f->overnext)
3294 {
3295 //printf("f->overnext = %p %s\n", f->overnext, f->overnext->toChars());
3296 TemplateDeclaration *td = f->overnext->isTemplateDeclaration();
3297 if (td)
3298 return td;
3299 f = f->overnext->isFuncDeclaration();
3300 }
3301 return NULL;
3302 }
3303
3304 /*************************************
3305 * Determine partial specialization order of 'this' vs g.
3306 * This is very similar to TemplateDeclaration::leastAsSpecialized().
3307 * Returns:
3308 * match 'this' is at least as specialized as g
3309 * 0 g is more specialized than 'this'
3310 */
3311
leastAsSpecialized(FuncDeclaration * g)3312 MATCH FuncDeclaration::leastAsSpecialized(FuncDeclaration *g)
3313 {
3314 /* This works by calling g() with f()'s parameters, and
3315 * if that is possible, then f() is at least as specialized
3316 * as g() is.
3317 */
3318
3319 TypeFunction *tf = type->toTypeFunction();
3320 TypeFunction *tg = g->type->toTypeFunction();
3321 size_t nfparams = Parameter::dim(tf->parameters);
3322
3323 /* If both functions have a 'this' pointer, and the mods are not
3324 * the same and g's is not const, then this is less specialized.
3325 */
3326 if (needThis() && g->needThis() && tf->mod != tg->mod)
3327 {
3328 if (isCtorDeclaration())
3329 {
3330 if (!MODimplicitConv(tg->mod, tf->mod))
3331 return MATCHnomatch;
3332 }
3333 else
3334 {
3335 if (!MODimplicitConv(tf->mod, tg->mod))
3336 return MATCHnomatch;
3337 }
3338 }
3339
3340 /* Create a dummy array of arguments out of the parameters to f()
3341 */
3342 Expressions args;
3343 args.setDim(nfparams);
3344 for (size_t u = 0; u < nfparams; u++)
3345 {
3346 Parameter *p = Parameter::getNth(tf->parameters, u);
3347 Expression *e;
3348 if (p->storageClass & (STCref | STCout))
3349 {
3350 e = new IdentifierExp(Loc(), p->ident);
3351 e->type = p->type;
3352 }
3353 else
3354 e = p->type->defaultInitLiteral(Loc());
3355 args[u] = e;
3356 }
3357
3358 MATCH m = (MATCH) tg->callMatch(NULL, &args, 1);
3359 if (m > MATCHnomatch)
3360 {
3361 /* A variadic parameter list is less specialized than a
3362 * non-variadic one.
3363 */
3364 if (tf->varargs && !tg->varargs)
3365 goto L1; // less specialized
3366
3367 return m;
3368 }
3369 L1:
3370 return MATCHnomatch;
3371 }
3372
3373 /// Walk through candidate template overloads and print them in the diagnostics.
3374 struct TemplateCandidateWalker
3375 {
3376 Loc loc;
3377 int numToDisplay; // max num of overloads to print (-v overrides this).
3378
3379 /// Count template overloads.
3380 struct CountWalker
3381 {
3382 int numOverloads;
3383
fpTemplateCandidateWalker::CountWalker3384 static int fp(void *param, Dsymbol *)
3385 {
3386 CountWalker *p = (CountWalker *)param;
3387 ++(p->numOverloads);
3388 return 0;
3389 }
3390 };
3391
fpTemplateCandidateWalker3392 static int fp(void *param, Dsymbol *s)
3393 {
3394 TemplateDeclaration *t = s->isTemplateDeclaration();
3395 if (!t) return 0;
3396
3397 TemplateCandidateWalker *p = (TemplateCandidateWalker *)param;
3398
3399 ::errorSupplemental(t->loc, "%s", t->toPrettyChars());
3400
3401 if (!global.params.verbose && --(p->numToDisplay) == 0 && t->overnext)
3402 {
3403 // Too many overloads to sensibly display.
3404 // Just show count of remaining overloads.
3405 CountWalker cw;
3406 cw.numOverloads = 0;
3407 overloadApply(t->overnext, &cw, &CountWalker::fp);
3408
3409 if (cw.numOverloads > 0)
3410 ::errorSupplemental(p->loc, "... (%d more, -v to show) ...", cw.numOverloads);
3411
3412 return 1; // stop iterating
3413 }
3414
3415 return 0;
3416 }
3417 };
3418
3419 /// Walk through candidate template overloads and print them in the diagnostics.
3420 struct FuncCandidateWalker
3421 {
3422 Loc loc;
3423 int numToDisplay; // max num of overloads to print (-v overrides this).
3424
3425 /// Count function overloads.
3426 struct CountWalker
3427 {
3428 int numOverloads;
3429
fpFuncCandidateWalker::CountWalker3430 static int fp(void *param, Dsymbol *)
3431 {
3432 CountWalker *p = (CountWalker *)param;
3433 ++(p->numOverloads);
3434 return 0;
3435 }
3436 };
3437
fpFuncCandidateWalker3438 static int fp(void *param, Dsymbol *s)
3439 {
3440 FuncDeclaration *fd = s->isFuncDeclaration();
3441 TemplateDeclaration *td = s->isTemplateDeclaration();
3442 if (fd)
3443 {
3444 if (fd->errors || fd->type->ty == Terror)
3445 return 0;
3446
3447 TypeFunction *tf = (TypeFunction *)fd->type;
3448
3449 ::errorSupplemental(fd->loc, "%s%s", fd->toPrettyChars(),
3450 parametersTypeToChars(tf->parameters, tf->varargs));
3451 }
3452 else
3453 {
3454 ::errorSupplemental(td->loc, "%s", td->toPrettyChars());
3455 }
3456
3457 FuncCandidateWalker *p = (FuncCandidateWalker *)param;
3458 if (global.params.verbose || --(p->numToDisplay) != 0 || !fd)
3459 return 0;
3460
3461 // Too many overloads to sensibly display.
3462 CountWalker cw;
3463 cw.numOverloads = 0;
3464 overloadApply(fd->overnext, &cw, &CountWalker::fp);
3465
3466 if (cw.numOverloads > 0)
3467 ::errorSupplemental(p->loc, "... (%d more, -v to show) ...", cw.numOverloads);
3468
3469 return 1; // stop iterating
3470 }
3471 };
3472
3473 /*******************************************
3474 * Given a symbol that could be either a FuncDeclaration or
3475 * a function template, resolve it to a function symbol.
3476 * loc instantiation location
3477 * sc instantiation scope
3478 * tiargs initial list of template arguments
3479 * tthis if !NULL, the 'this' pointer argument
3480 * fargs arguments to function
3481 * flags 1: do not issue error message on no match, just return NULL
3482 * 2: overloadResolve only
3483 */
3484
resolveFuncCall(Loc loc,Scope * sc,Dsymbol * s,Objects * tiargs,Type * tthis,Expressions * fargs,int flags)3485 FuncDeclaration *resolveFuncCall(Loc loc, Scope *sc, Dsymbol *s,
3486 Objects *tiargs, Type *tthis, Expressions *fargs, int flags)
3487 {
3488 if (!s)
3489 return NULL; // no match
3490
3491 if ((tiargs && arrayObjectIsError(tiargs)) ||
3492 (fargs && arrayObjectIsError((Objects *)fargs)))
3493 {
3494 return NULL;
3495 }
3496
3497 Match m;
3498 memset(&m, 0, sizeof(m));
3499 m.last = MATCHnomatch;
3500
3501 functionResolve(&m, s, loc, sc, tiargs, tthis, fargs);
3502
3503 if (m.last > MATCHnomatch && m.lastf)
3504 {
3505 if (m.count == 1) // exactly one match
3506 {
3507 if (!(flags & 1))
3508 m.lastf->functionSemantic();
3509 return m.lastf;
3510 }
3511 if ((flags & 2) && !tthis && m.lastf->needThis())
3512 {
3513 return m.lastf;
3514 }
3515 }
3516
3517 /* Failed to find a best match.
3518 * Do nothing or print error.
3519 */
3520 if (m.last <= MATCHnomatch)
3521 {
3522 // error was caused on matched function
3523 if (m.count == 1)
3524 return m.lastf;
3525
3526 // if do not print error messages
3527 if (flags & 1)
3528 return NULL; // no match
3529 }
3530
3531 FuncDeclaration *fd = s->isFuncDeclaration();
3532 OverDeclaration *od = s->isOverDeclaration();
3533 TemplateDeclaration *td = s->isTemplateDeclaration();
3534 if (td && td->funcroot)
3535 s = fd = td->funcroot;
3536
3537 OutBuffer tiargsBuf;
3538 arrayObjectsToBuffer(&tiargsBuf, tiargs);
3539
3540 OutBuffer fargsBuf;
3541 fargsBuf.writeByte('(');
3542 argExpTypesToCBuffer(&fargsBuf, fargs);
3543 fargsBuf.writeByte(')');
3544 if (tthis)
3545 tthis->modToBuffer(&fargsBuf);
3546
3547 const int numOverloadsDisplay = 5; // sensible number to display
3548
3549 if (!m.lastf && !(flags & 1)) // no match
3550 {
3551 if (td && !fd) // all of overloads are templates
3552 {
3553 ::error(loc, "%s %s.%s cannot deduce function from argument types !(%s)%s, candidates are:",
3554 td->kind(), td->parent->toPrettyChars(), td->ident->toChars(),
3555 tiargsBuf.peekString(), fargsBuf.peekString());
3556
3557 // Display candidate templates (even if there are no multiple overloads)
3558 TemplateCandidateWalker tcw;
3559 tcw.loc = loc;
3560 tcw.numToDisplay = numOverloadsDisplay;
3561 overloadApply(td, &tcw, &TemplateCandidateWalker::fp);
3562 }
3563 else if (od)
3564 {
3565 ::error(loc, "none of the overloads of '%s' are callable using argument types !(%s)%s",
3566 od->ident->toChars(), tiargsBuf.peekString(), fargsBuf.peekString());
3567 }
3568 else
3569 {
3570 assert(fd);
3571
3572 bool hasOverloads = fd->overnext != NULL;
3573 TypeFunction *tf = fd->type->toTypeFunction();
3574 if (tthis && !MODimplicitConv(tthis->mod, tf->mod)) // modifier mismatch
3575 {
3576 OutBuffer thisBuf, funcBuf;
3577 MODMatchToBuffer(&thisBuf, tthis->mod, tf->mod);
3578 MODMatchToBuffer(&funcBuf, tf->mod, tthis->mod);
3579 if (hasOverloads)
3580 ::error(loc, "none of the overloads of '%s' are callable using a %sobject, candidates are:",
3581 fd->ident->toChars(), thisBuf.peekString());
3582 else
3583 ::error(loc, "%smethod %s is not callable using a %sobject",
3584 funcBuf.peekString(), fd->toPrettyChars(), thisBuf.peekString());
3585 }
3586 else
3587 {
3588 //printf("tf = %s, args = %s\n", tf->deco, (*fargs)[0]->type->deco);
3589 if (hasOverloads)
3590 ::error(loc, "none of the overloads of '%s' are callable using argument types %s, candidates are:",
3591 fd->ident->toChars(), fargsBuf.peekString());
3592 else
3593 fd->error(loc, "%s%s is not callable using argument types %s",
3594 parametersTypeToChars(tf->parameters, tf->varargs),
3595 tf->modToChars(),
3596 fargsBuf.peekString());
3597 }
3598
3599 // Display candidate functions
3600 if (hasOverloads)
3601 {
3602 FuncCandidateWalker fcw;
3603 fcw.loc = loc;
3604 fcw.numToDisplay = numOverloadsDisplay;
3605 overloadApply(fd, &fcw, &FuncCandidateWalker::fp);
3606 }
3607 }
3608 }
3609 else if (m.nextf)
3610 {
3611 TypeFunction *tf1 = m.lastf->type->toTypeFunction();
3612 TypeFunction *tf2 = m.nextf->type->toTypeFunction();
3613 const char *lastprms = parametersTypeToChars(tf1->parameters, tf1->varargs);
3614 const char *nextprms = parametersTypeToChars(tf2->parameters, tf2->varargs);
3615 ::error(loc, "%s.%s called with argument types %s matches both:\n"
3616 "%s: %s%s\nand:\n%s: %s%s",
3617 s->parent->toPrettyChars(), s->ident->toChars(),
3618 fargsBuf.peekString(),
3619 m.lastf->loc.toChars(), m.lastf->toPrettyChars(), lastprms,
3620 m.nextf->loc.toChars(), m.nextf->toPrettyChars(), nextprms);
3621 }
3622 return NULL;
3623 }
3624
3625 /********************************
3626 * Labels are in a separate scope, one per function.
3627 */
3628
searchLabel(Identifier * ident)3629 LabelDsymbol *FuncDeclaration::searchLabel(Identifier *ident)
3630 { Dsymbol *s;
3631
3632 if (!labtab)
3633 labtab = new DsymbolTable(); // guess we need one
3634
3635 s = labtab->lookup(ident);
3636 if (!s)
3637 {
3638 s = new LabelDsymbol(ident);
3639 labtab->insert(s);
3640 }
3641 return (LabelDsymbol *)s;
3642 }
3643
3644 /*****************************************
3645 * Determine lexical level difference from 'this' to nested function 'fd'.
3646 * Error if this cannot call fd.
3647 * Returns:
3648 * 0 same level
3649 * >0 decrease nesting by number
3650 * -1 increase nesting by 1 (fd is nested within 'this')
3651 * -2 error
3652 */
3653
getLevel(Loc loc,Scope * sc,FuncDeclaration * fd)3654 int FuncDeclaration::getLevel(Loc loc, Scope *sc, FuncDeclaration *fd)
3655 {
3656 int level;
3657 Dsymbol *s;
3658 Dsymbol *fdparent;
3659
3660 //printf("FuncDeclaration::getLevel(fd = '%s')\n", fd->toChars());
3661 fdparent = fd->toParent2();
3662 if (fdparent == this)
3663 return -1;
3664 s = this;
3665 level = 0;
3666 while (fd != s && fdparent != s->toParent2())
3667 {
3668 //printf("\ts = %s, '%s'\n", s->kind(), s->toChars());
3669 FuncDeclaration *thisfd = s->isFuncDeclaration();
3670 if (thisfd)
3671 {
3672 if (!thisfd->isNested() && !thisfd->vthis && !sc->intypeof)
3673 goto Lerr;
3674 }
3675 else
3676 {
3677 AggregateDeclaration *thiscd = s->isAggregateDeclaration();
3678 if (thiscd)
3679 {
3680 /* AggregateDeclaration::isNested returns true only when
3681 * it has a hidden pointer.
3682 * But, calling the function belongs unrelated lexical scope
3683 * is still allowed inside typeof.
3684 *
3685 * struct Map(alias fun) {
3686 * typeof({ return fun(); }) RetType;
3687 * // No member function makes Map struct 'not nested'.
3688 * }
3689 */
3690 if (!thiscd->isNested() && !sc->intypeof)
3691 goto Lerr;
3692 }
3693 else
3694 goto Lerr;
3695 }
3696
3697 s = s->toParent2();
3698 assert(s);
3699 level++;
3700 }
3701 return level;
3702
3703 Lerr:
3704 // Don't give error if in template constraint
3705 if (!(sc->flags & SCOPEconstraint))
3706 {
3707 const char *xstatic = isStatic() ? "static " : "";
3708 // better diagnostics for static functions
3709 ::error(loc, "%s%s %s cannot access frame of function %s",
3710 xstatic, kind(), toPrettyChars(), fd->toPrettyChars());
3711 return -2;
3712 }
3713 return 1;
3714 }
3715
toPrettyChars(bool QualifyTypes)3716 const char *FuncDeclaration::toPrettyChars(bool QualifyTypes)
3717 {
3718 if (isMain())
3719 return "D main";
3720 else
3721 return Dsymbol::toPrettyChars(QualifyTypes);
3722 }
3723
3724 /** for diagnostics, e.g. 'int foo(int x, int y) pure' */
toFullSignature()3725 const char *FuncDeclaration::toFullSignature()
3726 {
3727 OutBuffer buf;
3728 functionToBufferWithIdent(type->toTypeFunction(), &buf, toChars());
3729 return buf.extractString();
3730 }
3731
isMain()3732 bool FuncDeclaration::isMain()
3733 {
3734 return ident == Id::main &&
3735 linkage != LINKc && !isMember() && !isNested();
3736 }
3737
isCMain()3738 bool FuncDeclaration::isCMain()
3739 {
3740 return ident == Id::main &&
3741 linkage == LINKc && !isMember() && !isNested();
3742 }
3743
isWinMain()3744 bool FuncDeclaration::isWinMain()
3745 {
3746 //printf("FuncDeclaration::isWinMain() %s\n", toChars());
3747 return ident == Id::WinMain &&
3748 linkage != LINKc && !isMember();
3749 }
3750
isDllMain()3751 bool FuncDeclaration::isDllMain()
3752 {
3753 return ident == Id::DllMain &&
3754 linkage != LINKc && !isMember();
3755 }
3756
isExport()3757 bool FuncDeclaration::isExport() const
3758 {
3759 return protection.kind == PROTexport;
3760 }
3761
isImportedSymbol()3762 bool FuncDeclaration::isImportedSymbol() const
3763 {
3764 //printf("isImportedSymbol()\n");
3765 //printf("protection = %d\n", protection);
3766 return (protection.kind == PROTexport) && !fbody;
3767 }
3768
3769 // Determine if function goes into virtual function pointer table
3770
isVirtual()3771 bool FuncDeclaration::isVirtual()
3772 {
3773 if (toAliasFunc() != this)
3774 return toAliasFunc()->isVirtual();
3775
3776 Dsymbol *p = toParent();
3777 return isMember() &&
3778 !(isStatic() || protection.kind == PROTprivate || protection.kind == PROTpackage) &&
3779 p->isClassDeclaration() &&
3780 !(p->isInterfaceDeclaration() && isFinalFunc());
3781 }
3782
3783 // Determine if a function is pedantically virtual
3784
isVirtualMethod()3785 bool FuncDeclaration::isVirtualMethod()
3786 {
3787 if (toAliasFunc() != this)
3788 return toAliasFunc()->isVirtualMethod();
3789
3790 //printf("FuncDeclaration::isVirtualMethod() %s\n", toChars());
3791 if (!isVirtual())
3792 return false;
3793 // If it's a final method, and does not override anything, then it is not virtual
3794 if (isFinalFunc() && foverrides.dim == 0)
3795 {
3796 return false;
3797 }
3798 return true;
3799 }
3800
isFinalFunc()3801 bool FuncDeclaration::isFinalFunc()
3802 {
3803 if (toAliasFunc() != this)
3804 return toAliasFunc()->isFinalFunc();
3805
3806 ClassDeclaration *cd;
3807 return isMember() &&
3808 (Declaration::isFinal() ||
3809 ((cd = toParent()->isClassDeclaration()) != NULL && cd->storage_class & STCfinal));
3810 }
3811
isCodeseg()3812 bool FuncDeclaration::isCodeseg() const
3813 {
3814 return true; // functions are always in the code segment
3815 }
3816
isOverloadable()3817 bool FuncDeclaration::isOverloadable()
3818 {
3819 return true; // functions can be overloaded
3820 }
3821
isPure()3822 PURE FuncDeclaration::isPure()
3823 {
3824 //printf("FuncDeclaration::isPure() '%s'\n", toChars());
3825 TypeFunction *tf = type->toTypeFunction();
3826 if (flags & FUNCFLAGpurityInprocess)
3827 setImpure();
3828 if (tf->purity == PUREfwdref)
3829 tf->purityLevel();
3830 PURE purity = tf->purity;
3831 if (purity > PUREweak && isNested())
3832 purity = PUREweak;
3833 if (purity > PUREweak && needThis())
3834 {
3835 // The attribute of the 'this' reference affects purity strength
3836 if (type->mod & MODimmutable)
3837 ;
3838 else if (type->mod & (MODconst | MODwild) && purity >= PUREconst)
3839 purity = PUREconst;
3840 else
3841 purity = PUREweak;
3842 }
3843 tf->purity = purity;
3844 // ^ This rely on the current situation that every FuncDeclaration has a
3845 // unique TypeFunction.
3846 return purity;
3847 }
3848
isPureBypassingInference()3849 PURE FuncDeclaration::isPureBypassingInference()
3850 {
3851 if (flags & FUNCFLAGpurityInprocess)
3852 return PUREfwdref;
3853 else
3854 return isPure();
3855 }
3856
3857 /**************************************
3858 * The function is doing something impure,
3859 * so mark it as impure.
3860 * If there's a purity error, return true.
3861 */
setImpure()3862 bool FuncDeclaration::setImpure()
3863 {
3864 if (flags & FUNCFLAGpurityInprocess)
3865 {
3866 flags &= ~FUNCFLAGpurityInprocess;
3867 if (fes)
3868 fes->func->setImpure();
3869 }
3870 else if (isPure())
3871 return true;
3872 return false;
3873 }
3874
isSafe()3875 bool FuncDeclaration::isSafe()
3876 {
3877 if (flags & FUNCFLAGsafetyInprocess)
3878 setUnsafe();
3879 return type->toTypeFunction()->trust == TRUSTsafe;
3880 }
3881
isSafeBypassingInference()3882 bool FuncDeclaration::isSafeBypassingInference()
3883 {
3884 return !(flags & FUNCFLAGsafetyInprocess) && isSafe();
3885 }
3886
isTrusted()3887 bool FuncDeclaration::isTrusted()
3888 {
3889 if (flags & FUNCFLAGsafetyInprocess)
3890 setUnsafe();
3891 return type->toTypeFunction()->trust == TRUSTtrusted;
3892 }
3893
3894 /**************************************
3895 * The function is doing something unsave,
3896 * so mark it as unsafe.
3897 * If there's a safe error, return true.
3898 */
setUnsafe()3899 bool FuncDeclaration::setUnsafe()
3900 {
3901 if (flags & FUNCFLAGsafetyInprocess)
3902 {
3903 flags &= ~FUNCFLAGsafetyInprocess;
3904 type->toTypeFunction()->trust = TRUSTsystem;
3905 if (fes)
3906 fes->func->setUnsafe();
3907 }
3908 else if (isSafe())
3909 return true;
3910 return false;
3911 }
3912
isNogc()3913 bool FuncDeclaration::isNogc()
3914 {
3915 if (flags & FUNCFLAGnogcInprocess)
3916 setGC();
3917 return type->toTypeFunction()->isnogc;
3918 }
3919
isNogcBypassingInference()3920 bool FuncDeclaration::isNogcBypassingInference()
3921 {
3922 return !(flags & FUNCFLAGnogcInprocess) && isNogc();
3923 }
3924
3925 /**************************************
3926 * The function is doing something that may allocate with the GC,
3927 * so mark it as not nogc (not no-how).
3928 * Returns:
3929 * true if function is marked as @nogc, meaning a user error occurred
3930 */
setGC()3931 bool FuncDeclaration::setGC()
3932 {
3933 if (flags & FUNCFLAGnogcInprocess)
3934 {
3935 flags &= ~FUNCFLAGnogcInprocess;
3936 type->toTypeFunction()->isnogc = false;
3937 if (fes)
3938 fes->func->setGC();
3939 }
3940 else if (isNogc())
3941 return true;
3942 return false;
3943 }
3944
3945 /**************************************
3946 * Returns an indirect type one step from t.
3947 */
3948
getIndirection(Type * t)3949 Type *getIndirection(Type *t)
3950 {
3951 t = t->baseElemOf();
3952 if (t->ty == Tarray || t->ty == Tpointer)
3953 return t->nextOf()->toBasetype();
3954 if (t->ty == Taarray || t->ty == Tclass)
3955 return t;
3956 if (t->ty == Tstruct)
3957 return t->hasPointers() ? t : NULL; // TODO
3958
3959 // should consider TypeDelegate?
3960 return NULL;
3961 }
3962
3963 /**************************************
3964 * Returns true if memory reachable through a reference B to a value of type tb,
3965 * which has been constructed with a reference A to a value of type ta
3966 * available, can alias memory reachable from A based on the types involved
3967 * (either directly or via any number of indirections).
3968 *
3969 * Note that this relation is not symmetric in the two arguments. For example,
3970 * a const(int) reference can point to a pre-existing int, but not the other
3971 * way round.
3972 */
3973 bool traverseIndirections(Type *ta, Type *tb, void *p = NULL, bool reversePass = false)
3974 {
3975 Type *source = ta;
3976 Type *target = tb;
3977 if (reversePass)
3978 {
3979 source = tb;
3980 target = ta;
3981 }
3982
3983 if (source->constConv(target))
3984 return true;
3985 else if (target->ty == Tvoid && MODimplicitConv(source->mod, target->mod))
3986 return true;
3987
3988 // No direct match, so try breaking up one of the types (starting with tb).
3989 Type *tbb = tb->toBasetype()->baseElemOf();
3990 if (tbb != tb)
3991 return traverseIndirections(ta, tbb, p, reversePass);
3992
3993 // context date to detect circular look up
3994 struct Ctxt
3995 {
3996 Ctxt *prev;
3997 Type *type;
3998 };
3999 Ctxt *ctxt = (Ctxt *)p;
4000
4001 if (tb->ty == Tclass || tb->ty == Tstruct)
4002 {
4003 for (Ctxt *c = ctxt; c; c = c->prev)
4004 if (tb == c->type) return false;
4005 Ctxt c;
4006 c.prev = ctxt;
4007 c.type = tb;
4008
4009 AggregateDeclaration *sym = tb->toDsymbol(NULL)->isAggregateDeclaration();
4010 for (size_t i = 0; i < sym->fields.dim; i++)
4011 {
4012 VarDeclaration *v = sym->fields[i];
4013 Type *tprmi = v->type->addMod(tb->mod);
4014 //printf("\ttb = %s, tprmi = %s\n", tb->toChars(), tprmi->toChars());
4015 if (traverseIndirections(ta, tprmi, &c, reversePass))
4016 return true;
4017 }
4018 }
4019 else if (tb->ty == Tarray || tb->ty == Taarray || tb->ty == Tpointer)
4020 {
4021 Type *tind = tb->nextOf();
4022 if (traverseIndirections(ta, tind, ctxt, reversePass))
4023 return true;
4024 }
4025 else if (tb->hasPointers())
4026 {
4027 // FIXME: function pointer/delegate types should be considered.
4028 return true;
4029 }
4030
4031 // Still no match, so try breaking up ta if we have note done so yet.
4032 if (!reversePass)
4033 return traverseIndirections(tb, ta, ctxt, true);
4034
4035 return false;
4036 }
4037
4038 /********************************************
4039 * Returns true if the function return value has no indirection
4040 * which comes from the parameters.
4041 */
4042
isolateReturn()4043 bool FuncDeclaration::isolateReturn()
4044 {
4045 TypeFunction *tf = type->toTypeFunction();
4046 assert(tf->next);
4047
4048 Type *treti = tf->next;
4049 treti = tf->isref ? treti : getIndirection(treti);
4050 if (!treti)
4051 return true; // target has no mutable indirection
4052 return parametersIntersect(treti);
4053 }
4054
4055 /********************************************
4056 * Returns true if an object typed t can have indirections
4057 * which come from the parameters.
4058 */
4059
parametersIntersect(Type * t)4060 bool FuncDeclaration::parametersIntersect(Type *t)
4061 {
4062 assert(t);
4063 if (!isPureBypassingInference() || isNested())
4064 return false;
4065
4066 TypeFunction *tf = type->toTypeFunction();
4067
4068 //printf("parametersIntersect(%s) t = %s\n", tf->toChars(), t->toChars());
4069
4070 size_t dim = Parameter::dim(tf->parameters);
4071 for (size_t i = 0; i < dim; i++)
4072 {
4073 Parameter *fparam = Parameter::getNth(tf->parameters, i);
4074 if (!fparam->type)
4075 continue;
4076 Type *tprmi = (fparam->storageClass & (STClazy | STCout | STCref))
4077 ? fparam->type : getIndirection(fparam->type);
4078 if (!tprmi)
4079 continue; // there is no mutable indirection
4080
4081 //printf("\t[%d] tprmi = %d %s\n", i, tprmi->ty, tprmi->toChars());
4082 if (traverseIndirections(tprmi, t))
4083 return false;
4084 }
4085 if (AggregateDeclaration *ad = isCtorDeclaration() ? NULL : isThis())
4086 {
4087 Type *tthis = ad->getType()->addMod(tf->mod);
4088 //printf("\ttthis = %s\n", tthis->toChars());
4089 if (traverseIndirections(tthis, t))
4090 return false;
4091 }
4092
4093 return true;
4094 }
4095
4096 /****************************************
4097 * Determine if function needs a static frame pointer.
4098 * Returns:
4099 * `true` if function is really nested within other function.
4100 * Contracts:
4101 * If isNested() returns true, isThis() should return false.
4102 */
isNested()4103 bool FuncDeclaration::isNested()
4104 {
4105 FuncDeclaration *f = toAliasFunc();
4106 //printf("\ttoParent2() = '%s'\n", f->toParent2()->toChars());
4107 return ((f->storage_class & STCstatic) == 0) &&
4108 (f->linkage == LINKd) &&
4109 (f->toParent2()->isFuncDeclaration() != NULL);
4110 }
4111
4112 /****************************************
4113 * Determine if function is a non-static member function
4114 * that has an implicit 'this' expression.
4115 * Returns:
4116 * The aggregate it is a member of, or null.
4117 * Contracts:
4118 * If isThis() returns true, isNested() should return false.
4119 */
isThis()4120 AggregateDeclaration *FuncDeclaration::isThis()
4121 {
4122 //printf("+FuncDeclaration::isThis() '%s'\n", toChars());
4123 AggregateDeclaration *ad = (storage_class & STCstatic) ? NULL : isMember2();
4124 //printf("-FuncDeclaration::isThis() %p\n", ad);
4125 return ad;
4126 }
4127
needThis()4128 bool FuncDeclaration::needThis()
4129 {
4130 //printf("FuncDeclaration::needThis() '%s'\n", toChars());
4131 return toAliasFunc()->isThis() != NULL;
4132 }
4133
addPreInvariant()4134 bool FuncDeclaration::addPreInvariant()
4135 {
4136 AggregateDeclaration *ad = isThis();
4137 ClassDeclaration *cd = ad ? ad->isClassDeclaration() : NULL;
4138 return (ad && !(cd && cd->isCPPclass()) &&
4139 global.params.useInvariants &&
4140 (protection.kind == PROTprotected || protection.kind == PROTpublic || protection.kind == PROTexport) &&
4141 !naked);
4142 }
4143
addPostInvariant()4144 bool FuncDeclaration::addPostInvariant()
4145 {
4146 AggregateDeclaration *ad = isThis();
4147 ClassDeclaration *cd = ad ? ad->isClassDeclaration() : NULL;
4148 return (ad && !(cd && cd->isCPPclass()) &&
4149 ad->inv &&
4150 global.params.useInvariants &&
4151 (protection.kind == PROTprotected || protection.kind == PROTpublic || protection.kind == PROTexport) &&
4152 !naked);
4153 }
4154
4155 /********************************************************
4156 * Generate Expression to call the invariant.
4157 * Input:
4158 * ad aggregate with the invariant
4159 * vthis variable with 'this'
4160 * direct call invariant directly
4161 * Returns:
4162 * void expression that calls the invariant
4163 */
addInvariant(Loc loc,Scope * sc,AggregateDeclaration * ad,VarDeclaration * vthis,bool direct)4164 Expression *addInvariant(Loc loc, Scope *sc, AggregateDeclaration *ad, VarDeclaration *vthis, bool direct)
4165 {
4166 Expression *e = NULL;
4167 if (direct)
4168 {
4169 // Call invariant directly only if it exists
4170 FuncDeclaration *inv = ad->inv;
4171 ClassDeclaration *cd = ad->isClassDeclaration();
4172
4173 while (!inv && cd)
4174 {
4175 cd = cd->baseClass;
4176 if (!cd)
4177 break;
4178 inv = cd->inv;
4179 }
4180 if (inv)
4181 {
4182 #if 1
4183 // Workaround for bugzilla 13394: For the correct mangling,
4184 // run attribute inference on inv if needed.
4185 inv->functionSemantic();
4186 #endif
4187
4188 //e = new DsymbolExp(Loc(), inv);
4189 //e = new CallExp(Loc(), e);
4190 //e = e->semantic(sc2);
4191
4192 /* Bugzilla 13113: Currently virtual invariant calls completely
4193 * bypass attribute enforcement.
4194 * Change the behavior of pre-invariant call by following it.
4195 */
4196 e = new ThisExp(Loc());
4197 e->type = vthis->type;
4198 e = new DotVarExp(Loc(), e, inv, false);
4199 e->type = inv->type;
4200 e = new CallExp(Loc(), e);
4201 e->type = Type::tvoid;
4202 }
4203 }
4204 else
4205 {
4206 #if 1
4207 // Workaround for bugzilla 13394: For the correct mangling,
4208 // run attribute inference on inv if needed.
4209 if (ad->isStructDeclaration() && ad->inv)
4210 ad->inv->functionSemantic();
4211 #endif
4212
4213 // Call invariant virtually
4214 Expression *v = new ThisExp(Loc());
4215 v->type = vthis->type;
4216 if (ad->isStructDeclaration())
4217 v = v->addressOf();
4218 e = new StringExp(Loc(), const_cast<char *>("null this"));
4219 e = new AssertExp(loc, v, e);
4220 e = semantic(e, sc);
4221 }
4222 return e;
4223 }
4224
4225 /**********************************
4226 * Generate a FuncDeclaration for a runtime library function.
4227 */
4228
genCfunc(Parameters * fparams,Type * treturn,const char * name,StorageClass stc)4229 FuncDeclaration *FuncDeclaration::genCfunc(Parameters *fparams, Type *treturn, const char *name, StorageClass stc)
4230 {
4231 return genCfunc(fparams, treturn, Identifier::idPool(name), stc);
4232 }
4233
genCfunc(Parameters * fparams,Type * treturn,Identifier * id,StorageClass stc)4234 FuncDeclaration *FuncDeclaration::genCfunc(Parameters *fparams, Type *treturn, Identifier *id, StorageClass stc)
4235 {
4236 FuncDeclaration *fd;
4237 TypeFunction *tf;
4238 Dsymbol *s;
4239 static DsymbolTable *st = NULL;
4240
4241 //printf("genCfunc(name = '%s')\n", id->toChars());
4242 //printf("treturn\n\t"); treturn->print();
4243
4244 // See if already in table
4245 if (!st)
4246 st = new DsymbolTable();
4247 s = st->lookup(id);
4248 if (s)
4249 {
4250 fd = s->isFuncDeclaration();
4251 assert(fd);
4252 assert(fd->type->nextOf()->equals(treturn));
4253 }
4254 else
4255 {
4256 tf = new TypeFunction(fparams, treturn, 0, LINKc, stc);
4257 fd = new FuncDeclaration(Loc(), Loc(), id, STCstatic, tf);
4258 fd->protection = Prot(PROTpublic);
4259 fd->linkage = LINKc;
4260
4261 st->insert(fd);
4262 }
4263 return fd;
4264 }
4265
4266 /******************
4267 * Check parameters and return type of D main() function.
4268 * Issue error messages.
4269 */
checkDmain()4270 void FuncDeclaration::checkDmain()
4271 {
4272 TypeFunction *tf = type->toTypeFunction();
4273 const size_t nparams = Parameter::dim(tf->parameters);
4274 bool argerr = false;
4275 if (nparams == 1)
4276 {
4277 Parameter *fparam0 = Parameter::getNth(tf->parameters, 0);
4278 Type *t = fparam0->type->toBasetype();
4279 if (t->ty != Tarray ||
4280 t->nextOf()->ty != Tarray ||
4281 t->nextOf()->nextOf()->ty != Tchar ||
4282 fparam0->storageClass & (STCout | STCref | STClazy))
4283 {
4284 argerr = true;
4285 }
4286 }
4287
4288 if (!tf->nextOf())
4289 error("must return int or void");
4290 else if (tf->nextOf()->ty != Tint32 && tf->nextOf()->ty != Tvoid)
4291 error("must return int or void, not %s", tf->nextOf()->toChars());
4292 else if (tf->varargs || nparams >= 2 || argerr)
4293 error("parameters must be main() or main(string[] args)");
4294 }
4295
kind()4296 const char *FuncDeclaration::kind() const
4297 {
4298 return generated ? "generated function" : "function";
4299 }
4300
4301 /*********************************************
4302 * In the current function, we are calling 'this' function.
4303 * 1. Check to see if the current function can call 'this' function, issue error if not.
4304 * 2. If the current function is not the parent of 'this' function, then add
4305 * the current function to the list of siblings of 'this' function.
4306 * 3. If the current function is a literal, and it's accessing an uplevel scope,
4307 * then mark it as a delegate.
4308 * Returns true if error occurs.
4309 */
checkNestedReference(Scope * sc,Loc loc)4310 bool FuncDeclaration::checkNestedReference(Scope *sc, Loc loc)
4311 {
4312 //printf("FuncDeclaration::checkNestedReference() %s\n", toPrettyChars());
4313
4314 if (FuncLiteralDeclaration *fld = this->isFuncLiteralDeclaration())
4315 {
4316 if (fld->tok == TOKreserved)
4317 {
4318 fld->tok = TOKfunction;
4319 fld->vthis = NULL;
4320 }
4321 }
4322
4323 if (!parent || parent == sc->parent)
4324 return false;
4325 if (ident == Id::require || ident == Id::ensure)
4326 return false;
4327 if (!isThis() && !isNested())
4328 return false;
4329
4330 // The current function
4331 FuncDeclaration *fdthis = sc->parent->isFuncDeclaration();
4332 if (!fdthis)
4333 return false; // out of function scope
4334
4335 Dsymbol *p = toParent2();
4336
4337 // Function literals from fdthis to p must be delegates
4338 checkNestedRef(fdthis, p);
4339
4340 if (isNested())
4341 {
4342 // The function that this function is in
4343 FuncDeclaration *fdv = p->isFuncDeclaration();
4344 if (!fdv)
4345 return false;
4346 if (fdv == fdthis)
4347 return false;
4348
4349 //printf("this = %s in [%s]\n", this->toChars(), this->loc.toChars());
4350 //printf("fdv = %s in [%s]\n", fdv->toChars(), fdv->loc.toChars());
4351 //printf("fdthis = %s in [%s]\n", fdthis->toChars(), fdthis->loc.toChars());
4352
4353 // Add this function to the list of those which called us
4354 if (fdthis != this)
4355 {
4356 bool found = false;
4357 for (size_t i = 0; i < siblingCallers.dim; ++i)
4358 {
4359 if (siblingCallers[i] == fdthis)
4360 found = true;
4361 }
4362 if (!found)
4363 {
4364 //printf("\tadding sibling %s\n", fdthis->toPrettyChars());
4365 if (!sc->intypeof && !(sc->flags & SCOPEcompile))
4366 siblingCallers.push(fdthis);
4367 }
4368 }
4369
4370 int lv = fdthis->getLevel(loc, sc, fdv);
4371 if (lv == -2)
4372 return true; // error
4373 if (lv == -1)
4374 return false; // downlevel call
4375 if (lv == 0)
4376 return false; // same level call
4377 // Uplevel call
4378 }
4379 return false;
4380 }
4381
4382 /* For all functions between outerFunc and f, mark them as needing
4383 * a closure.
4384 */
markAsNeedingClosure(Dsymbol * f,FuncDeclaration * outerFunc)4385 void markAsNeedingClosure(Dsymbol *f, FuncDeclaration *outerFunc)
4386 {
4387 for (Dsymbol *sx = f; sx && sx != outerFunc; sx = sx->parent)
4388 {
4389 FuncDeclaration *fy = sx->isFuncDeclaration();
4390 if (fy && fy->closureVars.dim)
4391 {
4392 /* fy needs a closure if it has closureVars[],
4393 * because the frame pointer in the closure will be accessed.
4394 */
4395 fy->requiresClosure = true;
4396 }
4397 }
4398 }
4399
4400
4401 /* Given a nested function f inside a function outerFunc, check
4402 * if any sibling callers of f have escaped. If so, mark
4403 * all the enclosing functions as needing closures.
4404 * Return true if any closures were detected.
4405 * This is recursive: we need to check the callers of our siblings.
4406 * Note that nested functions can only call lexically earlier nested
4407 * functions, so loops are impossible.
4408 */
4409 bool checkEscapingSiblings(FuncDeclaration *f, FuncDeclaration *outerFunc, void *p = NULL)
4410 {
4411 struct PrevSibling
4412 {
4413 PrevSibling *p;
4414 FuncDeclaration *f;
4415 };
4416
4417 PrevSibling ps;
4418 ps.p = (PrevSibling *)p;
4419 ps.f = f;
4420
4421 //printf("checkEscapingSiblings(f = %s, outerfunc = %s)\n", f->toChars(), outerFunc->toChars());
4422 bool bAnyClosures = false;
4423 for (size_t i = 0; i < f->siblingCallers.dim; ++i)
4424 {
4425 FuncDeclaration *g = f->siblingCallers[i];
4426 if (g->isThis() || g->tookAddressOf)
4427 {
4428 markAsNeedingClosure(g, outerFunc);
4429 bAnyClosures = true;
4430 }
4431
4432 PrevSibling *prev = (PrevSibling *)p;
4433 while (1)
4434 {
4435 if (!prev)
4436 {
4437 bAnyClosures |= checkEscapingSiblings(g, outerFunc, &ps);
4438 break;
4439 }
4440 if (prev->f == g)
4441 break;
4442 prev = prev->p;
4443 }
4444 }
4445 //printf("\t%d\n", bAnyClosures);
4446 return bAnyClosures;
4447 }
4448
4449
4450 /*******************************
4451 * Look at all the variables in this function that are referenced
4452 * by nested functions, and determine if a closure needs to be
4453 * created for them.
4454 */
4455
needsClosure()4456 bool FuncDeclaration::needsClosure()
4457 {
4458 /* Need a closure for all the closureVars[] if any of the
4459 * closureVars[] are accessed by a
4460 * function that escapes the scope of this function.
4461 * We take the conservative approach and decide that a function needs
4462 * a closure if it:
4463 * 1) is a virtual function
4464 * 2) has its address taken
4465 * 3) has a parent that escapes
4466 * 4) calls another nested function that needs a closure
4467 *
4468 * Note that since a non-virtual function can be called by
4469 * a virtual one, if that non-virtual function accesses a closure
4470 * var, the closure still has to be taken. Hence, we check for isThis()
4471 * instead of isVirtual(). (thanks to David Friedman)
4472 *
4473 * When the function returns a local struct or class, `requiresClosure`
4474 * is already set to `true` upon entering this function when the
4475 * struct/class refers to a local variable and a closure is needed.
4476 */
4477
4478 //printf("FuncDeclaration::needsClosure() %s\n", toChars());
4479
4480 if (requiresClosure)
4481 goto Lyes;
4482
4483 for (size_t i = 0; i < closureVars.dim; i++)
4484 {
4485 VarDeclaration *v = closureVars[i];
4486 //printf("\tv = %s\n", v->toChars());
4487
4488 for (size_t j = 0; j < v->nestedrefs.dim; j++)
4489 {
4490 FuncDeclaration *f = v->nestedrefs[j];
4491 assert(f != this);
4492
4493 //printf("\t\tf = %s, isVirtual=%d, isThis=%p, tookAddressOf=%d\n", f->toChars(), f->isVirtual(), f->isThis(), f->tookAddressOf);
4494
4495 /* Look to see if f escapes. We consider all parents of f within
4496 * this, and also all siblings which call f; if any of them escape,
4497 * so does f.
4498 * Mark all affected functions as requiring closures.
4499 */
4500 for (Dsymbol *s = f; s && s != this; s = s->parent)
4501 {
4502 FuncDeclaration *fx = s->isFuncDeclaration();
4503 if (!fx)
4504 continue;
4505 if (fx->isThis() || fx->tookAddressOf)
4506 {
4507 //printf("\t\tfx = %s, isVirtual=%d, isThis=%p, tookAddressOf=%d\n", fx->toChars(), fx->isVirtual(), fx->isThis(), fx->tookAddressOf);
4508
4509 /* Mark as needing closure any functions between this and f
4510 */
4511 markAsNeedingClosure( (fx == f) ? fx->parent : fx, this);
4512
4513 requiresClosure = true;
4514 }
4515
4516 /* We also need to check if any sibling functions that
4517 * called us, have escaped. This is recursive: we need
4518 * to check the callers of our siblings.
4519 */
4520 if (checkEscapingSiblings(fx, this))
4521 requiresClosure = true;
4522
4523 /* Bugzilla 12406: Iterate all closureVars to mark all descendant
4524 * nested functions that access to the closing context of this funciton.
4525 */
4526 }
4527 }
4528 }
4529 if (requiresClosure)
4530 goto Lyes;
4531
4532 return false;
4533
4534 Lyes:
4535 //printf("\tneeds closure\n");
4536 return true;
4537 }
4538
4539 /***********************************************
4540 * Check that the function contains any closure.
4541 * If it's @nogc, report suitable errors.
4542 * This is mostly consistent with FuncDeclaration::needsClosure().
4543 *
4544 * Returns:
4545 * true if any errors occur.
4546 */
checkClosure()4547 bool FuncDeclaration::checkClosure()
4548 {
4549 if (!needsClosure())
4550 return false;
4551
4552 if (setGC())
4553 {
4554 error("is @nogc yet allocates closures with the GC");
4555 if (global.gag) // need not report supplemental errors
4556 return true;
4557 }
4558 else
4559 {
4560 printGCUsage(loc, "using closure causes GC allocation");
4561 return false;
4562 }
4563
4564 FuncDeclarations a;
4565 for (size_t i = 0; i < closureVars.dim; i++)
4566 {
4567 VarDeclaration *v = closureVars[i];
4568
4569 for (size_t j = 0; j < v->nestedrefs.dim; j++)
4570 {
4571 FuncDeclaration *f = v->nestedrefs[j];
4572 assert(f != this);
4573
4574 for (Dsymbol *s = f; s && s != this; s = s->parent)
4575 {
4576 FuncDeclaration *fx = s->isFuncDeclaration();
4577 if (!fx)
4578 continue;
4579 if (fx->isThis() || fx->tookAddressOf)
4580 goto Lfound;
4581 if (checkEscapingSiblings(fx, this))
4582 goto Lfound;
4583 }
4584 continue;
4585
4586 Lfound:
4587 for (size_t k = 0; ; k++)
4588 {
4589 if (k == a.dim)
4590 {
4591 a.push(f);
4592 ::errorSupplemental(f->loc, "%s closes over variable %s at %s",
4593 f->toPrettyChars(), v->toChars(), v->loc.toChars());
4594 break;
4595 }
4596 if (a[k] == f)
4597 break;
4598 }
4599 continue;
4600 }
4601 }
4602
4603 return true;
4604 }
4605
4606 /***********************************************
4607 * Determine if function's variables are referenced by a function
4608 * nested within it.
4609 */
4610
hasNestedFrameRefs()4611 bool FuncDeclaration::hasNestedFrameRefs()
4612 {
4613 if (closureVars.dim)
4614 return true;
4615
4616 /* If a virtual function has contracts, assume its variables are referenced
4617 * by those contracts, even if they aren't. Because they might be referenced
4618 * by the overridden or overriding function's contracts.
4619 * This can happen because frequire and fensure are implemented as nested functions,
4620 * and they can be called directly by an overriding function and the overriding function's
4621 * context had better match, or Bugzilla 7335 will bite.
4622 */
4623 if (fdrequire || fdensure)
4624 return true;
4625
4626 if (foverrides.dim && isVirtualMethod())
4627 {
4628 for (size_t i = 0; i < foverrides.dim; i++)
4629 {
4630 FuncDeclaration *fdv = foverrides[i];
4631 if (fdv->hasNestedFrameRefs())
4632 return true;
4633 }
4634 }
4635
4636 return false;
4637 }
4638
4639 /*********************************************
4640 * Return the function's parameter list, and whether
4641 * it is variadic or not.
4642 */
4643
getParameters(int * pvarargs)4644 Parameters *FuncDeclaration::getParameters(int *pvarargs)
4645 {
4646 Parameters *fparameters = NULL;
4647 int fvarargs = 0;
4648
4649 if (type)
4650 {
4651 TypeFunction *fdtype = type->toTypeFunction();
4652 fparameters = fdtype->parameters;
4653 fvarargs = fdtype->varargs;
4654 }
4655 if (pvarargs)
4656 *pvarargs = fvarargs;
4657 return fparameters;
4658 }
4659
4660
4661 /****************************** FuncAliasDeclaration ************************/
4662
4663 // Used as a way to import a set of functions from another scope into this one.
4664
FuncAliasDeclaration(Identifier * ident,FuncDeclaration * funcalias,bool hasOverloads)4665 FuncAliasDeclaration::FuncAliasDeclaration(Identifier *ident, FuncDeclaration *funcalias, bool hasOverloads)
4666 : FuncDeclaration(funcalias->loc, funcalias->endloc, ident,
4667 funcalias->storage_class, funcalias->type)
4668 {
4669 assert(funcalias != this);
4670 this->funcalias = funcalias;
4671
4672 this->hasOverloads = hasOverloads;
4673 if (hasOverloads)
4674 {
4675 if (FuncAliasDeclaration *fad = funcalias->isFuncAliasDeclaration())
4676 this->hasOverloads = fad->hasOverloads;
4677 }
4678 else
4679 { // for internal use
4680 assert(!funcalias->isFuncAliasDeclaration());
4681 this->hasOverloads = false;
4682 }
4683 userAttribDecl = funcalias->userAttribDecl;
4684 }
4685
kind()4686 const char *FuncAliasDeclaration::kind() const
4687 {
4688 return "function alias";
4689 }
4690
toAliasFunc()4691 FuncDeclaration *FuncAliasDeclaration::toAliasFunc()
4692 {
4693 return funcalias->toAliasFunc();
4694 }
4695
4696
4697 /****************************** FuncLiteralDeclaration ************************/
4698
FuncLiteralDeclaration(Loc loc,Loc endloc,Type * type,TOK tok,ForeachStatement * fes,Identifier * id)4699 FuncLiteralDeclaration::FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type,
4700 TOK tok, ForeachStatement *fes, Identifier *id)
4701 : FuncDeclaration(loc, endloc, NULL, STCundefined, type)
4702 {
4703 this->ident = id ? id : Id::empty;
4704 this->tok = tok;
4705 this->fes = fes;
4706 this->treq = NULL;
4707 this->deferToObj = false;
4708 //printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this->ident->toChars(), type->toChars());
4709 }
4710
syntaxCopy(Dsymbol * s)4711 Dsymbol *FuncLiteralDeclaration::syntaxCopy(Dsymbol *s)
4712 {
4713 //printf("FuncLiteralDeclaration::syntaxCopy('%s')\n", toChars());
4714 assert(!s);
4715 FuncLiteralDeclaration *f = new FuncLiteralDeclaration(loc, endloc,
4716 type->syntaxCopy(), tok, fes, ident);
4717 f->treq = treq; // don't need to copy
4718 return FuncDeclaration::syntaxCopy(f);
4719 }
4720
isNested()4721 bool FuncLiteralDeclaration::isNested()
4722 {
4723 //printf("FuncLiteralDeclaration::isNested() '%s'\n", toChars());
4724 return (tok != TOKfunction) && !isThis();
4725 }
4726
isThis()4727 AggregateDeclaration *FuncLiteralDeclaration::isThis()
4728 {
4729 //printf("FuncLiteralDeclaration::isThis() '%s'\n", toChars());
4730 return tok == TOKdelegate ? FuncDeclaration::isThis() : NULL;
4731 }
4732
isVirtual()4733 bool FuncLiteralDeclaration::isVirtual()
4734 {
4735 return false;
4736 }
4737
addPreInvariant()4738 bool FuncLiteralDeclaration::addPreInvariant()
4739 {
4740 return false;
4741 }
4742
addPostInvariant()4743 bool FuncLiteralDeclaration::addPostInvariant()
4744 {
4745 return false;
4746 }
4747
4748 /*******************************
4749 * Modify all expression type of return statements to tret.
4750 *
4751 * On function literals, return type may be modified based on the context type
4752 * after its semantic3 is done, in FuncExp::implicitCastTo.
4753 *
4754 * A function() dg = (){ return new B(); } // OK if is(B : A) == true
4755 *
4756 * If B to A conversion is convariant that requires offseet adjusting,
4757 * all return statements should be adjusted to return expressions typed A.
4758 */
modifyReturns(Scope * sc,Type * tret)4759 void FuncLiteralDeclaration::modifyReturns(Scope *sc, Type *tret)
4760 {
4761 class RetWalker : public StatementRewriteWalker
4762 {
4763 public:
4764 Scope *sc;
4765 Type *tret;
4766 FuncLiteralDeclaration *fld;
4767
4768 void visit(ReturnStatement *s)
4769 {
4770 Expression *exp = s->exp;
4771 if (exp && !exp->type->equals(tret))
4772 {
4773 s->exp = exp->castTo(sc, tret);
4774 }
4775 }
4776 };
4777
4778 if (semanticRun < PASSsemantic3done)
4779 return;
4780
4781 if (fes)
4782 return;
4783
4784 RetWalker w;
4785 w.sc = sc;
4786 w.tret = tret;
4787 w.fld = this;
4788 fbody->accept(&w);
4789
4790 // Also update the inferred function type to match the new return type.
4791 // This is required so the code generator does not try to cast the
4792 // modified returns back to the original type.
4793 if (inferRetType && type->nextOf() != tret)
4794 type->toTypeFunction()->next = tret;
4795 }
4796
kind()4797 const char *FuncLiteralDeclaration::kind() const
4798 {
4799 return (tok != TOKfunction) ? "delegate" : "function";
4800 }
4801
toPrettyChars(bool QualifyTypes)4802 const char *FuncLiteralDeclaration::toPrettyChars(bool QualifyTypes)
4803 {
4804 if (parent)
4805 {
4806 TemplateInstance *ti = parent->isTemplateInstance();
4807 if (ti)
4808 return ti->tempdecl->toPrettyChars(QualifyTypes);
4809 }
4810 return Dsymbol::toPrettyChars(QualifyTypes);
4811 }
4812
4813 /********************************* CtorDeclaration ****************************/
4814
CtorDeclaration(Loc loc,Loc endloc,StorageClass stc,Type * type)4815 CtorDeclaration::CtorDeclaration(Loc loc, Loc endloc, StorageClass stc, Type *type)
4816 : FuncDeclaration(loc, endloc, Id::ctor, stc, type)
4817 {
4818 //printf("CtorDeclaration(loc = %s) %s\n", loc.toChars(), toChars());
4819 }
4820
syntaxCopy(Dsymbol * s)4821 Dsymbol *CtorDeclaration::syntaxCopy(Dsymbol *s)
4822 {
4823 assert(!s);
4824 CtorDeclaration *f = new CtorDeclaration(loc, endloc, storage_class, type->syntaxCopy());
4825 return FuncDeclaration::syntaxCopy(f);
4826 }
4827
semantic(Scope * sc)4828 void CtorDeclaration::semantic(Scope *sc)
4829 {
4830 //printf("CtorDeclaration::semantic() %s\n", toChars());
4831 if (semanticRun >= PASSsemanticdone)
4832 return;
4833 if (_scope)
4834 {
4835 sc = _scope;
4836 _scope = NULL;
4837 }
4838
4839 parent = sc->parent;
4840 Dsymbol *p = toParent2();
4841 AggregateDeclaration *ad = p->isAggregateDeclaration();
4842 if (!ad)
4843 {
4844 ::error(loc, "constructor can only be a member of aggregate, not %s %s",
4845 p->kind(), p->toChars());
4846 type = Type::terror;
4847 errors = true;
4848 return;
4849 }
4850
4851 sc = sc->push();
4852 sc->stc &= ~STCstatic; // not a static constructor
4853 sc->flags |= SCOPEctor;
4854
4855 FuncDeclaration::semantic(sc);
4856
4857 sc->pop();
4858
4859 if (errors)
4860 return;
4861
4862 TypeFunction *tf = type->toTypeFunction();
4863
4864 /* See if it's the default constructor
4865 * But, template constructor should not become a default constructor.
4866 */
4867 if (ad && (!parent->isTemplateInstance() || parent->isTemplateMixin()))
4868 {
4869 const size_t dim = Parameter::dim(tf->parameters);
4870
4871 if (StructDeclaration *sd = ad->isStructDeclaration())
4872 {
4873 if (dim == 0 && tf->varargs == 0) // empty default ctor w/o any varargs
4874 {
4875 if (fbody || !(storage_class & STCdisable) || dim)
4876 {
4877 error("default constructor for structs only allowed "
4878 "with @disable, no body, and no parameters");
4879 storage_class |= STCdisable;
4880 fbody = NULL;
4881 }
4882 sd->noDefaultCtor = true;
4883 }
4884 else if (dim == 0 && tf->varargs) // allow varargs only ctor
4885 {
4886 }
4887 else if (dim && Parameter::getNth(tf->parameters, 0)->defaultArg)
4888 {
4889 // if the first parameter has a default argument, then the rest does as well
4890 if (storage_class & STCdisable)
4891 {
4892 deprecation("@disable'd constructor cannot have default "
4893 "arguments for all parameters.");
4894 deprecationSupplemental(loc, "Use @disable this(); if you want to disable default initialization.");
4895 }
4896 else
4897 deprecation("all parameters have default arguments, "
4898 "but structs cannot have default constructors.");
4899 }
4900
4901 }
4902 else if (dim == 0 && tf->varargs == 0)
4903 {
4904 ad->defaultCtor = this;
4905 }
4906 }
4907 }
4908
kind()4909 const char *CtorDeclaration::kind() const
4910 {
4911 return "constructor";
4912 }
4913
toChars()4914 const char *CtorDeclaration::toChars()
4915 {
4916 return "this";
4917 }
4918
isVirtual()4919 bool CtorDeclaration::isVirtual()
4920 {
4921 return false;
4922 }
4923
addPreInvariant()4924 bool CtorDeclaration::addPreInvariant()
4925 {
4926 return false;
4927 }
4928
addPostInvariant()4929 bool CtorDeclaration::addPostInvariant()
4930 {
4931 return (isThis() && vthis && global.params.useInvariants);
4932 }
4933
4934
4935 /********************************* PostBlitDeclaration ****************************/
4936
PostBlitDeclaration(Loc loc,Loc endloc,StorageClass stc,Identifier * id)4937 PostBlitDeclaration::PostBlitDeclaration(Loc loc, Loc endloc, StorageClass stc, Identifier *id)
4938 : FuncDeclaration(loc, endloc, id, stc, NULL)
4939 {
4940 }
4941
syntaxCopy(Dsymbol * s)4942 Dsymbol *PostBlitDeclaration::syntaxCopy(Dsymbol *s)
4943 {
4944 assert(!s);
4945 PostBlitDeclaration *dd = new PostBlitDeclaration(loc, endloc, storage_class, ident);
4946 return FuncDeclaration::syntaxCopy(dd);
4947 }
4948
semantic(Scope * sc)4949 void PostBlitDeclaration::semantic(Scope *sc)
4950 {
4951 //printf("PostBlitDeclaration::semantic() %s\n", toChars());
4952 //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
4953 //printf("stc = x%llx\n", sc->stc);
4954 if (semanticRun >= PASSsemanticdone)
4955 return;
4956 if (_scope)
4957 {
4958 sc = _scope;
4959 _scope = NULL;
4960 }
4961
4962 parent = sc->parent;
4963 Dsymbol *p = toParent2();
4964 StructDeclaration *ad = p->isStructDeclaration();
4965 if (!ad)
4966 {
4967 ::error(loc, "postblit can only be a member of struct/union, not %s %s",
4968 p->kind(), p->toChars());
4969 type = Type::terror;
4970 errors = true;
4971 return;
4972 }
4973 if (ident == Id::postblit && semanticRun < PASSsemantic)
4974 ad->postblits.push(this);
4975 if (!type)
4976 type = new TypeFunction(NULL, Type::tvoid, false, LINKd, storage_class);
4977
4978 sc = sc->push();
4979 sc->stc &= ~STCstatic; // not static
4980 sc->linkage = LINKd;
4981
4982 FuncDeclaration::semantic(sc);
4983
4984 sc->pop();
4985 }
4986
overloadInsert(Dsymbol *)4987 bool PostBlitDeclaration::overloadInsert(Dsymbol *)
4988 {
4989 return false; // cannot overload postblits
4990 }
4991
addPreInvariant()4992 bool PostBlitDeclaration::addPreInvariant()
4993 {
4994 return false;
4995 }
4996
addPostInvariant()4997 bool PostBlitDeclaration::addPostInvariant()
4998 {
4999 return (isThis() && vthis && global.params.useInvariants);
5000 }
5001
isVirtual()5002 bool PostBlitDeclaration::isVirtual()
5003 {
5004 return false;
5005 }
5006
5007 /********************************* DtorDeclaration ****************************/
5008
DtorDeclaration(Loc loc,Loc endloc)5009 DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc)
5010 : FuncDeclaration(loc, endloc, Id::dtor, STCundefined, NULL)
5011 {
5012 }
5013
DtorDeclaration(Loc loc,Loc endloc,StorageClass stc,Identifier * id)5014 DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc, StorageClass stc, Identifier *id)
5015 : FuncDeclaration(loc, endloc, id, stc, NULL)
5016 {
5017 }
5018
syntaxCopy(Dsymbol * s)5019 Dsymbol *DtorDeclaration::syntaxCopy(Dsymbol *s)
5020 {
5021 assert(!s);
5022 DtorDeclaration *dd = new DtorDeclaration(loc, endloc, storage_class, ident);
5023 return FuncDeclaration::syntaxCopy(dd);
5024 }
5025
semantic(Scope * sc)5026 void DtorDeclaration::semantic(Scope *sc)
5027 {
5028 //printf("DtorDeclaration::semantic() %s\n", toChars());
5029 //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
5030 if (semanticRun >= PASSsemanticdone)
5031 return;
5032 if (_scope)
5033 {
5034 sc = _scope;
5035 _scope = NULL;
5036 }
5037
5038 parent = sc->parent;
5039 Dsymbol *p = toParent2();
5040 AggregateDeclaration *ad = p->isAggregateDeclaration();
5041 if (!ad)
5042 {
5043 ::error(loc, "destructor can only be a member of aggregate, not %s %s",
5044 p->kind(), p->toChars());
5045 type = Type::terror;
5046 errors = true;
5047 return;
5048 }
5049 if (ident == Id::dtor && semanticRun < PASSsemantic)
5050 ad->dtors.push(this);
5051 if (!type)
5052 type = new TypeFunction(NULL, Type::tvoid, false, LINKd, storage_class);
5053
5054 sc = sc->push();
5055 sc->stc &= ~STCstatic; // not a static destructor
5056 if (sc->linkage != LINKcpp)
5057 sc->linkage = LINKd;
5058
5059 FuncDeclaration::semantic(sc);
5060
5061 sc->pop();
5062 }
5063
overloadInsert(Dsymbol *)5064 bool DtorDeclaration::overloadInsert(Dsymbol *)
5065 {
5066 return false; // cannot overload destructors
5067 }
5068
addPreInvariant()5069 bool DtorDeclaration::addPreInvariant()
5070 {
5071 return (isThis() && vthis && global.params.useInvariants);
5072 }
5073
addPostInvariant()5074 bool DtorDeclaration::addPostInvariant()
5075 {
5076 return false;
5077 }
5078
kind()5079 const char *DtorDeclaration::kind() const
5080 {
5081 return "destructor";
5082 }
5083
toChars()5084 const char *DtorDeclaration::toChars()
5085 {
5086 return "~this";
5087 }
5088
isVirtual()5089 bool DtorDeclaration::isVirtual()
5090 {
5091 // false so that dtor's don't get put into the vtbl[]
5092 return false;
5093 }
5094
5095 /********************************* StaticCtorDeclaration ****************************/
5096
StaticCtorDeclaration(Loc loc,Loc endloc,StorageClass stc)5097 StaticCtorDeclaration::StaticCtorDeclaration(Loc loc, Loc endloc, StorageClass stc)
5098 : FuncDeclaration(loc, endloc,
5099 Identifier::generateId("_staticCtor"), STCstatic | stc, NULL)
5100 {
5101 }
5102
StaticCtorDeclaration(Loc loc,Loc endloc,const char * name,StorageClass stc)5103 StaticCtorDeclaration::StaticCtorDeclaration(Loc loc, Loc endloc, const char *name, StorageClass stc)
5104 : FuncDeclaration(loc, endloc,
5105 Identifier::generateId(name), STCstatic | stc, NULL)
5106 {
5107 }
5108
syntaxCopy(Dsymbol * s)5109 Dsymbol *StaticCtorDeclaration::syntaxCopy(Dsymbol *s)
5110 {
5111 assert(!s);
5112 StaticCtorDeclaration *scd = new StaticCtorDeclaration(loc, endloc, storage_class);
5113 return FuncDeclaration::syntaxCopy(scd);
5114 }
5115
semantic(Scope * sc)5116 void StaticCtorDeclaration::semantic(Scope *sc)
5117 {
5118 //printf("StaticCtorDeclaration::semantic()\n");
5119 if (semanticRun >= PASSsemanticdone)
5120 return;
5121 if (_scope)
5122 {
5123 sc = _scope;
5124 _scope = NULL;
5125 }
5126
5127 parent = sc->parent;
5128 Dsymbol *p = parent->pastMixin();
5129 if (!p->isScopeDsymbol())
5130 {
5131 const char *s = (isSharedStaticCtorDeclaration() ? "shared " : "");
5132 ::error(loc, "%sstatic constructor can only be member of module/aggregate/template, not %s %s",
5133 s, p->kind(), p->toChars());
5134 type = Type::terror;
5135 errors = true;
5136 return;
5137 }
5138 if (!type)
5139 type = new TypeFunction(NULL, Type::tvoid, false, LINKd, storage_class);
5140
5141 /* If the static ctor appears within a template instantiation,
5142 * it could get called multiple times by the module constructors
5143 * for different modules. Thus, protect it with a gate.
5144 */
5145 if (isInstantiated() && semanticRun < PASSsemantic)
5146 {
5147 /* Add this prefix to the function:
5148 * static int gate;
5149 * if (++gate != 1) return;
5150 * Note that this is not thread safe; should not have threads
5151 * during static construction.
5152 */
5153 VarDeclaration *v = new VarDeclaration(Loc(), Type::tint32, Id::gate, NULL);
5154 v->storage_class = STCtemp | (isSharedStaticCtorDeclaration() ? STCstatic : STCtls);
5155 Statements *sa = new Statements();
5156 Statement *s = new ExpStatement(Loc(), v);
5157 sa->push(s);
5158 Expression *e = new IdentifierExp(Loc(), v->ident);
5159 e = new AddAssignExp(Loc(), e, new IntegerExp(1));
5160 e = new EqualExp(TOKnotequal, Loc(), e, new IntegerExp(1));
5161 s = new IfStatement(Loc(), NULL, e, new ReturnStatement(Loc(), NULL), NULL, Loc());
5162 sa->push(s);
5163 if (fbody)
5164 sa->push(fbody);
5165 fbody = new CompoundStatement(Loc(), sa);
5166 }
5167
5168 FuncDeclaration::semantic(sc);
5169
5170 // We're going to need ModuleInfo
5171 Module *m = getModule();
5172 if (!m)
5173 m = sc->_module;
5174 if (m)
5175 {
5176 m->needmoduleinfo = 1;
5177 //printf("module1 %s needs moduleinfo\n", m->toChars());
5178 }
5179 }
5180
isThis()5181 AggregateDeclaration *StaticCtorDeclaration::isThis()
5182 {
5183 return NULL;
5184 }
5185
isVirtual()5186 bool StaticCtorDeclaration::isVirtual()
5187 {
5188 return false;
5189 }
5190
hasStaticCtorOrDtor()5191 bool StaticCtorDeclaration::hasStaticCtorOrDtor()
5192 {
5193 return true;
5194 }
5195
addPreInvariant()5196 bool StaticCtorDeclaration::addPreInvariant()
5197 {
5198 return false;
5199 }
5200
addPostInvariant()5201 bool StaticCtorDeclaration::addPostInvariant()
5202 {
5203 return false;
5204 }
5205
5206 /********************************* SharedStaticCtorDeclaration ****************************/
5207
SharedStaticCtorDeclaration(Loc loc,Loc endloc,StorageClass stc)5208 SharedStaticCtorDeclaration::SharedStaticCtorDeclaration(Loc loc, Loc endloc, StorageClass stc)
5209 : StaticCtorDeclaration(loc, endloc, "_sharedStaticCtor", stc)
5210 {
5211 }
5212
syntaxCopy(Dsymbol * s)5213 Dsymbol *SharedStaticCtorDeclaration::syntaxCopy(Dsymbol *s)
5214 {
5215 assert(!s);
5216 SharedStaticCtorDeclaration *scd = new SharedStaticCtorDeclaration(loc, endloc, storage_class);
5217 return FuncDeclaration::syntaxCopy(scd);
5218 }
5219
5220 /********************************* StaticDtorDeclaration ****************************/
5221
StaticDtorDeclaration(Loc loc,Loc endloc,StorageClass stc)5222 StaticDtorDeclaration::StaticDtorDeclaration(Loc loc, Loc endloc, StorageClass stc)
5223 : FuncDeclaration(loc, endloc,
5224 Identifier::generateId("_staticDtor"), STCstatic | stc, NULL)
5225 {
5226 vgate = NULL;
5227 }
5228
StaticDtorDeclaration(Loc loc,Loc endloc,const char * name,StorageClass stc)5229 StaticDtorDeclaration::StaticDtorDeclaration(Loc loc, Loc endloc, const char *name, StorageClass stc)
5230 : FuncDeclaration(loc, endloc,
5231 Identifier::generateId(name), STCstatic | stc, NULL)
5232 {
5233 vgate = NULL;
5234 }
5235
syntaxCopy(Dsymbol * s)5236 Dsymbol *StaticDtorDeclaration::syntaxCopy(Dsymbol *s)
5237 {
5238 assert(!s);
5239 StaticDtorDeclaration *sdd = new StaticDtorDeclaration(loc, endloc, storage_class);
5240 return FuncDeclaration::syntaxCopy(sdd);
5241 }
5242
semantic(Scope * sc)5243 void StaticDtorDeclaration::semantic(Scope *sc)
5244 {
5245 if (semanticRun >= PASSsemanticdone)
5246 return;
5247 if (_scope)
5248 {
5249 sc = _scope;
5250 _scope = NULL;
5251 }
5252
5253 parent = sc->parent;
5254 Dsymbol *p = parent->pastMixin();
5255 if (!p->isScopeDsymbol())
5256 {
5257 const char *s = (isSharedStaticDtorDeclaration() ? "shared " : "");
5258 ::error(loc, "%sstatic destructor can only be member of module/aggregate/template, not %s %s",
5259 s, p->kind(), p->toChars());
5260 type = Type::terror;
5261 errors = true;
5262 return;
5263 }
5264 if (!type)
5265 type = new TypeFunction(NULL, Type::tvoid, false, LINKd, storage_class);
5266
5267 /* If the static ctor appears within a template instantiation,
5268 * it could get called multiple times by the module constructors
5269 * for different modules. Thus, protect it with a gate.
5270 */
5271 if (isInstantiated() && semanticRun < PASSsemantic)
5272 {
5273 /* Add this prefix to the function:
5274 * static int gate;
5275 * if (--gate != 0) return;
5276 * Increment gate during constructor execution.
5277 * Note that this is not thread safe; should not have threads
5278 * during static destruction.
5279 */
5280 VarDeclaration *v = new VarDeclaration(Loc(), Type::tint32, Id::gate, NULL);
5281 v->storage_class = STCtemp | (isSharedStaticDtorDeclaration() ? STCstatic : STCtls);
5282 Statements *sa = new Statements();
5283 Statement *s = new ExpStatement(Loc(), v);
5284 sa->push(s);
5285 Expression *e = new IdentifierExp(Loc(), v->ident);
5286 e = new AddAssignExp(Loc(), e, new IntegerExp(-1));
5287 e = new EqualExp(TOKnotequal, Loc(), e, new IntegerExp(0));
5288 s = new IfStatement(Loc(), NULL, e, new ReturnStatement(Loc(), NULL), NULL, Loc());
5289 sa->push(s);
5290 if (fbody)
5291 sa->push(fbody);
5292 fbody = new CompoundStatement(Loc(), sa);
5293 vgate = v;
5294 }
5295
5296 FuncDeclaration::semantic(sc);
5297
5298 // We're going to need ModuleInfo
5299 Module *m = getModule();
5300 if (!m)
5301 m = sc->_module;
5302 if (m)
5303 {
5304 m->needmoduleinfo = 1;
5305 //printf("module2 %s needs moduleinfo\n", m->toChars());
5306 }
5307 }
5308
isThis()5309 AggregateDeclaration *StaticDtorDeclaration::isThis()
5310 {
5311 return NULL;
5312 }
5313
isVirtual()5314 bool StaticDtorDeclaration::isVirtual()
5315 {
5316 return false;
5317 }
5318
hasStaticCtorOrDtor()5319 bool StaticDtorDeclaration::hasStaticCtorOrDtor()
5320 {
5321 return true;
5322 }
5323
addPreInvariant()5324 bool StaticDtorDeclaration::addPreInvariant()
5325 {
5326 return false;
5327 }
5328
addPostInvariant()5329 bool StaticDtorDeclaration::addPostInvariant()
5330 {
5331 return false;
5332 }
5333
5334 /********************************* SharedStaticDtorDeclaration ****************************/
5335
SharedStaticDtorDeclaration(Loc loc,Loc endloc,StorageClass stc)5336 SharedStaticDtorDeclaration::SharedStaticDtorDeclaration(Loc loc, Loc endloc, StorageClass stc)
5337 : StaticDtorDeclaration(loc, endloc, "_sharedStaticDtor", stc)
5338 {
5339 }
5340
syntaxCopy(Dsymbol * s)5341 Dsymbol *SharedStaticDtorDeclaration::syntaxCopy(Dsymbol *s)
5342 {
5343 assert(!s);
5344 SharedStaticDtorDeclaration *sdd = new SharedStaticDtorDeclaration(loc, endloc, storage_class);
5345 return FuncDeclaration::syntaxCopy(sdd);
5346 }
5347
5348 /********************************* InvariantDeclaration ****************************/
5349
InvariantDeclaration(Loc loc,Loc endloc,StorageClass stc,Identifier * id)5350 InvariantDeclaration::InvariantDeclaration(Loc loc, Loc endloc, StorageClass stc, Identifier *id)
5351 : FuncDeclaration(loc, endloc,
5352 id ? id : Identifier::generateId("__invariant"),
5353 stc, NULL)
5354 {
5355 }
5356
syntaxCopy(Dsymbol * s)5357 Dsymbol *InvariantDeclaration::syntaxCopy(Dsymbol *s)
5358 {
5359 assert(!s);
5360 InvariantDeclaration *id = new InvariantDeclaration(loc, endloc, storage_class);
5361 return FuncDeclaration::syntaxCopy(id);
5362 }
5363
semantic(Scope * sc)5364 void InvariantDeclaration::semantic(Scope *sc)
5365 {
5366 if (semanticRun >= PASSsemanticdone)
5367 return;
5368 if (_scope)
5369 {
5370 sc = _scope;
5371 _scope = NULL;
5372 }
5373
5374 parent = sc->parent;
5375 Dsymbol *p = parent->pastMixin();
5376 AggregateDeclaration *ad = p->isAggregateDeclaration();
5377 if (!ad)
5378 {
5379 ::error(loc, "invariant can only be a member of aggregate, not %s %s",
5380 p->kind(), p->toChars());
5381 type = Type::terror;
5382 errors = true;
5383 return;
5384 }
5385 if (ident != Id::classInvariant &&
5386 semanticRun < PASSsemantic &&
5387 !ad->isUnionDeclaration() // users are on their own with union fields
5388 )
5389 ad->invs.push(this);
5390 if (!type)
5391 type = new TypeFunction(NULL, Type::tvoid, false, LINKd, storage_class);
5392
5393 sc = sc->push();
5394 sc->stc &= ~STCstatic; // not a static invariant
5395 sc->stc |= STCconst; // invariant() is always const
5396 sc->flags = (sc->flags & ~SCOPEcontract) | SCOPEinvariant;
5397 sc->linkage = LINKd;
5398
5399 FuncDeclaration::semantic(sc);
5400
5401 sc->pop();
5402 }
5403
isVirtual()5404 bool InvariantDeclaration::isVirtual()
5405 {
5406 return false;
5407 }
5408
addPreInvariant()5409 bool InvariantDeclaration::addPreInvariant()
5410 {
5411 return false;
5412 }
5413
addPostInvariant()5414 bool InvariantDeclaration::addPostInvariant()
5415 {
5416 return false;
5417 }
5418
5419 /********************************* UnitTestDeclaration ****************************/
5420
5421 /*******************************
5422 * Generate unique unittest function Id so we can have multiple
5423 * instances per module.
5424 */
5425
unitTestId(Loc loc)5426 static Identifier *unitTestId(Loc loc)
5427 {
5428 OutBuffer buf;
5429 buf.printf("__unittestL%u_", loc.linnum);
5430 return Identifier::generateId(buf.peekString());
5431 }
5432
UnitTestDeclaration(Loc loc,Loc endloc,StorageClass stc,char * codedoc)5433 UnitTestDeclaration::UnitTestDeclaration(Loc loc, Loc endloc, StorageClass stc, char *codedoc)
5434 : FuncDeclaration(loc, endloc, unitTestId(loc), stc, NULL)
5435 {
5436 this->codedoc = codedoc;
5437 }
5438
syntaxCopy(Dsymbol * s)5439 Dsymbol *UnitTestDeclaration::syntaxCopy(Dsymbol *s)
5440 {
5441 assert(!s);
5442 UnitTestDeclaration *utd = new UnitTestDeclaration(loc, endloc, storage_class, codedoc);
5443 return FuncDeclaration::syntaxCopy(utd);
5444 }
5445
semantic(Scope * sc)5446 void UnitTestDeclaration::semantic(Scope *sc)
5447 {
5448 if (semanticRun >= PASSsemanticdone)
5449 return;
5450 if (_scope)
5451 {
5452 sc = _scope;
5453 _scope = NULL;
5454 }
5455
5456 protection = sc->protection;
5457
5458 parent = sc->parent;
5459 Dsymbol *p = parent->pastMixin();
5460 if (!p->isScopeDsymbol())
5461 {
5462 ::error(loc, "unittest can only be a member of module/aggregate/template, not %s %s",
5463 p->kind(), p->toChars());
5464 type = Type::terror;
5465 errors = true;
5466 return;
5467 }
5468
5469 if (global.params.useUnitTests)
5470 {
5471 if (!type)
5472 type = new TypeFunction(NULL, Type::tvoid, false, LINKd, storage_class);
5473 Scope *sc2 = sc->push();
5474 sc2->linkage = LINKd;
5475 FuncDeclaration::semantic(sc2);
5476 sc2->pop();
5477 }
5478 }
5479
isThis()5480 AggregateDeclaration *UnitTestDeclaration::isThis()
5481 {
5482 return NULL;
5483 }
5484
isVirtual()5485 bool UnitTestDeclaration::isVirtual()
5486 {
5487 return false;
5488 }
5489
addPreInvariant()5490 bool UnitTestDeclaration::addPreInvariant()
5491 {
5492 return false;
5493 }
5494
addPostInvariant()5495 bool UnitTestDeclaration::addPostInvariant()
5496 {
5497 return false;
5498 }
5499
5500 /********************************* NewDeclaration ****************************/
5501
NewDeclaration(Loc loc,Loc endloc,StorageClass stc,Parameters * fparams,int varargs)5502 NewDeclaration::NewDeclaration(Loc loc, Loc endloc, StorageClass stc, Parameters *fparams, int varargs)
5503 : FuncDeclaration(loc, endloc, Id::classNew, STCstatic | stc, NULL)
5504 {
5505 this->parameters = fparams;
5506 this->varargs = varargs;
5507 }
5508
syntaxCopy(Dsymbol * s)5509 Dsymbol *NewDeclaration::syntaxCopy(Dsymbol *s)
5510 {
5511 assert(!s);
5512 NewDeclaration *f = new NewDeclaration(loc, endloc,
5513 storage_class, Parameter::arraySyntaxCopy(parameters), varargs);
5514 return FuncDeclaration::syntaxCopy(f);
5515 }
5516
semantic(Scope * sc)5517 void NewDeclaration::semantic(Scope *sc)
5518 {
5519 //printf("NewDeclaration::semantic()\n");
5520 if (semanticRun >= PASSsemanticdone)
5521 return;
5522 if (_scope)
5523 {
5524 sc = _scope;
5525 _scope = NULL;
5526 }
5527
5528 parent = sc->parent;
5529 Dsymbol *p = parent->pastMixin();
5530 if (!p->isAggregateDeclaration())
5531 {
5532 ::error(loc, "allocator can only be a member of aggregate, not %s %s",
5533 p->kind(), p->toChars());
5534 type = Type::terror;
5535 errors = true;
5536 return;
5537 }
5538 Type *tret = Type::tvoid->pointerTo();
5539 if (!type)
5540 type = new TypeFunction(parameters, tret, varargs, LINKd, storage_class);
5541
5542 type = type->semantic(loc, sc);
5543
5544 // Check that there is at least one argument of type size_t
5545 TypeFunction *tf = type->toTypeFunction();
5546 if (Parameter::dim(tf->parameters) < 1)
5547 {
5548 error("at least one argument of type size_t expected");
5549 }
5550 else
5551 {
5552 Parameter *fparam = Parameter::getNth(tf->parameters, 0);
5553 if (!fparam->type->equals(Type::tsize_t))
5554 error("first argument must be type size_t, not %s", fparam->type->toChars());
5555 }
5556
5557 FuncDeclaration::semantic(sc);
5558 }
5559
kind()5560 const char *NewDeclaration::kind() const
5561 {
5562 return "allocator";
5563 }
5564
isVirtual()5565 bool NewDeclaration::isVirtual()
5566 {
5567 return false;
5568 }
5569
addPreInvariant()5570 bool NewDeclaration::addPreInvariant()
5571 {
5572 return false;
5573 }
5574
addPostInvariant()5575 bool NewDeclaration::addPostInvariant()
5576 {
5577 return false;
5578 }
5579
5580 /********************************* DeleteDeclaration ****************************/
5581
DeleteDeclaration(Loc loc,Loc endloc,StorageClass stc,Parameters * fparams)5582 DeleteDeclaration::DeleteDeclaration(Loc loc, Loc endloc, StorageClass stc, Parameters *fparams)
5583 : FuncDeclaration(loc, endloc, Id::classDelete, STCstatic | stc, NULL)
5584 {
5585 this->parameters = fparams;
5586 }
5587
syntaxCopy(Dsymbol * s)5588 Dsymbol *DeleteDeclaration::syntaxCopy(Dsymbol *s)
5589 {
5590 assert(!s);
5591 DeleteDeclaration *f = new DeleteDeclaration(loc, endloc,
5592 storage_class, Parameter::arraySyntaxCopy(parameters));
5593 return FuncDeclaration::syntaxCopy(f);
5594 }
5595
semantic(Scope * sc)5596 void DeleteDeclaration::semantic(Scope *sc)
5597 {
5598 //printf("DeleteDeclaration::semantic()\n");
5599 if (semanticRun >= PASSsemanticdone)
5600 return;
5601 if (_scope)
5602 {
5603 sc = _scope;
5604 _scope = NULL;
5605 }
5606
5607 parent = sc->parent;
5608 Dsymbol *p = parent->pastMixin();
5609 if (!p->isAggregateDeclaration())
5610 {
5611 ::error(loc, "deallocator can only be a member of aggregate, not %s %s",
5612 p->kind(), p->toChars());
5613 type = Type::terror;
5614 errors = true;
5615 return;
5616 }
5617 if (!type)
5618 type = new TypeFunction(parameters, Type::tvoid, 0, LINKd, storage_class);
5619
5620 type = type->semantic(loc, sc);
5621
5622 // Check that there is only one argument of type void*
5623 TypeFunction *tf = type->toTypeFunction();
5624 if (Parameter::dim(tf->parameters) != 1)
5625 {
5626 error("one argument of type void* expected");
5627 }
5628 else
5629 {
5630 Parameter *fparam = Parameter::getNth(tf->parameters, 0);
5631 if (!fparam->type->equals(Type::tvoid->pointerTo()))
5632 error("one argument of type void* expected, not %s", fparam->type->toChars());
5633 }
5634
5635 FuncDeclaration::semantic(sc);
5636 }
5637
kind()5638 const char *DeleteDeclaration::kind() const
5639 {
5640 return "deallocator";
5641 }
5642
isDelete()5643 bool DeleteDeclaration::isDelete()
5644 {
5645 return true;
5646 }
5647
isVirtual()5648 bool DeleteDeclaration::isVirtual()
5649 {
5650 return false;
5651 }
5652
addPreInvariant()5653 bool DeleteDeclaration::addPreInvariant()
5654 {
5655 return false;
5656 }
5657
addPostInvariant()5658 bool DeleteDeclaration::addPostInvariant()
5659 {
5660 return false;
5661 }
5662