1: 2: // Compiler implementation of the D programming language 3: // Copyright (c) 1999-2010 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: #include <stdlib.h> 13: static char __file__[] = __FILE__; /* for tassert.h */ 14: #include "tassert.h" 15: 16: #include "rmem.h" 17: 18: #include "init.h" 19: #include "declaration.h" 20: #include "attrib.h" 21: #include "cond.h" 22: #include "scope.h" 23: #include "id.h" 24: #include "expression.h" 25: #include "dsymbol.h" 26: #include "aggregate.h" 27: #include "module.h" 28: #include "parse.h" 29: #include "template.h" 30: #if TARGET_NET 31: #include "frontend.net/pragma.h" 32: #endif 33: 34: extern void obj_includelib(const char *name); 35: void obj_startaddress(Symbol *s); 36: 37: 38: /********************************* AttribDeclaration ****************************/ 39: 40: AttribDeclaration::AttribDeclaration(Dsymbols *decl) 41: : Dsymbol() 42: { 43: this->decl = decl; 44: } 45: 46: Dsymbols *AttribDeclaration::include(Scope *sc, ScopeDsymbol *sd) 47: { 48: return decl; 49: } 50: 51: int AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) 52: { 53: int m = 0; 54: Dsymbols *d = include(sc, sd); 55: 56: if (d) 57: { 58: for (unsigned i = 0; i < d->dim; i++) 59: { Dsymbol *s = d->tdata()[i]; 60: //printf("\taddMember %s to %s\n", s->toChars(), sd->toChars()); 61: m |= s->addMember(sc, sd, m | memnum); 62: } 63: } 64: return m; 65: } 66: 67: void AttribDeclaration::setScopeNewSc(Scope *sc, 68: StorageClass stc, enum LINK linkage, enum PROT protection, int explicitProtection, 69: unsigned structalign) 70: { 71: if (decl) 72: { 73: Scope *newsc = sc; 74: if (stc != sc->stc || 75: linkage != sc->linkage || 76: protection != sc->protection || 77: explicitProtection != sc->explicitProtection || 78: structalign != sc->structalign) 79: { 80: // create new one for changes 81: newsc = new Scope(*sc); 82: newsc->flags &= ~SCOPEfree; 83: newsc->stc = stc; 84: newsc->linkage = linkage; 85: newsc->protection = protection; 86: newsc->explicitProtection = explicitProtection; 87: newsc->structalign = structalign; 88: } 89: for (unsigned i = 0; i < decl->dim; i++) 90: { Dsymbol *s = decl->tdata()[i]; 91: 92: s->setScope(newsc); // yes, the only difference from semanticNewSc() 93: } 94: if (newsc != sc) 95: { 96: sc->offset = newsc->offset; 97: newsc->pop(); 98: } 99: } 100: } 101: 102: void AttribDeclaration::semanticNewSc(Scope *sc, 103: StorageClass stc, enum LINK linkage, enum PROT protection, int explicitProtection, 104: unsigned structalign) 105: { 106: if (decl) 107: { 108: Scope *newsc = sc; 109: if (stc != sc->stc || 110: linkage != sc->linkage || 111: protection != sc->protection || 112: explicitProtection != sc->explicitProtection || 113: structalign != sc->structalign) 114: { 115: // create new one for changes 116: newsc = new Scope(*sc); 117: newsc->flags &= ~SCOPEfree; 118: newsc->stc = stc; 119: newsc->linkage = linkage; 120: newsc->protection = protection; 121: newsc->explicitProtection = explicitProtection; 122: newsc->structalign = structalign; 123: } 124: for (unsigned i = 0; i < decl->dim; i++) 125: { Dsymbol *s = decl->tdata()[i]; 126: 127: s->semantic(newsc); 128: } 129: if (newsc != sc) 130: { 131: sc->offset = newsc->offset; 132: newsc->pop(); 133: } 134: } 135: } 136: 137: void AttribDeclaration::semantic(Scope *sc) 138: { 139: Dsymbols *d = include(sc, NULL); 140: 141: //printf("\tAttribDeclaration::semantic '%s', d = %p\n",toChars(), d); 142: if (d) 143: { 144: for (unsigned i = 0; i < d->dim; i++) 145: { 146: Dsymbol *s = d->tdata()[i]; 147: 148: s->semantic(sc); 149: } 150: } 151: } 152: 153: void AttribDeclaration::semantic2(Scope *sc) 154: { 155: Dsymbols *d = include(sc, NULL); 156: 157: if (d) 158: { 159: for (unsigned i = 0; i < d->dim; i++) 160: { Dsymbol *s = d->tdata()[i]; 161: s->semantic2(sc); 162: } 163: } 164: } 165: 166: void AttribDeclaration::semantic3(Scope *sc) 167: { 168: Dsymbols *d = include(sc, NULL); 169: 170: if (d) 171: { 172: for (unsigned i = 0; i < d->dim; i++) 173: { Dsymbol *s = d->tdata()[i]; 174: s->semantic3(sc); 175: } 176: } 177: } 178: 179: void AttribDeclaration::inlineScan() 180: { 181: Dsymbols *d = include(NULL, NULL); 182: 183: if (d) 184: { 185: for (unsigned i = 0; i < d->dim; i++) 186: { Dsymbol *s = d->tdata()[i]; 187: //printf("AttribDeclaration::inlineScan %s\n", s->toChars()); 188: s->inlineScan(); 189: } 190: } 191: } 192: 193: void AttribDeclaration::addComment(unsigned char *comment) 194: { 195: //printf("AttribDeclaration::addComment %s\n", comment); 196: if (comment) 197: { 198: Dsymbols *d = include(NULL, NULL); 199: 200: if (d) 201: { 202: for (unsigned i = 0; i < d->dim; i++) 203: { Dsymbol *s = d->tdata()[i]; 204: //printf("AttribDeclaration::addComment %s\n", s->toChars()); 205: s->addComment(comment); 206: } 207: } 208: } 209: } 210: 211: void AttribDeclaration::emitComment(Scope *sc) 212: { 213: //printf("AttribDeclaration::emitComment(sc = %p)\n", sc); 214: 215: /* A general problem with this, illustrated by BUGZILLA 2516, 216: * is that attributes are not transmitted through to the underlying 217: * member declarations for template bodies, because semantic analysis 218: * is not done for template declaration bodies 219: * (only template instantiations). 220: * Hence, Ddoc omits attributes from template members. 221: */ 222: 223: Dsymbols *d = include(NULL, NULL); 224: 225: if (d) 226: { 227: for (unsigned i = 0; i < d->dim; i++) 228: { Dsymbol *s = d->tdata()[i]; 229: //printf("AttribDeclaration::emitComment %s\n", s->toChars()); 230: s->emitComment(sc); 231: } 232: } 233: } 234: 235: void AttribDeclaration::toObjFile(int multiobj) 236: { 237: Dsymbols *d = include(NULL, NULL); 238: 239: if (d) 240: { 241: for (unsigned i = 0; i < d->dim; i++) 242: { Dsymbol *s = d->tdata()[i]; 243: s->toObjFile(multiobj); 244: } 245: } 246: } 247: 248: int AttribDeclaration::cvMember(unsigned char *p) 249: { 250: int nwritten = 0; 251: int n; 252: Dsymbols *d = include(NULL, NULL); 253: 254: if (d) 255: { 256: for (unsigned i = 0; i < d->dim; i++) 257: { Dsymbol *s = d->tdata()[i]; 258: n = s->cvMember(p); 259: if (p) 260: p += n; 261: nwritten += n; 262: } 263: } 264: return nwritten; 265: } 266: 267: int AttribDeclaration::hasPointers() 268: { 269: Dsymbols *d = include(NULL, NULL); 270: 271: if (d) 272: { 273: for (size_t i = 0; i < d->dim; i++) 274: { 275: Dsymbol *s = d->tdata()[i]; 276: if (s->hasPointers()) 277: return 1; 278: } 279: } 280: return 0; 281: } 282: 283: const char *AttribDeclaration::kind() 284: { 285: return "attribute"; 286: } 287: 288: int AttribDeclaration::oneMember(Dsymbol **ps) 289: { 290: Dsymbols *d = include(NULL, NULL); 291: 292: return Dsymbol::oneMembers(d, ps); 293: } 294: 295: void AttribDeclaration::checkCtorConstInit() 296: { 297: Dsymbols *d = include(NULL, NULL); 298: 299: if (d) 300: { 301: for (unsigned i = 0; i < d->dim; i++) 302: { Dsymbol *s = d->tdata()[i]; 303: s->checkCtorConstInit(); 304: } 305: } 306: } 307: 308: /**************************************** 309: */ 310: 311: void AttribDeclaration::addLocalClass(ClassDeclarations *aclasses) 312: { 313: Dsymbols *d = include(NULL, NULL); 314: 315: if (d) 316: { 317: for (unsigned i = 0; i < d->dim; i++) 318: { Dsymbol *s = d->tdata()[i]; 319: s->addLocalClass(aclasses); 320: } 321: } 322: } 323: 324: 325: void AttribDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 326: { 327: if (decl) 328: { 329: if (decl->dim == 0) 330: buf->writestring("{}"); 331: else if (decl->dim == 1) 332: (decl->tdata()[0])->toCBuffer(buf, hgs); 333: else 334: { 335: buf->writenl(); 336: buf->writeByte('{'); 337: buf->writenl(); 338: for (unsigned i = 0; i < decl->dim; i++) 339: { 340: Dsymbol *s = decl->tdata()[i]; 341: 342: buf->writestring(" "); 343: s->toCBuffer(buf, hgs); 344: } 345: buf->writeByte('}'); 346: } 347: } 348: else 349: buf->writeByte(';'); 350: buf->writenl(); 351: } 352: 353: /************************* StorageClassDeclaration ****************************/ 354: 355: StorageClassDeclaration::StorageClassDeclaration(StorageClass stc, Dsymbols *decl) 356: : AttribDeclaration(decl) 357: { 358: this->stc = stc; 359: } 360: 361: Dsymbol *StorageClassDeclaration::syntaxCopy(Dsymbol *s) 362: { 363: StorageClassDeclaration *scd; 364: 365: assert(!s); 366: scd = new StorageClassDeclaration(stc, Dsymbol::arraySyntaxCopy(decl)); 367: return scd; 368: } 369: 370: void StorageClassDeclaration::setScope(Scope *sc) 371: { 372: if (decl) 373: { 374: StorageClass scstc = sc->stc; 375: 376: /* These sets of storage classes are mutually exclusive, 377: * so choose the innermost or most recent one. 378: */ 379: if (stc & (STCauto | STCscope | STCstatic | STCextern | STCmanifest)) 380: scstc &= ~(STCauto | STCscope | STCstatic | STCextern | STCmanifest); 381: if (stc & (STCauto | STCscope | STCstatic | STCtls | STCmanifest | STCgshared)) 382: scstc &= ~(STCauto | STCscope | STCstatic | STCtls | STCmanifest | STCgshared); 383: if (stc & (STCconst | STCimmutable | STCmanifest)) 384: scstc &= ~(STCconst | STCimmutable | STCmanifest); 385: if (stc & (STCgshared | STCshared | STCtls)) 386: scstc &= ~(STCgshared | STCshared | STCtls); 387: if (stc & (STCsafe | STCtrusted | STCsystem)) 388: scstc &= ~(STCsafe | STCtrusted | STCsystem); 389: scstc |= stc; 390: 391: setScopeNewSc(sc, scstc, sc->linkage, sc->protection, sc->explicitProtection, sc->structalign); 392: } 393: } 394: 395: void StorageClassDeclaration::semantic(Scope *sc) 396: { 397: if (decl) 398: { 399: StorageClass scstc = sc->stc; 400: 401: /* These sets of storage classes are mutually exclusive, 402: * so choose the innermost or most recent one. 403: */ 404: if (stc & (STCauto | STCscope | STCstatic | STCextern | STCmanifest)) 405: scstc &= ~(STCauto | STCscope | STCstatic | STCextern | STCmanifest); 406: if (stc & (STCauto | STCscope | STCstatic | STCtls | STCmanifest | STCgshared)) 407: scstc &= ~(STCauto | STCscope | STCstatic | STCtls | STCmanifest | STCgshared); 408: if (stc & (STCconst | STCimmutable | STCmanifest)) 409: scstc &= ~(STCconst | STCimmutable | STCmanifest); 410: if (stc & (STCgshared | STCshared | STCtls)) 411: scstc &= ~(STCgshared | STCshared | STCtls); 412: if (stc & (STCsafe | STCtrusted | STCsystem)) 413: scstc &= ~(STCsafe | STCtrusted | STCsystem); 414: scstc |= stc; 415: 416: semanticNewSc(sc, scstc, sc->linkage, sc->protection, sc->explicitProtection, sc->structalign); 417: } 418: } 419: 420: void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, StorageClass stc) 421: { 422: struct SCstring 423: { 424: StorageClass stc; 425: enum TOK tok; 426: Identifier *id; 427: }; 428: 429: static SCstring table[] = 430: { 431: { STCauto, TOKauto }, 432: { STCscope, TOKscope }, 433: { STCstatic, TOKstatic }, 434: { STCextern, TOKextern }, 435: { STCconst, TOKconst }, 436: { STCfinal, TOKfinal }, 437: { STCabstract, TOKabstract }, 438: { STCsynchronized, TOKsynchronized }, 439: { STCdeprecated, TOKdeprecated }, 440: { STCoverride, TOKoverride }, 441: { STClazy, TOKlazy }, 442: { STCalias, TOKalias }, 443: { STCout, TOKout }, 444: { STCin, TOKin }, 445: #if DMDV2 446: { STCmanifest, TOKenum }, 447: { STCimmutable, TOKimmutable }, 448: { STCshared, TOKshared }, 449: { STCnothrow, TOKnothrow }, 450: { STCpure, TOKpure }, 451: { STCref, TOKref }, 452: { STCtls, TOKtls }, 453: { STCgshared, TOKgshared }, 454: { STCproperty, TOKat, Id::property }, 455: { STCsafe, TOKat, Id::safe }, 456: { STCtrusted, TOKat, Id::trusted }, 457: { STCsystem, TOKat, Id::system }, 458: { STCdisable, TOKat, Id::disable }, 459: #endif 460: }; 461: 462: for (int i = 0; i < sizeof(table)/sizeof(table[0]); i++) 463: { 464: if (stc & table[i].stc) 465: { 466: enum TOK tok = table[i].tok; 467: #if DMDV2 468: if (tok == TOKat) 469: { 470: buf->writeByte('@'); 471: buf->writestring(table[i].id->toChars()); 472: } 473: else 474: #endif 475: buf->writestring(Token::toChars(tok)); 476: buf->writeByte(' '); 477: } 478: } 479: } 480: 481: void StorageClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 482: { 483: stcToCBuffer(buf, stc); 484: AttribDeclaration::toCBuffer(buf, hgs); 485: } 486: 487: /********************************* LinkDeclaration ****************************/ 488: 489: LinkDeclaration::LinkDeclaration(enum LINK p, Dsymbols *decl) 490: : AttribDeclaration(decl) 491: { 492: //printf("LinkDeclaration(linkage = %d, decl = %p)\n", p, decl); 493: linkage = p; 494: } 495: 496: Dsymbol *LinkDeclaration::syntaxCopy(Dsymbol *s) 497: { 498: LinkDeclaration *ld; 499: 500: assert(!s); 501: ld = new LinkDeclaration(linkage, Dsymbol::arraySyntaxCopy(decl)); 502: return ld; 503: } 504: 505: void LinkDeclaration::setScope(Scope *sc) 506: { 507: //printf("LinkDeclaration::setScope(linkage = %d, decl = %p)\n", linkage, decl); 508: if (decl) 509: { 510: setScopeNewSc(sc, sc->stc, linkage, sc->protection, sc->explicitProtection, sc->structalign); 511: } 512: } 513: 514: void LinkDeclaration::semantic(Scope *sc) 515: { 516: //printf("LinkDeclaration::semantic(linkage = %d, decl = %p)\n", linkage, decl); 517: if (decl) 518: { 519: semanticNewSc(sc, sc->stc, linkage, sc->protection, sc->explicitProtection, sc->structalign); 520: } 521: } 522: 523: void LinkDeclaration::semantic3(Scope *sc) 524: { 525: //printf("LinkDeclaration::semantic3(linkage = %d, decl = %p)\n", linkage, decl); 526: if (decl) 527: { enum LINK linkage_save = sc->linkage; 528: 529: sc->linkage = linkage; 530: for (unsigned i = 0; i < decl->dim; i++) 531: { 532: Dsymbol *s = decl->tdata()[i]; 533: 534: s->semantic3(sc); 535: } 536: sc->linkage = linkage_save; 537: } 538: else 539: { 540: sc->linkage = linkage; 541: } 542: } 543: 544: void LinkDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 545: { const char *p; 546: 547: switch (linkage) 548: { 549: case LINKd: p = "D"; break; 550: case LINKc: p = "C"; break; 551: case LINKcpp: p = "C++"; break; 552: case LINKwindows: p = "Windows"; break; 553: case LINKpascal: p = "Pascal"; break; 554: default: 555: assert(0); 556: break; 557: } 558: buf->writestring("extern ("); 559: buf->writestring(p); 560: buf->writestring(") "); 561: AttribDeclaration::toCBuffer(buf, hgs); 562: } 563: 564: char *LinkDeclaration::toChars() 565: { 566: return (char *)"extern ()"; 567: } 568: 569: /********************************* ProtDeclaration ****************************/ 570: 571: ProtDeclaration::ProtDeclaration(enum PROT p, Dsymbols *decl) 572: : AttribDeclaration(decl) 573: { 574: protection = p; 575: //printf("decl = %p\n", decl); 576: } 577: 578: Dsymbol *ProtDeclaration::syntaxCopy(Dsymbol *s) 579: { 580: ProtDeclaration *pd; 581: 582: assert(!s); 583: pd = new ProtDeclaration(protection, Dsymbol::arraySyntaxCopy(decl)); 584: return pd; 585: } 586: 587: void ProtDeclaration::setScope(Scope *sc) 588: { 589: if (decl) 590: { 591: setScopeNewSc(sc, sc->stc, sc->linkage, protection, 1, sc->structalign); 592: } 593: } 594: 595: void ProtDeclaration::importAll(Scope *sc) 596: { 597: Scope *newsc = sc; 598: if (sc->protection != protection || 599: sc->explicitProtection != 1) 600: { 601: // create new one for changes 602: newsc = new Scope(*sc); 603: newsc->flags &= ~SCOPEfree; 604: newsc->protection = protection; 605: newsc->explicitProtection = 1; 606: } 607: 608: for (int i = 0; i < decl->dim; i++)warning C4018: '<' : signed/unsigned mismatch609: { 610: Dsymbol *s = decl->tdata()[i]; 611: s->importAll(newsc); 612: } 613: 614: if (newsc != sc) 615: newsc->pop(); 616: } 617: 618: void ProtDeclaration::semantic(Scope *sc) 619: { 620: if (decl) 621: { 622: semanticNewSc(sc, sc->stc, sc->linkage, protection, 1, sc->structalign); 623: } 624: } 625: 626: void ProtDeclaration::protectionToCBuffer(OutBuffer *buf, enum PROT protection) 627: { 628: const char *p; 629: 630: switch (protection) 631: { 632: case PROTprivate: p = "private"; break; 633: case PROTpackage: p = "package"; break; 634: case PROTprotected: p = "protected"; break; 635: case PROTpublic: p = "public"; break; 636: case PROTexport: p = "export"; break; 637: default: 638: assert(0); 639: break; 640: } 641: buf->writestring(p); 642: buf->writeByte(' '); 643: } 644: 645: void ProtDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 646: { 647: protectionToCBuffer(buf, protection); 648: AttribDeclaration::toCBuffer(buf, hgs); 649: } 650: 651: /********************************* AlignDeclaration ****************************/ 652: 653: AlignDeclaration::AlignDeclaration(unsigned sa, Dsymbols *decl) 654: : AttribDeclaration(decl) 655: { 656: salign = sa; 657: } 658: 659: Dsymbol *AlignDeclaration::syntaxCopy(Dsymbol *s) 660: { 661: AlignDeclaration *ad; 662: 663: assert(!s); 664: ad = new AlignDeclaration(salign, Dsymbol::arraySyntaxCopy(decl)); 665: return ad; 666: } 667: 668: void AlignDeclaration::setScope(Scope *sc) 669: { 670: //printf("\tAlignDeclaration::setScope '%s'\n",toChars()); 671: if (decl) 672: { 673: setScopeNewSc(sc, sc->stc, sc->linkage, sc->protection, sc->explicitProtection, salign); 674: } 675: } 676: 677: void AlignDeclaration::semantic(Scope *sc) 678: { 679: //printf("\tAlignDeclaration::semantic '%s'\n",toChars()); 680: if (decl) 681: { 682: semanticNewSc(sc, sc->stc, sc->linkage, sc->protection, sc->explicitProtection, salign); 683: } 684: } 685: 686: 687: void AlignDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 688: { 689: buf->printf("align (%d)", salign); 690: AttribDeclaration::toCBuffer(buf, hgs); 691: } 692: 693: /********************************* AnonDeclaration ****************************/ 694: 695: AnonDeclaration::AnonDeclaration(Loc loc, int isunion, Dsymbols *decl) 696: : AttribDeclaration(decl) 697: { 698: this->loc = loc; 699: this->isunion = isunion; 700: this->sem = 0; 701: } 702: 703: Dsymbol *AnonDeclaration::syntaxCopy(Dsymbol *s) 704: { 705: AnonDeclaration *ad; 706: 707: assert(!s); 708: ad = new AnonDeclaration(loc, isunion, Dsymbol::arraySyntaxCopy(decl)); 709: return ad; 710: } 711: 712: void AnonDeclaration::semantic(Scope *sc) 713: { 714: //printf("\tAnonDeclaration::semantic %s %p\n", isunion ? "union" : "struct", this); 715: 716: if (sem == 1) 717: { //printf("already completed\n"); 718: scope = NULL; 719: return; // semantic() already completed 720: } 721: 722: Scope *scx = NULL; 723: if (scope) 724: { sc = scope; 725: scx = scope; 726: scope = NULL; 727: } 728: 729: unsigned dprogress_save = Module::dprogress; 730: 731: assert(sc->parent); 732: 733: Dsymbol *parent = sc->parent->pastMixin(); 734: AggregateDeclaration *ad = parent->isAggregateDeclaration(); 735: 736: if (!ad || (!ad->isStructDeclaration() && !ad->isClassDeclaration())) 737: { 738: error("can only be a part of an aggregate"); 739: return; 740: } 741: 742: if (decl) 743: { 744: AnonymousAggregateDeclaration aad; 745: int adisunion; 746: 747: if (sc->anonAgg) 748: { ad = sc->anonAgg; 749: adisunion = sc->inunion; 750: } 751: else 752: adisunion = ad->isUnionDeclaration() != NULL; 753: 754: // printf("\tsc->anonAgg = %p\n", sc->anonAgg); 755: // printf("\tad = %p\n", ad); 756: // printf("\taad = %p\n", &aad); 757: 758: sc = sc->push(); 759: sc->anonAgg = &aad; 760: sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls | STCgshared); 761: sc->inunion = isunion; 762: sc->offset = 0; 763: sc->flags = 0; 764: aad.structalign = sc->structalign; 765: aad.parent = ad; 766: 767: for (unsigned i = 0; i < decl->dim; i++) 768: { 769: Dsymbol *s = decl->tdata()[i]; 770: 771: s->semantic(sc); 772: if (isunion) 773: sc->offset = 0; 774: if (aad.sizeok == 2) 775: { 776: break; 777: } 778: } 779: sc = sc->pop(); 780: 781: // If failed due to forward references, unwind and try again later 782: if (aad.sizeok == 2) 783: { 784: ad->sizeok = 2; 785: //printf("\tsetting ad->sizeok %p to 2\n", ad); 786: if (!sc->anonAgg) 787: { 788: scope = scx ? scx : new Scope(*sc); 789: scope->setNoFree(); 790: scope->module->addDeferredSemantic(this); 791: } 792: Module::dprogress = dprogress_save; 793: //printf("\tforward reference %p\n", this); 794: return; 795: } 796: if (sem == 0) 797: { Module::dprogress++; 798: sem = 1; 799: //printf("\tcompleted %p\n", this); 800: } 801: else 802: ;//printf("\talready completed %p\n", this); 803: 804: // 0 sized structs are set to 1 byte 805: if (aad.structsize == 0) 806: { 807: aad.structsize = 1; 808: aad.alignsize = 1; 809: } 810: 811: // Align size of anonymous aggregate 812: //printf("aad.structalign = %d, aad.alignsize = %d, sc->offset = %d\n", aad.structalign, aad.alignsize, sc->offset); 813: ad->alignmember(aad.structalign, aad.alignsize, &sc->offset); 814: //ad->structsize = sc->offset; 815: //printf("sc->offset = %d\n", sc->offset); 816: 817: // Add members of aad to ad 818: //printf("\tadding members of aad to '%s'\n", ad->toChars()); 819: for (unsigned i = 0; i < aad.fields.dim; i++) 820: { 821: VarDeclaration *v = aad.fields.tdata()[i]; 822: 823: v->offset += sc->offset; 824: ad->fields.push(v); 825: } 826: 827: // Add size of aad to ad 828: if (adisunion) 829: { 830: if (aad.structsize > ad->structsize) 831: ad->structsize = aad.structsize; 832: sc->offset = 0; 833: } 834: else 835: { 836: ad->structsize = sc->offset + aad.structsize; 837: sc->offset = ad->structsize; 838: } 839: 840: if (ad->alignsize < aad.alignsize) 841: ad->alignsize = aad.alignsize; 842: } 843: } 844: 845: 846: void AnonDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 847: { 848: buf->printf(isunion ? "union" : "struct"); 849: buf->writestring("\n{\n"); 850: if (decl) 851: { 852: for (unsigned i = 0; i < decl->dim; i++) 853: { 854: Dsymbol *s = decl->tdata()[i]; 855: 856: //buf->writestring(" "); 857: s->toCBuffer(buf, hgs); 858: } 859: } 860: buf->writestring("}\n"); 861: } 862: 863: const char *AnonDeclaration::kind() 864: { 865: return (isunion ? "anonymous union" : "anonymous struct"); 866: } 867: 868: /********************************* PragmaDeclaration ****************************/ 869: 870: PragmaDeclaration::PragmaDeclaration(Loc loc, Identifier *ident, Expressions *args, Dsymbols *decl) 871: : AttribDeclaration(decl) 872: { 873: this->loc = loc; 874: this->ident = ident; 875: this->args = args; 876: } 877: 878: Dsymbol *PragmaDeclaration::syntaxCopy(Dsymbol *s) 879: { 880: //printf("PragmaDeclaration::syntaxCopy(%s)\n", toChars()); 881: PragmaDeclaration *pd; 882: 883: assert(!s); 884: pd = new PragmaDeclaration(loc, ident, 885: Expression::arraySyntaxCopy(args), Dsymbol::arraySyntaxCopy(decl)); 886: return pd; 887: } 888: 889: void PragmaDeclaration::setScope(Scope *sc) 890: { 891: #if TARGET_NET 892: if (ident == Lexer::idPool("assembly")) 893: { 894: if (!args || args->dim != 1) 895: { 896: error("pragma has invalid number of arguments"); 897: } 898: else 899: { 900: Expression *e = args->tdata()[0]; 901: e = e->semantic(sc); 902: e = e->optimize(WANTvalue | WANTinterpret); 903: args->tdata()[0] = e; 904: if (e->op != TOKstring) 905: { 906: error("string expected, not '%s'", e->toChars()); 907: } 908: PragmaScope* pragma = new PragmaScope(this, sc->parent, static_cast<StringExp*>(e)); 909: 910: assert(sc); 911: pragma->setScope(sc); 912: 913: //add to module members 914: assert(sc->module); 915: assert(sc->module->members); 916: sc->module->members->push(pragma); 917: } 918: } 919: #endif // TARGET_NET 920: } 921: 922: void PragmaDeclaration::semantic(Scope *sc) 923: { // Should be merged with PragmaStatement 924: 925: //printf("\tPragmaDeclaration::semantic '%s'\n",toChars()); 926: if (ident == Id::msg) 927: { 928: if (args) 929: { 930: for (size_t i = 0; i < args->dim; i++) 931: { 932: Expression *e = args->tdata()[i]; 933: 934: e = e->semantic(sc); 935: e = e->optimize(WANTvalue | WANTinterpret); 936: if (e->op == TOKstring) 937: { 938: StringExp *se = (StringExp *)e; 939: fprintf(stdmsg, "%.*s", (int)se->len, (char *)se->string); 940: } 941: else 942: fprintf(stdmsg, "%s", e->toChars()); 943: } 944: fprintf(stdmsg, "\n"); 945: } 946: goto Lnodecl; 947: } 948: else if (ident == Id::lib) 949: { 950: if (!args || args->dim != 1) 951: error("string expected for library name"); 952: else 953: { 954: Expression *e = args->tdata()[0]; 955: 956: e = e->semantic(sc); 957: e = e->optimize(WANTvalue | WANTinterpret); 958: args->tdata()[0] = e; 959: if (e->op == TOKerror) 960: goto Lnodecl; 961: if (e->op != TOKstring) 962: error("string expected for library name, not '%s'", e->toChars()); 963: else if (global.params.verbose) 964: { 965: StringExp *se = (StringExp *)e; 966: char *name = (char *)mem.malloc(se->len + 1); 967: memcpy(name, se->string, se->len); 968: name[se->len] = 0; 969: printf("library %s\n", name); 970: mem.free(name); 971: } 972: } 973: goto Lnodecl; 974: } 975: #if IN_GCC 976: else if (ident == Id::GNU_asm) 977: { 978: if (! args || args->dim != 2) 979: error("identifier and string expected for asm name"); 980: else 981: { 982: Expression *e; 983: Declaration *d = NULL; 984: StringExp *s = NULL; 985: 986: e = args->tdata()[0]; 987: e = e->semantic(sc); 988: if (e->op == TOKvar) 989: { 990: d = ((VarExp *)e)->var; 991: if (! d->isFuncDeclaration() && ! d->isVarDeclaration()) 992: d = NULL; 993: } 994: if (!d) 995: error("first argument of GNU_asm must be a function or variable declaration"); 996: 997: e = args->tdata()[1]; 998: e = e->semantic(sc); 999: e = e->optimize(WANTvalue); 1000: if (e->op == TOKstring && ((StringExp *)e)->sz == 1) 1001: s = ((StringExp *)e); 1002: else 1003: error("second argument of GNU_asm must be a char string"); 1004: 1005: if (d && s) 1006: d->c_ident = Lexer::idPool((char*) s->string); 1007: } 1008: goto Lnodecl; 1009: } 1010: #endif 1011: #if DMDV2 1012: else if (ident == Id::startaddress) 1013: { 1014: if (!args || args->dim != 1) 1015: error("function name expected for start address"); 1016: else 1017: { 1018: Expression *e = args->tdata()[0]; 1019: e = e->semantic(sc); 1020: e = e->optimize(WANTvalue | WANTinterpret); 1021: args->tdata()[0] = e; 1022: Dsymbol *sa = getDsymbol(e); 1023: if (!sa || !sa->isFuncDeclaration()) 1024: error("function name expected for start address, not '%s'", e->toChars()); 1025: } 1026: goto Lnodecl; 1027: } 1028: #endif 1029: #if TARGET_NET 1030: else if (ident == Lexer::idPool("assembly")) 1031: { 1032: } 1033: #endif // TARGET_NET 1034: else if (global.params.ignoreUnsupportedPragmas) 1035: { 1036: if (global.params.verbose) 1037: { 1038: /* Print unrecognized pragmas 1039: */ 1040: printf("pragma %s", ident->toChars()); 1041: if (args) 1042: { 1043: for (size_t i = 0; i < args->dim; i++) 1044: { 1045: Expression *e = args->tdata()[i]; 1046: e = e->semantic(sc); 1047: e = e->optimize(WANTvalue | WANTinterpret); 1048: if (i == 0) 1049: printf(" ("); 1050: else 1051: printf(","); 1052: printf("%s", e->toChars()); 1053: } 1054: if (args->dim) 1055: printf(")"); 1056: } 1057: printf("\n"); 1058: } 1059: goto Lnodecl; 1060: } 1061: else 1062: error("unrecognized pragma(%s)", ident->toChars()); 1063: 1064: if (decl) 1065: { 1066: for (unsigned i = 0; i < decl->dim; i++) 1067: { 1068: Dsymbol *s = decl->tdata()[i]; 1069: 1070: s->semantic(sc); 1071: } 1072: } 1073: return; 1074: 1075: Lnodecl: 1076: if (decl) 1077: error("pragma is missing closing ';'"); 1078: } 1079: 1080: int PragmaDeclaration::oneMember(Dsymbol **ps) 1081: { 1082: *ps = NULL; 1083: return TRUE; 1084: } 1085: 1086: const char *PragmaDeclaration::kind() 1087: { 1088: return "pragma"; 1089: } 1090: 1091: void PragmaDeclaration::toObjFile(int multiobj) 1092: { 1093: if (ident == Id::lib) 1094: { 1095: assert(args && args->dim == 1); 1096: 1097: Expression *e = args->tdata()[0]; 1098: 1099: assert(e->op == TOKstring); 1100: 1101: StringExp *se = (StringExp *)e; 1102: char *name = (char *)mem.malloc(se->len + 1); 1103: memcpy(name, se->string, se->len); 1104: name[se->len] = 0; 1105: #if OMFOBJ 1106: /* The OMF format allows library names to be inserted 1107: * into the object file. The linker will then automatically 1108: * search that library, too. 1109: */ 1110: obj_includelib(name); 1111: #elif ELFOBJ || MACHOBJ 1112: /* The format does not allow embedded library names, 1113: * so instead append the library name to the list to be passed 1114: * to the linker. 1115: */ 1116: global.params.libfiles->push(name); 1117: #else 1118: error("pragma lib not supported"); 1119: #endif 1120: } 1121: #if DMDV2 1122: else if (ident == Id::startaddress) 1123: { 1124: assert(args && args->dim == 1); 1125: Expression *e = args->tdata()[0]; 1126: Dsymbol *sa = getDsymbol(e); 1127: FuncDeclaration *f = sa->isFuncDeclaration(); 1128: assert(f); 1129: Symbol *s = f->toSymbol(); 1130: obj_startaddress(s); 1131: } 1132: #endif 1133: AttribDeclaration::toObjFile(multiobj); 1134: } 1135: 1136: void PragmaDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 1137: { 1138: buf->printf("pragma (%s", ident->toChars()); 1139: if (args && args->dim) 1140: { 1141: buf->writestring(", "); 1142: argsToCBuffer(buf, args, hgs); 1143: } 1144: buf->writeByte(')'); 1145: AttribDeclaration::toCBuffer(buf, hgs); 1146: } 1147: 1148: 1149: /********************************* ConditionalDeclaration ****************************/ 1150: 1151: ConditionalDeclaration::ConditionalDeclaration(Condition *condition, Dsymbols *decl, Dsymbols *elsedecl) 1152: : AttribDeclaration(decl) 1153: { 1154: //printf("ConditionalDeclaration::ConditionalDeclaration()\n"); 1155: this->condition = condition; 1156: this->elsedecl = elsedecl; 1157: } 1158: 1159: Dsymbol *ConditionalDeclaration::syntaxCopy(Dsymbol *s) 1160: { 1161: ConditionalDeclaration *dd; 1162: 1163: assert(!s); 1164: dd = new ConditionalDeclaration(condition->syntaxCopy(), 1165: Dsymbol::arraySyntaxCopy(decl), 1166: Dsymbol::arraySyntaxCopy(elsedecl)); 1167: return dd; 1168: } 1169: 1170: 1171: int ConditionalDeclaration::oneMember(Dsymbol **ps) 1172: { 1173: //printf("ConditionalDeclaration::oneMember(), inc = %d\n", condition->inc); 1174: if (condition->inc) 1175: { 1176: Dsymbols *d = condition->include(NULL, NULL) ? decl : elsedecl; 1177: return Dsymbol::oneMembers(d, ps); 1178: } 1179: *ps = NULL; 1180: return TRUE; 1181: } 1182: 1183: void ConditionalDeclaration::emitComment(Scope *sc) 1184: { 1185: //printf("ConditionalDeclaration::emitComment(sc = %p)\n", sc); 1186: if (condition->inc) 1187: { 1188: AttribDeclaration::emitComment(sc); 1189: } 1190: else if (sc->docbuf) 1191: { 1192: /* If generating doc comment, be careful because if we're inside 1193: * a template, then include(NULL, NULL) will fail. 1194: */ 1195: Dsymbols *d = decl ? decl : elsedecl; 1196: for (unsigned i = 0; i < d->dim; i++) 1197: { Dsymbol *s = d->tdata()[i]; 1198: s->emitComment(sc); 1199: } 1200: } 1201: } 1202: 1203: // Decide if 'then' or 'else' code should be included 1204: 1205: Dsymbols *ConditionalDeclaration::include(Scope *sc, ScopeDsymbol *sd) 1206: { 1207: //printf("ConditionalDeclaration::include()\n"); 1208: assert(condition); 1209: return condition->include(sc, sd) ? decl : elsedecl; 1210: } 1211: 1212: void ConditionalDeclaration::setScope(Scope *sc) 1213: { 1214: Dsymbols *d = include(sc, NULL); 1215: 1216: //printf("\tConditionalDeclaration::setScope '%s', d = %p\n",toChars(), d); 1217: if (d) 1218: { 1219: for (unsigned i = 0; i < d->dim; i++) 1220: { 1221: Dsymbol *s = d->tdata()[i]; 1222: 1223: s->setScope(sc); 1224: } 1225: } 1226: } 1227: 1228: void ConditionalDeclaration::importAll(Scope *sc) 1229: { 1230: Dsymbols *d = include(sc, NULL); 1231: 1232: //printf("\tConditionalDeclaration::importAll '%s', d = %p\n",toChars(), d); 1233: if (d) 1234: { 1235: for (unsigned i = 0; i < d->dim; i++) 1236: { 1237: Dsymbol *s = d->tdata()[i]; 1238: 1239: s->importAll(sc); 1240: } 1241: } 1242: } 1243: 1244: void ConditionalDeclaration::addComment(unsigned char *comment) 1245: { 1246: /* Because addComment is called by the parser, if we called 1247: * include() it would define a version before it was used. 1248: * But it's no problem to drill down to both decl and elsedecl, 1249: * so that's the workaround. 1250: */ 1251: 1252: if (comment) 1253: { 1254: Dsymbols *d = decl; 1255: 1256: for (int j = 0; j < 2; j++) 1257: { 1258: if (d) 1259: { 1260: for (unsigned i = 0; i < d->dim; i++) 1261: { Dsymbol *s; 1262: 1263: s = d->tdata()[i]; 1264: //printf("ConditionalDeclaration::addComment %s\n", s->toChars()); 1265: s->addComment(comment); 1266: } 1267: } 1268: d = elsedecl; 1269: } 1270: } 1271: } 1272: 1273: void ConditionalDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 1274: { 1275: condition->toCBuffer(buf, hgs); 1276: if (decl || elsedecl) 1277: { 1278: buf->writenl(); 1279: buf->writeByte('{'); 1280: buf->writenl(); 1281: if (decl) 1282: { 1283: for (unsigned i = 0; i < decl->dim; i++) 1284: { 1285: Dsymbol *s = decl->tdata()[i]; 1286: 1287: buf->writestring(" "); 1288: s->toCBuffer(buf, hgs); 1289: } 1290: } 1291: buf->writeByte('}'); 1292: if (elsedecl) 1293: { 1294: buf->writenl(); 1295: buf->writestring("else"); 1296: buf->writenl(); 1297: buf->writeByte('{'); 1298: buf->writenl(); 1299: for (unsigned i = 0; i < elsedecl->dim; i++) 1300: { 1301: Dsymbol *s = elsedecl->tdata()[i]; 1302: 1303: buf->writestring(" "); 1304: s->toCBuffer(buf, hgs); 1305: } 1306: buf->writeByte('}'); 1307: } 1308: } 1309: else 1310: buf->writeByte(':'); 1311: buf->writenl(); 1312: } 1313: 1314: /***************************** StaticIfDeclaration ****************************/ 1315: 1316: StaticIfDeclaration::StaticIfDeclaration(Condition *condition, 1317: Dsymbols *decl, Dsymbols *elsedecl) 1318: : ConditionalDeclaration(condition, decl, elsedecl) 1319: { 1320: //printf("StaticIfDeclaration::StaticIfDeclaration()\n"); 1321: sd = NULL; 1322: addisdone = 0; 1323: } 1324: 1325: 1326: Dsymbol *StaticIfDeclaration::syntaxCopy(Dsymbol *s) 1327: { 1328: StaticIfDeclaration *dd; 1329: 1330: assert(!s); 1331: dd = new StaticIfDeclaration(condition->syntaxCopy(), 1332: Dsymbol::arraySyntaxCopy(decl), 1333: Dsymbol::arraySyntaxCopy(elsedecl)); 1334: return dd; 1335: } 1336: 1337: 1338: int StaticIfDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) 1339: { 1340: //printf("StaticIfDeclaration::addMember() '%s'\n",toChars()); 1341: /* This is deferred until semantic(), so that 1342: * expressions in the condition can refer to declarations 1343: * in the same scope, such as: 1344: * 1345: * template Foo(int i) 1346: * { 1347: * const int j = i + 1; 1348: * static if (j == 3) 1349: * const int k; 1350: * } 1351: */ 1352: this->sd = sd; 1353: int m = 0; 1354: 1355: if (memnum == 0) 1356: { m = AttribDeclaration::addMember(sc, sd, memnum); 1357: addisdone = 1; 1358: } 1359: return m; 1360: } 1361: 1362: 1363: void StaticIfDeclaration::importAll(Scope *sc) 1364: { 1365: // do not evaluate condition before semantic pass 1366: } 1367: 1368: void StaticIfDeclaration::setScope(Scope *sc) 1369: { 1370: // do not evaluate condition before semantic pass 1371: } 1372: 1373: void StaticIfDeclaration::semantic(Scope *sc) 1374: { 1375: Dsymbols *d = include(sc, sd); 1376: 1377: //printf("\tStaticIfDeclaration::semantic '%s', d = %p\n",toChars(), d); 1378: if (d) 1379: { 1380: if (!addisdone) 1381: { AttribDeclaration::addMember(sc, sd, 1); 1382: addisdone = 1; 1383: } 1384: 1385: for (unsigned i = 0; i < d->dim; i++) 1386: { 1387: Dsymbol *s = d->tdata()[i]; 1388: 1389: s->semantic(sc); 1390: } 1391: } 1392: } 1393: 1394: const char *StaticIfDeclaration::kind() 1395: { 1396: return "static if"; 1397: } 1398: 1399: 1400: /***************************** CompileDeclaration *****************************/ 1401: 1402: CompileDeclaration::CompileDeclaration(Loc loc, Expression *exp) 1403: : AttribDeclaration(NULL) 1404: { 1405: //printf("CompileDeclaration(loc = %d)\n", loc.linnum); 1406: this->loc = loc; 1407: this->exp = exp; 1408: this->sd = NULL; 1409: this->compiled = 0; 1410: } 1411: 1412: Dsymbol *CompileDeclaration::syntaxCopy(Dsymbol *s) 1413: { 1414: //printf("CompileDeclaration::syntaxCopy('%s')\n", toChars()); 1415: CompileDeclaration *sc = new CompileDeclaration(loc, exp->syntaxCopy()); 1416: return sc; 1417: } 1418: 1419: int CompileDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) 1420: { 1421: //printf("CompileDeclaration::addMember(sc = %p, sd = %p, memnum = %d)\n", sc, sd, memnum); 1422: this->sd = sd; 1423: if (memnum == 0) 1424: { /* No members yet, so parse the mixin now 1425: */ 1426: compileIt(sc); 1427: memnum |= AttribDeclaration::addMember(sc, sd, memnum); 1428: compiled = 1; 1429: } 1430: return memnum; 1431: } 1432: 1433: void CompileDeclaration::compileIt(Scope *sc) 1434: { 1435: //printf("CompileDeclaration::compileIt(loc = %d) %s\n", loc.linnum, exp->toChars()); 1436: exp = exp->semantic(sc); 1437: exp = resolveProperties(sc, exp); 1438: exp = exp->optimize(WANTvalue | WANTinterpret); 1439: if (exp->op != TOKstring) 1440: { exp->error("argument to mixin must be a string, not (%s)", exp->toChars()); 1441: } 1442: else 1443: { 1444: StringExp *se = (StringExp *)exp; 1445: se = se->toUTF8(sc); 1446: Parser p(sc->module, (unsigned char *)se->string, se->len, 0); 1447: p.loc = loc; 1448: p.nextToken(); 1449: decl = p.parseDeclDefs(0); 1450: if (p.token.value != TOKeof) 1451: exp->error("incomplete mixin declaration (%s)", se->toChars()); 1452: } 1453: } 1454: 1455: void CompileDeclaration::semantic(Scope *sc) 1456: { 1457: //printf("CompileDeclaration::semantic()\n"); 1458: 1459: if (!compiled) 1460: { 1461: compileIt(sc); 1462: AttribDeclaration::addMember(sc, sd, 0); 1463: compiled = 1; 1464: } 1465: AttribDeclaration::semantic(sc); 1466: } 1467: 1468: void CompileDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 1469: { 1470: buf->writestring("mixin("); 1471: exp->toCBuffer(buf, hgs); 1472: buf->writestring(");"); 1473: buf->writenl(); 1474: } 1475: