1: // Compiler implementation of the D programming language
   2: // Copyright (c) 1999-2011 by Digital Mars
   3: // All Rights Reserved
   4: // written by Walter Bright
   5: // http://www.digitalmars.com
   6: // License for redistribution is by either the Artistic License
   7: // in artistic.txt, or the GNU General Public License in gnu.txt.
   8: // See the included readme.txt for details.
   9: 
  10: #include <stdio.h>
  11: static char __file__[] = __FILE__;      /* for tassert.h                */
  12: #include        "tassert.h"
  13: 
  14: #include "mars.h"
  15: #include "init.h"
  16: #include "declaration.h"
  17: #include "attrib.h"
  18: #include "expression.h"
  19: #include "scope.h"
  20: #include "mtype.h"
  21: #include "aggregate.h"
  22: #include "identifier.h"
  23: #include "id.h"
  24: #include "module.h"
  25: #include "statement.h"
  26: #include "template.h"
  27: #include "hdrgen.h"
  28: 
  29: #ifdef IN_GCC
  30: #include "d-dmd-gcc.h"
  31: #endif
  32: 
  33: /********************************* FuncDeclaration ****************************/
  34: 
  35: FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageClass storage_class, Type *type)
  36:     : Declaration(id)
  37: {
  38:     //printf("FuncDeclaration(id = '%s', type = %p)\n", id->toChars(), type);
  39:     //printf("storage_class = x%x\n", storage_class);
  40:     this->storage_class = storage_class;
  41:     this->type = type;
  42:     this->loc = loc;
  43:     this->endloc = endloc;
  44:     fthrows = NULL;
  45:     frequire = NULL;
  46:     fdrequire = NULL;
  47:     fdensure = NULL;
  48:     outId = NULL;
  49:     vresult = NULL;
  50:     returnLabel = NULL;
  51:     fensure = NULL;
  52:     fbody = NULL;
  53:     localsymtab = NULL;
  54:     vthis = NULL;
  55:     v_arguments = NULL;
  56: #if IN_GCC
  57:     v_argptr = NULL;
  58: #endif
  59:     v_argsave = NULL;
  60:     parameters = NULL;
  61:     labtab = NULL;
  62:     overnext = NULL;
  63:     vtblIndex = -1;
  64:     hasReturnExp = 0;
  65:     naked = 0;
  66:     inlineStatus = ILSuninitialized;
  67:     inlineNest = 0;
  68:     cantInterpret = 0;
  69:     isArrayOp = 0;
  70:     semanticRun = PASSinit;
  71: #if DMDV1
  72:     nestedFrameRef = 0;
  73: #endif
  74:     fes = NULL;
  75:     introducing = 0;
  76:     tintro = NULL;
  77:     /* The type given for "infer the return type" is a TypeFunction with
  78:      * NULL for the return type.
  79:      */
  80:     inferRetType = (type && type->nextOf() == NULL);
  81:     hasReturnExp = 0;
  82:     nrvo_can = 1;
  83:     nrvo_var = NULL;
  84:     shidden = NULL;
  85: #if DMDV2
  86:     builtin = BUILTINunknown;
  87:     tookAddressOf = 0;
  88:     flags = 0;
  89: #endif
  90: }
  91: 
  92: Dsymbol *FuncDeclaration::syntaxCopy(Dsymbol *s)
  93: {
  94:     FuncDeclaration *f;
  95: 
  96:     //printf("FuncDeclaration::syntaxCopy('%s')\n", toChars());
  97:     if (s)
  98:         f = (FuncDeclaration *)s;
  99:     else
 100:         f = new FuncDeclaration(loc, endloc, ident, storage_class, type->syntaxCopy());
 101:     f->outId = outId;
 102:     f->frequire = frequire ? frequire->syntaxCopy() : NULL;
 103:     f->fensure  = fensure  ? fensure->syntaxCopy()  : NULL;
 104:     f->fbody    = fbody    ? fbody->syntaxCopy()    : NULL;
 105:     assert(!fthrows); // deprecated
 106:     return f;
 107: }
 108: 
 109: 
 110: // Do the semantic analysis on the external interface to the function.
 111: 
 112: void FuncDeclaration::semantic(Scope *sc)
 113: {   TypeFunction *f;
 114:     AggregateDeclaration *ad;
 115:     StructDeclaration *sd;
 116:     ClassDeclaration *cd;
 117:     InterfaceDeclaration *id;
 118:     Dsymbol *pd;
 119: 
 120: #if 0
 121:     printf("FuncDeclaration::semantic(sc = %p, this = %p, '%s', linkage = %d)\n", sc, this, toPrettyChars(), sc->linkage);
 122:     if (isFuncLiteralDeclaration())
 123:         printf("\tFuncLiteralDeclaration()\n");
 124:     printf("sc->parent = %s, parent = %s\n", sc->parent->toChars(), parent ? parent->toChars() : "");
 125:     printf("type: %p, %s\n", type, type->toChars());
 126: #endif
 127: 
 128:     if (semanticRun != PASSinit && isFuncLiteralDeclaration())
 129:     {
 130:         /* Member functions that have return types that are
 131:          * forward references can have semantic() run more than
 132:          * once on them.
 133:          * See test\interface2.d, test20
 134:          */
 135:         return;
 136:     }
 137: 
 138:     parent = sc->parent;
 139:     Dsymbol *parent = toParent();
 140: 
 141:     if (semanticRun >= PASSsemanticdone)
 142:     {
 143:         if (!parent->isClassDeclaration())
 144:         {
 145:             return;
 146:         }
 147:         // need to re-run semantic() in order to set the class's vtbl[]
 148:     }
 149:     else
 150:     {
 151:         assert(semanticRun <= PASSsemantic);
 152:         semanticRun = PASSsemantic;
 153:     }
 154: 
 155:     unsigned dprogress_save = Module::dprogress;
 156: 
 157:     foverrides.setDim(0);       // reset in case semantic() is being retried for this function
 158: 
 159:     storage_class |= sc->stc & ~STCref;
 160:     ad = isThis();
 161:     if (ad)
 162:         storage_class |= ad->storage_class & (STC_TYPECTOR | STCsynchronized);
 163: 
 164:     //printf("function storage_class = x%llx, sc->stc = x%llx, %x\n", storage_class, sc->stc, Declaration::isFinal());
 165: 
 166:     if (!originalType)
 167:         originalType = type;
 168:     if (!type->deco)
 169:     {
 170:         sc = sc->push();
 171:         sc->stc |= storage_class & (STCref | STCnothrow | STCpure | STCdisable
 172:             | STCsafe | STCtrusted | STCsystem | STCproperty);      // forward to function type
 173: 
 174:         if (isCtorDeclaration())
 175:             sc->flags |= SCOPEctor;
 176:         type = type->semantic(loc, sc);
 177:         sc = sc->pop();
 178: 
 179:         /* Apply const, immutable and shared storage class
 180:          * to the function type
 181:          */
 182:         StorageClass stc = storage_class;
 183:         if (type->isImmutable())
 184:             stc |= STCimmutable;
 185:         if (type->isConst())
 186:             stc |= STCconst;
 187:         if (type->isShared() || storage_class & STCsynchronized)
 188:             stc |= STCshared;
 189:         if (type->isWild())
 190:             stc |= STCwild;
 191:         switch (stc & STC_TYPECTOR)
 192:         {
 193:             case STCimmutable:
 194:             case STCimmutable | STCconst:
 195:             case STCimmutable | STCconst | STCshared:
 196:             case STCimmutable | STCshared:
 197:             case STCimmutable | STCwild:
 198:             case STCimmutable | STCconst | STCwild:
 199:             case STCimmutable | STCconst | STCshared | STCwild:
 200:             case STCimmutable | STCshared | STCwild:
 201:                 // Don't use toInvariant(), as that will do a merge()
 202:                 type = type->makeInvariant();
 203:                 goto Lmerge;
 204: 
 205:             case STCconst:
 206:             case STCconst | STCwild:
 207:                 type = type->makeConst();
 208:                 goto Lmerge;
 209: 
 210:             case STCshared | STCconst:
 211:             case STCshared | STCconst | STCwild:
 212:                 type = type->makeSharedConst();
 213:                 goto Lmerge;
 214: 
 215:             case STCshared:
 216:                 type = type->makeShared();
 217:                 goto Lmerge;
 218: 
 219:             case STCwild:
 220:                 type = type->makeWild();
 221:                 goto Lmerge;
 222: 
 223:             case STCshared | STCwild:
 224:                 type = type->makeSharedWild();
 225:                 goto Lmerge;
 226: 
 227:             Lmerge:
 228:                 if (!(type->ty == Tfunction && !type->nextOf()))
 229:                     /* Can't do merge if return type is not known yet
 230:                      */
 231:                     type->deco = type->merge()->deco;
 232:                 break;
 233: 
 234:             case 0:
 235:                 break;
 236: 
 237:             default:
 238:                 assert(0);
 239:         }
 240:     }
 241:     storage_class &= ~STCref;
 242:     if (type->ty != Tfunction)
 243:     {
 244:         error("%s must be a function instead of %s", toChars(), type->toChars());
 245:         return;
 246:     }
 247:     f = (TypeFunction *)(type);
 248:     size_t nparams = Parameter::dim(f->parameters);
 249: 
 250:     linkage = sc->linkage;
 251:     protection = sc->protection;
 252: 
 253:     /* Purity and safety can be inferred for some functions by examining
 254:      * the function body.
 255:      */
 256:     if (fbody &&
 257:         (isFuncLiteralDeclaration() || parent->isTemplateInstance()))
 258:     {
 259:         if (f->purity == PUREimpure &&      // purity not specified
 260:             !f->hasLazyParameters()
 261:            )
 262:         {
 263:             flags |= FUNCFLAGpurityInprocess;
 264:         }
 265:         if (f->trust == TRUSTdefault)
 266:             flags |= FUNCFLAGsafetyInprocess;
 267: 
 268:         if (!f->isnothrow)
 269:             flags |= FUNCFLAGnothrowInprocess;
 270:     }
 271: 
 272:     if (storage_class & STCscope)
 273:         error("functions cannot be scope");
 274: 
 275:     if (isAbstract() && !isVirtual())
 276:         error("non-virtual functions cannot be abstract");
 277: 
 278:     if ((f->isConst() || f->isImmutable()) && !isThis())
 279:         error("without 'this' cannot be const/immutable");
 280: 
 281:     if (isAbstract() && isFinal())
 282:         error("cannot be both final and abstract");
 283: #if 0
 284:     if (isAbstract() && fbody)
 285:         error("abstract functions cannot have bodies");
 286: #endif
 287: 
 288: #if 0
 289:     if (isStaticConstructor() || isStaticDestructor())
 290:     {
 291:         if (!isStatic() || type->nextOf()->ty != Tvoid)
 292:             error("static constructors / destructors must be static void");
 293:         if (f->arguments && f->arguments->dim)
 294:             error("static constructors / destructors must have empty parameter list");
 295:         // BUG: check for invalid storage classes
 296:     }
 297: #endif
 298: 
 299: #ifdef IN_GCC
 300:     {
 301:         AggregateDeclaration *ad = parent->isAggregateDeclaration();
 302:         if (ad)
 303:             ad->methods.push(this);
 304:     }
 305: #endif
 306:     sd = parent->isStructDeclaration();
 307:     if (sd)
 308:     {
 309:         if (isCtorDeclaration())
 310:         {
 311:             goto Ldone;
 312:         }
 313: #if 0
 314:         // Verify no constructors, destructors, etc.
 315:         if (isCtorDeclaration()
 316:             //||isDtorDeclaration()
 317:             //|| isInvariantDeclaration()
 318:             //|| isUnitTestDeclaration()
 319:            )
 320:         {
 321:             error("special member functions not allowed for %ss", sd->kind());
 322:         }
 323: 
 324:         if (!sd->inv)
 325:             sd->inv = isInvariantDeclaration();
 326: 
 327:         if (!sd->aggNew)
 328:             sd->aggNew = isNewDeclaration();
 329: 
 330:         if (isDelete())
 331:         {
 332:             if (sd->aggDelete)
 333:                 error("multiple delete's for struct %s", sd->toChars());
 334:             sd->aggDelete = (DeleteDeclaration *)(this);
 335:         }
 336: #endif
 337:     }
 338: 
 339:     id = parent->isInterfaceDeclaration();
 340:     if (id)
 341:     {
 342:         storage_class |= STCabstract;
 343: 
 344:         if (isCtorDeclaration() ||
 345: #if DMDV2
 346:             isPostBlitDeclaration() ||
 347: #endif
 348:             isDtorDeclaration() ||
 349:             isInvariantDeclaration() ||
 350:             isUnitTestDeclaration() || isNewDeclaration() || isDelete())
 351:             error("constructors, destructors, postblits, invariants, unittests, new and delete functions are not allowed in interface %s", id->toChars());
 352:         if (fbody && isVirtual())
 353:             error("function body is not abstract in interface %s", id->toChars());
 354:     }
 355: 
 356:     /* Contracts can only appear without a body when they are virtual interface functions
 357:      */
 358:     if (!fbody && (fensure || frequire) && !(id && isVirtual()))
 359:         error("in and out contracts require function body");
 360: 
 361:     /* Template member functions aren't virtual:
 362:      *   interface TestInterface { void tpl(T)(); }
 363:      * and so won't work in interfaces
 364:      */
 365:     if ((pd = toParent()) != NULL &&
 366:         pd->isTemplateInstance() &&
 367:         (pd = toParent2()) != NULL &&
 368:         (id = pd->isInterfaceDeclaration()) != NULL)
 369:     {
 370:         error("template member functions are not allowed in interface %s", id->toChars());
 371:     }
 372: 
 373:     cd = parent->isClassDeclaration();
 374:     if (cd)
 375:     {   int vi;
 376:         CtorDeclaration *ctor;
warning C4101: 'ctor' : unreferenced local variable
377: DtorDeclaration *dtor;
warning C4101: 'dtor' : unreferenced local variable
378: InvariantDeclaration *inv;
warning C4101: 'inv' : unreferenced local variable
379: 380: if (isCtorDeclaration()) 381: { 382: // ctor = (CtorDeclaration *)this; 383: // if (!cd->ctor) 384: // cd->ctor = ctor; 385: return; 386: } 387: 388: #if 0 389: dtor = isDtorDeclaration(); 390: if (dtor) 391: { 392: if (cd->dtor) 393: error("multiple destructors for class %s", cd->toChars()); 394: cd->dtor = dtor; 395: } 396: 397: inv = isInvariantDeclaration(); 398: if (inv) 399: { 400: cd->inv = inv; 401: } 402: 403: if (isNewDeclaration()) 404: { 405: if (!cd->aggNew) 406: cd->aggNew = (NewDeclaration *)(this); 407: } 408: 409: if (isDelete()) 410: { 411: if (cd->aggDelete) 412: error("multiple delete's for class %s", cd->toChars()); 413: cd->aggDelete = (DeleteDeclaration *)(this); 414: } 415: #endif 416: 417: if (storage_class & STCabstract) 418: cd->isabstract = 1; 419: 420: // if static function, do not put in vtbl[] 421: if (!isVirtual()) 422: { 423: //printf("\tnot virtual\n"); 424: goto Ldone; 425: } 426: 427: /* Find index of existing function in base class's vtbl[] to override 428: * (the index will be the same as in cd's current vtbl[]) 429: */ 430: vi = cd->baseClass ? findVtblIndex((Dsymbols*)&cd->baseClass->vtbl, cd->baseClass->vtbl.dim) 431: : -1; 432: 433: switch (vi) 434: { 435: case -1: 436: /* Didn't find one, so 437: * This is an 'introducing' function which gets a new 438: * slot in the vtbl[]. 439: */ 440: 441: // Verify this doesn't override previous final function 442: if (cd->baseClass) 443: { Dsymbol *s = cd->baseClass->search(loc, ident, 0); 444: if (s) 445: { 446: FuncDeclaration *f = s->isFuncDeclaration();
warning C6246: Local declaration of 'f' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '113' of 'c:\projects\extern\d\dmd\src\func.c': Lines: 113
447: f = f->overloadExactMatch(type); 448: if (f && f->isFinal() && f->prot() != PROTprivate) 449: error("cannot override final function %s", f->toPrettyChars()); 450: } 451: } 452: 453: if (isFinal()) 454: { 455: if (isOverride()) 456: error("is marked as override, but does not override any function"); 457: cd->vtblFinal.push(this); 458: } 459: else 460: { 461: // Append to end of vtbl[] 462: //printf("\tintroducing function\n"); 463: introducing = 1; 464: vi = cd->vtbl.dim; 465: cd->vtbl.push(this); 466: vtblIndex = vi; 467: } 468: break; 469: 470: case -2: // can't determine because of fwd refs 471: cd->sizeok = 2; // can't finish due to forward reference 472: Module::dprogress = dprogress_save; 473: return; 474: 475: default: 476: { FuncDeclaration *fdv = (FuncDeclaration *)cd->baseClass->vtbl.tdata()[vi]; 477: // This function is covariant with fdv 478: if (fdv->isFinal()) 479: error("cannot override final function %s", fdv->toPrettyChars()); 480: 481: #if DMDV2 482: if (!isOverride()) 483: warning(loc, "overrides base class function %s, but is not marked with 'override'", fdv->toPrettyChars()); 484: #endif 485: 486: if (fdv->toParent() == parent) 487: { 488: // If both are mixins, then error. 489: // If either is not, the one that is not overrides 490: // the other. 491: if (fdv->parent->isClassDeclaration()) 492: break; 493: if (!this->parent->isClassDeclaration() 494: #if !BREAKABI 495: && !isDtorDeclaration() 496: #endif 497: #if DMDV2 498: && !isPostBlitDeclaration() 499: #endif 500: ) 501: error("multiple overrides of same function"); 502: } 503: cd->vtbl.tdata()[vi] = this; 504: vtblIndex = vi; 505: 506: /* Remember which functions this overrides 507: */ 508: foverrides.push(fdv); 509: 510: /* This works by whenever this function is called, 511: * it actually returns tintro, which gets dynamically 512: * cast to type. But we know that tintro is a base 513: * of type, so we could optimize it by not doing a 514: * dynamic cast, but just subtracting the isBaseOf() 515: * offset if the value is != null. 516: */ 517: 518: if (fdv->tintro) 519: tintro = fdv->tintro; 520: else if (!type->equals(fdv->type)) 521: { 522: /* Only need to have a tintro if the vptr 523: * offsets differ 524: */ 525: int offset; 526: if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset)) 527: { 528: tintro = fdv->type; 529: } 530: } 531: break; 532: } 533: } 534: 535: /* Go through all the interface bases. 536: * If this function is covariant with any members of those interface 537: * functions, set the tintro. 538: */ 539: for (int i = 0; i < cd->interfaces_dim; i++) 540: { 541: BaseClass *b = cd->interfaces[i]; 542: vi = findVtblIndex((Dsymbols *)&b->base->vtbl, b->base->vtbl.dim); 543: switch (vi) 544: { 545: case -1: 546: break; 547: 548: case -2: 549: cd->sizeok = 2; // can't finish due to forward reference 550: Module::dprogress = dprogress_save; 551: return; 552: 553: default: 554: { FuncDeclaration *fdv = (FuncDeclaration *)b->base->vtbl.tdata()[vi]; 555: Type *ti = NULL; 556: 557: /* Remember which functions this overrides 558: */ 559: foverrides.push(fdv); 560: 561: if (fdv->tintro) 562: ti = fdv->tintro; 563: else if (!type->equals(fdv->type)) 564: { 565: /* Only need to have a tintro if the vptr 566: * offsets differ 567: */ 568: unsigned errors = global.errors; 569: global.gag++; // suppress printing of error messages 570: int offset; 571: int baseOf = fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset); 572: global.gag--; // suppress printing of error messages 573: if (errors != global.errors) 574: { 575: // any error in isBaseOf() is a forward reference error, so we bail out 576: global.errors = errors; 577: cd->sizeok = 2; // can't finish due to forward reference 578: Module::dprogress = dprogress_save; 579: return; 580: } 581: if (baseOf) 582: { 583: ti = fdv->type; 584: } 585: } 586: if (ti) 587: { 588: if (tintro && !tintro->equals(ti)) 589: { 590: error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars()); 591: } 592: tintro = ti; 593: } 594: goto L2; 595: } 596: } 597: } 598: 599: if (introducing && isOverride()) 600: { 601: error("does not override any function"); 602: } 603: 604: L2: ; 605: 606: /* Go through all the interface bases. 607: * Disallow overriding any final functions in the interface(s). 608: */ 609: for (int i = 0; i < cd->interfaces_dim; i++) 610: { 611: BaseClass *b = cd->interfaces[i]; 612: if (b->base) 613: { 614: Dsymbol *s = search_function(b->base, ident); 615: if (s) 616: { 617: FuncDeclaration *f = s->isFuncDeclaration();
warning C6246: Local declaration of 'f' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '113' of 'c:\projects\extern\d\dmd\src\func.c': Lines: 113
618: if (f) 619: { 620: f = f->overloadExactMatch(type); 621: if (f && f->isFinal() && f->prot() != PROTprivate) 622: error("cannot override final function %s.%s", b->base->toChars(), f->toPrettyChars()); 623: } 624: } 625: } 626: } 627: } 628: else if (isOverride() && !parent->isTemplateInstance()) 629: error("override only applies to class member functions"); 630: 631: /* Do not allow template instances to add virtual functions 632: * to a class. 633: */ 634: if (isVirtual()) 635: { 636: TemplateInstance *ti = parent->isTemplateInstance(); 637: if (ti) 638: { 639: // Take care of nested templates 640: while (1) 641: { 642: TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance(); 643: if (!ti2) 644: break; 645: ti = ti2; 646: } 647: 648: // If it's a member template 649: ClassDeclaration *cd = ti->tempdecl->isClassMember();
warning C6246: Local declaration of 'cd' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '116' of 'c:\projects\extern\d\dmd\src\func.c': Lines: 116
650: if (cd) 651: { 652: error("cannot use template to add virtual function to class '%s'", cd->toChars()); 653: } 654: } 655: } 656: 657: if (isMain()) 658: { 659: // Check parameters to see if they are either () or (char[][] args) 660: switch (nparams) 661: { 662: case 0: 663: break; 664: 665: case 1: 666: { 667: Parameter *arg0 = Parameter::getNth(f->parameters, 0); 668: if (arg0->type->ty != Tarray || 669: arg0->type->nextOf()->ty != Tarray || 670: arg0->type->nextOf()->nextOf()->ty != Tchar || 671: arg0->storageClass & (STCout | STCref | STClazy)) 672: goto Lmainerr; 673: break; 674: } 675: 676: default: 677: goto Lmainerr; 678: } 679: 680: if (!f->nextOf()) 681: error("must return int or void"); 682: else if (f->nextOf()->ty != Tint32 && f->nextOf()->ty != Tvoid) 683: error("must return int or void, not %s", f->nextOf()->toChars()); 684: if (f->varargs) 685: { 686: Lmainerr: 687: error("parameters must be main() or main(string[] args)"); 688: } 689: } 690: 691: if (ident == Id::assign && (sd || cd)) 692: { // Disallow identity assignment operator. 693: 694: // opAssign(...) 695: if (nparams == 0) 696: { if (f->varargs == 1) 697: goto Lassignerr; 698: } 699: else 700: { 701: Parameter *arg0 = Parameter::getNth(f->parameters, 0); 702: Type *t0 = arg0->type->toBasetype(); 703: Type *tb = sd ? sd->type : cd->type; 704: if (arg0->type->implicitConvTo(tb) || 705: (sd && t0->ty == Tpointer && t0->nextOf()->implicitConvTo(tb)) 706: ) 707: { 708: if (nparams == 1) 709: goto Lassignerr; 710: Parameter *arg1 = Parameter::getNth(f->parameters, 1); 711: if (arg1->defaultArg) 712: goto Lassignerr; 713: } 714: } 715: } 716: 717: if (isVirtual() && semanticRun != PASSsemanticdone) 718: { 719: /* Rewrite contracts as nested functions, then call them. 720: * Doing it as nested functions means that overriding functions 721: * can call them. 722: */ 723: if (frequire) 724: { /* in { ... } 725: * becomes: 726: * void __require() { ... } 727: * __require(); 728: */ 729: Loc loc = frequire->loc; 730: TypeFunction *tf = new TypeFunction(NULL, Type::tvoid, 0, LINKd); 731: FuncDeclaration *fd = new FuncDeclaration(loc, loc, 732: Id::require, STCundefined, tf); 733: fd->fbody = frequire; 734: Statement *s1 = new ExpStatement(loc, fd);
warning C6211: Leaking memory 's1' due to an exception. Consider using a local catch block to clean up memory: Lines: 113, 114, 115, 116, 117, 118, 128, 138, 139, 141, 151, 152, 155, 157, 159, 160, 161, 162, 166, 168, 170, 171, 174, 175, 176, 177, 182, 183, 184, 185, 186, 187, 189, 190, 191, 193, 194, 195, 196, 197, 198, 199, 200, 202, 203, 227, 228, 241, 242, 247, 248, 250, 251, 256, 272, 273, 275, 276, 278, 281, 282, 306, 307, 309, 339, 340, 342, 350, 352, 353, 358, 367, 373, 374, 375, 376, 377, 378, 380, 417, 418, 421, 430, 433, 435, 442, 453, 455, 456, 457, 539, 599, 604, 609, 634, 636, 637, 640, 642, 643, 649, 650, 652, 657, 660, 662, 680, 681, 684, 686, 687, 691, 717, 723, 729, 730, 731, 733, 734, 735
735: Expression *e = new CallExp(loc, new VarExp(loc, fd, 0), (Expressions *)NULL); 736: Statement *s2 = new ExpStatement(loc, e); 737: frequire = new CompoundStatement(loc, s1, s2); 738: fdrequire = fd; 739: } 740: 741: if (!outId && f->nextOf() && f->nextOf()->toBasetype()->ty != Tvoid) 742: outId = Id::result; // provide a default 743: 744: if (fensure) 745: { /* out (result) { ... } 746: * becomes: 747: * tret __ensure(ref tret result) { ... } 748: * __ensure(result); 749: */ 750: Loc loc = fensure->loc; 751: Parameters *arguments = new Parameters();
warning C6211: Leaking memory 'arguments' due to an exception. Consider using a local catch block to clean up memory: Lines: 113, 114, 115, 116, 117, 118, 128, 138, 139, 141, 151, 152, 155, 157, 159, 160, 161, 162, 166, 168, 170, 171, 174, 175, 176, 177, 182, 183, 184, 185, 186, 187, 189, 190, 191, 193, 194, 195, 196, 197, 198, 199, 200, 202, 203, 227, 228, 241, 242, 247, 248, 250, 251, 256, 272, 273, 275, 276, 278, 281, 282, 306, 307, 309, 339, 340, 342, 350, 352, 353, 358, 367, 373, 374, 375, 376, 377, 378, 380, 417, 418, 421, 430, 433, 435, 442, 453, 455, 456, 457, 539, 599, 604, 609, 634, 636, 637, 640, 642, 643, 649, 650, 652, 657, 660, 662, 680, 681, 684, 686, 687, 691, 717, 723, 729, 730, 731, 733, 734, 735, 736, 737, 738, 741, 744, 750, 751, 752, 753, 754
752: Parameter *a = NULL; 753: if (outId) 754: { a = new Parameter(STCref | STCconst, f->nextOf(), outId, NULL); 755: arguments->push(a); 756: } 757: TypeFunction *tf = new TypeFunction(arguments, Type::tvoid, 0, LINKd); 758: FuncDeclaration *fd = new FuncDeclaration(loc, loc, 759: Id::ensure, STCundefined, tf); 760: fd->fbody = fensure; 761: Statement *s1 = new ExpStatement(loc, fd); 762: Expression *eresult = NULL; 763: if (outId) 764: eresult = new IdentifierExp(loc, outId); 765: Expression *e = new CallExp(loc, new VarExp(loc, fd, 0), eresult); 766: Statement *s2 = new ExpStatement(loc, e); 767: fensure = new CompoundStatement(loc, s1, s2); 768: fdensure = fd; 769: } 770: } 771: 772: Ldone: 773: Module::dprogress++; 774: semanticRun = PASSsemanticdone; 775: 776: /* Save scope for possible later use (if we need the 777: * function internals) 778: */ 779: scope = new Scope(*sc); 780: scope->setNoFree(); 781: return; 782: 783: Lassignerr: 784: if (sd) 785: { 786: sd->hasIdentityAssign = 1; // don't need to generate it 787: goto Ldone; 788: } 789: error("identity assignment operator overload is illegal"); 790: } 791: 792: void FuncDeclaration::semantic2(Scope *sc) 793: { 794: } 795: 796: // Do the semantic analysis on the internals of the function. 797: 798: void FuncDeclaration::semantic3(Scope *sc) 799: { TypeFunction *f; 800: VarDeclaration *argptr = NULL; 801: VarDeclaration *_arguments = NULL; 802: int nerrors = global.errors; 803: 804: if (!parent) 805: { 806: if (global.errors) 807: return; 808: //printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc); 809: assert(0); 810: } 811: //printf("FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars()); 812: //fflush(stdout); 813: //printf("storage class = x%x %x\n", sc->stc, storage_class); 814: //{ static int x; if (++x == 2) *(char*)0=0; } 815: //printf("\tlinkage = %d\n", sc->linkage); 816: 817: //printf(" sc->incontract = %d\n", sc->incontract); 818: if (semanticRun >= PASSsemantic3) 819: return; 820: semanticRun = PASSsemantic3; 821: 822: if (!type || type->ty != Tfunction) 823: return; 824: f = (TypeFunction *)(type); 825: 826: #if 0 827: // Check the 'throws' clause 828: if (fthrows) 829: { 830: for (int i = 0; i < fthrows->dim; i++) 831: { 832: Type *t = fthrows->tdata()[i]; 833: 834: t = t->semantic(loc, sc); 835: if (!t->isClassHandle()) 836: error("can only throw classes, not %s", t->toChars()); 837: } 838: } 839: #endif 840: 841: if (frequire) 842: { 843: for (int i = 0; i < foverrides.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
844: { 845: FuncDeclaration *fdv = foverrides.tdata()[i]; 846: 847: if (fdv->fbody && !fdv->frequire) 848: { 849: error("cannot have an in contract when overriden function %s does not have an in contract", fdv->toPrettyChars()); 850: break; 851: } 852: } 853: } 854: 855: frequire = mergeFrequire(frequire); 856: fensure = mergeFensure(fensure); 857: 858: if (fbody || frequire || fensure) 859: { 860: /* Symbol table into which we place parameters and nested functions, 861: * solely to diagnose name collisions. 862: */ 863: localsymtab = new DsymbolTable(); 864: 865: // Establish function scope 866: ScopeDsymbol *ss = new ScopeDsymbol(); 867: ss->parent = sc->scopesym; 868: Scope *sc2 = sc->push(ss); 869: sc2->func = this; 870: sc2->parent = this; 871: sc2->callSuper = 0; 872: sc2->sbreak = NULL; 873: sc2->scontinue = NULL; 874: sc2->sw = NULL; 875: sc2->fes = fes; 876: sc2->linkage = LINKd; 877: sc2->stc &= ~(STCauto | STCscope | STCstatic | STCabstract | STCdeprecated | 878: STC_TYPECTOR | STCfinal | STCtls | STCgshared | STCref | 879: STCproperty | STCsafe | STCtrusted | STCsystem); 880: sc2->protection = PROTpublic; 881: sc2->explicitProtection = 0; 882: sc2->structalign = 8; 883: sc2->incontract = 0; 884: sc2->tf = NULL; 885: sc2->noctor = 0; 886: 887: // Declare 'this' 888: AggregateDeclaration *ad = isThis(); 889: if (ad) 890: { VarDeclaration *v; 891: 892: if (isFuncLiteralDeclaration() && isNested() && !sc->intypeof) 893: { 894: error("function literals cannot be class members"); 895: return; 896: } 897: else 898: { 899: assert(!isNested() || sc->intypeof); // can't be both member and nested 900: assert(ad->handle); 901: Type *thandle = ad->handle; 902: #if STRUCTTHISREF 903: thandle = thandle->addMod(type->mod); 904: thandle = thandle->addStorageClass(storage_class); 905: //if (isPure()) 906: //thandle = thandle->addMod(MODconst); 907: #else 908: if (storage_class & STCconst || type->isConst()) 909: { 910: assert(0); // BUG: shared not handled 911: if (thandle->ty == Tclass) 912: thandle = thandle->constOf(); 913: else 914: { assert(thandle->ty == Tpointer); 915: thandle = thandle->nextOf()->constOf()->pointerTo(); 916: } 917: } 918: else if (storage_class & STCimmutable || type->isImmutable()) 919: { 920: if (thandle->ty == Tclass) 921: thandle = thandle->invariantOf(); 922: else 923: { assert(thandle->ty == Tpointer); 924: thandle = thandle->nextOf()->invariantOf()->pointerTo(); 925: } 926: } 927: else if (storage_class & STCshared || type->isShared()) 928: { 929: assert(0); // not implemented 930: } 931: #endif 932: v = new ThisDeclaration(loc, thandle); 933: //v = new ThisDeclaration(loc, isCtorDeclaration() ? ad->handle : thandle); 934: v->storage_class |= STCparameter; 935: #if STRUCTTHISREF 936: if (thandle->ty == Tstruct) 937: v->storage_class |= STCref; 938: #endif 939: v->semantic(sc2); 940: if (!sc2->insert(v)) 941: assert(0); 942: v->parent = this; 943: vthis = v; 944: } 945: } 946: else if (isNested()) 947: { 948: /* The 'this' for a nested function is the link to the 949: * enclosing function's stack frame. 950: * Note that nested functions and member functions are disjoint. 951: */ 952: VarDeclaration *v = new ThisDeclaration(loc, Type::tvoid->pointerTo()); 953: v->storage_class |= STCparameter; 954: v->semantic(sc2); 955: if (!sc2->insert(v)) 956: assert(0); 957: v->parent = this; 958: vthis = v; 959: } 960: 961: // Declare hidden variable _arguments[] and _argptr 962: if (f->varargs == 1) 963: { 964: #if TARGET_NET 965: varArgs(sc2, f, argptr, _arguments); 966: #else 967: Type *t; 968: 969: if (global.params.is64bit) 970: { // Declare save area for varargs registers 971: Type *t = new TypeIdentifier(loc, Id::va_argsave_t);
warning C6246: Local declaration of 't' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '967' of 'c:\projects\extern\d\dmd\src\func.c': Lines: 967
972: t = t->semantic(loc, sc); 973: if (t == Type::terror) 974: error("must import core.vararg to use variadic functions"); 975: else 976: { 977: v_argsave = new VarDeclaration(loc, t, Id::va_argsave, NULL); 978: v_argsave->semantic(sc2); 979: sc2->insert(v_argsave); 980: v_argsave->parent = this; 981: } 982: } 983: 984: if (f->linkage == LINKd) 985: { // Declare _arguments[] 986: #if BREAKABI 987: v_arguments = new VarDeclaration(0, Type::typeinfotypelist->type, Id::_arguments_typeinfo, NULL); 988: v_arguments->storage_class = STCparameter; 989: v_arguments->semantic(sc2); 990: sc2->insert(v_arguments); 991: v_arguments->parent = this; 992: 993: //t = Type::typeinfo->type->constOf()->arrayOf(); 994: t = Type::typeinfo->type->arrayOf(); 995: _arguments = new VarDeclaration(0, t, Id::_arguments, NULL); 996: _arguments->semantic(sc2); 997: sc2->insert(_arguments); 998: _arguments->parent = this; 999: #else 1000: t = Type::typeinfo->type->arrayOf(); 1001: v_arguments = new VarDeclaration(0, t, Id::_arguments, NULL); 1002: v_arguments->storage_class = STCparameter | STCin; 1003: v_arguments->semantic(sc2); 1004: sc2->insert(v_arguments); 1005: v_arguments->parent = this; 1006: #endif 1007: } 1008: if (f->linkage == LINKd || (f->parameters && Parameter::dim(f->parameters))) 1009: { // Declare _argptr 1010: #if IN_GCC 1011: t = d_gcc_builtin_va_list_d_type; 1012: #else 1013: t = Type::tvoid->pointerTo(); 1014: #endif 1015: argptr = new VarDeclaration(0, t, Id::_argptr, NULL); 1016: argptr->semantic(sc2); 1017: sc2->insert(argptr); 1018: argptr->parent = this; 1019: } 1020: #endif 1021: } 1022: 1023: #if 0 1024: // Propagate storage class from tuple parameters to their element-parameters. 1025: if (f->parameters) 1026: { 1027: for (size_t i = 0; i < f->parameters->dim; i++) 1028: { Parameter *arg = f->parameters->tdata()[i]; 1029: 1030: //printf("[%d] arg->type->ty = %d %s\n", i, arg->type->ty, arg->type->toChars()); 1031: if (arg->type->ty == Ttuple) 1032: { TypeTuple *t = (TypeTuple *)arg->type; 1033: size_t dim = Parameter::dim(t->arguments); 1034: for (size_t j = 0; j < dim; j++) 1035: { Parameter *narg = Parameter::getNth(t->arguments, j); 1036: narg->storageClass = arg->storageClass; 1037: } 1038: } 1039: } 1040: } 1041: #endif 1042: 1043: /* Declare all the function parameters as variables 1044: * and install them in parameters[] 1045: */ 1046: size_t nparams = Parameter::dim(f->parameters); 1047: if (nparams) 1048: { /* parameters[] has all the tuples removed, as the back end 1049: * doesn't know about tuples 1050: */ 1051: parameters = new VarDeclarations(); 1052: parameters->reserve(nparams); 1053: for (size_t i = 0; i < nparams; i++) 1054: { 1055: Parameter *arg = Parameter::getNth(f->parameters, i); 1056: Identifier *id = arg->ident; 1057: if (!id) 1058: { 1059: /* Generate identifier for un-named parameter, 1060: * because we need it later on. 1061: */ 1062: arg->ident = id = Identifier::generateId("_param_", i); 1063: } 1064: Type *vtype = arg->type; 1065: //if (isPure()) 1066: //vtype = vtype->addMod(MODconst); 1067: VarDeclaration *v = new VarDeclaration(loc, vtype, id, NULL); 1068: //printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars()); 1069: v->storage_class |= STCparameter; 1070: if (f->varargs == 2 && i + 1 == nparams) 1071: v->storage_class |= STCvariadic; 1072: v->storage_class |= arg->storageClass & (STCin | STCout | STCref | STClazy | STCfinal | STC_TYPECTOR | STCnodtor); 1073: v->semantic(sc2); 1074: if (!sc2->insert(v)) 1075: error("parameter %s.%s is already defined", toChars(), v->toChars()); 1076: else 1077: parameters->push(v); 1078: localsymtab->insert(v); 1079: v->parent = this; 1080: } 1081: } 1082: 1083: // Declare the tuple symbols and put them in the symbol table, 1084: // but not in parameters[]. 1085: if (f->parameters) 1086: { 1087: for (size_t i = 0; i < f->parameters->dim; i++) 1088: { Parameter *arg = f->parameters->tdata()[i]; 1089: 1090: if (!arg->ident) 1091: continue; // never used, so ignore 1092: if (arg->type->ty == Ttuple) 1093: { TypeTuple *t = (TypeTuple *)arg->type; 1094: size_t dim = Parameter::dim(t->arguments); 1095: Objects *exps = new Objects(); 1096: exps->setDim(dim); 1097: for (size_t j = 0; j < dim; j++) 1098: { Parameter *narg = Parameter::getNth(t->arguments, j); 1099: assert(narg->ident); 1100: VarDeclaration *v = sc2->search(0, narg->ident, NULL)->isVarDeclaration(); 1101: assert(v); 1102: Expression *e = new VarExp(v->loc, v); 1103: exps->tdata()[j] = e; 1104: } 1105: assert(arg->ident); 1106: TupleDeclaration *v = new TupleDeclaration(loc, arg->ident, exps); 1107: //printf("declaring tuple %s\n", v->toChars()); 1108: v->isexp = 1; 1109: if (!sc2->insert(v)) 1110: error("parameter %s.%s is already defined", toChars(), v->toChars()); 1111: localsymtab->insert(v); 1112: v->parent = this; 1113: } 1114: } 1115: } 1116: 1117: /* Do the semantic analysis on the [in] preconditions and 1118: * [out] postconditions. 1119: */ 1120: sc2->incontract++; 1121: 1122: if (frequire) 1123: { /* frequire is composed of the [in] contracts 1124: */ 1125: // BUG: need to error if accessing out parameters 1126: // BUG: need to treat parameters as const 1127: // BUG: need to disallow returns and throws 1128: // BUG: verify that all in and ref parameters are read 1129: frequire = frequire->semantic(sc2); 1130: labtab = NULL; // so body can't refer to labels 1131: } 1132: 1133: if (fensure || addPostInvariant()) 1134: { /* fensure is composed of the [out] contracts 1135: */ 1136: if (!type->nextOf()) // if return type is inferred 1137: { /* This case: 1138: * auto fp = function() out { } body { }; 1139: * Can fix by doing semantic() onf fbody first. 1140: */ 1141: error("post conditions are not supported if the return type is inferred"); 1142: return; 1143: } 1144: 1145: ScopeDsymbol *sym = new ScopeDsymbol(); 1146: sym->parent = sc2->scopesym; 1147: sc2 = sc2->push(sym); 1148: 1149: assert(type->nextOf()); 1150: if (type->nextOf()->ty == Tvoid) 1151: { 1152: if (outId) 1153: error("void functions have no result"); 1154: } 1155: else 1156: { 1157: if (!outId) 1158: outId = Id::result; // provide a default 1159: } 1160: 1161: if (outId) 1162: { // Declare result variable 1163: Loc loc = this->loc; 1164: 1165: if (fensure) 1166: loc = fensure->loc; 1167: 1168: VarDeclaration *v = new VarDeclaration(loc, type->nextOf(), outId, NULL); 1169: v->noscope = 1; 1170: v->storage_class |= STCresult; 1171: #if DMDV2 1172: if (!isVirtual()) 1173: v->storage_class |= STCconst; 1174: if (f->isref) 1175: { 1176: v->storage_class |= STCref | STCforeach; 1177: } 1178: #endif 1179: sc2->incontract--; 1180: v->semantic(sc2); 1181: sc2->incontract++; 1182: if (!sc2->insert(v)) 1183: error("out result %s is already defined", v->toChars()); 1184: v->parent = this; 1185: vresult = v; 1186: 1187: // vresult gets initialized with the function return value 1188: // in ReturnStatement::semantic() 1189: } 1190: 1191: // BUG: need to treat parameters as const 1192: // BUG: need to disallow returns and throws 1193: if (fensure) 1194: { fensure = fensure->semantic(sc2); 1195: labtab = NULL; // so body can't refer to labels 1196: } 1197: 1198: if (!global.params.useOut) 1199: { fensure = NULL; // discard 1200: vresult = NULL; 1201: } 1202: 1203: // Postcondition invariant 1204: if (addPostInvariant()) 1205: { 1206: Expression *e = NULL; 1207: if (isCtorDeclaration()) 1208: { 1209: // Call invariant directly only if it exists 1210: InvariantDeclaration *inv = ad->inv; 1211: ClassDeclaration *cd = ad->isClassDeclaration(); 1212: 1213: while (!inv && cd) 1214: { 1215: cd = cd->baseClass; 1216: if (!cd) 1217: break; 1218: inv = cd->inv; 1219: } 1220: if (inv) 1221: { 1222: e = new DsymbolExp(0, inv); 1223: e = new CallExp(0, e); 1224: e = e->semantic(sc2); 1225: } 1226: } 1227: else 1228: { // Call invariant virtually 1229: Expression *v = new ThisExp(0); 1230: v->type = vthis->type; 1231: #if STRUCTTHISREF 1232: if (ad->isStructDeclaration()) 1233: v = v->addressOf(sc); 1234: #endif 1235: e = new AssertExp(0, v); 1236: } 1237: if (e) 1238: { 1239: ExpStatement *s = new ExpStatement(0, e); 1240: if (fensure) 1241: fensure = new CompoundStatement(0, s, fensure); 1242: else 1243: fensure = s; 1244: } 1245: } 1246: 1247: if (fensure) 1248: { returnLabel = new LabelDsymbol(Id::returnLabel); 1249: LabelStatement *ls = new LabelStatement(0, Id::returnLabel, fensure); 1250: returnLabel->statement = ls; 1251: } 1252: sc2 = sc2->pop(); 1253: } 1254: 1255: sc2->incontract--; 1256: 1257: if (fbody) 1258: { ClassDeclaration *cd = isClassMember(); 1259: 1260: /* If this is a class constructor 1261: */ 1262: if (isCtorDeclaration() && cd) 1263: { 1264: for (int i = 0; i < cd->fields.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1265: { VarDeclaration *v = cd->fields.tdata()[i]; 1266: 1267: v->ctorinit = 0; 1268: } 1269: } 1270: 1271: if (inferRetType || f->retStyle() != RETstack) 1272: nrvo_can = 0; 1273: 1274: fbody = fbody->semantic(sc2); 1275: if (!fbody) 1276: fbody = new CompoundStatement(0, new Statements()); 1277: 1278: if (inferRetType) 1279: { // If no return type inferred yet, then infer a void 1280: if (!type->nextOf()) 1281: { 1282: ((TypeFunction *)type)->next = Type::tvoid; 1283: type = type->semantic(loc, sc); 1284: } 1285: f = (TypeFunction *)type; 1286: } 1287: 1288: if (isStaticCtorDeclaration()) 1289: { /* It's a static constructor. Ensure that all 1290: * ctor consts were initialized. 1291: */ 1292: 1293: Dsymbol *p = toParent(); 1294: ScopeDsymbol *ad = p->isScopeDsymbol();
warning C6246: Local declaration of 'ad' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '888' of 'c:\projects\extern\d\dmd\src\func.c': Lines: 888
1295: if (!ad) 1296: { 1297: error("static constructor can only be member of struct/class/module, not %s %s", p->kind(), p->toChars()); 1298: } 1299: else 1300: { 1301: for (int i = 0; i < ad->members->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1302: { Dsymbol *s = ad->members->tdata()[i]; 1303: 1304: s->checkCtorConstInit(); 1305: } 1306: } 1307: } 1308: 1309: if (isCtorDeclaration() && cd) 1310: { 1311: //printf("callSuper = x%x\n", sc2->callSuper); 1312: 1313: // Verify that all the ctorinit fields got initialized 1314: if (!(sc2->callSuper & CSXthis_ctor)) 1315: { 1316: for (int i = 0; i < cd->fields.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1317: { VarDeclaration *v = cd->fields.tdata()[i]; 1318: 1319: if (v->ctorinit == 0 && v->isCtorinit() && !v->type->isMutable()) 1320: error("missing initializer for final field %s", v->toChars()); 1321: } 1322: } 1323: 1324: if (!(sc2->callSuper & CSXany_ctor) && 1325: cd->baseClass && cd->baseClass->ctor) 1326: { 1327: sc2->callSuper = 0; 1328: 1329: // Insert implicit super() at start of fbody 1330: Expression *e1 = new SuperExp(0); 1331: Expression *e = new CallExp(0, e1); 1332: 1333: e = e->trySemantic(sc2); 1334: if (!e) 1335: error("no match for implicit super() call in constructor"); 1336: else 1337: { 1338: Statement *s = new ExpStatement(0, e); 1339: fbody = new CompoundStatement(0, s, fbody); 1340: } 1341: } 1342: } 1343: else if (fes) 1344: { // For foreach(){} body, append a return 0; 1345: Expression *e = new IntegerExp(0); 1346: Statement *s = new ReturnStatement(0, e); 1347: fbody = new CompoundStatement(0, fbody, s); 1348: assert(!returnLabel); 1349: } 1350: else if (!hasReturnExp && type->nextOf()->ty != Tvoid) 1351: error("has no return statement, but is expected to return a value of type %s", type->nextOf()->toChars()); 1352: else if (hasReturnExp & 8) // if inline asm 1353: { 1354: flags &= ~FUNCFLAGnothrowInprocess; 1355: } 1356: else 1357: { 1358: #if DMDV2 1359: // Check for errors related to 'nothrow'. 1360: int nothrowErrors = global.errors; 1361: int blockexit = fbody ? fbody->blockExit(f->isnothrow) : BEfallthru; 1362: if (f->isnothrow && (global.errors != nothrowErrors) ) 1363: error("'%s' is nothrow yet may throw", toChars()); 1364: if (flags & FUNCFLAGnothrowInprocess) 1365: { 1366: flags &= ~FUNCFLAGnothrowInprocess; 1367: if (!(blockexit & BEthrow)) 1368: f->isnothrow = TRUE; 1369: } 1370: 1371: int offend = blockexit & BEfallthru; 1372: #endif 1373: if (type->nextOf()->ty == Tvoid) 1374: { 1375: if (offend && isMain()) 1376: { // Add a return 0; statement 1377: Statement *s = new ReturnStatement(0, new IntegerExp(0)); 1378: fbody = new CompoundStatement(0, fbody, s); 1379: } 1380: } 1381: else 1382: { 1383: if (offend) 1384: { Expression *e; 1385: #if DMDV1 1386: warning(loc, "no return exp; or assert(0); at end of function"); 1387: #else 1388: error("no return exp; or assert(0); at end of function"); 1389: #endif 1390: if (global.params.useAssert && 1391: !global.params.useInline) 1392: { /* Add an assert(0, msg); where the missing return 1393: * should be. 1394: */ 1395: e = new AssertExp( 1396: endloc, 1397: new IntegerExp(0), 1398: new StringExp(loc, (char *)"missing return expression") 1399: ); 1400: } 1401: else 1402: e = new HaltExp(endloc); 1403: e = new CommaExp(0, e, type->nextOf()->defaultInit()); 1404: e = e->semantic(sc2); 1405: Statement *s = new ExpStatement(0, e); 1406: fbody = new CompoundStatement(0, fbody, s); 1407: } 1408: } 1409: } 1410: } 1411: 1412: { 1413: Statements *a = new Statements();
warning C6211: Leaking memory 'a' due to an exception. Consider using a local catch block to clean up memory: Lines: 799, 800, 801, 802, 804, 818, 820, 822, 824, 841, 843, 855, 856, 858, 863, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 880, 881, 882, 883, 884, 885, 888, 889, 890, 892, 899, 900, 901, 903, 904, 932, 934, 936, 939, 940, 942, 943, 962, 1046, 1047, 1051, 1052, 1053, 1055, 1056, 1057, 1062, 1064, 1067, 1069, 1070, 1072, 1073, 1074, 1075, 1078, 1079, 1053, 1055, 1056, 1057, 1064, 1067, 1069, 1070, 1072, 1073, 1074, 1075, 1078, 1079, 1053, 1055, 1056, 1057, 1064, 1067, 1069, 1070, 1072, 1073, 1074, 1075, 1078, 1079, 1053, 1085, 1087, 1120, 1122, 1129, 1130, 1133, 1136, 1145, 1146, 1147, 1149, 1150, 1157, 1161, 1163, 1165, 1166, 1168, 1169, 1170, 1172, 1173, 1174, 1176, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1193, 1194, 1195, 1198, 1199, 1200, 1204, 1206, 1207, 1210, 1211, 1213, 1220, 1237, 1247, 1248, 1249, 1250, 1252, 1255, 1257, 1258, 1262, 1264, 1271, 1274, 1275, 1278, 1288, 1293, 1294, 1295, 1297, 1309, 1314, 1316, 1325, 1413, 1416, 1417, 1432, 1495, 1510, 1516, 1518, 1519, 1522, 1523, 1525, 1532, 1552, 1559, 1560, 1562, 1564, 1566, 1569, 1570
1414: 1415: // Merge in initialization of 'out' parameters 1416: if (parameters) 1417: { for (size_t i = 0; i < parameters->dim; i++) 1418: { 1419: VarDeclaration *v = parameters->tdata()[i]; 1420: if (v->storage_class & STCout) 1421: { 1422: assert(v->init); 1423: ExpInitializer *ie = v->init->isExpInitializer(); 1424: assert(ie); 1425: if (ie->exp->op == TOKconstruct) 1426: ie->exp->op = TOKassign; // construction occured in parameter processing 1427: a->push(new ExpStatement(0, ie->exp)); 1428: } 1429: } 1430: } 1431: 1432: if (argptr) 1433: { // Initialize _argptr 1434: #if IN_GCC 1435: // Handled in FuncDeclaration::toObjFile 1436: v_argptr = argptr; 1437: v_argptr->init = new VoidInitializer(loc); 1438: #else 1439: Type *t = argptr->type; 1440: if (global.params.is64bit) 1441: { // Initialize _argptr to point to v_argsave 1442: Expression *e1 = new VarExp(0, argptr); 1443: Expression *e = new SymOffExp(0, v_argsave, 6*8 + 8*16); 1444: e->type = argptr->type; 1445: e = new AssignExp(0, e1, e); 1446: e = e->semantic(sc); 1447: a->push(new ExpStatement(0, e)); 1448: } 1449: else 1450: { // Initialize _argptr to point past non-variadic arg 1451: VarDeclaration *p; 1452: unsigned offset = 0; 1453: 1454: Expression *e1 = new VarExp(0, argptr); 1455: // Find the last non-ref parameter 1456: if (parameters && parameters->dim) 1457: { 1458: int lastNonref = parameters->dim -1; 1459: p = parameters->tdata()[lastNonref]; 1460: /* The trouble with out and ref parameters is that taking 1461: * the address of it doesn't work, because later processing 1462: * adds in an extra level of indirection. So we skip over them. 1463: */ 1464: while (p->storage_class & (STCout | STCref)) 1465: { 1466: --lastNonref; 1467: offset += PTRSIZE; 1468: if (lastNonref < 0) 1469: { 1470: p = v_arguments; 1471: break; 1472: } 1473: p = parameters->tdata()[lastNonref]; 1474: } 1475: } 1476: else 1477: p = v_arguments; // last parameter is _arguments[] 1478: if (p->storage_class & STClazy) 1479: // If the last parameter is lazy, it's the size of a delegate 1480: offset += PTRSIZE * 2; 1481: else 1482: offset += p->type->size();
warning C4244: '+=' : conversion from 'd_uns64' to 'unsigned int', possible loss of data
1483: offset = (offset + PTRSIZE - 1) & ~(PTRSIZE - 1); // assume stack aligns on pointer size 1484: Expression *e = new SymOffExp(0, p, offset); 1485: e->type = Type::tvoidptr; 1486: //e = e->semantic(sc); 1487: e = new AssignExp(0, e1, e); 1488: e->type = t; 1489: a->push(new ExpStatement(0, e)); 1490: p->isargptr = TRUE; 1491: } 1492: #endif 1493: } 1494: 1495: if (_arguments) 1496: { 1497: /* Advance to elements[] member of TypeInfo_Tuple with: 1498: * _arguments = v_arguments.elements; 1499: */ 1500: Expression *e = new VarExp(0, v_arguments); 1501: e = new DotIdExp(0, e, Id::elements); 1502: Expression *e1 = new VarExp(0, _arguments); 1503: e = new ConstructExp(0, e1, e); 1504: e = e->semantic(sc2); 1505: a->push(new ExpStatement(0, e)); 1506: } 1507: 1508: // Merge contracts together with body into one compound statement 1509: 1510: if (frequire && global.params.useIn) 1511: { frequire->incontract = 1; 1512: a->push(frequire); 1513: } 1514: 1515: // Precondition invariant 1516: if (addPreInvariant()) 1517: { 1518: Expression *e = NULL; 1519: if (isDtorDeclaration()) 1520: { 1521: // Call invariant directly only if it exists 1522: InvariantDeclaration *inv = ad->inv; 1523: ClassDeclaration *cd = ad->isClassDeclaration(); 1524: 1525: while (!inv && cd) 1526: { 1527: cd = cd->baseClass; 1528: if (!cd) 1529: break; 1530: inv = cd->inv; 1531: } 1532: if (inv) 1533: { 1534: e = new DsymbolExp(0, inv); 1535: e = new CallExp(0, e); 1536: e = e->semantic(sc2); 1537: } 1538: } 1539: else 1540: { // Call invariant virtually 1541: Expression *v = new ThisExp(0); 1542: v->type = vthis->type; 1543: #if STRUCTTHISREF 1544: if (ad->isStructDeclaration()) 1545: v = v->addressOf(sc); 1546: #endif 1547: Expression *se = new StringExp(0, (char *)"null this"); 1548: se = se->semantic(sc); 1549: se->type = Type::tchar->arrayOf(); 1550: e = new AssertExp(loc, v, se); 1551: } 1552: if (e) 1553: { 1554: ExpStatement *s = new ExpStatement(0, e); 1555: a->push(s); 1556: } 1557: } 1558: 1559: if (fbody) 1560: a->push(fbody); 1561: 1562: if (fensure) 1563: { 1564: a->push(returnLabel->statement); 1565: 1566: if (type->nextOf()->ty != Tvoid) 1567: { 1568: // Create: return vresult; 1569: assert(vresult); 1570: Expression *e = new VarExp(0, vresult);
warning C6211: Leaking memory 'e' due to an exception. Consider using a local catch block to clean up memory: Lines: 799, 800, 801, 802, 804, 818, 820, 822, 824, 841, 843, 855, 856, 858, 863, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 880, 881, 882, 883, 884, 885, 888, 889, 890, 892, 899, 900, 901, 903, 904, 932, 934, 936, 939, 940, 942, 943, 962, 1046, 1047, 1051, 1052, 1053, 1055, 1056, 1057, 1062, 1064, 1067, 1069, 1070, 1072, 1073, 1074, 1075, 1078, 1079, 1053, 1055, 1056, 1057, 1064, 1067, 1069, 1070, 1072, 1073, 1074, 1075, 1078, 1079, 1053, 1055, 1056, 1057, 1064, 1067, 1069, 1070, 1072, 1073, 1074, 1075, 1078, 1079, 1053, 1085, 1087, 1120, 1122, 1129, 1130, 1133, 1136, 1145, 1146, 1147, 1149, 1150, 1157, 1161, 1163, 1165, 1166, 1168, 1169, 1170, 1172, 1173, 1174, 1176, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1193, 1194, 1195, 1198, 1199, 1200, 1204, 1206, 1207, 1210, 1211, 1213, 1220, 1237, 1247, 1248, 1249, 1250, 1252, 1255, 1257, 1258, 1262, 1264, 1271, 1274, 1275, 1278, 1288, 1293, 1294, 1295, 1297, 1309, 1314, 1316, 1325, 1413, 1416, 1417, 1432, 1495, 1510, 1516, 1518, 1519, 1522, 1523, 1525, 1532, 1552, 1559, 1560, 1562, 1564, 1566, 1569, 1570, 1571, 1572, 1573, 1575
1571: if (tintro) 1572: { e = e->implicitCastTo(sc, tintro->nextOf()); 1573: e = e->semantic(sc); 1574: } 1575: ReturnStatement *s = new ReturnStatement(0, e); 1576: a->push(s); 1577: } 1578: } 1579: 1580: fbody = new CompoundStatement(0, a); 1581: #if DMDV2 1582: /* Append destructor calls for parameters as finally blocks. 1583: */ 1584: if (parameters) 1585: { for (size_t i = 0; i < parameters->dim; i++) 1586: { 1587: VarDeclaration *v = parameters->tdata()[i]; 1588: 1589: if (v->storage_class & (STCref | STCout)) 1590: continue; 1591: 1592: /* Don't do this for static arrays, since static 1593: * arrays are called by reference. Remove this 1594: * when we change them to call by value. 1595: */ 1596: if (v->type->toBasetype()->ty == Tsarray) 1597: continue; 1598: 1599: if (v->noscope) 1600: continue; 1601: 1602: Expression *e = v->edtor; 1603: if (e) 1604: { Statement *s = new ExpStatement(0, e); 1605: s = s->semantic(sc2); 1606: if (fbody->blockExit(f->isnothrow) == BEfallthru) 1607: fbody = new CompoundStatement(0, fbody, s); 1608: else 1609: fbody = new TryFinallyStatement(0, fbody, s); 1610: } 1611: } 1612: } 1613: #endif 1614: 1615: #if 1 1616: if (isSynchronized()) 1617: { /* Wrap the entire function body in a synchronized statement 1618: */ 1619: AggregateDeclaration *ad = isThis();
warning C6246: Local declaration of 'ad' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '888' of 'c:\projects\extern\d\dmd\src\func.c': Lines: 888
1620: ClassDeclaration *cd = ad ? ad->isClassDeclaration() : parent->isClassDeclaration(); 1621: 1622: if (cd) 1623: { 1624: #if TARGET_WINDOS 1625: if (/*config.flags2 & CFG2seh &&*/ // always on for WINDOS 1626: !isStatic() && !fbody->usesEH()) 1627: { 1628: /* The back end uses the "jmonitor" hack for syncing; 1629: * no need to do the sync at this level. 1630: */ 1631: } 1632: else 1633: #endif 1634: { 1635: Expression *vsync; 1636: if (isStatic()) 1637: { // The monitor is in the ClassInfo 1638: vsync = new DotIdExp(loc, new DsymbolExp(loc, cd), Id::classinfo);
warning C6211: Leaking memory 'vsync' due to an exception. Consider using a local catch block to clean up memory: Lines: 799, 800, 801, 802, 804, 818, 820, 822, 824, 841, 843, 855, 856, 858, 863, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 880, 881, 882, 883, 884, 885, 888, 889, 890, 892, 899, 900, 901, 903, 904, 932, 934, 936, 939, 940,942, 943, 962, 1046, 1047, 1051, 1052, 1053, 1055, 1056, 1057, 1062, 1064, 1067, 1069, 1070, 1072, 1073, 1074, 1075, 1078, 1079, 1053, 1055, 1056, 1057, 1064, 1067, 1069, 1070, 1072, 1073, 1074, 1075, 1078, 1079, 1053, 1055, 1056, 1057, 1064, 1067, 1069, 1070, 1072, 1073, 1074, 1075, 1078, 1079, 1053, 1085, 1087, 1120, 1122, 1129, 1130, 1133, 1136, 1145, 1146, 1147, 1149, 1150, 1157, 1161, 1163, 1165, 1166, 1168, 1169, 1170, 1172, 1173, 1174, 1176, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1193, 1194, 1195, 1198, 1199, 1200, 1204, 1206, 1207, 1210, 1211, 1213, 1220, 1237, 1247, 1248, 1249, 1250, 1252, 1255, 1257, 1258, 1262, 1264, 1271, 1274, 1275, 1278, 1288, 1293, 1294, 1295, 1297, 1309, 1314, 1316, 1325, 1413, 1416, 1417, 1432, 1495, 1510, 1516, 1518, 1519, 1522, 1523, 1525, 1532, 1552, 1559, 1560, 1562, 1564, 1566, 1580, 1584, 1585, 1616, 1619, 1620, 1622, 1626, 1635, 1636, 1638, 1644
1639: } 1640: else 1641: { // 'this' is the monitor 1642: vsync = new VarExp(loc, vthis); 1643: } 1644: fbody = new PeelStatement(fbody); // don't redo semantic() 1645: fbody = new SynchronizedStatement(loc, vsync, fbody); 1646: fbody = fbody->semantic(sc2); 1647: } 1648: } 1649: else 1650: { 1651: error("synchronized function %s must be a member of a class", toChars()); 1652: } 1653: } 1654: #endif 1655: } 1656: 1657: sc2->callSuper = 0; 1658: sc2->pop(); 1659: } 1660: 1661: /* If function survived being marked as impure, then it is pure 1662: */ 1663: if (flags & FUNCFLAGpurityInprocess) 1664: { 1665: flags &= ~FUNCFLAGpurityInprocess; 1666: f->purity = PUREfwdref; 1667: } 1668: 1669: if (flags & FUNCFLAGsafetyInprocess) 1670: { 1671: flags &= ~FUNCFLAGsafetyInprocess; 1672: f->trust = TRUSTsafe; 1673: } 1674: 1675: if (global.gag && global.errors != nerrors) 1676: semanticRun = PASSsemanticdone; // Ensure errors get reported again 1677: else 1678: semanticRun = PASSsemantic3done; 1679: //printf("-FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars()); 1680: //fflush(stdout); 1681: } 1682: 1683: void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 1684: { 1685: //printf("FuncDeclaration::toCBuffer() '%s'\n", toChars()); 1686: 1687: StorageClassDeclaration::stcToCBuffer(buf, storage_class); 1688: type->toCBuffer(buf, ident, hgs); 1689: bodyToCBuffer(buf, hgs); 1690: } 1691: 1692: int FuncDeclaration::equals(Object *o) 1693: { 1694: if (this == o) 1695: return TRUE; 1696: 1697: Dsymbol *s = isDsymbol(o); 1698: if (s) 1699: { 1700: FuncDeclaration *fd = s->isFuncDeclaration(); 1701: if (fd) 1702: { 1703: return toParent()->equals(fd->toParent()) && 1704: ident->equals(fd->ident) && type->equals(fd->type); 1705: } 1706: } 1707: return FALSE; 1708: } 1709: 1710: void FuncDeclaration::bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs) 1711: { 1712: if (fbody && 1713: (!hgs->hdrgen || hgs->tpltMember || canInline(1,1)) 1714: ) 1715: { buf->writenl(); 1716: 1717: // in{} 1718: if (frequire) 1719: { buf->writestring("in"); 1720: buf->writenl(); 1721: frequire->toCBuffer(buf, hgs); 1722: } 1723: 1724: // out{} 1725: if (fensure) 1726: { buf->writestring("out"); 1727: if (outId) 1728: { buf->writebyte('('); 1729: buf->writestring(outId->toChars()); 1730: buf->writebyte(')'); 1731: } 1732: buf->writenl(); 1733: fensure->toCBuffer(buf, hgs); 1734: } 1735: 1736: if (frequire || fensure) 1737: { buf->writestring("body"); 1738: buf->writenl(); 1739: } 1740: 1741: buf->writebyte('{'); 1742: buf->writenl(); 1743: fbody->toCBuffer(buf, hgs); 1744: buf->writebyte('}'); 1745: buf->writenl(); 1746: } 1747: else 1748: { buf->writeByte(';'); 1749: buf->writenl(); 1750: } 1751: } 1752: 1753: /**************************************************** 1754: * Merge into this function the 'in' contracts of all it overrides. 1755: * 'in's are OR'd together, i.e. only one of them needs to pass. 1756: */ 1757: 1758: Statement *FuncDeclaration::mergeFrequire(Statement *sf) 1759: { 1760: /* Implementing this is done by having the overriding function call 1761: * nested functions (the fdrequire functions) nested inside the overridden 1762: * function. This requires that the stack layout of the calling function's 1763: * parameters and 'this' pointer be in the same place (as the nested 1764: * function refers to them). 1765: * This is easy for the parameters, as they are all on the stack in the same 1766: * place by definition, since it's an overriding function. The problem is 1767: * getting the 'this' pointer in the same place, since it is a local variable. 1768: * We did some hacks in the code generator to make this happen: 1769: * 1. always generate exception handler frame, or at least leave space for it 1770: * in the frame (Windows 32 SEH only) 1771: * 2. always generate an EBP style frame 1772: * 3. since 'this' is passed in a register that is subsequently copied into 1773: * a stack local, allocate that local immediately following the exception 1774: * handler block, so it is always at the same offset from EBP. 1775: */ 1776: for (int i = 0; i < foverrides.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1777: { 1778: FuncDeclaration *fdv = foverrides.tdata()[i]; 1779: 1780: /* The semantic pass on the contracts of the overridden functions must 1781: * be completed before code generation occurs (bug 3602). 1782: */ 1783: if (fdv->fdrequire && fdv->fdrequire->semanticRun != PASSsemantic3done) 1784: { 1785: assert(fdv->scope); 1786: Scope *sc = fdv->scope->push(); 1787: sc->stc &= ~STCoverride; 1788: fdv->semantic3(sc); 1789: sc->pop(); 1790: } 1791: 1792: sf = fdv->mergeFrequire(sf); 1793: if (sf && fdv->fdrequire) 1794: { 1795: //printf("fdv->frequire: %s\n", fdv->frequire->toChars()); 1796: /* Make the call: 1797: * try { __require(); } 1798: * catch { frequire; } 1799: */ 1800: Expression *eresult = NULL; 1801: Expression *e = new CallExp(loc, new VarExp(loc, fdv->fdrequire, 0), eresult); 1802: Statement *s2 = new ExpStatement(loc, e);
warning C6211: Leaking memory 's2' due to an exception. Consider using a local catch block to clean up memory: Lines: 1776, 1778, 1783, 1792, 1793, 1800, 1801, 1802, 1804
1803: 1804: Catch *c = new Catch(loc, NULL, NULL, sf);
warning C6211: Leaking memory 'c' due to an exception. Consider using a local catch block to clean up memory: Lines: 1776, 1778, 1783, 1792, 1793, 1800, 1801, 1802, 1804, 1805
1805: Catches *catches = new Catches(); 1806: catches->push(c); 1807: sf = new TryCatchStatement(loc, s2, catches); 1808: } 1809: else 1810: return NULL; 1811: } 1812: return sf; 1813: } 1814: 1815: /**************************************************** 1816: * Merge into this function the 'out' contracts of all it overrides. 1817: * 'out's are AND'd together, i.e. all of them need to pass. 1818: */ 1819: 1820: Statement *FuncDeclaration::mergeFensure(Statement *sf) 1821: { 1822: /* Same comments as for mergeFrequire(), except that we take care 1823: * of generating a consistent reference to the 'result' local by 1824: * explicitly passing 'result' to the nested function as a reference 1825: * argument. 1826: * This won't work for the 'this' parameter as it would require changing 1827: * the semantic code for the nested function so that it looks on the parameter 1828: * list for the 'this' pointer, something that would need an unknown amount 1829: * of tweaking of various parts of the compiler that I'd rather leave alone. 1830: */ 1831: for (int i = 0; i < foverrides.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1832: { 1833: FuncDeclaration *fdv = foverrides.tdata()[i]; 1834: 1835: /* The semantic pass on the contracts of the overridden functions must 1836: * be completed before code generation occurs (bug 3602 and 5230). 1837: */ 1838: if (fdv->fdensure && fdv->fdensure->semanticRun != PASSsemantic3done) 1839: { 1840: assert(fdv->scope); 1841: Scope *sc = fdv->scope->push(); 1842: sc->stc &= ~STCoverride; 1843: fdv->semantic3(sc); 1844: sc->pop(); 1845: } 1846: 1847: sf = fdv->mergeFensure(sf); 1848: if (fdv->fdensure) 1849: { 1850: //printf("fdv->fensure: %s\n", fdv->fensure->toChars()); 1851: // Make the call: __ensure(result) 1852: Expression *eresult = NULL; 1853: if (outId) 1854: eresult = new IdentifierExp(loc, outId); 1855: Expression *e = new CallExp(loc, new VarExp(loc, fdv->fdensure, 0), eresult); 1856: Statement *s2 = new ExpStatement(loc, e); 1857: 1858: if (sf) 1859: { 1860: sf = new CompoundStatement(fensure->loc, s2, sf); 1861: } 1862: else 1863: sf = s2; 1864: } 1865: } 1866: return sf; 1867: } 1868: 1869: /**************************************************** 1870: * Determine if 'this' overrides fd. 1871: * Return !=0 if it does. 1872: */ 1873: 1874: int FuncDeclaration::overrides(FuncDeclaration *fd) 1875: { int result = 0; 1876: 1877: if (fd->ident == ident) 1878: { 1879: int cov = type->covariant(fd->type); 1880: if (cov) 1881: { ClassDeclaration *cd1 = toParent()->isClassDeclaration(); 1882: ClassDeclaration *cd2 = fd->toParent()->isClassDeclaration(); 1883: 1884: if (cd1 && cd2 && cd2->isBaseOf(cd1, NULL)) 1885: result = 1; 1886: } 1887: } 1888: return result; 1889: } 1890: 1891: /************************************************* 1892: * Find index of function in vtbl[0..dim] that 1893: * this function overrides. 1894: * Prefer an exact match to a covariant one. 1895: * Returns: 1896: * -1 didn't find one 1897: * -2 can't determine because of forward references 1898: */ 1899: 1900: int FuncDeclaration::findVtblIndex(Dsymbols *vtbl, int dim) 1901: { 1902: FuncDeclaration *mismatch = NULL; 1903: int bestvi = -1; 1904: for (int vi = 0; vi < dim; vi++) 1905: { 1906: FuncDeclaration *fdv = vtbl->tdata()[vi]->isFuncDeclaration(); 1907: if (fdv && fdv->ident == ident) 1908: { 1909: if (type->equals(fdv->type)) // if exact match 1910: return vi; // no need to look further 1911: 1912: int cov = type->covariant(fdv->type); 1913: //printf("\tbaseclass cov = %d\n", cov); 1914: switch (cov) 1915: { 1916: case 0: // types are distinct 1917: break; 1918: 1919: case 1: 1920: bestvi = vi; // covariant, but not identical 1921: break; // keep looking for an exact match 1922: 1923: case 2: 1924: mismatch = fdv; // overrides, but is not covariant 1925: break; // keep looking for an exact match 1926: 1927: case 3: 1928: return -2; // forward references 1929: 1930: default: 1931: assert(0); 1932: } 1933: } 1934: } 1935: if (bestvi == -1 && mismatch) 1936: { 1937: //type->print(); 1938: //mismatch->type->print(); 1939: //printf("%s %s\n", type->deco, mismatch->type->deco); 1940: error("of type %s overrides but is not covariant with %s of type %s", 1941: type->toChars(), mismatch->toPrettyChars(), mismatch->type->toChars()); 1942: } 1943: return bestvi; 1944: } 1945: 1946: /**************************************************** 1947: * Overload this FuncDeclaration with the new one f. 1948: * Return !=0 if successful; i.e. no conflict. 1949: */ 1950: 1951: int FuncDeclaration::overloadInsert(Dsymbol *s) 1952: { 1953: FuncDeclaration *f; 1954: AliasDeclaration *a; 1955: 1956: //printf("FuncDeclaration::overloadInsert(s = %s) this = %s\n", s->toChars(), toChars()); 1957: a = s->isAliasDeclaration(); 1958: if (a) 1959: { 1960: if (overnext) 1961: return overnext->overloadInsert(a); 1962: if (!a->aliassym && a->type->ty != Tident && a->type->ty != Tinstance) 1963: { 1964: //printf("\ta = '%s'\n", a->type->toChars()); 1965: return FALSE; 1966: } 1967: overnext = a; 1968: //printf("\ttrue: no conflict\n"); 1969: return TRUE; 1970: } 1971: f = s->isFuncDeclaration(); 1972: if (!f) 1973: return FALSE; 1974: 1975: #if 0 1976: /* Disable this check because: 1977: * const void foo(); 1978: * semantic() isn't run yet on foo(), so the const hasn't been 1979: * applied yet. 1980: */ 1981: if (type) 1982: { printf("type = %s\n", type->toChars()); 1983: printf("f->type = %s\n", f->type->toChars()); 1984: } 1985: if (type && f->type && // can be NULL for overloaded constructors 1986: f->type->covariant(type) && 1987: f->type->mod == type->mod && 1988: !isFuncAliasDeclaration()) 1989: { 1990: //printf("\tfalse: conflict %s\n", kind()); 1991: return FALSE; 1992: } 1993: #endif 1994: 1995: if (overnext) 1996: return overnext->overloadInsert(f); 1997: overnext = f; 1998: //printf("\ttrue: no conflict\n"); 1999: return TRUE; 2000: } 2001: 2002: /******************************************** 2003: * Find function in overload list that exactly matches t. 2004: */ 2005: 2006: /*************************************************** 2007: * Visit each overloaded function in turn, and call 2008: * (*fp)(param, f) on it. 2009: * Exit when no more, or (*fp)(param, f) returns 1. 2010: * Returns: 2011: * 0 continue 2012: * 1 done 2013: */ 2014: 2015: int overloadApply(FuncDeclaration *fstart, 2016: int (*fp)(void *, FuncDeclaration *), 2017: void *param) 2018: { 2019: FuncDeclaration *f; 2020: Declaration *d; 2021: Declaration *next; 2022: 2023: for (d = fstart; d; d = next) 2024: { FuncAliasDeclaration *fa = d->isFuncAliasDeclaration(); 2025: 2026: if (fa) 2027: { 2028: if (overloadApply(fa->funcalias, fp, param)) 2029: return 1; 2030: next = fa->overnext; 2031: } 2032: else 2033: { 2034: AliasDeclaration *a = d->isAliasDeclaration(); 2035: 2036: if (a) 2037: { 2038: Dsymbol *s = a->toAlias(); 2039: next = s->isDeclaration(); 2040: if (next == a) 2041: break; 2042: if (next == fstart) 2043: break; 2044: } 2045: else 2046: { 2047: f = d->isFuncDeclaration(); 2048: if (!f) 2049: { d->error("is aliased to a function"); 2050: break; // BUG: should print error message? 2051: } 2052: if ((*fp)(param, f)) 2053: return 1; 2054: 2055: next = f->overnext; 2056: } 2057: } 2058: } 2059: return 0; 2060: } 2061: 2062: /******************************************** 2063: * If there are no overloads of function f, return that function, 2064: * otherwise return NULL. 2065: */ 2066: 2067: static int fpunique(void *param, FuncDeclaration *f) 2068: { FuncDeclaration **pf = (FuncDeclaration **)param; 2069: 2070: if (*pf) 2071: { *pf = NULL; 2072: return 1; // ambiguous, done 2073: } 2074: else 2075: { *pf = f; 2076: return 0; 2077: } 2078: } 2079: 2080: FuncDeclaration *FuncDeclaration::isUnique() 2081: { FuncDeclaration *result = NULL; 2082: 2083: overloadApply(this, &fpunique, &result); 2084: return result; 2085: } 2086: 2087: /******************************************** 2088: * Find function in overload list that exactly matches t. 2089: */ 2090: 2091: struct Param1 2092: { 2093: Type *t; // type to match 2094: FuncDeclaration *f; // return value 2095: }; 2096: 2097: int fp1(void *param, FuncDeclaration *f) 2098: { Param1 *p = (Param1 *)param; 2099: Type *t = p->t; 2100: 2101: if (t->equals(f->type)) 2102: { p->f = f; 2103: return 1; 2104: } 2105: 2106: #if DMDV2 2107: /* Allow covariant matches, as long as the return type 2108: * is just a const conversion. 2109: * This allows things like pure functions to match with an impure function type. 2110: */ 2111: if (t->ty == Tfunction) 2112: { TypeFunction *tf = (TypeFunction *)f->type; 2113: if (tf->covariant(t) == 1 && 2114: tf->nextOf()->implicitConvTo(t->nextOf()) >= MATCHconst) 2115: { 2116: p->f = f; 2117: return 1; 2118: } 2119: } 2120: #endif 2121: return 0; 2122: } 2123: 2124: FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t) 2125: { 2126: Param1 p; 2127: p.t = t; 2128: p.f = NULL; 2129: overloadApply(this, &fp1, &p); 2130: return p.f; 2131: } 2132: 2133: 2134: /******************************************** 2135: * Decide which function matches the arguments best. 2136: */ 2137: 2138: struct Param2 2139: { 2140: Match *m; 2141: #if DMDV2 2142: Expression *ethis; 2143: int property; // 0: unintialized 2144: // 1: seen @property 2145: // 2: not @property 2146: #endif 2147: Expressions *arguments; 2148: }; 2149: 2150: int fp2(void *param, FuncDeclaration *f) 2151: { Param2 *p = (Param2 *)param; 2152: Match *m = p->m; 2153: Expressions *arguments = p->arguments; 2154: MATCH match; 2155: 2156: if (f != m->lastf) // skip duplicates 2157: { 2158: m->anyf = f; 2159: TypeFunction *tf = (TypeFunction *)f->type; 2160: 2161: int property = (tf->isproperty) ? 1 : 2; 2162: if (p->property == 0) 2163: p->property = property; 2164: else if (p->property != property) 2165: error(f->loc, "cannot overload both property and non-property functions"); 2166: 2167: /* For constructors, don't worry about the right type of ethis. It's a problem 2168: * anyway, because the constructor attribute may not match the ethis attribute, 2169: * but we don't care because the attribute on the ethis doesn't matter until 2170: * after it's constructed. 2171: */ 2172: match = (MATCH) tf->callMatch(f->needThis() && !f->isCtorDeclaration() ? p->ethis : NULL, arguments); 2173: //printf("test1: match = %d\n", match); 2174: if (match != MATCHnomatch) 2175: { 2176: if (match > m->last) 2177: goto LfIsBetter; 2178: 2179: if (match < m->last) 2180: goto LlastIsBetter; 2181: 2182: /* See if one of the matches overrides the other. 2183: */ 2184: if (m->lastf->overrides(f)) 2185: goto LlastIsBetter; 2186: else if (f->overrides(m->lastf)) 2187: goto LfIsBetter; 2188: 2189: #if DMDV2 2190: /* Try to disambiguate using template-style partial ordering rules. 2191: * In essence, if f() and g() are ambiguous, if f() can call g(), 2192: * but g() cannot call f(), then pick f(). 2193: * This is because f() is "more specialized." 2194: */ 2195: { 2196: MATCH c1 = f->leastAsSpecialized(m->lastf); 2197: MATCH c2 = m->lastf->leastAsSpecialized(f); 2198: //printf("c1 = %d, c2 = %d\n", c1, c2); 2199: if (c1 > c2) 2200: goto LfIsBetter; 2201: if (c1 < c2) 2202: goto LlastIsBetter; 2203: } 2204: #endif 2205: Lambiguous:
warning C4102: 'Lambiguous' : unreferenced label
2206: m->nextf = f; 2207: m->count++; 2208: return 0; 2209: 2210: LfIsBetter: 2211: m->last = match; 2212: m->lastf = f; 2213: m->count = 1; 2214: return 0; 2215: 2216: LlastIsBetter: 2217: return 0; 2218: } 2219: } 2220: return 0; 2221: } 2222: 2223: 2224: void overloadResolveX(Match *m, FuncDeclaration *fstart, 2225: Expression *ethis, Expressions *arguments) 2226: { 2227: Param2 p; 2228: p.m = m; 2229: p.ethis = ethis; 2230: p.property = 0; 2231: p.arguments = arguments; 2232: overloadApply(fstart, &fp2, &p); 2233: } 2234: 2235: 2236: FuncDeclaration *FuncDeclaration::overloadResolve(Loc loc, Expression *ethis, Expressions *arguments, int flags) 2237: { 2238: TypeFunction *tf; 2239: Match m; 2240: 2241: #if 0 2242: printf("FuncDeclaration::overloadResolve('%s')\n", toChars()); 2243: if (arguments) 2244: { int i; 2245: 2246: for (i = 0; i < arguments->dim; i++) 2247: { Expression *arg; 2248: 2249: arg = arguments->tdata()[i]; 2250: assert(arg->type); 2251: printf("\t%s: ", arg->toChars()); 2252: arg->type->print(); 2253: } 2254: } 2255: #endif 2256: 2257: memset(&m, 0, sizeof(m)); 2258: m.last = MATCHnomatch; 2259: overloadResolveX(&m, this, ethis, arguments); 2260: 2261: if (m.count == 1) // exactly one match 2262: { 2263: return m.lastf; 2264: } 2265: else 2266: { 2267: OutBuffer buf; 2268: 2269: buf.writeByte('('); 2270: if (arguments) 2271: { 2272: HdrGenState hgs; 2273: 2274: argExpTypesToCBuffer(&buf, arguments, &hgs); 2275: buf.writeByte(')'); 2276: if (ethis) 2277: ethis->type->modToBuffer(&buf); 2278: } 2279: else 2280: buf.writeByte(')'); 2281: 2282: if (m.last == MATCHnomatch) 2283: { 2284: if (flags & 1) // if do not print error messages 2285: return NULL; // no match 2286: 2287: tf = (TypeFunction *)type; 2288: 2289: OutBuffer buf2; 2290: tf->modToBuffer(&buf2); 2291: 2292: //printf("tf = %s, args = %s\n", tf->deco, arguments->tdata()[0]->type->deco); 2293: error(loc, "%s%s is not callable using argument types %s", 2294: Parameter::argsTypesToChars(tf->parameters, tf->varargs), 2295: buf2.toChars(), 2296: buf.toChars()); 2297: return m.anyf; // as long as it's not a FuncAliasDeclaration 2298: } 2299: else 2300: { 2301: #if 1 2302: TypeFunction *t1 = (TypeFunction *)m.lastf->type; 2303: TypeFunction *t2 = (TypeFunction *)m.nextf->type; 2304: 2305: error(loc, "called with argument types:\n\t(%s)\nmatches both:\n\t%s%s\nand:\n\t%s%s", 2306: buf.toChars(), 2307: m.lastf->toPrettyChars(), Parameter::argsTypesToChars(t1->parameters, t1->varargs), 2308: m.nextf->toPrettyChars(), Parameter::argsTypesToChars(t2->parameters, t2->varargs)); 2309: #else 2310: error(loc, "overloads %s and %s both match argument list for %s", 2311: m.lastf->type->toChars(), 2312: m.nextf->type->toChars(), 2313: m.lastf->toChars()); 2314: #endif 2315: return m.lastf; 2316: } 2317: } 2318: } 2319: 2320: /************************************* 2321: * Determine partial specialization order of 'this' vs g. 2322: * This is very similar to TemplateDeclaration::leastAsSpecialized(). 2323: * Returns: 2324: * match 'this' is at least as specialized as g 2325: * 0 g is more specialized than 'this' 2326: */ 2327: 2328: #if DMDV2 2329: MATCH FuncDeclaration::leastAsSpecialized(FuncDeclaration *g) 2330: { 2331: #define LOG_LEASTAS 0 2332: 2333: #if LOG_LEASTAS 2334: printf("%s.leastAsSpecialized(%s)\n", toChars(), g->toChars()); 2335: printf("%s, %s\n", type->toChars(), g->type->toChars()); 2336: #endif 2337: 2338: /* This works by calling g() with f()'s parameters, and 2339: * if that is possible, then f() is at least as specialized 2340: * as g() is. 2341: */ 2342: 2343: TypeFunction *tf = (TypeFunction *)type; 2344: TypeFunction *tg = (TypeFunction *)g->type; 2345: size_t nfparams = Parameter::dim(tf->parameters); 2346: size_t ngparams = Parameter::dim(tg->parameters); 2347: MATCH match = MATCHexact; 2348: 2349: /* If both functions have a 'this' pointer, and the mods are not 2350: * the same and g's is not const, then this is less specialized. 2351: */ 2352: if (needThis() && g->needThis()) 2353: { 2354: if (tf->mod != tg->mod) 2355: { 2356: if (tg->mod == MODconst) 2357: match = MATCHconst; 2358: else 2359: return MATCHnomatch; 2360: } 2361: } 2362: 2363: /* Create a dummy array of arguments out of the parameters to f() 2364: */ 2365: Expressions args; 2366: args.setDim(nfparams); 2367: for (int u = 0; u < nfparams; u++)
warning C4018: '<' : signed/unsigned mismatch
2368: { 2369: Parameter *p = Parameter::getNth(tf->parameters, u); 2370: Expression *e; 2371: if (p->storageClass & (STCref | STCout)) 2372: { 2373: e = new IdentifierExp(0, p->ident); 2374: e->type = p->type; 2375: } 2376: else 2377: e = p->type->defaultInit(); 2378: args.tdata()[u] = e; 2379: } 2380: 2381: MATCH m = (MATCH) tg->callMatch(NULL, &args, 1); 2382: if (m) 2383: { 2384: /* A variadic parameter list is less specialized than a 2385: * non-variadic one. 2386: */ 2387: if (tf->varargs && !tg->varargs) 2388: goto L1; // less specialized 2389: 2390: #if LOG_LEASTAS 2391: printf(" matches %d, so is least as specialized\n", m); 2392: #endif 2393: return m; 2394: } 2395: L1: 2396: #if LOG_LEASTAS 2397: printf(" doesn't match, so is not as specialized\n"); 2398: #endif 2399: return MATCHnomatch; 2400: } 2401: 2402: /******************************************* 2403: * Given a symbol that could be either a FuncDeclaration or 2404: * a function template, resolve it to a function symbol. 2405: * sc instantiation scope 2406: * loc instantiation location 2407: * targsi initial list of template arguments 2408: * ethis if !NULL, the 'this' pointer argument 2409: * fargs arguments to function 2410: * flags 1: do not issue error message on no match, just return NULL 2411: */ 2412: 2413: FuncDeclaration *resolveFuncCall(Scope *sc, Loc loc, Dsymbol *s, 2414: Objects *tiargs, 2415: Expression *ethis, 2416: Expressions *arguments, 2417: int flags) 2418: { 2419: if (!s) 2420: return NULL; // no match 2421: FuncDeclaration *f = s->isFuncDeclaration(); 2422: if (f) 2423: f = f->overloadResolve(loc, ethis, arguments); 2424: else 2425: { TemplateDeclaration *td = s->isTemplateDeclaration(); 2426: assert(td); 2427: f = td->deduceFunctionTemplate(sc, loc, tiargs, NULL, arguments, flags); 2428: } 2429: return f; 2430: } 2431: #endif 2432: 2433: /******************************** 2434: * Labels are in a separate scope, one per function. 2435: */ 2436: 2437: LabelDsymbol *FuncDeclaration::searchLabel(Identifier *ident) 2438: { Dsymbol *s; 2439: 2440: if (!labtab) 2441: labtab = new DsymbolTable(); // guess we need one 2442: 2443: s = labtab->lookup(ident); 2444: if (!s) 2445: { 2446: s = new LabelDsymbol(ident); 2447: labtab->insert(s); 2448: } 2449: return (LabelDsymbol *)s; 2450: } 2451: 2452: /**************************************** 2453: * If non-static member function that has a 'this' pointer, 2454: * return the aggregate it is a member of. 2455: * Otherwise, return NULL. 2456: */ 2457: 2458: AggregateDeclaration *FuncDeclaration::isThis() 2459: { AggregateDeclaration *ad; 2460: 2461: //printf("+FuncDeclaration::isThis() '%s'\n", toChars()); 2462: ad = NULL; 2463: if ((storage_class & STCstatic) == 0) 2464: { 2465: ad = isMember2(); 2466: } 2467: //printf("-FuncDeclaration::isThis() %p\n", ad); 2468: return ad; 2469: } 2470: 2471: AggregateDeclaration *FuncDeclaration::isMember2() 2472: { AggregateDeclaration *ad; 2473: 2474: //printf("+FuncDeclaration::isMember2() '%s'\n", toChars()); 2475: ad = NULL; 2476: for (Dsymbol *s = this; s; s = s->parent) 2477: { 2478: //printf("\ts = '%s', parent = '%s', kind = %s\n", s->toChars(), s->parent->toChars(), s->parent->kind()); 2479: ad = s->isMember(); 2480: if (ad) 2481: { 2482: break; 2483: } 2484: if (!s->parent || 2485: (!s->parent->isTemplateInstance())) 2486: { 2487: break; 2488: } 2489: } 2490: //printf("-FuncDeclaration::isMember2() %p\n", ad); 2491: return ad; 2492: } 2493: 2494: /***************************************** 2495: * Determine lexical level difference from 'this' to nested function 'fd'. 2496: * Error if this cannot call fd. 2497: * Returns: 2498: * 0 same level 2499: * -1 increase nesting by 1 (fd is nested within 'this') 2500: * >0 decrease nesting by number 2501: */ 2502: 2503: int FuncDeclaration::getLevel(Loc loc, FuncDeclaration *fd) 2504: { int level; 2505: Dsymbol *s; 2506: Dsymbol *fdparent; 2507: 2508: //printf("FuncDeclaration::getLevel(fd = '%s')\n", fd->toChars()); 2509: fdparent = fd->toParent2(); 2510: if (fdparent == this) 2511: return -1; 2512: s = this; 2513: level = 0; 2514: while (fd != s && fdparent != s->toParent2()) 2515: { 2516: //printf("\ts = %s, '%s'\n", s->kind(), s->toChars()); 2517: FuncDeclaration *thisfd = s->isFuncDeclaration(); 2518: if (thisfd) 2519: { if (!thisfd->isNested() && !thisfd->vthis) 2520: goto Lerr; 2521: } 2522: else 2523: { 2524: AggregateDeclaration *thiscd = s->isAggregateDeclaration(); 2525: if (thiscd) 2526: { if (!thiscd->isNested()) 2527: goto Lerr; 2528: } 2529: else 2530: goto Lerr; 2531: } 2532: 2533: s = s->toParent2(); 2534: assert(s); 2535: level++; 2536: } 2537: return level; 2538: 2539: Lerr: 2540: error(loc, "cannot access frame of function %s", fd->toPrettyChars()); 2541: return 1; 2542: } 2543: 2544: void FuncDeclaration::appendExp(Expression *e) 2545: { Statement *s; 2546: 2547: s = new ExpStatement(0, e); 2548: appendState(s); 2549: } 2550: 2551: void FuncDeclaration::appendState(Statement *s) 2552: { 2553: if (!fbody) 2554: fbody = s; 2555: else 2556: { 2557: CompoundStatement *cs = fbody->isCompoundStatement(); 2558: if (cs) 2559: { 2560: if (!cs->statements) 2561: fbody = s; 2562: else 2563: cs->statements->push(s); 2564: } 2565: else 2566: fbody = new CompoundStatement(0, fbody, s); 2567: } 2568: } 2569: 2570: const char *FuncDeclaration::toPrettyChars() 2571: { 2572: if (isMain()) 2573: return "D main"; 2574: else 2575: return Dsymbol::toPrettyChars(); 2576: } 2577: 2578: int FuncDeclaration::isMain() 2579: { 2580: return ident == Id::main && 2581: linkage != LINKc && !isMember() && !isNested(); 2582: } 2583: 2584: int FuncDeclaration::isWinMain() 2585: { 2586: //printf("FuncDeclaration::isWinMain() %s\n", toChars()); 2587: #if 0 2588: int x = ident == Id::WinMain && 2589: linkage != LINKc && !isMember(); 2590: printf("%s\n", x ? "yes" : "no"); 2591: return x; 2592: #else 2593: return ident == Id::WinMain && 2594: linkage != LINKc && !isMember(); 2595: #endif 2596: } 2597: 2598: int FuncDeclaration::isDllMain() 2599: { 2600: return ident == Id::DllMain && 2601: linkage != LINKc && !isMember(); 2602: } 2603: 2604: int FuncDeclaration::isExport() 2605: { 2606: return protection == PROTexport; 2607: } 2608: 2609: int FuncDeclaration::isImportedSymbol() 2610: { 2611: //printf("isImportedSymbol()\n"); 2612: //printf("protection = %d\n", protection); 2613: return (protection == PROTexport) && !fbody; 2614: } 2615: 2616: // Determine if function goes into virtual function pointer table 2617: 2618: int FuncDeclaration::isVirtual() 2619: { 2620: #if 0 2621: printf("FuncDeclaration::isVirtual(%s)\n", toChars()); 2622: printf("isMember:%p isStatic:%d private:%d ctor:%d !Dlinkage:%d\n", isMember(), isStatic(), protection == PROTprivate, isCtorDeclaration(), linkage != LINKd); 2623: printf("result is %d\n", 2624: isMember() && 2625: !(isStatic() || protection == PROTprivate || protection == PROTpackage) && 2626: toParent()->isClassDeclaration()); 2627: #endif 2628: Dsymbol *p = toParent(); 2629: return isMember() && 2630: !(isStatic() || protection == PROTprivate || protection == PROTpackage) && 2631: p->isClassDeclaration() && 2632: !(p->isInterfaceDeclaration() && isFinal()); 2633: } 2634: 2635: int FuncDeclaration::isFinal() 2636: { 2637: ClassDeclaration *cd; 2638: #if 0 2639: printf("FuncDeclaration::isFinal(%s), %x\n", toChars(), Declaration::isFinal()); 2640: printf("%p %d %d %d\n", isMember(), isStatic(), Declaration::isFinal(), ((cd = toParent()->isClassDeclaration()) != NULL && cd->storage_class & STCfinal)); 2641: printf("result is %d\n", 2642: isMember() && 2643: (Declaration::isFinal() || 2644: ((cd = toParent()->isClassDeclaration()) != NULL && cd->storage_class & STCfinal))); 2645: if (cd) 2646: printf("\tmember of %s\n", cd->toChars()); 2647: #if 0 2648: !(isStatic() || protection == PROTprivate || protection == PROTpackage) && 2649: (cd = toParent()->isClassDeclaration()) != NULL && 2650: cd->storage_class & STCfinal); 2651: #endif 2652: #endif 2653: return isMember() && 2654: (Declaration::isFinal() || 2655: ((cd = toParent()->isClassDeclaration()) != NULL && cd->storage_class & STCfinal)); 2656: } 2657: 2658: int FuncDeclaration::isAbstract() 2659: { 2660: return storage_class & STCabstract; 2661: } 2662: 2663: int FuncDeclaration::isCodeseg() 2664: { 2665: return TRUE; // functions are always in the code segment 2666: } 2667: 2668: int FuncDeclaration::isOverloadable() 2669: { 2670: return 1; // functions can be overloaded 2671: } 2672: 2673: enum PURE FuncDeclaration::isPure() 2674: { 2675: //printf("FuncDeclaration::isPure() '%s'\n", toChars()); 2676: assert(type->ty == Tfunction); 2677: TypeFunction *tf = (TypeFunction *)type; 2678: if (flags & FUNCFLAGpurityInprocess) 2679: setImpure(); 2680: if (tf->purity == PUREfwdref) 2681: tf->purityLevel(); 2682: enum PURE purity = tf->purity; 2683: if (purity > PUREweak && needThis()) 2684: { // The attribute of the 'this' reference affects purity strength 2685: if (type->mod & (MODimmutable | MODwild)) 2686: ; 2687: else if (type->mod & MODconst && purity >= PUREconst) 2688: purity = PUREconst; 2689: else 2690: purity = PUREweak; 2691: } 2692: tf->purity = purity; 2693: // ^ This rely on the current situation that every FuncDeclaration has a 2694: // unique TypeFunction. 2695: return purity; 2696: } 2697: 2698: /************************************** 2699: * The function is doing something impure, 2700: * so mark it as impure. 2701: * If there's a purity error, return TRUE. 2702: */ 2703: bool FuncDeclaration::setImpure() 2704: { 2705: if (flags & FUNCFLAGpurityInprocess) 2706: { 2707: flags &= ~FUNCFLAGpurityInprocess; 2708: } 2709: else if (isPure()) 2710: return TRUE; 2711: return FALSE; 2712: } 2713: 2714: int FuncDeclaration::isSafe() 2715: { 2716: assert(type->ty == Tfunction); 2717: if (flags & FUNCFLAGsafetyInprocess) 2718: setUnsafe(); 2719: return ((TypeFunction *)type)->trust == TRUSTsafe; 2720: } 2721: 2722: int FuncDeclaration::isTrusted() 2723: { 2724: assert(type->ty == Tfunction); 2725: if (flags & FUNCFLAGsafetyInprocess) 2726: setUnsafe(); 2727: return ((TypeFunction *)type)->trust == TRUSTtrusted; 2728: } 2729: 2730: /************************************** 2731: * The function is doing something unsave, 2732: * so mark it as unsafe. 2733: * If there's a safe error, return TRUE. 2734: */ 2735: bool FuncDeclaration::setUnsafe() 2736: { 2737: if (flags & FUNCFLAGsafetyInprocess) 2738: { 2739: flags &= ~FUNCFLAGsafetyInprocess; 2740: ((TypeFunction *)type)->trust = TRUSTsystem; 2741: } 2742: else if (isSafe()) 2743: return TRUE; 2744: return FALSE; 2745: } 2746: 2747: // Determine if function needs 2748: // a static frame pointer to its lexically enclosing function 2749: 2750: int FuncDeclaration::isNested() 2751: { 2752: //if (!toParent()) 2753: //printf("FuncDeclaration::isNested('%s') parent=%p\n", toChars(), parent); 2754: //printf("\ttoParent2() = '%s'\n", toParent2()->toChars()); 2755: return ((storage_class & STCstatic) == 0) && 2756: (toParent2()->isFuncDeclaration() != NULL); 2757: } 2758: 2759: int FuncDeclaration::needThis() 2760: { 2761: //printf("FuncDeclaration::needThis() '%s'\n", toChars()); 2762: int i = isThis() != NULL; 2763: //printf("\t%d\n", i); 2764: if (!i && isFuncAliasDeclaration()) 2765: i = ((FuncAliasDeclaration *)this)->funcalias->needThis(); 2766: return i; 2767: } 2768: 2769: int FuncDeclaration::addPreInvariant() 2770: { 2771: AggregateDeclaration *ad = isThis(); 2772: return (ad && 2773: //ad->isClassDeclaration() && 2774: global.params.useInvariants && 2775: (protection == PROTpublic || protection == PROTexport) && 2776: !naked && 2777: ident != Id::cpctor); 2778: } 2779: 2780: int FuncDeclaration::addPostInvariant() 2781: { 2782: AggregateDeclaration *ad = isThis(); 2783: return (ad && 2784: ad->inv && 2785: //ad->isClassDeclaration() && 2786: global.params.useInvariants && 2787: (protection == PROTpublic || protection == PROTexport) && 2788: !naked && 2789: ident != Id::cpctor); 2790: } 2791: 2792: /********************************** 2793: * Generate a FuncDeclaration for a runtime library function. 2794: */ 2795: 2796: FuncDeclaration *FuncDeclaration::genCfunc(Type *treturn, const char *name) 2797: { 2798: return genCfunc(treturn, Lexer::idPool(name)); 2799: } 2800: 2801: FuncDeclaration *FuncDeclaration::genCfunc(Type *treturn, Identifier *id) 2802: { 2803: FuncDeclaration *fd; 2804: TypeFunction *tf; 2805: Dsymbol *s; 2806: static DsymbolTable *st = NULL; 2807: 2808: //printf("genCfunc(name = '%s')\n", id->toChars()); 2809: //printf("treturn\n\t"); treturn->print(); 2810: 2811: // See if already in table 2812: if (!st) 2813: st = new DsymbolTable(); 2814: s = st->lookup(id); 2815: if (s) 2816: { 2817: fd = s->isFuncDeclaration(); 2818: assert(fd); 2819: assert(fd->type->nextOf()->equals(treturn)); 2820: } 2821: else 2822: { 2823: tf = new TypeFunction(NULL, treturn, 0, LINKc); 2824: fd = new FuncDeclaration(0, 0, id, STCstatic, tf); 2825: fd->protection = PROTpublic; 2826: fd->linkage = LINKc; 2827: 2828: st->insert(fd); 2829: } 2830: return fd; 2831: } 2832: 2833: const char *FuncDeclaration::kind() 2834: { 2835: return "function"; 2836: } 2837: 2838: /******************************* 2839: * Look at all the variables in this function that are referenced 2840: * by nested functions, and determine if a closure needs to be 2841: * created for them. 2842: */ 2843: 2844: #if DMDV2 2845: int FuncDeclaration::needsClosure() 2846: { 2847: /* Need a closure for all the closureVars[] if any of the 2848: * closureVars[] are accessed by a 2849: * function that escapes the scope of this function. 2850: * We take the conservative approach and decide that any function that: 2851: * 1) is a virtual function 2852: * 2) has its address taken 2853: * 3) has a parent that escapes 2854: * -or- 2855: * 4) this function returns a local struct/class 2856: * 2857: * Note that since a non-virtual function can be called by 2858: * a virtual one, if that non-virtual function accesses a closure 2859: * var, the closure still has to be taken. Hence, we check for isThis() 2860: * instead of isVirtual(). (thanks to David Friedman) 2861: */ 2862: 2863: //printf("FuncDeclaration::needsClosure() %s\n", toChars()); 2864: for (int i = 0; i < closureVars.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
2865: { VarDeclaration *v = closureVars.tdata()[i]; 2866: assert(v->isVarDeclaration()); 2867: //printf("\tv = %s\n", v->toChars()); 2868: 2869: for (int j = 0; j < v->nestedrefs.dim; j++)
warning C4018: '<' : signed/unsigned mismatch
2870: { FuncDeclaration *f = v->nestedrefs.tdata()[j]; 2871: assert(f != this); 2872: 2873: //printf("\t\tf = %s, %d, %p, %d\n", f->toChars(), f->isVirtual(), f->isThis(), f->tookAddressOf); 2874: if (f->isThis() || f->tookAddressOf) 2875: goto Lyes; // assume f escapes this function's scope 2876: 2877: // Look to see if any parents of f that are below this escape 2878: for (Dsymbol *s = f->parent; s && s != this; s = s->parent) 2879: { 2880: f = s->isFuncDeclaration(); 2881: if (f && (f->isThis() || f->tookAddressOf)) 2882: goto Lyes; 2883: } 2884: } 2885: } 2886: 2887: /* Look for case (4) 2888: */ 2889: if (closureVars.dim) 2890: { 2891: assert(type->ty == Tfunction); 2892: Type *tret = ((TypeFunction *)type)->next; 2893: assert(tret); 2894: tret = tret->toBasetype(); 2895: if (tret->ty == Tclass || tret->ty == Tstruct) 2896: { Dsymbol *st = tret->toDsymbol(NULL); 2897: for (Dsymbol *s = st->parent; s; s = s->parent) 2898: { 2899: if (s == this) 2900: goto Lyes; 2901: } 2902: } 2903: } 2904: 2905: return 0; 2906: 2907: Lyes: 2908: //printf("\tneeds closure\n"); 2909: return 1; 2910: } 2911: #endif 2912: 2913: /********************************************* 2914: * Return the function's parameter list, and whether 2915: * it is variadic or not. 2916: */ 2917: 2918: Parameters *FuncDeclaration::getParameters(int *pvarargs) 2919: { Parameters *fparameters; 2920: int fvarargs; 2921: 2922: if (type) 2923: { 2924: assert(type->ty == Tfunction); 2925: TypeFunction *fdtype = (TypeFunction *)type; 2926: fparameters = fdtype->parameters; 2927: fvarargs = fdtype->varargs; 2928: } 2929: if (pvarargs) 2930: *pvarargs = fvarargs;
warning C6001: Using uninitialized memory 'fvarargs': Lines: 2919, 2920, 2922, 2929, 2930
2931: return fparameters;
warning C6001: Using uninitialized memory 'fparameters': Lines: 2919, 2920, 2922, 2929, 2930, 2931
2932: } 2933: 2934: 2935: /****************************** FuncAliasDeclaration ************************/ 2936: 2937: // Used as a way to import a set of functions from another scope into this one. 2938: 2939: FuncAliasDeclaration::FuncAliasDeclaration(FuncDeclaration *funcalias) 2940: : FuncDeclaration(funcalias->loc, funcalias->endloc, funcalias->ident, 2941: funcalias->storage_class, funcalias->type) 2942: { 2943: assert(funcalias != this); 2944: this->funcalias = funcalias; 2945: } 2946: 2947: const char *FuncAliasDeclaration::kind() 2948: { 2949: return "function alias"; 2950: } 2951: 2952: 2953: /****************************** FuncLiteralDeclaration ************************/ 2954: 2955: FuncLiteralDeclaration::FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type, 2956: enum TOK tok, ForeachStatement *fes) 2957: : FuncDeclaration(loc, endloc, NULL, STCundefined, type) 2958: { 2959: const char *id; 2960: 2961: if (fes) 2962: id = "__foreachbody"; 2963: else if (tok == TOKdelegate) 2964: id = "__dgliteral"; 2965: else 2966: id = "__funcliteral"; 2967: this->ident = Lexer::uniqueId(id); 2968: this->tok = tok; 2969: this->fes = fes; 2970: //printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this->ident->toChars(), type->toChars()); 2971: } 2972: 2973: Dsymbol *FuncLiteralDeclaration::syntaxCopy(Dsymbol *s) 2974: { 2975: FuncLiteralDeclaration *f; 2976: 2977: //printf("FuncLiteralDeclaration::syntaxCopy('%s')\n", toChars()); 2978: if (s) 2979: f = (FuncLiteralDeclaration *)s; 2980: else 2981: { f = new FuncLiteralDeclaration(loc, endloc, type->syntaxCopy(), tok, fes); 2982: f->ident = ident; // keep old identifier 2983: } 2984: FuncDeclaration::syntaxCopy(f); 2985: return f; 2986: } 2987: 2988: int FuncLiteralDeclaration::isNested() 2989: { 2990: //printf("FuncLiteralDeclaration::isNested() '%s'\n", toChars()); 2991: return (tok == TOKdelegate); 2992: } 2993: 2994: int FuncLiteralDeclaration::isVirtual() 2995: { 2996: return FALSE; 2997: } 2998: 2999: const char *FuncLiteralDeclaration::kind() 3000: { 3001: // GCC requires the (char*) casts 3002: return (tok == TOKdelegate) ? (char*)"delegate" : (char*)"function"; 3003: } 3004: 3005: void FuncLiteralDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3006: { 3007: buf->writestring(kind()); 3008: buf->writeByte(' '); 3009: type->toCBuffer(buf, NULL, hgs); 3010: bodyToCBuffer(buf, hgs); 3011: } 3012: 3013: 3014: /********************************* CtorDeclaration ****************************/ 3015: 3016: CtorDeclaration::CtorDeclaration(Loc loc, Loc endloc, StorageClass stc, Type *type) 3017: : FuncDeclaration(loc, endloc, Id::ctor, stc, type) 3018: { 3019: //printf("CtorDeclaration(loc = %s) %s\n", loc.toChars(), toChars()); 3020: } 3021: 3022: Dsymbol *CtorDeclaration::syntaxCopy(Dsymbol *s) 3023: { 3024: CtorDeclaration *f = new CtorDeclaration(loc, endloc, storage_class, type->syntaxCopy()); 3025: 3026: f->outId = outId; 3027: f->frequire = frequire ? frequire->syntaxCopy() : NULL; 3028: f->fensure = fensure ? fensure->syntaxCopy() : NULL; 3029: f->fbody = fbody ? fbody->syntaxCopy() : NULL; 3030: assert(!fthrows); // deprecated 3031: 3032: return f; 3033: } 3034: 3035: 3036: void CtorDeclaration::semantic(Scope *sc) 3037: { 3038: //printf("CtorDeclaration::semantic() %s\n", toChars()); 3039: TypeFunction *tf = (TypeFunction *)type; 3040: assert(tf && tf->ty == Tfunction); 3041: Expressions *fargs = ((TypeFunction *)type)->fargs; // for auto ref 3042: 3043: sc = sc->push(); 3044: sc->stc &= ~STCstatic; // not a static constructor 3045: 3046: parent = sc->parent; 3047: Dsymbol *parent = toParent2(); 3048: Type *tret; 3049: AggregateDeclaration *ad = parent->isAggregateDeclaration(); 3050: if (!ad || parent->isUnionDeclaration()) 3051: { 3052: error("constructors are only for class or struct definitions"); 3053: tret = Type::tvoid; 3054: } 3055: else 3056: { tret = ad->handle; 3057: assert(tret); 3058: tret = tret->addStorageClass(storage_class | sc->stc); 3059: } 3060: tf = new TypeFunction(tf->parameters, tret, tf->varargs, LINKd, storage_class | sc->stc); 3061: tf->fargs = fargs; 3062: type = tf; 3063: 3064: #if STRUCTTHISREF 3065: if (ad && ad->isStructDeclaration()) 3066: { ((TypeFunction *)type)->isref = 1; 3067: if (!originalType) 3068: // Leave off the "ref" 3069: originalType = new TypeFunction(tf->parameters, tret, tf->varargs, LINKd, storage_class | sc->stc); 3070: } 3071: #endif 3072: if (!originalType) 3073: originalType = type; 3074: 3075: // Append: 3076: // return this; 3077: // to the function body 3078: if (fbody && semanticRun < PASSsemantic) 3079: { 3080: Expression *e = new ThisExp(loc); 3081: if (parent->isClassDeclaration()) 3082: e->type = tret; 3083: Statement *s = new ReturnStatement(loc, e); 3084: fbody = new CompoundStatement(loc, fbody, s); 3085: } 3086: 3087: FuncDeclaration::semantic(sc); 3088: 3089: sc->pop(); 3090: 3091: // See if it's the default constructor 3092: if (ad && tf->varargs == 0 && Parameter::dim(tf->parameters) == 0) 3093: { 3094: StructDeclaration *sd = ad->isStructDeclaration(); 3095: if (sd) 3096: { 3097: if (fbody || !(storage_class & STCdisable)) 3098: { error("default constructor for structs only allowed with @disable and no body"); 3099: storage_class |= STCdisable; 3100: fbody = NULL; 3101: } 3102: sd->noDefaultCtor = TRUE; 3103: } 3104: else 3105: ad->defaultCtor = this; 3106: } 3107: } 3108: 3109: const char *CtorDeclaration::kind() 3110: { 3111: return "constructor"; 3112: } 3113: 3114: char *CtorDeclaration::toChars() 3115: { 3116: return (char *)"this"; 3117: } 3118: 3119: int CtorDeclaration::isVirtual() 3120: { 3121: return FALSE; 3122: } 3123: 3124: int CtorDeclaration::addPreInvariant() 3125: { 3126: return FALSE; 3127: } 3128: 3129: int CtorDeclaration::addPostInvariant() 3130: { 3131: return (isThis() && vthis && global.params.useInvariants); 3132: } 3133: 3134: 3135: void CtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3136: { 3137: TypeFunction *tf = (TypeFunction *)type; 3138: assert(tf && tf->ty == Tfunction); 3139: 3140: if (originalType && originalType->ty == Tfunction) 3141: ((TypeFunction *)originalType)->attributesToCBuffer(buf, 0); 3142: buf->writestring("this"); 3143: Parameter::argsToCBuffer(buf, hgs, tf->parameters, tf->varargs); 3144: bodyToCBuffer(buf, hgs); 3145: } 3146: 3147: /********************************* PostBlitDeclaration ****************************/ 3148: 3149: #if DMDV2 3150: PostBlitDeclaration::PostBlitDeclaration(Loc loc, Loc endloc) 3151: : FuncDeclaration(loc, endloc, Id::_postblit, STCundefined, NULL) 3152: { 3153: } 3154: 3155: PostBlitDeclaration::PostBlitDeclaration(Loc loc, Loc endloc, Identifier *id) 3156: : FuncDeclaration(loc, endloc, id, STCundefined, NULL) 3157: { 3158: } 3159: 3160: Dsymbol *PostBlitDeclaration::syntaxCopy(Dsymbol *s) 3161: { 3162: assert(!s); 3163: PostBlitDeclaration *dd = new PostBlitDeclaration(loc, endloc, ident); 3164: return FuncDeclaration::syntaxCopy(dd); 3165: } 3166: 3167: 3168: void PostBlitDeclaration::semantic(Scope *sc) 3169: { 3170: //printf("PostBlitDeclaration::semantic() %s\n", toChars()); 3171: //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor); 3172: //printf("stc = x%llx\n", sc->stc); 3173: parent = sc->parent; 3174: Dsymbol *parent = toParent(); 3175: StructDeclaration *ad = parent->isStructDeclaration(); 3176: if (!ad) 3177: { 3178: error("post blits are only for struct/union definitions, not %s %s", parent->kind(), parent->toChars()); 3179: } 3180: else if (ident == Id::_postblit && semanticRun < PASSsemantic) 3181: ad->postblits.push(this); 3182: 3183: if (!type) 3184: type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); 3185: 3186: sc = sc->push(); 3187: sc->stc &= ~STCstatic; // not static 3188: sc->linkage = LINKd; 3189: 3190: FuncDeclaration::semantic(sc); 3191: 3192: sc->pop(); 3193: } 3194: 3195: int PostBlitDeclaration::overloadInsert(Dsymbol *s) 3196: { 3197: return FALSE; // cannot overload postblits 3198: } 3199: 3200: int PostBlitDeclaration::addPreInvariant() 3201: { 3202: return FALSE; 3203: } 3204: 3205: int PostBlitDeclaration::addPostInvariant() 3206: { 3207: return (isThis() && vthis && global.params.useInvariants); 3208: } 3209: 3210: int PostBlitDeclaration::isVirtual() 3211: { 3212: return FALSE; 3213: } 3214: 3215: void PostBlitDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3216: { 3217: buf->writestring("this(this)"); 3218: bodyToCBuffer(buf, hgs); 3219: } 3220: #endif 3221: 3222: /********************************* DtorDeclaration ****************************/ 3223: 3224: DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc) 3225: : FuncDeclaration(loc, endloc, Id::dtor, STCundefined, NULL) 3226: { 3227: } 3228: 3229: DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc, Identifier *id) 3230: : FuncDeclaration(loc, endloc, id, STCundefined, NULL) 3231: { 3232: } 3233: 3234: Dsymbol *DtorDeclaration::syntaxCopy(Dsymbol *s) 3235: { 3236: assert(!s); 3237: DtorDeclaration *dd = new DtorDeclaration(loc, endloc, ident); 3238: return FuncDeclaration::syntaxCopy(dd); 3239: } 3240: 3241: 3242: void DtorDeclaration::semantic(Scope *sc) 3243: { 3244: //printf("DtorDeclaration::semantic() %s\n", toChars()); 3245: //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor); 3246: parent = sc->parent; 3247: Dsymbol *parent = toParent(); 3248: AggregateDeclaration *ad = parent->isAggregateDeclaration(); 3249: if (!ad) 3250: { 3251: error("destructors are only for class/struct/union definitions, not %s %s", parent->kind(), parent->toChars()); 3252: } 3253: else if (ident == Id::dtor && semanticRun < PASSsemantic) 3254: ad->dtors.push(this); 3255: 3256: if (!type) 3257: type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); 3258: 3259: sc = sc->push(); 3260: sc->stc &= ~STCstatic; // not a static destructor 3261: sc->linkage = LINKd; 3262: 3263: FuncDeclaration::semantic(sc); 3264: 3265: sc->pop(); 3266: } 3267: 3268: int DtorDeclaration::overloadInsert(Dsymbol *s) 3269: { 3270: return FALSE; // cannot overload destructors 3271: } 3272: 3273: int DtorDeclaration::addPreInvariant() 3274: { 3275: return (isThis() && vthis && global.params.useInvariants); 3276: } 3277: 3278: int DtorDeclaration::addPostInvariant() 3279: { 3280: return FALSE; 3281: } 3282: 3283: const char *DtorDeclaration::kind() 3284: { 3285: return "destructor"; 3286: } 3287: 3288: char *DtorDeclaration::toChars() 3289: { 3290: return (char *)"~this"; 3291: } 3292: 3293: int DtorDeclaration::isVirtual() 3294: { 3295: /* This should be FALSE so that dtor's don't get put into the vtbl[], 3296: * but doing so will require recompiling everything. 3297: */ 3298: #if BREAKABI 3299: return FALSE; 3300: #else 3301: return FuncDeclaration::isVirtual(); 3302: #endif 3303: } 3304: 3305: void DtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3306: { 3307: buf->writestring("~this()"); 3308: bodyToCBuffer(buf, hgs); 3309: } 3310: 3311: /********************************* StaticCtorDeclaration ****************************/ 3312: 3313: StaticCtorDeclaration::StaticCtorDeclaration(Loc loc, Loc endloc) 3314: : FuncDeclaration(loc, endloc, 3315: Identifier::generateId("_staticCtor"), STCstatic, NULL) 3316: { 3317: } 3318: 3319: StaticCtorDeclaration::StaticCtorDeclaration(Loc loc, Loc endloc, const char *name) 3320: : FuncDeclaration(loc, endloc, 3321: Identifier::generateId(name), STCstatic, NULL) 3322: { 3323: } 3324: 3325: Dsymbol *StaticCtorDeclaration::syntaxCopy(Dsymbol *s) 3326: { 3327: assert(!s); 3328: StaticCtorDeclaration *scd = new StaticCtorDeclaration(loc, endloc); 3329: return FuncDeclaration::syntaxCopy(scd); 3330: } 3331: 3332: 3333: void StaticCtorDeclaration::semantic(Scope *sc) 3334: { 3335: //printf("StaticCtorDeclaration::semantic()\n"); 3336: 3337: if (!type) 3338: type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); 3339: 3340: /* If the static ctor appears within a template instantiation, 3341: * it could get called multiple times by the module constructors 3342: * for different modules. Thus, protect it with a gate. 3343: */ 3344: if (inTemplateInstance() && semanticRun < PASSsemantic) 3345: { 3346: /* Add this prefix to the function: 3347: * static int gate; 3348: * if (++gate != 1) return; 3349: * Note that this is not thread safe; should not have threads 3350: * during static construction. 3351: */ 3352: Identifier *id = Lexer::idPool("__gate"); 3353: VarDeclaration *v = new VarDeclaration(0, Type::tint32, id, NULL);
warning C6211: Leaking memory 'v' due to an exception. Consider using a local catch block to clean up memory: Lines: 3337, 3338, 3344, 3352, 3353, 3354, 3355
3354: v->storage_class = isSharedStaticCtorDeclaration() ? STCstatic : STCtls; 3355: Statements *sa = new Statements();
warning C6211: Leaking memory 'sa' due to an exception. Consider using a local catch block to clean up memory: Lines: 3337, 3338, 3344, 3352, 3353, 3354, 3355, 3356
3356: Statement *s = new ExpStatement(0, v); 3357: sa->push(s); 3358: Expression *e = new IdentifierExp(0, id); 3359: e = new AddAssignExp(0, e, new IntegerExp(1)); 3360: e = new EqualExp(TOKnotequal, 0, e, new IntegerExp(1)); 3361: s = new IfStatement(0, NULL, e, new ReturnStatement(0, NULL), NULL); 3362: sa->push(s); 3363: if (fbody) 3364: sa->push(fbody); 3365: fbody = new CompoundStatement(0, sa); 3366: } 3367: 3368: FuncDeclaration::semantic(sc); 3369: 3370: // We're going to need ModuleInfo 3371: Module *m = getModule(); 3372: if (!m) 3373: m = sc->module; 3374: if (m) 3375: { m->needmoduleinfo = 1; 3376: //printf("module1 %s needs moduleinfo\n", m->toChars()); 3377: #ifdef IN_GCC 3378: m->strictlyneedmoduleinfo = 1; 3379: #endif 3380: } 3381: } 3382: 3383: AggregateDeclaration *StaticCtorDeclaration::isThis() 3384: { 3385: return NULL; 3386: } 3387: 3388: int StaticCtorDeclaration::isVirtual() 3389: { 3390: return FALSE; 3391: } 3392: 3393: int StaticCtorDeclaration::addPreInvariant() 3394: { 3395: return FALSE; 3396: } 3397: 3398: int StaticCtorDeclaration::addPostInvariant() 3399: { 3400: return FALSE; 3401: } 3402: 3403: void StaticCtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3404: { 3405: if (hgs->hdrgen) 3406: { buf->writestring("static this();"); 3407: buf->writenl(); 3408: return; 3409: } 3410: buf->writestring("static this()"); 3411: bodyToCBuffer(buf, hgs); 3412: } 3413: 3414: /********************************* SharedStaticCtorDeclaration ****************************/ 3415: 3416: SharedStaticCtorDeclaration::SharedStaticCtorDeclaration(Loc loc, Loc endloc) 3417: : StaticCtorDeclaration(loc, endloc, "_sharedStaticCtor") 3418: { 3419: } 3420: 3421: Dsymbol *SharedStaticCtorDeclaration::syntaxCopy(Dsymbol *s) 3422: { 3423: assert(!s); 3424: SharedStaticCtorDeclaration *scd = new SharedStaticCtorDeclaration(loc, endloc); 3425: return FuncDeclaration::syntaxCopy(scd); 3426: } 3427: 3428: void SharedStaticCtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3429: { 3430: buf->writestring("shared "); 3431: StaticCtorDeclaration::toCBuffer(buf, hgs); 3432: } 3433: 3434: /********************************* StaticDtorDeclaration ****************************/ 3435: 3436: StaticDtorDeclaration::StaticDtorDeclaration(Loc loc, Loc endloc) 3437: : FuncDeclaration(loc, endloc, 3438: Identifier::generateId("_staticDtor"), STCstatic, NULL) 3439: { 3440: vgate = NULL; 3441: } 3442: 3443: StaticDtorDeclaration::StaticDtorDeclaration(Loc loc, Loc endloc, const char *name) 3444: : FuncDeclaration(loc, endloc, 3445: Identifier::generateId(name), STCstatic, NULL) 3446: { 3447: vgate = NULL; 3448: } 3449: 3450: Dsymbol *StaticDtorDeclaration::syntaxCopy(Dsymbol *s) 3451: { 3452: assert(!s); 3453: StaticDtorDeclaration *sdd = new StaticDtorDeclaration(loc, endloc); 3454: return FuncDeclaration::syntaxCopy(sdd); 3455: } 3456: 3457: 3458: void StaticDtorDeclaration::semantic(Scope *sc) 3459: { 3460: ClassDeclaration *cd = sc->scopesym->isClassDeclaration(); 3461: 3462: if (!type) 3463: type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); 3464: 3465: /* If the static ctor appears within a template instantiation, 3466: * it could get called multiple times by the module constructors 3467: * for different modules. Thus, protect it with a gate. 3468: */ 3469: if (inTemplateInstance() && semanticRun < PASSsemantic) 3470: { 3471: /* Add this prefix to the function: 3472: * static int gate; 3473: * if (--gate != 0) return; 3474: * Increment gate during constructor execution. 3475: * Note that this is not thread safe; should not have threads 3476: * during static destruction. 3477: */ 3478: Identifier *id = Lexer::idPool("__gate"); 3479: VarDeclaration *v = new VarDeclaration(0, Type::tint32, id, NULL);
warning C6211: Leaking memory 'v' due to an exception. Consider using a local catch block to clean up memory: Lines: 3460, 3462, 3463, 3469, 3478, 3479, 3480, 3481
3480: v->storage_class = isSharedStaticDtorDeclaration() ? STCstatic : STCtls; 3481: Statements *sa = new Statements();
warning C6211: Leaking memory 'sa' due to an exception. Consider using a local catch block to clean up memory: Lines: 3460, 3462, 3463, 3469, 3478, 3479, 3480, 3481, 3482
3482: Statement *s = new ExpStatement(0, v); 3483: sa->push(s); 3484: Expression *e = new IdentifierExp(0, id); 3485: e = new AddAssignExp(0, e, new IntegerExp(-1)); 3486: e = new EqualExp(TOKnotequal, 0, e, new IntegerExp(0)); 3487: s = new IfStatement(0, NULL, e, new ReturnStatement(0, NULL), NULL); 3488: sa->push(s); 3489: if (fbody) 3490: sa->push(fbody); 3491: fbody = new CompoundStatement(0, sa); 3492: vgate = v; 3493: } 3494: 3495: FuncDeclaration::semantic(sc); 3496: 3497: // We're going to need ModuleInfo 3498: Module *m = getModule(); 3499: if (!m) 3500: m = sc->module; 3501: if (m) 3502: { m->needmoduleinfo = 1; 3503: //printf("module2 %s needs moduleinfo\n", m->toChars()); 3504: #ifdef IN_GCC 3505: m->strictlyneedmoduleinfo = 1; 3506: #endif 3507: } 3508: } 3509: 3510: AggregateDeclaration *StaticDtorDeclaration::isThis() 3511: { 3512: return NULL; 3513: } 3514: 3515: int StaticDtorDeclaration::isVirtual() 3516: { 3517: return FALSE; 3518: } 3519: 3520: int StaticDtorDeclaration::addPreInvariant() 3521: { 3522: return FALSE; 3523: } 3524: 3525: int StaticDtorDeclaration::addPostInvariant() 3526: { 3527: return FALSE; 3528: } 3529: 3530: void StaticDtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3531: { 3532: if (hgs->hdrgen) 3533: return; 3534: buf->writestring("static ~this()"); 3535: bodyToCBuffer(buf, hgs); 3536: } 3537: 3538: /********************************* SharedStaticDtorDeclaration ****************************/ 3539: 3540: SharedStaticDtorDeclaration::SharedStaticDtorDeclaration(Loc loc, Loc endloc) 3541: : StaticDtorDeclaration(loc, endloc, "_sharedStaticDtor") 3542: { 3543: } 3544: 3545: Dsymbol *SharedStaticDtorDeclaration::syntaxCopy(Dsymbol *s) 3546: { 3547: assert(!s); 3548: SharedStaticDtorDeclaration *sdd = new SharedStaticDtorDeclaration(loc, endloc); 3549: return FuncDeclaration::syntaxCopy(sdd); 3550: } 3551: 3552: void SharedStaticDtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3553: { 3554: if (!hgs->hdrgen) 3555: { 3556: buf->writestring("shared "); 3557: StaticDtorDeclaration::toCBuffer(buf, hgs); 3558: } 3559: } 3560: 3561: 3562: /********************************* InvariantDeclaration ****************************/ 3563: 3564: InvariantDeclaration::InvariantDeclaration(Loc loc, Loc endloc) 3565: : FuncDeclaration(loc, endloc, Id::classInvariant, STCundefined, NULL) 3566: { 3567: } 3568: 3569: Dsymbol *InvariantDeclaration::syntaxCopy(Dsymbol *s) 3570: { 3571: InvariantDeclaration *id; 3572: 3573: assert(!s); 3574: id = new InvariantDeclaration(loc, endloc); 3575: FuncDeclaration::syntaxCopy(id); 3576: return id; 3577: } 3578: 3579: 3580: void InvariantDeclaration::semantic(Scope *sc) 3581: { 3582: parent = sc->parent; 3583: Dsymbol *parent = toParent(); 3584: AggregateDeclaration *ad = parent->isAggregateDeclaration(); 3585: if (!ad) 3586: { 3587: error("invariants are only for struct/union/class definitions"); 3588: return; 3589: } 3590: else if (ad->inv && ad->inv != this && semanticRun < PASSsemantic) 3591: { 3592: error("more than one invariant for %s", ad->toChars()); 3593: } 3594: ad->inv = this; 3595: if (!type) 3596: type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); 3597: 3598: sc = sc->push(); 3599: sc->stc &= ~STCstatic; // not a static invariant 3600: sc->incontract++; 3601: sc->linkage = LINKd; 3602: 3603: FuncDeclaration::semantic(sc); 3604: 3605: sc->pop(); 3606: } 3607: 3608: int InvariantDeclaration::isVirtual() 3609: { 3610: return FALSE; 3611: } 3612: 3613: int InvariantDeclaration::addPreInvariant() 3614: { 3615: return FALSE; 3616: } 3617: 3618: int InvariantDeclaration::addPostInvariant() 3619: { 3620: return FALSE; 3621: } 3622: 3623: void InvariantDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3624: { 3625: if (hgs->hdrgen) 3626: return; 3627: buf->writestring("invariant"); 3628: bodyToCBuffer(buf, hgs); 3629: } 3630: 3631: 3632: /********************************* UnitTestDeclaration ****************************/ 3633: 3634: /******************************* 3635: * Generate unique unittest function Id so we can have multiple 3636: * instances per module. 3637: */ 3638: 3639: static Identifier *unitTestId() 3640: { 3641: return Lexer::uniqueId("__unittest"); 3642: } 3643: 3644: UnitTestDeclaration::UnitTestDeclaration(Loc loc, Loc endloc) 3645: : FuncDeclaration(loc, endloc, unitTestId(), STCundefined, NULL) 3646: { 3647: } 3648: 3649: Dsymbol *UnitTestDeclaration::syntaxCopy(Dsymbol *s) 3650: { 3651: UnitTestDeclaration *utd; 3652: 3653: assert(!s); 3654: utd = new UnitTestDeclaration(loc, endloc); 3655: return FuncDeclaration::syntaxCopy(utd); 3656: } 3657: 3658: 3659: void UnitTestDeclaration::semantic(Scope *sc) 3660: { 3661: if (global.params.useUnitTests) 3662: { 3663: if (!type) 3664: type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); 3665: Scope *sc2 = sc->push(); 3666: // It makes no sense for unit tests to be pure or nothrow. 3667: sc2->stc &= ~(STCnothrow | STCpure); 3668: sc2->linkage = LINKd; 3669: FuncDeclaration::semantic(sc2); 3670: sc2->pop(); 3671: } 3672: 3673: #if 0 3674: // We're going to need ModuleInfo even if the unit tests are not 3675: // compiled in, because other modules may import this module and refer 3676: // to this ModuleInfo. 3677: // (This doesn't make sense to me?) 3678: Module *m = getModule(); 3679: if (!m) 3680: m = sc->module; 3681: if (m) 3682: { 3683: //printf("module3 %s needs moduleinfo\n", m->toChars()); 3684: m->needmoduleinfo = 1; 3685: } 3686: #endif 3687: } 3688: 3689: AggregateDeclaration *UnitTestDeclaration::isThis() 3690: { 3691: return NULL; 3692: } 3693: 3694: int UnitTestDeclaration::isVirtual() 3695: { 3696: return FALSE; 3697: } 3698: 3699: int UnitTestDeclaration::addPreInvariant() 3700: { 3701: return FALSE; 3702: } 3703: 3704: int UnitTestDeclaration::addPostInvariant() 3705: { 3706: return FALSE; 3707: } 3708: 3709: void UnitTestDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3710: { 3711: if (hgs->hdrgen) 3712: return; 3713: buf->writestring("unittest"); 3714: bodyToCBuffer(buf, hgs); 3715: } 3716: 3717: /********************************* NewDeclaration ****************************/ 3718: 3719: NewDeclaration::NewDeclaration(Loc loc, Loc endloc, Parameters *arguments, int varargs) 3720: : FuncDeclaration(loc, endloc, Id::classNew, STCstatic, NULL) 3721: { 3722: this->arguments = arguments; 3723: this->varargs = varargs; 3724: } 3725: 3726: Dsymbol *NewDeclaration::syntaxCopy(Dsymbol *s) 3727: { 3728: NewDeclaration *f; 3729: 3730: f = new NewDeclaration(loc, endloc, NULL, varargs); 3731: 3732: FuncDeclaration::syntaxCopy(f); 3733: 3734: f->arguments = Parameter::arraySyntaxCopy(arguments); 3735: 3736: return f; 3737: } 3738: 3739: 3740: void NewDeclaration::semantic(Scope *sc) 3741: { 3742: //printf("NewDeclaration::semantic()\n"); 3743: 3744: parent = sc->parent; 3745: Dsymbol *parent = toParent(); 3746: ClassDeclaration *cd = parent->isClassDeclaration(); 3747: if (!cd && !parent->isStructDeclaration()) 3748: { 3749: error("new allocators only are for class or struct definitions"); 3750: } 3751: Type *tret = Type::tvoid->pointerTo(); 3752: if (!type) 3753: type = new TypeFunction(arguments, tret, varargs, LINKd); 3754: 3755: type = type->semantic(loc, sc); 3756: assert(type->ty == Tfunction); 3757: 3758: // Check that there is at least one argument of type size_t 3759: TypeFunction *tf = (TypeFunction *)type; 3760: if (Parameter::dim(tf->parameters) < 1) 3761: { 3762: error("at least one argument of type size_t expected"); 3763: } 3764: else 3765: { 3766: Parameter *a = Parameter::getNth(tf->parameters, 0); 3767: if (!a->type->equals(Type::tsize_t)) 3768: error("first argument must be type size_t, not %s", a->type->toChars()); 3769: } 3770: 3771: FuncDeclaration::semantic(sc); 3772: } 3773: 3774: const char *NewDeclaration::kind() 3775: { 3776: return "allocator"; 3777: } 3778: 3779: int NewDeclaration::isVirtual() 3780: { 3781: return FALSE; 3782: } 3783: 3784: int NewDeclaration::addPreInvariant() 3785: { 3786: return FALSE; 3787: } 3788: 3789: int NewDeclaration::addPostInvariant() 3790: { 3791: return FALSE; 3792: } 3793: 3794: void NewDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3795: { 3796: buf->writestring("new"); 3797: Parameter::argsToCBuffer(buf, hgs, arguments, varargs); 3798: bodyToCBuffer(buf, hgs); 3799: } 3800: 3801: 3802: /********************************* DeleteDeclaration ****************************/ 3803: 3804: DeleteDeclaration::DeleteDeclaration(Loc loc, Loc endloc, Parameters *arguments) 3805: : FuncDeclaration(loc, endloc, Id::classDelete, STCstatic, NULL) 3806: { 3807: this->arguments = arguments; 3808: } 3809: 3810: Dsymbol *DeleteDeclaration::syntaxCopy(Dsymbol *s) 3811: { 3812: DeleteDeclaration *f; 3813: 3814: f = new DeleteDeclaration(loc, endloc, NULL); 3815: 3816: FuncDeclaration::syntaxCopy(f); 3817: 3818: f->arguments = Parameter::arraySyntaxCopy(arguments); 3819: 3820: return f; 3821: } 3822: 3823: 3824: void DeleteDeclaration::semantic(Scope *sc) 3825: { 3826: //printf("DeleteDeclaration::semantic()\n"); 3827: 3828: parent = sc->parent; 3829: Dsymbol *parent = toParent(); 3830: ClassDeclaration *cd = parent->isClassDeclaration(); 3831: if (!cd && !parent->isStructDeclaration()) 3832: { 3833: error("new allocators only are for class or struct definitions"); 3834: } 3835: if (!type) 3836: type = new TypeFunction(arguments, Type::tvoid, 0, LINKd); 3837: 3838: type = type->semantic(loc, sc); 3839: assert(type->ty == Tfunction); 3840: 3841: // Check that there is only one argument of type void* 3842: TypeFunction *tf = (TypeFunction *)type; 3843: if (Parameter::dim(tf->parameters) != 1) 3844: { 3845: error("one argument of type void* expected"); 3846: } 3847: else 3848: { 3849: Parameter *a = Parameter::getNth(tf->parameters, 0); 3850: if (!a->type->equals(Type::tvoid->pointerTo())) 3851: error("one argument of type void* expected, not %s", a->type->toChars()); 3852: } 3853: 3854: FuncDeclaration::semantic(sc); 3855: } 3856: 3857: const char *DeleteDeclaration::kind() 3858: { 3859: return "deallocator"; 3860: } 3861: 3862: int DeleteDeclaration::isDelete() 3863: { 3864: return TRUE; 3865: } 3866: 3867: int DeleteDeclaration::isVirtual() 3868: { 3869: return FALSE; 3870: } 3871: 3872: int DeleteDeclaration::addPreInvariant() 3873: { 3874: return FALSE; 3875: } 3876: 3877: int DeleteDeclaration::addPostInvariant() 3878: { 3879: return FALSE; 3880: } 3881: 3882: void DeleteDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3883: { 3884: buf->writestring("delete"); 3885: Parameter::argsToCBuffer(buf, hgs, arguments, 0); 3886: bodyToCBuffer(buf, hgs); 3887: } 3888: 3889: 3890: 3891: 3892: