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 33Expression *addInvariant(Loc loc, Scope *sc, AggregateDeclaration *ad, VarDeclaration *vthis, bool direct); 34bool checkReturnEscape(Scope *sc, Expression *e, bool gag); 35bool checkReturnEscapeRef(Scope *sc, Expression *e, bool gag); 36bool checkNestedRef(Dsymbol *s, Dsymbol *p); 37Statement *semantic(Statement *s, Scope *sc); 38void semantic(Catch *c, Scope *sc); 39Expression *resolve(Loc loc, Scope *sc, Dsymbol *s, bool hasOverloads); 40Expression *semantic(Expression *e, Scope *sc); 41int blockExit(Statement *s, FuncDeclaration *func, bool mustNotThrow); 42TypeIdentifier *getThrowable(); 43 44RET retStyle(TypeFunction *tf); 45void MODtoBuffer(OutBuffer *buf, MOD mod); 46char *MODtoChars(MOD mod); 47bool MODimplicitConv(MOD modfrom, MOD modto); 48MATCH MODmethodConv(MOD modfrom, MOD modto); 49void allocFieldinit(Scope *sc, size_t dim); 50void freeFieldinit(Scope *sc); 51Objc *objc(); 52 53 54/* A visitor to walk entire statements and provides ability to replace any sub-statements. 55 */ 56class 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; 62public: 63 void visitStmt(Statement *&s) { ps = &s; s->accept(this); } 64 void replaceCurrent(Statement *s) { *ps = s; } 65 66 void visit(ErrorStatement *) { } 67 void visit(PeelStatement *s) 68 { 69 if (s->s) 70 visitStmt(s->s); 71 } 72 void visit(ExpStatement *) { } 73 void visit(DtorExpStatement *) { } 74 void visit(CompileStatement *) { } 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 } 86 void visit(CompoundDeclarationStatement *s) { visit((CompoundStatement *)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 } 98 void visit(ScopeStatement *s) 99 { 100 if (s->statement) 101 visitStmt(s->statement); 102 } 103 void visit(WhileStatement *s) 104 { 105 if (s->_body) 106 visitStmt(s->_body); 107 } 108 void visit(DoStatement *s) 109 { 110 if (s->_body) 111 visitStmt(s->_body); 112 } 113 void visit(ForStatement *s) 114 { 115 if (s->_init) 116 visitStmt(s->_init); 117 if (s->_body) 118 visitStmt(s->_body); 119 } 120 void visit(ForeachStatement *s) 121 { 122 if (s->_body) 123 visitStmt(s->_body); 124 } 125 void visit(ForeachRangeStatement *s) 126 { 127 if (s->_body) 128 visitStmt(s->_body); 129 } 130 void visit(IfStatement *s) 131 { 132 if (s->ifbody) 133 visitStmt(s->ifbody); 134 if (s->elsebody) 135 visitStmt(s->elsebody); 136 } 137 void visit(ConditionalStatement *) { } 138 void visit(PragmaStatement *) { } 139 void visit(StaticAssertStatement *) { } 140 void visit(SwitchStatement *s) 141 { 142 if (s->_body) 143 visitStmt(s->_body); 144 } 145 void visit(CaseStatement *s) 146 { 147 if (s->statement) 148 visitStmt(s->statement); 149 } 150 void visit(CaseRangeStatement *s) 151 { 152 if (s->statement) 153 visitStmt(s->statement); 154 } 155 void visit(DefaultStatement *s) 156 { 157 if (s->statement) 158 visitStmt(s->statement); 159 } 160 void visit(GotoDefaultStatement *) { } 161 void visit(GotoCaseStatement *) { } 162 void visit(SwitchErrorStatement *) { } 163 void visit(ReturnStatement *) { } 164 void visit(BreakStatement *) { } 165 void visit(ContinueStatement *) { } 166 void visit(SynchronizedStatement *s) 167 { 168 if (s->_body) 169 visitStmt(s->_body); 170 } 171 void visit(WithStatement *s) 172 { 173 if (s->_body) 174 visitStmt(s->_body); 175 } 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 } 190 void visit(TryFinallyStatement *s) 191 { 192 if (s->_body) 193 visitStmt(s->_body); 194 if (s->finalbody) 195 visitStmt(s->finalbody); 196 } 197 void visit(OnScopeStatement *) { } 198 void visit(ThrowStatement *) { } 199 void visit(DebugStatement *s) 200 { 201 if (s->statement) 202 visitStmt(s->statement); 203 } 204 void visit(GotoStatement *) { } 205 void visit(LabelStatement *s) 206 { 207 if (s->statement) 208 visitStmt(s->statement); 209 } 210 void visit(AsmStatement *) { } 211 void visit(ImportStatement *) { } 212}; 213 214/* Tweak all return statements and dtor call for nrvo_var, for correct NRVO. 215 */ 216class NrvoWalker : public StatementRewriteWalker 217{ 218public: 219 FuncDeclaration *fd; 220 Scope *sc; 221 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 } 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 298FuncDeclaration::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 365FuncDeclaration *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 370Dsymbol *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 */ 390static 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 */ 421static 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 447void 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 1190Ldone: 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 1227void 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 */ 1252static 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 */ 1276static 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 */ 1345static 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 1355void 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 */ 2375bool 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 */ 2429bool 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 */ 2460bool 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 2479VarDeclaration *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 2547bool 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 2585void 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 2628Statement *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 2708Statement *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 2782int 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 2810int 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 */ 2895BaseClass *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 2913bool 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 2968int 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 3043FuncDeclaration *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 3075FuncDeclaration *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 3119void 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 */ 3160FuncDeclaration *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 */ 3273bool 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 3290TemplateDeclaration *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 3312MATCH 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. 3374struct 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 3384 static int fp(void *param, Dsymbol *) 3385 { 3386 CountWalker *p = (CountWalker *)param; 3387 ++(p->numOverloads); 3388 return 0; 3389 } 3390 }; 3391 3392 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. 3420struct 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 3430 static int fp(void *param, Dsymbol *) 3431 { 3432 CountWalker *p = (CountWalker *)param; 3433 ++(p->numOverloads); 3434 return 0; 3435 } 3436 }; 3437 3438 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 3485FuncDeclaration *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 3629LabelDsymbol *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 3654int 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 3703Lerr: 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 3716const 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' */ 3725const char *FuncDeclaration::toFullSignature() 3726{ 3727 OutBuffer buf; 3728 functionToBufferWithIdent(type->toTypeFunction(), &buf, toChars()); 3729 return buf.extractString(); 3730} 3731 3732bool FuncDeclaration::isMain() 3733{ 3734 return ident == Id::main && 3735 linkage != LINKc && !isMember() && !isNested(); 3736} 3737 3738bool FuncDeclaration::isCMain() 3739{ 3740 return ident == Id::main && 3741 linkage == LINKc && !isMember() && !isNested(); 3742} 3743 3744bool FuncDeclaration::isWinMain() 3745{ 3746 //printf("FuncDeclaration::isWinMain() %s\n", toChars()); 3747 return ident == Id::WinMain && 3748 linkage != LINKc && !isMember(); 3749} 3750 3751bool FuncDeclaration::isDllMain() 3752{ 3753 return ident == Id::DllMain && 3754 linkage != LINKc && !isMember(); 3755} 3756 3757bool FuncDeclaration::isExport() const 3758{ 3759 return protection.kind == PROTexport; 3760} 3761 3762bool 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 3771bool 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 3785bool 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 3801bool 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 3812bool FuncDeclaration::isCodeseg() const 3813{ 3814 return true; // functions are always in the code segment 3815} 3816 3817bool FuncDeclaration::isOverloadable() 3818{ 3819 return true; // functions can be overloaded 3820} 3821 3822PURE 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 3849PURE 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 */ 3862bool 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 3875bool FuncDeclaration::isSafe() 3876{ 3877 if (flags & FUNCFLAGsafetyInprocess) 3878 setUnsafe(); 3879 return type->toTypeFunction()->trust == TRUSTsafe; 3880} 3881 3882bool FuncDeclaration::isSafeBypassingInference() 3883{ 3884 return !(flags & FUNCFLAGsafetyInprocess) && isSafe(); 3885} 3886 3887bool 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 */ 3899bool 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 3913bool FuncDeclaration::isNogc() 3914{ 3915 if (flags & FUNCFLAGnogcInprocess) 3916 setGC(); 3917 return type->toTypeFunction()->isnogc; 3918} 3919 3920bool 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 */ 3931bool 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 3949Type *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 */ 3973bool 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 4043bool 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 4060bool 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 */ 4103bool 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 */ 4120AggregateDeclaration *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 4128bool FuncDeclaration::needThis() 4129{ 4130 //printf("FuncDeclaration::needThis() '%s'\n", toChars()); 4131 return toAliasFunc()->isThis() != NULL; 4132} 4133 4134bool 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 4144bool 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 */ 4164Expression *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 4229FuncDeclaration *FuncDeclaration::genCfunc(Parameters *fparams, Type *treturn, const char *name, StorageClass stc) 4230{ 4231 return genCfunc(fparams, treturn, Identifier::idPool(name), stc); 4232} 4233 4234FuncDeclaration *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 */ 4270void 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 4296const 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 */ 4310bool 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 */ 4385void 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 */ 4409bool 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 4456bool 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 4534Lyes: 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 */ 4547bool 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 4611bool 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 4644Parameters *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 4665FuncAliasDeclaration::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 4686const char *FuncAliasDeclaration::kind() const 4687{ 4688 return "function alias"; 4689} 4690 4691FuncDeclaration *FuncAliasDeclaration::toAliasFunc() 4692{ 4693 return funcalias->toAliasFunc(); 4694} 4695 4696 4697/****************************** FuncLiteralDeclaration ************************/ 4698 4699FuncLiteralDeclaration::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 4711Dsymbol *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 4721bool FuncLiteralDeclaration::isNested() 4722{ 4723 //printf("FuncLiteralDeclaration::isNested() '%s'\n", toChars()); 4724 return (tok != TOKfunction) && !isThis(); 4725} 4726 4727AggregateDeclaration *FuncLiteralDeclaration::isThis() 4728{ 4729 //printf("FuncLiteralDeclaration::isThis() '%s'\n", toChars()); 4730 return tok == TOKdelegate ? FuncDeclaration::isThis() : NULL; 4731} 4732 4733bool FuncLiteralDeclaration::isVirtual() 4734{ 4735 return false; 4736} 4737 4738bool FuncLiteralDeclaration::addPreInvariant() 4739{ 4740 return false; 4741} 4742 4743bool 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 */ 4759void 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 4797const char *FuncLiteralDeclaration::kind() const 4798{ 4799 return (tok != TOKfunction) ? "delegate" : "function"; 4800} 4801 4802const 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 4815CtorDeclaration::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 4821Dsymbol *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 4828void 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 4909const char *CtorDeclaration::kind() const 4910{ 4911 return "constructor"; 4912} 4913 4914const char *CtorDeclaration::toChars() 4915{ 4916 return "this"; 4917} 4918 4919bool CtorDeclaration::isVirtual() 4920{ 4921 return false; 4922} 4923 4924bool CtorDeclaration::addPreInvariant() 4925{ 4926 return false; 4927} 4928 4929bool CtorDeclaration::addPostInvariant() 4930{ 4931 return (isThis() && vthis && global.params.useInvariants); 4932} 4933 4934 4935/********************************* PostBlitDeclaration ****************************/ 4936 4937PostBlitDeclaration::PostBlitDeclaration(Loc loc, Loc endloc, StorageClass stc, Identifier *id) 4938 : FuncDeclaration(loc, endloc, id, stc, NULL) 4939{ 4940} 4941 4942Dsymbol *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 4949void 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 4987bool PostBlitDeclaration::overloadInsert(Dsymbol *) 4988{ 4989 return false; // cannot overload postblits 4990} 4991 4992bool PostBlitDeclaration::addPreInvariant() 4993{ 4994 return false; 4995} 4996 4997bool PostBlitDeclaration::addPostInvariant() 4998{ 4999 return (isThis() && vthis && global.params.useInvariants); 5000} 5001 5002bool PostBlitDeclaration::isVirtual() 5003{ 5004 return false; 5005} 5006 5007/********************************* DtorDeclaration ****************************/ 5008 5009DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc) 5010 : FuncDeclaration(loc, endloc, Id::dtor, STCundefined, NULL) 5011{ 5012} 5013 5014DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc, StorageClass stc, Identifier *id) 5015 : FuncDeclaration(loc, endloc, id, stc, NULL) 5016{ 5017} 5018 5019Dsymbol *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 5026void 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 5064bool DtorDeclaration::overloadInsert(Dsymbol *) 5065{ 5066 return false; // cannot overload destructors 5067} 5068 5069bool DtorDeclaration::addPreInvariant() 5070{ 5071 return (isThis() && vthis && global.params.useInvariants); 5072} 5073 5074bool DtorDeclaration::addPostInvariant() 5075{ 5076 return false; 5077} 5078 5079const char *DtorDeclaration::kind() const 5080{ 5081 return "destructor"; 5082} 5083 5084const char *DtorDeclaration::toChars() 5085{ 5086 return "~this"; 5087} 5088 5089bool DtorDeclaration::isVirtual() 5090{ 5091 // false so that dtor's don't get put into the vtbl[] 5092 return false; 5093} 5094 5095/********************************* StaticCtorDeclaration ****************************/ 5096 5097StaticCtorDeclaration::StaticCtorDeclaration(Loc loc, Loc endloc, StorageClass stc) 5098 : FuncDeclaration(loc, endloc, 5099 Identifier::generateId("_staticCtor"), STCstatic | stc, NULL) 5100{ 5101} 5102 5103StaticCtorDeclaration::StaticCtorDeclaration(Loc loc, Loc endloc, const char *name, StorageClass stc) 5104 : FuncDeclaration(loc, endloc, 5105 Identifier::generateId(name), STCstatic | stc, NULL) 5106{ 5107} 5108 5109Dsymbol *StaticCtorDeclaration::syntaxCopy(Dsymbol *s) 5110{ 5111 assert(!s); 5112 StaticCtorDeclaration *scd = new StaticCtorDeclaration(loc, endloc, storage_class); 5113 return FuncDeclaration::syntaxCopy(scd); 5114} 5115 5116void 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 5181AggregateDeclaration *StaticCtorDeclaration::isThis() 5182{ 5183 return NULL; 5184} 5185 5186bool StaticCtorDeclaration::isVirtual() 5187{ 5188 return false; 5189} 5190 5191bool StaticCtorDeclaration::hasStaticCtorOrDtor() 5192{ 5193 return true; 5194} 5195 5196bool StaticCtorDeclaration::addPreInvariant() 5197{ 5198 return false; 5199} 5200 5201bool StaticCtorDeclaration::addPostInvariant() 5202{ 5203 return false; 5204} 5205 5206/********************************* SharedStaticCtorDeclaration ****************************/ 5207 5208SharedStaticCtorDeclaration::SharedStaticCtorDeclaration(Loc loc, Loc endloc, StorageClass stc) 5209 : StaticCtorDeclaration(loc, endloc, "_sharedStaticCtor", stc) 5210{ 5211} 5212 5213Dsymbol *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 5222StaticDtorDeclaration::StaticDtorDeclaration(Loc loc, Loc endloc, StorageClass stc) 5223 : FuncDeclaration(loc, endloc, 5224 Identifier::generateId("_staticDtor"), STCstatic | stc, NULL) 5225{ 5226 vgate = NULL; 5227} 5228 5229StaticDtorDeclaration::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 5236Dsymbol *StaticDtorDeclaration::syntaxCopy(Dsymbol *s) 5237{ 5238 assert(!s); 5239 StaticDtorDeclaration *sdd = new StaticDtorDeclaration(loc, endloc, storage_class); 5240 return FuncDeclaration::syntaxCopy(sdd); 5241} 5242 5243void 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 5309AggregateDeclaration *StaticDtorDeclaration::isThis() 5310{ 5311 return NULL; 5312} 5313 5314bool StaticDtorDeclaration::isVirtual() 5315{ 5316 return false; 5317} 5318 5319bool StaticDtorDeclaration::hasStaticCtorOrDtor() 5320{ 5321 return true; 5322} 5323 5324bool StaticDtorDeclaration::addPreInvariant() 5325{ 5326 return false; 5327} 5328 5329bool StaticDtorDeclaration::addPostInvariant() 5330{ 5331 return false; 5332} 5333 5334/********************************* SharedStaticDtorDeclaration ****************************/ 5335 5336SharedStaticDtorDeclaration::SharedStaticDtorDeclaration(Loc loc, Loc endloc, StorageClass stc) 5337 : StaticDtorDeclaration(loc, endloc, "_sharedStaticDtor", stc) 5338{ 5339} 5340 5341Dsymbol *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 5350InvariantDeclaration::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 5357Dsymbol *InvariantDeclaration::syntaxCopy(Dsymbol *s) 5358{ 5359 assert(!s); 5360 InvariantDeclaration *id = new InvariantDeclaration(loc, endloc, storage_class); 5361 return FuncDeclaration::syntaxCopy(id); 5362} 5363 5364void 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 5404bool InvariantDeclaration::isVirtual() 5405{ 5406 return false; 5407} 5408 5409bool InvariantDeclaration::addPreInvariant() 5410{ 5411 return false; 5412} 5413 5414bool 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 5426static Identifier *unitTestId(Loc loc) 5427{ 5428 OutBuffer buf; 5429 buf.printf("__unittestL%u_", loc.linnum); 5430 return Identifier::generateId(buf.peekString()); 5431} 5432 5433UnitTestDeclaration::UnitTestDeclaration(Loc loc, Loc endloc, StorageClass stc, char *codedoc) 5434 : FuncDeclaration(loc, endloc, unitTestId(loc), stc, NULL) 5435{ 5436 this->codedoc = codedoc; 5437} 5438 5439Dsymbol *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 5446void 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 5480AggregateDeclaration *UnitTestDeclaration::isThis() 5481{ 5482 return NULL; 5483} 5484 5485bool UnitTestDeclaration::isVirtual() 5486{ 5487 return false; 5488} 5489 5490bool UnitTestDeclaration::addPreInvariant() 5491{ 5492 return false; 5493} 5494 5495bool UnitTestDeclaration::addPostInvariant() 5496{ 5497 return false; 5498} 5499 5500/********************************* NewDeclaration ****************************/ 5501 5502NewDeclaration::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 5509Dsymbol *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 5517void 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 5560const char *NewDeclaration::kind() const 5561{ 5562 return "allocator"; 5563} 5564 5565bool NewDeclaration::isVirtual() 5566{ 5567 return false; 5568} 5569 5570bool NewDeclaration::addPreInvariant() 5571{ 5572 return false; 5573} 5574 5575bool NewDeclaration::addPostInvariant() 5576{ 5577 return false; 5578} 5579 5580/********************************* DeleteDeclaration ****************************/ 5581 5582DeleteDeclaration::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 5588Dsymbol *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 5596void 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 5638const char *DeleteDeclaration::kind() const 5639{ 5640 return "deallocator"; 5641} 5642 5643bool DeleteDeclaration::isDelete() 5644{ 5645 return true; 5646} 5647 5648bool DeleteDeclaration::isVirtual() 5649{ 5650 return false; 5651} 5652 5653bool DeleteDeclaration::addPreInvariant() 5654{ 5655 return false; 5656} 5657 5658bool DeleteDeclaration::addPostInvariant() 5659{ 5660 return false; 5661} 5662