1: 
  2: // Compiler implementation of the D programming language
  3: // Copyright (c) 1999-2011 by Digital Mars
  4: // All Rights Reserved
  5: // written by Walter Bright
  6: // http://www.digitalmars.com
  7: // License for redistribution is by either the Artistic License
  8: // in artistic.txt, or the GNU General Public License in gnu.txt.
  9: // See the included readme.txt for details.
 10: 
 11: #include <stdio.h>
 12: static char __file__[] = __FILE__;      /* for tassert.h                */
 13: #include        "tassert.h"
 14: 
 15: #include "root.h"
 16: #include "aggregate.h"
 17: #include "scope.h"
 18: #include "mtype.h"
 19: #include "declaration.h"
 20: #include "module.h"
 21: #include "id.h"
 22: #include "statement.h"
 23: #include "template.h"
 24: 
 25: /********************************* AggregateDeclaration ****************************/
 26: 
 27: AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
 28:     : ScopeDsymbol(id)
 29: {
 30:     this->loc = loc;
 31: 
 32:     storage_class = 0;
 33:     protection = PROTpublic;
 34:     type = NULL;
 35:     handle = NULL;
 36:     structsize = 0;             // size of struct
 37:     alignsize = 0;              // size of struct for alignment purposes
 38:     structalign = 0;            // struct member alignment in effect
 39:     hasUnions = 0;
 40:     sizeok = 0;                 // size not determined yet
 41:     deferred = NULL;
 42:     isdeprecated = 0;
 43:     inv = NULL;
 44:     aggNew = NULL;
 45:     aggDelete = NULL;
 46: 
 47:     stag = NULL;
 48:     sinit = NULL;
 49:     isnested = 0;
 50:     vthis = NULL;
 51: 
 52: #if DMDV2
 53:     ctor = NULL;
 54:     defaultCtor = NULL;
 55:     aliasthis = NULL;
 56:     noDefaultCtor = FALSE;
 57: #endif
 58:     dtor = NULL;
 59: }
 60: 
 61: enum PROT AggregateDeclaration::prot()
 62: {
 63:     return protection;
 64: }
 65: 
 66: void AggregateDeclaration::semantic2(Scope *sc)
 67: {
 68:     //printf("AggregateDeclaration::semantic2(%s)\n", toChars());
 69:     if (scope && members)
 70:     {   error("has forward references");
 71:         return;
 72:     }
 73:     if (members)
 74:     {
 75:         sc = sc->push(this);
 76:         for (size_t i = 0; i < members->dim; i++)
 77:         {
 78:             Dsymbol *s = members->tdata()[i];
 79:             s->semantic2(sc);
 80:         }
 81:         sc->pop();
 82:     }
 83: }
 84: 
 85: void AggregateDeclaration::semantic3(Scope *sc)
 86: {   int i;
 87: 
 88:     //printf("AggregateDeclaration::semantic3(%s)\n", toChars());
 89:     if (members)
 90:     {
 91:         sc = sc->push(this);
 92:         for (i = 0; i < members->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
93: { 94: Dsymbol *s = members->tdata()[i]; 95: s->semantic3(sc); 96: } 97: sc->pop(); 98: } 99: } 100: 101: void AggregateDeclaration::inlineScan() 102: { int i; 103: 104: //printf("AggregateDeclaration::inlineScan(%s)\n", toChars()); 105: if (members) 106: { 107: for (i = 0; i < members->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
108: { 109: Dsymbol *s = members->tdata()[i]; 110: //printf("inline scan aggregate symbol '%s'\n", s->toChars()); 111: s->inlineScan(); 112: } 113: } 114: } 115: 116: unsigned AggregateDeclaration::size(Loc loc) 117: { 118: //printf("AggregateDeclaration::size() = %d\n", structsize); 119: if (!members) 120: error(loc, "unknown size"); 121: if (sizeok != 1 && scope) 122: semantic(NULL); 123: if (sizeok != 1) 124: { error(loc, "no size yet for forward reference"); 125: //*(char*)0=0; 126: } 127: return structsize; 128: } 129: 130: Type *AggregateDeclaration::getType() 131: { 132: return type; 133: } 134: 135: int AggregateDeclaration::isDeprecated() 136: { 137: return isdeprecated; 138: } 139: 140: /**************************** 141: * Do byte or word alignment as necessary. 142: * Align sizes of 0, as we may not know array sizes yet. 143: */ 144: 145: void AggregateDeclaration::alignmember( 146: unsigned salign, // struct alignment that is in effect 147: unsigned size, // alignment requirement of field 148: unsigned *poffset) 149: { 150: //printf("salign = %d, size = %d, offset = %d\n",salign,size,offset); 151: if (salign > 1) 152: { 153: assert(size != 3); 154: int sa = size; 155: if (sa == 0 || salign < sa)
warning C4018: '<' : signed/unsigned mismatch
156: sa = salign; 157: *poffset = (*poffset + sa - 1) & ~(sa - 1); 158: } 159: //printf("result = %d\n",offset); 160: } 161: 162: 163: void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v) 164: { 165: unsigned memsize; // size of member 166: unsigned memalignsize; // size of member for alignment purposes 167: unsigned xalign; // alignment boundaries 168: 169: //printf("AggregateDeclaration::addField('%s') %s\n", v->toChars(), toChars()); 170: assert(!(v->storage_class & (STCstatic | STCextern | STCparameter | STCtls))); 171: 172: // Check for forward referenced types which will fail the size() call 173: Type *t = v->type->toBasetype(); 174: if (v->storage_class & STCref) 175: { // References are the size of a pointer 176: t = Type::tvoidptr; 177: } 178: if (t->ty == Tstruct /*&& isStructDeclaration()*/) 179: { TypeStruct *ts = (TypeStruct *)t; 180: #if DMDV2 181: if (ts->sym == this) 182: { 183: error("cannot have field %s with same struct type", v->toChars()); 184: } 185: #endif 186: 187: if (ts->sym->sizeok != 1 && ts->sym->scope) 188: ts->sym->semantic(NULL); 189: if (ts->sym->sizeok != 1) 190: { 191: sizeok = 2; // cannot finish; flag as forward referenced 192: return; 193: } 194: } 195: if (t->ty == Tident) 196: { 197: sizeok = 2; // cannot finish; flag as forward referenced 198: return; 199: } 200: 201: memsize = t->size(loc);
warning C4244: '=' : conversion from 'd_uns64' to 'unsigned int', possible loss of data
202: memalignsize = t->alignsize(); 203: xalign = t->memalign(sc->structalign); 204: #if 0 205: alignmember(xalign, memalignsize, &sc->offset); 206: v->offset = sc->offset; 207: sc->offset += memsize; 208: if (sc->offset > structsize) 209: structsize = sc->offset; 210: #else 211: unsigned ofs = sc->offset; 212: alignmember(xalign, memalignsize, &ofs); 213: v->offset = ofs; 214: ofs += memsize; 215: if (ofs > structsize) 216: structsize = ofs; 217: if (!isUnionDeclaration()) 218: sc->offset = ofs; 219: #endif 220: if (global.params.is64bit && sc->structalign == 8 && memalignsize == 16) 221: /* Not sure how to handle this */ 222: ; 223: else if (sc->structalign < memalignsize) 224: memalignsize = sc->structalign; 225: if (alignsize < memalignsize) 226: alignsize = memalignsize; 227: //printf("\t%s: alignsize = %d\n", toChars(), alignsize); 228: 229: v->storage_class |= STCfield; 230: //printf(" addField '%s' to '%s' at offset %d, size = %d\n", v->toChars(), toChars(), v->offset, memsize); 231: fields.push(v); 232: } 233: 234: 235: /**************************************** 236: * Returns !=0 if there's an extra member which is the 'this' 237: * pointer to the enclosing context (enclosing aggregate or function) 238: */ 239: 240: int AggregateDeclaration::isNested() 241: { 242: return isnested; 243: } 244: 245: /**************************************** 246: * If field[indx] is not part of a union, return indx. 247: * Otherwise, return the lowest field index of the union. 248: */ 249: int AggregateDeclaration::firstFieldInUnion(int indx) 250: { 251: if (isUnionDeclaration()) 252: return 0; 253: VarDeclaration * vd = fields.tdata()[indx]; 254: int firstNonZero = indx; // first index in the union with non-zero size 255: for (; ;) 256: { 257: if (indx == 0) 258: return firstNonZero; 259: VarDeclaration * v = fields.tdata()[indx - 1]; 260: if (v->offset != vd->offset) 261: return firstNonZero; 262: --indx; 263: /* If it is a zero-length field, it's ambiguous: we don't know if it is 264: * in the union unless we find an earlier non-zero sized field with the 265: * same offset. 266: */ 267: if (v->size(loc) != 0) 268: firstNonZero = indx; 269: } 270: } 271: 272: /**************************************** 273: * Count the number of fields starting at firstIndex which are part of the 274: * same union as field[firstIndex]. If not a union, return 1. 275: */ 276: int AggregateDeclaration::numFieldsInUnion(int firstIndex) 277: { 278: VarDeclaration * vd = fields.tdata()[firstIndex]; 279: /* If it is a zero-length field, AND we can't find an earlier non-zero 280: * sized field with the same offset, we assume it's not part of a union. 281: */ 282: if (vd->size(loc) == 0 && !isUnionDeclaration() && 283: firstFieldInUnion(firstIndex) == firstIndex) 284: return 1; 285: int count = 1; 286: for (int i = firstIndex+1; i < fields.dim; ++i)
warning C4018: '<' : signed/unsigned mismatch
287: { 288: VarDeclaration * v = fields.tdata()[i]; 289: // If offsets are different, they are not in the same union 290: if (v->offset != vd->offset) 291: break; 292: ++count; 293: } 294: return count; 295: } 296: 297: /********************************* StructDeclaration ****************************/ 298: 299: StructDeclaration::StructDeclaration(Loc loc, Identifier *id) 300: : AggregateDeclaration(loc, id) 301: { 302: zeroInit = 0; // assume false until we do semantic processing 303: #if DMDV2 304: hasIdentityAssign = 0; 305: cpctor = NULL; 306: postblit = NULL; 307: eq = NULL; 308: #endif 309: 310: // For forward references 311: type = new TypeStruct(this); 312: } 313: 314: Dsymbol *StructDeclaration::syntaxCopy(Dsymbol *s) 315: { 316: StructDeclaration *sd; 317: 318: if (s) 319: sd = (StructDeclaration *)s; 320: else 321: sd = new StructDeclaration(loc, ident); 322: ScopeDsymbol::syntaxCopy(sd); 323: return sd; 324: } 325: 326: void StructDeclaration::semantic(Scope *sc) 327: { 328: Scope *sc2; 329: 330: //printf("+StructDeclaration::semantic(this=%p, %s '%s', sizeok = %d)\n", this, parent->toChars(), toChars(), sizeok); 331: 332: //static int count; if (++count == 20) halt(); 333: 334: assert(type); 335: if (!members) // if forward reference 336: return; 337: 338: if (symtab) 339: { if (sizeok == 1 || !scope) 340: { //printf("already completed\n"); 341: scope = NULL; 342: return; // semantic() already completed 343: } 344: } 345: else 346: symtab = new DsymbolTable(); 347: 348: Scope *scx = NULL; 349: if (scope) 350: { sc = scope; 351: scx = scope; // save so we don't make redundant copies 352: scope = NULL; 353: } 354: 355: unsigned dprogress_save = Module::dprogress; 356: 357: parent = sc->parent; 358: type = type->semantic(loc, sc); 359: #if STRUCTTHISREF 360: handle = type; 361: #else 362: handle = type->pointerTo(); 363: #endif 364: structalign = sc->structalign; 365: protection = sc->protection; 366: storage_class |= sc->stc; 367: if (sc->stc & STCdeprecated) 368: isdeprecated = 1; 369: assert(!isAnonymous()); 370: if (sc->stc & STCabstract) 371: error("structs, unions cannot be abstract"); 372: #if DMDV2 373: if (storage_class & STCimmutable) 374: type = type->addMod(MODimmutable); 375: if (storage_class & STCconst) 376: type = type->addMod(MODconst); 377: if (storage_class & STCshared) 378: type = type->addMod(MODshared); 379: #endif 380: 381: if (sizeok == 0) // if not already done the addMember step 382: { 383: int hasfunctions = 0; 384: for (int i = 0; i < members->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
385: { 386: Dsymbol *s = members->tdata()[i]; 387: //printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars()); 388: s->addMember(sc, this, 1); 389: if (s->isFuncDeclaration()) 390: hasfunctions = 1; 391: } 392: 393: // If nested struct, add in hidden 'this' pointer to outer scope 394: if (hasfunctions && !(storage_class & STCstatic)) 395: { Dsymbol *s = toParent2(); 396: if (s) 397: { 398: AggregateDeclaration *ad = s->isAggregateDeclaration(); 399: FuncDeclaration *fd = s->isFuncDeclaration(); 400: 401: TemplateInstance *ti; 402: if (ad && (ti = ad->parent->isTemplateInstance()) != NULL && ti->isnested || fd) 403: { isnested = 1; 404: Type *t; 405: if (ad) 406: t = ad->handle; 407: else if (fd) 408: { AggregateDeclaration *ad = fd->isMember2();
warning C6246: Local declaration of 'ad' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '398' of 'c:\projects\extern\d\dmd\src\struct.c': Lines: 398
409: if (ad) 410: t = ad->handle; 411: else 412: t = Type::tvoidptr; 413: } 414: else 415: assert(0); 416: if (t->ty == Tstruct) 417: t = Type::tvoidptr; // t should not be a ref type 418: assert(!vthis); 419: vthis = new ThisDeclaration(loc, t); 420: //vthis->storage_class |= STCref; 421: members->push(vthis); 422: } 423: } 424: } 425: } 426: 427: sizeok = 0; 428: sc2 = sc->push(this); 429: sc2->stc &= STCsafe | STCtrusted | STCsystem; 430: sc2->parent = this; 431: if (isUnionDeclaration()) 432: sc2->inunion = 1; 433: sc2->protection = PROTpublic; 434: sc2->explicitProtection = 0; 435: 436: int members_dim = members->dim; 437: 438: /* Set scope so if there are forward references, we still might be able to 439: * resolve individual members like enums. 440: */ 441: for (int i = 0; i < members_dim; i++) 442: { Dsymbol *s = members->tdata()[i]; 443: /* There are problems doing this in the general case because 444: * Scope keeps track of things like 'offset' 445: */ 446: if (s->isEnumDeclaration() || (s->isAggregateDeclaration() && s->ident)) 447: { 448: //printf("setScope %s %s\n", s->kind(), s->toChars()); 449: s->setScope(sc2); 450: } 451: } 452: 453: for (int i = 0; i < members_dim; i++) 454: { 455: Dsymbol *s = members->tdata()[i]; 456: s->semantic(sc2); 457: #if 0 458: if (sizeok == 2) 459: { //printf("forward reference\n"); 460: break; 461: } 462: #endif 463: 464: #if 0 /* Decided to allow this because if the field is initialized by copying it from 465: * a correctly initialized struct, it will work. 466: */ 467: Type *t; 468: if (s->isDeclaration() && 469: (t = s->isDeclaration()->type) != NULL && 470: t->toBasetype()->ty == Tstruct) 471: { StructDeclaration *sd = (StructDeclaration *)t->toDsymbol(sc); 472: if (sd->isnested) 473: error("inner struct %s cannot be the type for field %s as it must embed a reference to its enclosing %s", 474: sd->toChars(), s->toChars(), sd->toParent2()->toPrettyChars()); 475: } 476: #endif 477: } 478: 479: #if DMDV1 480: /* This doesn't work for DMDV2 because (ref S) and (S) parameter 481: * lists will overload the same. 482: */ 483: /* The TypeInfo_Struct is expecting an opEquals and opCmp with 484: * a parameter that is a pointer to the struct. But if there 485: * isn't one, but is an opEquals or opCmp with a value, write 486: * another that is a shell around the value: 487: * int opCmp(struct *p) { return opCmp(*p); } 488: */ 489: 490: TypeFunction *tfeqptr; 491: { 492: Parameters *arguments = new Parameters; 493: Parameter *arg = new Parameter(STCin, handle, Id::p, NULL); 494: 495: arguments->push(arg); 496: tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd); 497: tfeqptr = (TypeFunction *)tfeqptr->semantic(0, sc); 498: } 499: 500: TypeFunction *tfeq; 501: { 502: Parameters *arguments = new Parameters; 503: Parameter *arg = new Parameter(STCin, type, NULL, NULL); 504: 505: arguments->push(arg); 506: tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd); 507: tfeq = (TypeFunction *)tfeq->semantic(0, sc); 508: } 509: 510: Identifier *id = Id::eq; 511: for (int i = 0; i < 2; i++) 512: { 513: Dsymbol *s = search_function(this, id); 514: FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL; 515: if (fdx) 516: { FuncDeclaration *fd = fdx->overloadExactMatch(tfeqptr); 517: if (!fd) 518: { fd = fdx->overloadExactMatch(tfeq); 519: if (fd) 520: { // Create the thunk, fdptr 521: FuncDeclaration *fdptr = new FuncDeclaration(loc, loc, fdx->ident, STCundefined, tfeqptr); 522: Expression *e = new IdentifierExp(loc, Id::p); 523: e = new PtrExp(loc, e); 524: Expressions *args = new Expressions(); 525: args->push(e); 526: e = new IdentifierExp(loc, id); 527: e = new CallExp(loc, e, args); 528: fdptr->fbody = new ReturnStatement(loc, e); 529: ScopeDsymbol *s = fdx->parent->isScopeDsymbol(); 530: assert(s); 531: s->members->push(fdptr); 532: fdptr->addMember(sc, s, 1); 533: fdptr->semantic(sc2); 534: } 535: } 536: } 537: 538: id = Id::cmp; 539: } 540: #endif 541: #if DMDV2 542: /* Try to find the opEquals function. Build it if necessary. 543: */ 544: TypeFunction *tfeqptr; 545: { // bool opEquals(const T*) const; 546: Parameters *parameters = new Parameters;
warning C6211: Leaking memory 'parameters' due to an exception. Consider using a local catch block to clean up memory: Lines: 328, 334, 335, 338, 339, 348, 349, 350, 351, 352, 355, 357, 358, 360, 364, 365, 366, 367, 368, 369, 370, 371, 373, 374, 375, 376, 377, 378, 381, 427, 428, 429, 430, 431, 432, 433, 434, 436, 441, 453, 544, 546, 549
547: #if STRUCTTHISREF 548: // bool opEquals(ref const T) const; 549: Parameter *param = new Parameter(STCref, type->constOf(), NULL, NULL); 550: #else 551: // bool opEquals(const T*) const; 552: Parameter *param = new Parameter(STCin, type->pointerTo(), NULL, NULL); 553: #endif 554: 555: parameters->push(param); 556: tfeqptr = new TypeFunction(parameters, Type::tbool, 0, LINKd); 557: tfeqptr->mod = MODconst; 558: tfeqptr = (TypeFunction *)tfeqptr->semantic(0, sc2); 559: 560: Dsymbol *s = search_function(this, Id::eq); 561: FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL; 562: if (fdx) 563: { 564: eq = fdx->overloadExactMatch(tfeqptr); 565: if (!eq) 566: fdx->error("type signature should be %s not %s", tfeqptr->toChars(), fdx->type->toChars()); 567: } 568: 569: TemplateDeclaration *td = s ? s->isTemplateDeclaration() : NULL; 570: // BUG: should also check that td is a function template, not just a template 571: 572: if (!eq && !td) 573: eq = buildOpEquals(sc2); 574: } 575: 576: dtor = buildDtor(sc2); 577: postblit = buildPostBlit(sc2); 578: cpctor = buildCpCtor(sc2); 579: buildOpAssign(sc2); 580: #endif 581: 582: sc2->pop(); 583: 584: if (sizeok == 2) 585: { // semantic() failed because of forward references. 586: // Unwind what we did, and defer it for later 587: fields.setDim(0); 588: structsize = 0; 589: alignsize = 0; 590: structalign = 0; 591: 592: scope = scx ? scx : new Scope(*sc); 593: scope->setNoFree(); 594: scope->module->addDeferredSemantic(this); 595: 596: Module::dprogress = dprogress_save; 597: //printf("\tdeferring %s\n", toChars()); 598: return; 599: } 600: 601: // 0 sized struct's are set to 1 byte 602: if (structsize == 0) 603: { 604: structsize = 1; 605: alignsize = 1; 606: } 607: 608: // Round struct size up to next alignsize boundary. 609: // This will ensure that arrays of structs will get their internals 610: // aligned properly. 611: structsize = (structsize + alignsize - 1) & ~(alignsize - 1); 612: 613: sizeok = 1; 614: Module::dprogress++; 615: 616: //printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars()); 617: 618: // Determine if struct is all zeros or not 619: zeroInit = 1; 620: for (int i = 0; i < fields.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
621: { 622: Dsymbol *s = fields.tdata()[i]; 623: VarDeclaration *vd = s->isVarDeclaration(); 624: if (vd && !vd->isDataseg()) 625: { 626: if (vd->init) 627: { 628: // Should examine init to see if it is really all 0's 629: zeroInit = 0; 630: break; 631: } 632: else 633: { 634: if (!vd->type->isZeroInit(loc)) 635: { 636: zeroInit = 0; 637: break; 638: } 639: } 640: } 641: } 642: 643: /* Look for special member functions. 644: */ 645: #if DMDV2 646: ctor = search(0, Id::ctor, 0); 647: #endif 648: inv = (InvariantDeclaration *)search(0, Id::classInvariant, 0); 649: aggNew = (NewDeclaration *)search(0, Id::classNew, 0); 650: aggDelete = (DeleteDeclaration *)search(0, Id::classDelete, 0); 651: 652: if (sc->func) 653: { 654: semantic2(sc); 655: semantic3(sc); 656: } 657: if (deferred) 658: { 659: deferred->semantic2(sc); 660: deferred->semantic3(sc); 661: } 662: } 663: 664: Dsymbol *StructDeclaration::search(Loc loc, Identifier *ident, int flags) 665: { 666: //printf("%s.StructDeclaration::search('%s')\n", toChars(), ident->toChars()); 667: 668: if (scope && !symtab) 669: semantic(scope); 670: 671: if (!members || !symtab) 672: { 673: error("is forward referenced when looking for '%s'", ident->toChars()); 674: return NULL; 675: } 676: 677: return ScopeDsymbol::search(loc, ident, flags); 678: } 679: 680: void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 681: { int i; 682: 683: buf->printf("%s ", kind()); 684: if (!isAnonymous()) 685: buf->writestring(toChars()); 686: if (!members) 687: { 688: buf->writeByte(';'); 689: buf->writenl(); 690: return; 691: } 692: buf->writenl(); 693: buf->writeByte('{'); 694: buf->writenl(); 695: for (i = 0; i < members->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
696: { 697: Dsymbol *s = members->tdata()[i]; 698: 699: buf->writestring(" "); 700: s->toCBuffer(buf, hgs); 701: } 702: buf->writeByte('}'); 703: buf->writenl(); 704: } 705: 706: 707: const char *StructDeclaration::kind() 708: { 709: return "struct"; 710: } 711: 712: /********************************* UnionDeclaration ****************************/ 713: 714: UnionDeclaration::UnionDeclaration(Loc loc, Identifier *id) 715: : StructDeclaration(loc, id) 716: { 717: hasUnions = 1; 718: } 719: 720: Dsymbol *UnionDeclaration::syntaxCopy(Dsymbol *s) 721: { 722: UnionDeclaration *ud; 723: 724: if (s) 725: ud = (UnionDeclaration *)s; 726: else 727: ud = new UnionDeclaration(loc, ident); 728: StructDeclaration::syntaxCopy(ud); 729: return ud; 730: } 731: 732: 733: const char *UnionDeclaration::kind() 734: { 735: return "union"; 736: } 737: 738: 739: