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 <string.h>
  13: static char __file__[] = __FILE__;      /* for tassert.h                */
  14: #include        "tassert.h"
  15: 
  16: #include "rmem.h"
  17: #include "speller.h"
  18: #include "aav.h"
  19: 
  20: #include "mars.h"
  21: #include "dsymbol.h"
  22: #include "aggregate.h"
  23: #include "identifier.h"
  24: #include "module.h"
  25: #include "mtype.h"
  26: #include "expression.h"
  27: #include "statement.h"
  28: #include "declaration.h"
  29: #include "id.h"
  30: #include "scope.h"
  31: #include "init.h"
  32: #include "import.h"
  33: #include "template.h"
  34: #include "attrib.h"
  35: 
  36: /****************************** Dsymbol ******************************/
  37: 
  38: Dsymbol::Dsymbol()
  39: {
  40:     //printf("Dsymbol::Dsymbol(%p)\n", this);
  41:     this->ident = NULL;
  42:     this->c_ident = NULL;
  43:     this->parent = NULL;
  44:     this->csym = NULL;
  45:     this->isym = NULL;
  46:     this->loc = 0;
  47:     this->comment = NULL;
  48:     this->scope = NULL;
  49: }
  50: 
  51: Dsymbol::Dsymbol(Identifier *ident)
  52: {
  53:     //printf("Dsymbol::Dsymbol(%p, ident)\n", this);
  54:     this->ident = ident;
  55:     this->c_ident = NULL;
  56:     this->parent = NULL;
  57:     this->csym = NULL;
  58:     this->isym = NULL;
  59:     this->loc = 0;
  60:     this->comment = NULL;
  61:     this->scope = NULL;
  62: }
  63: 
  64: int Dsymbol::equals(Object *o)
  65: {   Dsymbol *s;
  66: 
  67:     if (this == o)
  68:         return TRUE;
  69:     s = (Dsymbol *)(o);
  70:     // Overload sets don't have an ident
  71:     if (s && ident && s->ident && ident->equals(s->ident))
  72:         return TRUE;
  73:     return FALSE;
  74: }
  75: 
  76: /**************************************
  77:  * Copy the syntax.
  78:  * Used for template instantiations.
  79:  * If s is NULL, allocate the new object, otherwise fill it in.
  80:  */
  81: 
  82: Dsymbol *Dsymbol::syntaxCopy(Dsymbol *s)
  83: {
  84:     print();
  85:     printf("%s %s\n", kind(), toChars());
  86:     assert(0);
  87:     return NULL;
  88: }
  89: 
  90: /**************************************
  91:  * Determine if this symbol is only one.
  92:  * Returns:
  93:  *      FALSE, *ps = NULL: There are 2 or more symbols
  94:  *      TRUE,  *ps = NULL: There are zero symbols
  95:  *      TRUE,  *ps = symbol: The one and only one symbol
  96:  */
  97: 
  98: int Dsymbol::oneMember(Dsymbol **ps)
  99: {
 100:     //printf("Dsymbol::oneMember()\n");
 101:     *ps = this;
 102:     return TRUE;
 103: }
 104: 
 105: /*****************************************
 106:  * Same as Dsymbol::oneMember(), but look at an array of Dsymbols.
 107:  */
 108: 
 109: int Dsymbol::oneMembers(Dsymbols *members, Dsymbol **ps)
 110: {
 111:     //printf("Dsymbol::oneMembers() %d\n", members ? members->dim : 0);
 112:     Dsymbol *s = NULL;
 113: 
 114:     if (members)
 115:     {
 116:         for (int i = 0; i < members->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
117: { Dsymbol *sx = members->tdata()[i]; 118: 119: int x = sx->oneMember(ps); 120: //printf("\t[%d] kind %s = %d, s = %p\n", i, sx->kind(), x, *ps); 121: if (!x) 122: { 123: //printf("\tfalse 1\n"); 124: assert(*ps == NULL); 125: return FALSE; 126: } 127: if (*ps) 128: { 129: if (s) // more than one symbol 130: { *ps = NULL; 131: //printf("\tfalse 2\n"); 132: return FALSE; 133: } 134: s = *ps; 135: } 136: } 137: } 138: *ps = s; // s is the one symbol, NULL if none 139: //printf("\ttrue\n"); 140: return TRUE; 141: } 142: 143: /***************************************** 144: * Is Dsymbol a variable that contains pointers? 145: */ 146: 147: int Dsymbol::hasPointers() 148: { 149: //printf("Dsymbol::hasPointers() %s\n", toChars()); 150: return 0; 151: } 152: 153: char *Dsymbol::toChars() 154: { 155: return ident ? ident->toChars() : (char *)"__anonymous"; 156: } 157: 158: const char *Dsymbol::toPrettyChars() 159: { Dsymbol *p; 160: char *s; 161: char *q; 162: size_t len; 163: 164: //printf("Dsymbol::toPrettyChars() '%s'\n", toChars()); 165: if (!parent) 166: return toChars(); 167: 168: len = 0; 169: for (p = this; p; p = p->parent) 170: len += strlen(p->toChars()) + 1; 171: 172: s = (char *)mem.malloc(len); 173: q = s + len - 1; 174: *q = 0; 175: for (p = this; p; p = p->parent) 176: { 177: char *t = p->toChars(); 178: len = strlen(t); 179: q -= len; 180: memcpy(q, t, len); 181: if (q == s) 182: break; 183: q--; 184: #if TARGET_NET 185: if (AggregateDeclaration* ad = p->isAggregateDeclaration()) 186: { 187: if (ad->isNested() && p->parent && p->parent->isAggregateDeclaration()) 188: { 189: *q = '/'; 190: continue; 191: } 192: } 193: #endif 194: *q = '.'; 195: } 196: return s; 197: } 198: 199: char *Dsymbol::locToChars() 200: { 201: OutBuffer buf; 202: char *p;
warning C4101: 'p' : unreferenced local variable
203: 204: if (!loc.filename) // avoid bug 5861. 205: { 206: Module *m = getModule(); 207: 208: if (m && m->srcfile) 209: loc.filename = m->srcfile->toChars(); 210: } 211: return loc.toChars(); 212: } 213: 214: const char *Dsymbol::kind() 215: { 216: return "symbol"; 217: } 218: 219: /********************************* 220: * If this symbol is really an alias for another, 221: * return that other. 222: */ 223: 224: Dsymbol *Dsymbol::toAlias() 225: { 226: return this; 227: } 228: 229: Dsymbol *Dsymbol::toParent() 230: { 231: return parent ? parent->pastMixin() : NULL; 232: } 233: 234: Dsymbol *Dsymbol::pastMixin() 235: { 236: Dsymbol *s = this; 237: 238: //printf("Dsymbol::pastMixin() %s\n", toChars()); 239: while (s && s->isTemplateMixin()) 240: s = s->parent; 241: return s; 242: } 243: 244: /********************************** 245: * Use this instead of toParent() when looking for the 246: * 'this' pointer of the enclosing function/class. 247: */ 248: 249: Dsymbol *Dsymbol::toParent2() 250: { 251: Dsymbol *s = parent; 252: while (s && s->isTemplateInstance()) 253: s = s->parent; 254: return s; 255: } 256: 257: TemplateInstance *Dsymbol::inTemplateInstance() 258: { 259: for (Dsymbol *parent = this->parent; parent; parent = parent->parent) 260: { 261: TemplateInstance *ti = parent->isTemplateInstance(); 262: if (ti) 263: return ti; 264: } 265: return NULL; 266: } 267: 268: int Dsymbol::isAnonymous() 269: { 270: return ident ? 0 : 1; 271: } 272: 273: /************************************* 274: * Set scope for future semantic analysis so we can 275: * deal better with forward references. 276: */ 277: 278: void Dsymbol::setScope(Scope *sc) 279: { 280: //printf("Dsymbol::setScope() %p %s\n", this, toChars()); 281: if (!sc->nofree) 282: sc->setNoFree(); // may need it even after semantic() finishes 283: scope = sc; 284: } 285: 286: void Dsymbol::importAll(Scope *sc) 287: { 288: } 289: 290: /************************************* 291: * Does semantic analysis on the public face of declarations. 292: */ 293: 294: void Dsymbol::semantic0(Scope *sc) 295: { 296: } 297: 298: void Dsymbol::semantic(Scope *sc) 299: { 300: error("%p has no semantic routine", this); 301: } 302: 303: /************************************* 304: * Does semantic analysis on initializers and members of aggregates. 305: */ 306: 307: void Dsymbol::semantic2(Scope *sc) 308: { 309: // Most Dsymbols have no further semantic analysis needed 310: } 311: 312: /************************************* 313: * Does semantic analysis on function bodies. 314: */ 315: 316: void Dsymbol::semantic3(Scope *sc) 317: { 318: // Most Dsymbols have no further semantic analysis needed 319: } 320: 321: /************************************* 322: * Look for function inlining possibilities. 323: */ 324: 325: void Dsymbol::inlineScan() 326: { 327: // Most Dsymbols aren't functions 328: } 329: 330: /********************************************* 331: * Search for ident as member of s. 332: * Input: 333: * flags: 1 don't find private members 334: * 2 don't give error messages 335: * 4 return NULL if ambiguous 336: * Returns: 337: * NULL if not found 338: */ 339: 340: Dsymbol *Dsymbol::search(Loc loc, Identifier *ident, int flags) 341: { 342: //printf("Dsymbol::search(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars()); 343: return NULL; 344: } 345: 346: /*************************************************** 347: * Search for symbol with correct spelling. 348: */ 349: 350: void *symbol_search_fp(void *arg, const char *seed) 351: { 352: Dsymbol *s = (Dsymbol *)arg; 353: Identifier id(seed, 0); 354: Module::clearCache(); 355: s = s->search(0, &id, 4|2); 356: return s; 357: } 358: 359: Dsymbol *Dsymbol::search_correct(Identifier *ident) 360: { 361: if (global.gag) 362: return NULL; // don't do it for speculative compiles; too time consuming 363: 364: return (Dsymbol *)speller(ident->toChars(), &symbol_search_fp, this, idchars); 365: } 366: 367: /*************************************** 368: * Search for identifier id as a member of 'this'. 369: * id may be a template instance. 370: * Returns: 371: * symbol found, NULL if not 372: */ 373: 374: Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, Identifier *id) 375: { 376: //printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars()); 377: Dsymbol *s = toAlias(); 378: Dsymbol *sm; 379: 380: switch (id->dyncast()) 381: { 382: case DYNCAST_IDENTIFIER: 383: sm = s->search(loc, id, 0); 384: break; 385: 386: case DYNCAST_DSYMBOL: 387: { // It's a template instance 388: //printf("\ttemplate instance id\n"); 389: Dsymbol *st = (Dsymbol *)id; 390: TemplateInstance *ti = st->isTemplateInstance(); 391: id = ti->name; 392: sm = s->search(loc, id, 0); 393: if (!sm) 394: { error("template identifier %s is not a member of %s %s", 395: id->toChars(), s->kind(), s->toChars()); 396: return NULL; 397: } 398: sm = sm->toAlias(); 399: TemplateDeclaration *td = sm->isTemplateDeclaration(); 400: if (!td) 401: { 402: error("%s is not a template, it is a %s", id->toChars(), sm->kind()); 403: return NULL; 404: } 405: ti->tempdecl = td; 406: if (!ti->semanticRun) 407: ti->semantic(sc); 408: sm = ti->toAlias(); 409: break; 410: } 411: 412: default: 413: assert(0); 414: } 415: return sm; 416: } 417: 418: int Dsymbol::overloadInsert(Dsymbol *s) 419: { 420: //printf("Dsymbol::overloadInsert('%s')\n", s->toChars()); 421: return FALSE; 422: } 423: 424: void Dsymbol::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 425: { 426: buf->writestring(toChars()); 427: } 428: 429: unsigned Dsymbol::size(Loc loc) 430: { 431: error("Dsymbol '%s' has no size\n", toChars()); 432: return 0; 433: } 434: 435: int Dsymbol::isforwardRef() 436: { 437: return FALSE; 438: } 439: 440: AggregateDeclaration *Dsymbol::isThis() 441: { 442: return NULL; 443: } 444: 445: ClassDeclaration *Dsymbol::isClassMember() // are we a member of a class? 446: { 447: Dsymbol *parent = toParent(); 448: if (parent && parent->isClassDeclaration()) 449: return (ClassDeclaration *)parent; 450: return NULL; 451: } 452: 453: void Dsymbol::defineRef(Dsymbol *s) 454: { 455: assert(0); 456: } 457: 458: int Dsymbol::isExport() 459: { 460: return FALSE; 461: } 462: 463: int Dsymbol::isImportedSymbol() 464: { 465: return FALSE; 466: } 467: 468: int Dsymbol::isDeprecated() 469: { 470: return FALSE; 471: } 472: 473: #if DMDV2 474: int Dsymbol::isOverloadable() 475: { 476: return 0; 477: } 478: #endif 479: 480: LabelDsymbol *Dsymbol::isLabel() // is this a LabelDsymbol()? 481: { 482: return NULL; 483: } 484: 485: AggregateDeclaration *Dsymbol::isMember() // is this a member of an AggregateDeclaration? 486: { 487: //printf("Dsymbol::isMember() %s\n", toChars()); 488: Dsymbol *parent = toParent(); 489: //printf("parent is %s %s\n", parent->kind(), parent->toChars()); 490: return parent ? parent->isAggregateDeclaration() : NULL; 491: } 492: 493: Type *Dsymbol::getType() 494: { 495: return NULL; 496: } 497: 498: int Dsymbol::needThis() 499: { 500: return FALSE; 501: } 502: 503: int Dsymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) 504: { 505: //printf("Dsymbol::addMember('%s')\n", toChars()); 506: //printf("Dsymbol::addMember(this = %p, '%s' scopesym = '%s')\n", this, toChars(), sd->toChars()); 507: //printf("Dsymbol::addMember(this = %p, '%s' sd = %p, sd->symtab = %p)\n", this, toChars(), sd, sd->symtab); 508: parent = sd; 509: if (!isAnonymous()) // no name, so can't add it to symbol table 510: { 511: if (!sd->symtabInsert(this)) // if name is already defined 512: { 513: Dsymbol *s2; 514: 515: s2 = sd->symtab->lookup(ident); 516: if (!s2->overloadInsert(this)) 517: { 518: sd->multiplyDefined(0, this, s2); 519: } 520: } 521: if (sd->isAggregateDeclaration() || sd->isEnumDeclaration()) 522: { 523: if (ident == Id::__sizeof || ident == Id::__xalignof || ident == Id::mangleof) 524: error(".%s property cannot be redefined", ident->toChars()); 525: } 526: return 1; 527: } 528: return 0; 529: } 530: 531: void Dsymbol::error(const char *format, ...) 532: { 533: //printf("Dsymbol::error()\n"); 534: if (!global.gag) 535: { 536: char *p = locToChars(); 537: 538: if (*p) 539: fprintf(stdmsg, "%s: ", p); 540: mem.free(p); 541: 542: fprintf(stdmsg, "Error: "); 543: if (isAnonymous()) 544: fprintf(stdmsg, "%s ", kind()); 545: else 546: fprintf(stdmsg, "%s %s ", kind(), toPrettyChars()); 547: 548: va_list ap; 549: va_start(ap, format); 550: vfprintf(stdmsg, format, ap); 551: va_end(ap); 552: 553: fprintf(stdmsg, "\n"); 554: fflush(stdmsg); 555: //halt(); 556: } 557: global.errors++; 558: 559: //fatal(); 560: } 561: 562: void Dsymbol::error(Loc loc, const char *format, ...) 563: { 564: if (!global.gag) 565: { 566: char *p = loc.toChars(); 567: if (!*p) 568: p = locToChars(); 569: 570: if (*p) 571: fprintf(stdmsg, "%s: ", p); 572: mem.free(p); 573: 574: fprintf(stdmsg, "Error: "); 575: fprintf(stdmsg, "%s %s ", kind(), toPrettyChars()); 576: 577: va_list ap; 578: va_start(ap, format); 579: vfprintf(stdmsg, format, ap); 580: va_end(ap); 581: 582: fprintf(stdmsg, "\n"); 583: fflush(stdmsg); 584: //halt(); 585: } 586: 587: global.errors++; 588: 589: //fatal(); 590: } 591: 592: void Dsymbol::checkDeprecated(Loc loc, Scope *sc) 593: { 594: if (!global.params.useDeprecated && isDeprecated()) 595: { 596: // Don't complain if we're inside a deprecated symbol's scope 597: for (Dsymbol *sp = sc->parent; sp; sp = sp->parent) 598: { if (sp->isDeprecated()) 599: goto L1; 600: } 601: 602: for (; sc; sc = sc->enclosing) 603: { 604: if (sc->scopesym && sc->scopesym->isDeprecated()) 605: goto L1; 606: 607: // If inside a StorageClassDeclaration that is deprecated 608: if (sc->stc & STCdeprecated) 609: goto L1; 610: } 611: 612: error(loc, "is deprecated"); 613: } 614: 615: L1: 616: Declaration *d = isDeclaration(); 617: if (d && d->storage_class & STCdisable) 618: { 619: if (!(sc->func && sc->func->storage_class & STCdisable)) 620: { 621: if (d->ident == Id::cpctor && d->toParent()) 622: d->toParent()->error(loc, "is not copyable because it is annotated with @disable"); 623: else 624: error(loc, "is not callable because it is annotated with @disable"); 625: } 626: } 627: } 628: 629: /********************************** 630: * Determine which Module a Dsymbol is in. 631: */ 632: 633: Module *Dsymbol::getModule() 634: { 635: Module *m; 636: Dsymbol *s; 637: 638: //printf("Dsymbol::getModule()\n"); 639: TemplateDeclaration *td = getFuncTemplateDecl(this); 640: if (td) 641: return td->getModule(); 642: 643: s = this; 644: while (s) 645: { 646: //printf("\ts = '%s'\n", s->toChars()); 647: m = s->isModule(); 648: if (m) 649: return m; 650: s = s->parent; 651: } 652: return NULL; 653: } 654: 655: /************************************* 656: */ 657: 658: enum PROT Dsymbol::prot() 659: { 660: return PROTpublic; 661: } 662: 663: /************************************* 664: * Do syntax copy of an array of Dsymbol's. 665: */ 666: 667: 668: Dsymbols *Dsymbol::arraySyntaxCopy(Dsymbols *a) 669: { 670: 671: Dsymbols *b = NULL; 672: if (a) 673: { 674: b = (Dsymbols *)a->copy(); 675: for (int i = 0; i < b->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
676: { 677: Dsymbol *s = b->tdata()[i]; 678: 679: s = s->syntaxCopy(NULL); 680: b->tdata()[i] = s; 681: } 682: } 683: return b; 684: } 685: 686: 687: /**************************************** 688: * Add documentation comment to Dsymbol. 689: * Ignore NULL comments. 690: */ 691: 692: void Dsymbol::addComment(unsigned char *comment) 693: { 694: //if (comment) 695: //printf("adding comment '%s' to symbol %p '%s'\n", comment, this, toChars()); 696: 697: if (!this->comment) 698: this->comment = comment; 699: #if 1 700: else if (comment && strcmp((char *)comment, (char *)this->comment)) 701: { // Concatenate the two 702: this->comment = Lexer::combineComments(this->comment, comment); 703: } 704: #endif 705: } 706: 707: /********************************* OverloadSet ****************************/ 708: 709: #if DMDV2 710: OverloadSet::OverloadSet() 711: : Dsymbol() 712: { 713: } 714: 715: void OverloadSet::push(Dsymbol *s) 716: { 717: a.push(s); 718: } 719: 720: const char *OverloadSet::kind() 721: { 722: return "overloadset"; 723: } 724: #endif 725: 726: 727: /********************************* ScopeDsymbol ****************************/ 728: 729: ScopeDsymbol::ScopeDsymbol() 730: : Dsymbol() 731: { 732: members = NULL; 733: symtab = NULL; 734: imports = NULL; 735: prots = NULL; 736: } 737: 738: ScopeDsymbol::ScopeDsymbol(Identifier *id) 739: : Dsymbol(id) 740: { 741: members = NULL; 742: symtab = NULL; 743: imports = NULL; 744: prots = NULL; 745: } 746: 747: Dsymbol *ScopeDsymbol::syntaxCopy(Dsymbol *s) 748: { 749: //printf("ScopeDsymbol::syntaxCopy('%s')\n", toChars()); 750: 751: ScopeDsymbol *sd; 752: if (s) 753: sd = (ScopeDsymbol *)s; 754: else 755: sd = new ScopeDsymbol(ident); 756: sd->members = arraySyntaxCopy(members); 757: return sd; 758: } 759: 760: Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags) 761: { 762: //printf("%s->ScopeDsymbol::search(ident='%s', flags=x%x)\n", toChars(), ident->toChars(), flags); 763: //if (strcmp(ident->toChars(),"c") == 0) *(char*)0=0; 764: 765: // Look in symbols declared in this module 766: Dsymbol *s = symtab ? symtab->lookup(ident) : NULL; 767: //printf("\ts = %p, imports = %p, %d\n", s, imports, imports ? imports->dim : 0); 768: if (s) 769: { 770: //printf("\ts = '%s.%s'\n",toChars(),s->toChars()); 771: } 772: else if (imports) 773: { 774: OverloadSet *a = NULL; 775: 776: // Look in imported modules 777: for (int i = 0; i < imports->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
778: { ScopeDsymbol *ss = imports->tdata()[i]; 779: Dsymbol *s2; 780: 781: // If private import, don't search it 782: if (flags & 1 && prots[i] == PROTprivate) 783: continue; 784: 785: //printf("\tscanning import '%s', prots = %d, isModule = %p, isImport = %p\n", ss->toChars(), prots[i], ss->isModule(), ss->isImport()); 786: /* Don't find private members if ss is a module 787: */ 788: s2 = ss->search(loc, ident, ss->isModule() ? 1 : 0); 789: if (!s) 790: s = s2; 791: else if (s2 && s != s2) 792: { 793: if (s->toAlias() == s2->toAlias()) 794: { 795: /* After following aliases, we found the same symbol, 796: * so it's not an ambiguity. 797: * But if one alias is deprecated, prefer the other. 798: */ 799: if (s->isDeprecated()) 800: s = s2; 801: } 802: else 803: { 804: /* Two imports of the same module should be regarded as 805: * the same. 806: */ 807: Import *i1 = s->isImport(); 808: Import *i2 = s2->isImport(); 809: if (!(i1 && i2 && 810: (i1->mod == i2->mod || 811: (!i1->parent->isImport() && !i2->parent->isImport() && 812: i1->ident->equals(i2->ident)) 813: ) 814: ) 815: ) 816: { 817: /* If both s2 and s are overloadable (though we only 818: * need to check s once) 819: */ 820: if (s2->isOverloadable() && (a || s->isOverloadable())) 821: { if (!a) 822: a = new OverloadSet(); 823: /* Don't add to a[] if s2 is alias of previous sym 824: */ 825: for (int j = 0; j < a->a.dim; j++)
warning C4018: '<' : signed/unsigned mismatch
826: { Dsymbol *s3 = a->a.tdata()[j]; 827: if (s2->toAlias() == s3->toAlias()) 828: { 829: if (s3->isDeprecated()) 830: a->a.tdata()[j] = s2; 831: goto Lcontinue; 832: } 833: } 834: a->push(s2); 835: Lcontinue: 836: continue; 837: } 838: if (flags & 4) // if return NULL on ambiguity 839: return NULL; 840: if (!(flags & 2)) 841: ss->multiplyDefined(loc, s, s2); 842: break; 843: } 844: } 845: } 846: } 847: 848: /* Build special symbol if we had multiple finds 849: */ 850: if (a) 851: { assert(s); 852: a->push(s); 853: s = a; 854: } 855: 856: if (s) 857: { 858: Declaration *d = s->isDeclaration(); 859: if (d && d->protection == PROTprivate && 860: !d->parent->isTemplateMixin() && 861: !(flags & 2)) 862: error(loc, "%s is private", d->toPrettyChars()); 863: } 864: } 865: return s; 866: } 867: 868: void ScopeDsymbol::importScope(ScopeDsymbol *s, enum PROT protection) 869: { 870: //printf("%s->ScopeDsymbol::importScope(%s, %d)\n", toChars(), s->toChars(), protection); 871: 872: // No circular or redundant import's 873: if (s != this) 874: { 875: if (!imports) 876: imports = new ScopeDsymbols(); 877: else 878: { 879: for (int i = 0; i < imports->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
880: { ScopeDsymbol *ss; 881: 882: ss = imports->tdata()[i]; 883: if (ss == s) // if already imported 884: { 885: if (protection > prots[i]) 886: prots[i] = protection; // upgrade access 887: return; 888: } 889: } 890: } 891: imports->push(s); 892: prots = (unsigned char *)mem.realloc(prots, imports->dim * sizeof(prots[0])); 893: prots[imports->dim - 1] = protection; 894: } 895: } 896: 897: int ScopeDsymbol::isforwardRef() 898: { 899: return (members == NULL); 900: } 901: 902: void ScopeDsymbol::defineRef(Dsymbol *s) 903: { 904: ScopeDsymbol *ss; 905: 906: ss = s->isScopeDsymbol(); 907: members = ss->members; 908: ss->members = NULL; 909: } 910: 911: void ScopeDsymbol::multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2) 912: { 913: #if 0 914: printf("ScopeDsymbol::multiplyDefined()\n"); 915: printf("s1 = %p, '%s' kind = '%s', parent = %s\n", s1, s1->toChars(), s1->kind(), s1->parent ? s1->parent->toChars() : ""); 916: printf("s2 = %p, '%s' kind = '%s', parent = %s\n", s2, s2->toChars(), s2->kind(), s2->parent ? s2->parent->toChars() : ""); 917: #endif 918: if (loc.filename) 919: { ::error(loc, "%s at %s conflicts with %s at %s", 920: s1->toPrettyChars(), 921: s1->locToChars(), 922: s2->toPrettyChars(), 923: s2->locToChars()); 924: } 925: else 926: { 927: s1->error(loc, "conflicts with %s %s at %s", 928: s2->kind(), 929: s2->toPrettyChars(), 930: s2->locToChars()); 931: } 932: } 933: 934: Dsymbol *ScopeDsymbol::nameCollision(Dsymbol *s) 935: { 936: Dsymbol *sprev; 937: 938: // Look to see if we are defining a forward referenced symbol 939: 940: sprev = symtab->lookup(s->ident); 941: assert(sprev); 942: if (s->equals(sprev)) // if the same symbol 943: { 944: if (s->isforwardRef()) // if second declaration is a forward reference 945: return sprev; 946: if (sprev->isforwardRef()) 947: { 948: sprev->defineRef(s); // copy data from s into sprev 949: return sprev; 950: } 951: } 952: multiplyDefined(0, s, sprev); 953: return sprev; 954: } 955: 956: const char *ScopeDsymbol::kind() 957: { 958: return "ScopeDsymbol"; 959: } 960: 961: Dsymbol *ScopeDsymbol::symtabInsert(Dsymbol *s) 962: { 963: return symtab->insert(s); 964: } 965: 966: /*************************************** 967: * Determine number of Dsymbols, folding in AttribDeclaration members. 968: */ 969: 970: #if DMDV2 971: size_t ScopeDsymbol::dim(Dsymbols *members) 972: { 973: size_t n = 0; 974: if (members) 975: { 976: for (size_t i = 0; i < members->dim; i++) 977: { Dsymbol *s = members->tdata()[i]; 978: AttribDeclaration *a = s->isAttribDeclaration(); 979: 980: if (a) 981: { 982: n += dim(a->decl); 983: } 984: else 985: n++; 986: } 987: } 988: return n; 989: } 990: #endif 991: 992: /*************************************** 993: * Get nth Dsymbol, folding in AttribDeclaration members. 994: * Returns: 995: * Dsymbol* nth Dsymbol 996: * NULL not found, *pn gets incremented by the number 997: * of Dsymbols 998: */ 999: 1000: #if DMDV2 1001: Dsymbol *ScopeDsymbol::getNth(Dsymbols *members, size_t nth, size_t *pn) 1002: { 1003: if (!members) 1004: return NULL; 1005: 1006: size_t n = 0; 1007: for (size_t i = 0; i < members->dim; i++) 1008: { Dsymbol *s = members->tdata()[i]; 1009: AttribDeclaration *a = s->isAttribDeclaration(); 1010: 1011: if (a) 1012: { 1013: s = getNth(a->decl, nth - n, &n); 1014: if (s) 1015: return s; 1016: } 1017: else if (n == nth) 1018: return s; 1019: else 1020: n++; 1021: } 1022: 1023: if (pn) 1024: *pn += n; 1025: return NULL; 1026: } 1027: #endif 1028: 1029: /******************************************* 1030: * Look for member of the form: 1031: * const(MemberInfo)[] getMembers(string); 1032: * Returns NULL if not found 1033: */ 1034: 1035: #if DMDV2 1036: FuncDeclaration *ScopeDsymbol::findGetMembers() 1037: { 1038: Dsymbol *s = search_function(this, Id::getmembers); 1039: FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL; 1040: 1041: #if 0 // Finish 1042: static TypeFunction *tfgetmembers; 1043: 1044: if (!tfgetmembers) 1045: { 1046: Scope sc; 1047: Parameters *arguments = new Parameters; 1048: Parameters *arg = new Parameter(STCin, Type::tchar->constOf()->arrayOf(), NULL, NULL); 1049: arguments->push(arg); 1050: 1051: Type *tret = NULL; 1052: tfgetmembers = new TypeFunction(arguments, tret, 0, LINKd); 1053: tfgetmembers = (TypeFunction *)tfgetmembers->semantic(0, &sc); 1054: } 1055: if (fdx) 1056: fdx = fdx->overloadExactMatch(tfgetmembers); 1057: #endif 1058: if (fdx && fdx->isVirtual()) 1059: fdx = NULL; 1060: 1061: return fdx; 1062: } 1063: #endif 1064: 1065: 1066: /****************************** WithScopeSymbol ******************************/ 1067: 1068: WithScopeSymbol::WithScopeSymbol(WithStatement *withstate) 1069: : ScopeDsymbol() 1070: { 1071: this->withstate = withstate; 1072: } 1073: 1074: Dsymbol *WithScopeSymbol::search(Loc loc, Identifier *ident, int flags) 1075: { 1076: // Acts as proxy to the with class declaration 1077: return withstate->exp->type->toDsymbol(NULL)->search(loc, ident, 0); 1078: } 1079: 1080: /****************************** ArrayScopeSymbol ******************************/ 1081: 1082: ArrayScopeSymbol::ArrayScopeSymbol(Scope *sc, Expression *e) 1083: : ScopeDsymbol() 1084: { 1085: assert(e->op == TOKindex || e->op == TOKslice); 1086: exp = e; 1087: type = NULL; 1088: td = NULL; 1089: this->sc = sc; 1090: } 1091: 1092: ArrayScopeSymbol::ArrayScopeSymbol(Scope *sc, TypeTuple *t) 1093: : ScopeDsymbol() 1094: { 1095: exp = NULL; 1096: type = t; 1097: td = NULL; 1098: this->sc = sc; 1099: } 1100: 1101: ArrayScopeSymbol::ArrayScopeSymbol(Scope *sc, TupleDeclaration *s) 1102: : ScopeDsymbol() 1103: { 1104: exp = NULL; 1105: type = NULL; 1106: td = s; 1107: this->sc = sc; 1108: } 1109: 1110: Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags) 1111: { 1112: //printf("ArrayScopeSymbol::search('%s', flags = %d)\n", ident->toChars(), flags); 1113: if (ident == Id::length || ident == Id::dollar) 1114: { VarDeclaration **pvar; 1115: Expression *ce; 1116: 1117: if (ident == Id::length && !global.params.useDeprecated) 1118: error("using 'length' inside [ ] is deprecated, use '$' instead"); 1119: 1120: L1: 1121: 1122: if (td) 1123: { /* $ gives the number of elements in the tuple 1124: */ 1125: VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
warning C6211: Leaking memory 'v' due to an exception. Consider using a local catch block to clean up memory: Lines: 1113, 1114, 1115, 1117, 1120, 1122, 1125, 1126
1126: Expression *e = new IntegerExp(0, td->objects->dim, Type::tsize_t); 1127: v->init = new ExpInitializer(0, e); 1128: v->storage_class |= STCstatic | STCconst; 1129: v->semantic(sc); 1130: return v; 1131: } 1132: 1133: if (type) 1134: { /* $ gives the number of type entries in the type tuple 1135: */ 1136: VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL); 1137: Expression *e = new IntegerExp(0, type->arguments->dim, Type::tsize_t); 1138: v->init = new ExpInitializer(0, e); 1139: v->storage_class |= STCstatic | STCconst; 1140: v->semantic(sc); 1141: return v; 1142: } 1143: 1144: if (exp->op == TOKindex) 1145: { /* array[index] where index is some function of $ 1146: */ 1147: IndexExp *ie = (IndexExp *)exp; 1148: 1149: pvar = &ie->lengthVar; 1150: ce = ie->e1; 1151: } 1152: else if (exp->op == TOKslice) 1153: { /* array[lwr .. upr] where lwr or upr is some function of $ 1154: */ 1155: SliceExp *se = (SliceExp *)exp; 1156: 1157: pvar = &se->lengthVar; 1158: ce = se->e1; 1159: } 1160: else 1161: /* Didn't find $, look in enclosing scope(s). 1162: */ 1163: return NULL; 1164: 1165: /* If we are indexing into an array that is really a type 1166: * tuple, rewrite this as an index into a type tuple and 1167: * try again. 1168: */ 1169: if (ce->op == TOKtype) 1170: { 1171: Type *t = ((TypeExp *)ce)->type; 1172: if (t->ty == Ttuple) 1173: { type = (TypeTuple *)t; 1174: goto L1; 1175: } 1176: } 1177: 1178: /* *pvar is lazily initialized, so if we refer to $ 1179: * multiple times, it gets set only once. 1180: */ 1181: if (!*pvar) // if not already initialized 1182: { /* Create variable v and set it to the value of $ 1183: */ 1184: VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL); 1185: if (ce->op == TOKtuple) 1186: { /* It is for an expression tuple, so the 1187: * length will be a const. 1188: */ 1189: Expression *e = new IntegerExp(0, ((TupleExp *)ce)->exps->dim, Type::tsize_t); 1190: v->init = new ExpInitializer(0, e); 1191: v->storage_class |= STCstatic | STCconst; 1192: } 1193: else 1194: { /* For arrays, $ will either be a compile-time constant 1195: * (in which case its value in set during constant-folding), 1196: * or a variable (in which case an expression is created in 1197: * toir.c). 1198: */ 1199: v->init = new VoidInitializer(0); 1200: } 1201: *pvar = v; 1202: } 1203: (*pvar)->semantic(sc); 1204: return (*pvar); 1205: } 1206: return NULL; 1207: } 1208: 1209: 1210: /****************************** DsymbolTable ******************************/ 1211: 1212: DsymbolTable::DsymbolTable() 1213: { 1214: #if STRINGTABLE 1215: tab = new StringTable; 1216: #else 1217: tab = NULL; 1218: #endif 1219: } 1220: 1221: DsymbolTable::~DsymbolTable() 1222: { 1223: #if STRINGTABLE 1224: delete tab; 1225: #endif 1226: } 1227: 1228: Dsymbol *DsymbolTable::lookup(Identifier *ident) 1229: { 1230: #if STRINGTABLE 1231: #ifdef DEBUG 1232: assert(ident); 1233: assert(tab); 1234: #endif 1235: //printf("DsymbolTable::lookup(%s)\n", (char*)ident->string); 1236: StringValue *sv = tab->lookup((char*)ident->string, ident->len); 1237: return (Dsymbol *)(sv ? sv->ptrvalue : NULL); 1238: #else 1239: //printf("DsymbolTable::lookup(%s)\n", (char*)ident->string); 1240: return (Dsymbol *)_aaGetRvalue(tab, ident); 1241: #endif 1242: } 1243: 1244: Dsymbol *DsymbolTable::insert(Dsymbol *s) 1245: { 1246: //printf("DsymbolTable::insert(this = %p, '%s')\n", this, s->ident->toChars()); 1247: Identifier *ident = s->ident; 1248: #if STRINGTABLE 1249: #ifdef DEBUG 1250: assert(ident); 1251: assert(tab); 1252: #endif 1253: StringValue *sv = tab->insert(ident->toChars(), ident->len); 1254: if (!sv) 1255: return NULL; // already in table 1256: sv->ptrvalue = s; 1257: return s; 1258: #else 1259: Dsymbol **ps = (Dsymbol **)_aaGet(&tab, ident); 1260: if (*ps) 1261: return NULL; // already in table 1262: *ps = s; 1263: return s; 1264: #endif 1265: } 1266: 1267: Dsymbol *DsymbolTable::insert(Identifier *ident, Dsymbol *s) 1268: { 1269: //printf("DsymbolTable::insert()\n"); 1270: #if STRINGTABLE 1271: StringValue *sv = tab->insert(ident->toChars(), ident->len); 1272: if (!sv) 1273: return NULL; // already in table 1274: sv->ptrvalue = s; 1275: return s; 1276: #else 1277: Dsymbol **ps = (Dsymbol **)_aaGet(&tab, ident); 1278: if (*ps) 1279: return NULL; // already in table 1280: *ps = s; 1281: return s; 1282: #endif 1283: } 1284: 1285: Dsymbol *DsymbolTable::update(Dsymbol *s) 1286: { 1287: Identifier *ident = s->ident; 1288: #if STRINGTABLE 1289: StringValue *sv = tab->update(ident->toChars(), ident->len); 1290: sv->ptrvalue = s; 1291: return s; 1292: #else 1293: Dsymbol **ps = (Dsymbol **)_aaGet(&tab, ident); 1294: *ps = s; 1295: return s; 1296: #endif 1297: } 1298: 1299: 1300: 1301: 1302: