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 mismatch
609: { 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: