dsymbol.c revision 1.1.1.2
1 2/* Compiler implementation of the D programming language 3 * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved 4 * written by Walter Bright 5 * http://www.digitalmars.com 6 * Distributed under the Boost Software License, Version 1.0. 7 * http://www.boost.org/LICENSE_1_0.txt 8 * https://github.com/D-Programming-Language/dmd/blob/master/src/dsymbol.c 9 */ 10 11#include "root/dsystem.h" 12#include "root/rmem.h" 13#include "root/speller.h" 14#include "root/aav.h" 15 16#include "mars.h" 17#include "dsymbol.h" 18#include "aggregate.h" 19#include "identifier.h" 20#include "module.h" 21#include "mtype.h" 22#include "expression.h" 23#include "statement.h" 24#include "declaration.h" 25#include "id.h" 26#include "scope.h" 27#include "init.h" 28#include "import.h" 29#include "template.h" 30#include "attrib.h" 31#include "enum.h" 32#include "lexer.h" 33#include "nspace.h" 34 35bool symbolIsVisible(Dsymbol *origin, Dsymbol *s); 36typedef int (*ForeachDg)(void *ctx, size_t idx, Dsymbol *s); 37int ScopeDsymbol_foreach(Scope *sc, Dsymbols *members, ForeachDg dg, void *ctx, size_t *pn = NULL); 38Expression *semantic(Expression *e, Scope *sc); 39 40 41/****************************** Dsymbol ******************************/ 42 43Dsymbol::Dsymbol() 44{ 45 //printf("Dsymbol::Dsymbol(%p)\n", this); 46 this->ident = NULL; 47 this->parent = NULL; 48 this->csym = NULL; 49 this->isym = NULL; 50 this->loc = Loc(); 51 this->comment = NULL; 52 this->_scope = NULL; 53 this->prettystring = NULL; 54 this->semanticRun = PASSinit; 55 this->errors = false; 56 this->depdecl = NULL; 57 this->userAttribDecl = NULL; 58 this->ddocUnittest = NULL; 59} 60 61Dsymbol::Dsymbol(Identifier *ident) 62{ 63 //printf("Dsymbol::Dsymbol(%p, ident)\n", this); 64 this->ident = ident; 65 this->parent = NULL; 66 this->csym = NULL; 67 this->isym = NULL; 68 this->loc = Loc(); 69 this->comment = NULL; 70 this->_scope = NULL; 71 this->prettystring = NULL; 72 this->semanticRun = PASSinit; 73 this->errors = false; 74 this->depdecl = NULL; 75 this->userAttribDecl = NULL; 76 this->ddocUnittest = NULL; 77} 78 79Dsymbol *Dsymbol::create(Identifier *ident) 80{ 81 return new Dsymbol(ident); 82} 83 84bool Dsymbol::equals(RootObject *o) 85{ 86 if (this == o) 87 return true; 88 Dsymbol *s = (Dsymbol *)(o); 89 // Overload sets don't have an ident 90 if (s && ident && s->ident && ident->equals(s->ident)) 91 return true; 92 return false; 93} 94 95/************************************** 96 * Copy the syntax. 97 * Used for template instantiations. 98 * If s is NULL, allocate the new object, otherwise fill it in. 99 */ 100 101Dsymbol *Dsymbol::syntaxCopy(Dsymbol *) 102{ 103 print(); 104 printf("%s %s\n", kind(), toChars()); 105 assert(0); 106 return NULL; 107} 108 109/************************************** 110 * Determine if this symbol is only one. 111 * Returns: 112 * false, *ps = NULL: There are 2 or more symbols 113 * true, *ps = NULL: There are zero symbols 114 * true, *ps = symbol: The one and only one symbol 115 */ 116 117bool Dsymbol::oneMember(Dsymbol **ps, Identifier *) 118{ 119 //printf("Dsymbol::oneMember()\n"); 120 *ps = this; 121 return true; 122} 123 124/***************************************** 125 * Same as Dsymbol::oneMember(), but look at an array of Dsymbols. 126 */ 127 128bool Dsymbol::oneMembers(Dsymbols *members, Dsymbol **ps, Identifier *ident) 129{ 130 //printf("Dsymbol::oneMembers() %d\n", members ? members->dim : 0); 131 Dsymbol *s = NULL; 132 133 if (members) 134 { 135 for (size_t i = 0; i < members->dim; i++) 136 { 137 Dsymbol *sx = (*members)[i]; 138 bool x = sx->oneMember(ps, ident); 139 //printf("\t[%d] kind %s = %d, s = %p\n", i, sx->kind(), x, *ps); 140 if (!x) 141 { 142 //printf("\tfalse 1\n"); 143 assert(*ps == NULL); 144 return false; 145 } 146 if (*ps) 147 { 148 assert(ident); 149 if (!(*ps)->ident || !(*ps)->ident->equals(ident)) 150 continue; 151 if (!s) 152 s = *ps; 153 else if (s->isOverloadable() && (*ps)->isOverloadable()) 154 { 155 // keep head of overload set 156 FuncDeclaration *f1 = s->isFuncDeclaration(); 157 FuncDeclaration *f2 = (*ps)->isFuncDeclaration(); 158 if (f1 && f2) 159 { 160 assert(!f1->isFuncAliasDeclaration()); 161 assert(!f2->isFuncAliasDeclaration()); 162 for (; f1 != f2; f1 = f1->overnext0) 163 { 164 if (f1->overnext0 == NULL) 165 { 166 f1->overnext0 = f2; 167 break; 168 } 169 } 170 } 171 } 172 else // more than one symbol 173 { 174 *ps = NULL; 175 //printf("\tfalse 2\n"); 176 return false; 177 } 178 } 179 } 180 } 181 *ps = s; // s is the one symbol, NULL if none 182 //printf("\ttrue\n"); 183 return true; 184} 185 186/***************************************** 187 * Is Dsymbol a variable that contains pointers? 188 */ 189 190bool Dsymbol::hasPointers() 191{ 192 //printf("Dsymbol::hasPointers() %s\n", toChars()); 193 return false; 194} 195 196bool Dsymbol::hasStaticCtorOrDtor() 197{ 198 //printf("Dsymbol::hasStaticCtorOrDtor() %s\n", toChars()); 199 return false; 200} 201 202void Dsymbol::setFieldOffset(AggregateDeclaration *, unsigned *, bool) 203{ 204} 205 206Identifier *Dsymbol::getIdent() 207{ 208 return ident; 209} 210 211const char *Dsymbol::toChars() 212{ 213 return ident ? ident->toChars() : "__anonymous"; 214} 215 216const char *Dsymbol::toPrettyCharsHelper() 217{ 218 return toChars(); 219} 220 221const char *Dsymbol::toPrettyChars(bool QualifyTypes) 222{ 223 if (prettystring && !QualifyTypes) 224 return (const char *)prettystring; 225 226 //printf("Dsymbol::toPrettyChars() '%s'\n", toChars()); 227 if (!parent) 228 { 229 const char *s = toChars(); 230 if (!QualifyTypes) 231 prettystring = (const utf8_t *)s; 232 return s; 233 } 234 235 // Computer number of components 236 size_t complength = 0; 237 for (Dsymbol *p = this; p; p = p->parent) 238 ++complength; 239 240 // Allocate temporary array comp[] 241 const char **comp = (const char **)mem.xmalloc(complength * sizeof(char**)); 242 243 // Fill in comp[] and compute length of final result 244 size_t length = 0; 245 int i = 0; 246 for (Dsymbol *p = this; p; p = p->parent) 247 { 248 const char *s = QualifyTypes ? p->toPrettyCharsHelper() : p->toChars(); 249 const size_t len = strlen(s); 250 comp[i] = s; 251 ++i; 252 length += len + 1; 253 } 254 255 char *s = (char *)mem.xmalloc(length); 256 char *q = s + length - 1; 257 *q = 0; 258 for (size_t j = 0; j < complength; j++) 259 { 260 const char *t = comp[j]; 261 const size_t len = strlen(t); 262 q -= len; 263 memcpy(q, t, len); 264 if (q == s) 265 break; 266 *--q = '.'; 267 } 268 free(comp); 269 if (!QualifyTypes) 270 prettystring = (utf8_t *)s; 271 return s; 272} 273 274Loc& Dsymbol::getLoc() 275{ 276 if (!loc.filename) // avoid bug 5861. 277 { 278 Module *m = getModule(); 279 280 if (m && m->srcfile) 281 loc.filename = m->srcfile->toChars(); 282 } 283 return loc; 284} 285 286const char *Dsymbol::locToChars() 287{ 288 return getLoc().toChars(); 289} 290 291const char *Dsymbol::kind() const 292{ 293 return "symbol"; 294} 295 296/********************************* 297 * If this symbol is really an alias for another, 298 * return that other. 299 * If needed, semantic() is invoked due to resolve forward reference. 300 */ 301Dsymbol *Dsymbol::toAlias() 302{ 303 return this; 304} 305 306/********************************* 307 * Resolve recursive tuple expansion in eponymous template. 308 */ 309Dsymbol *Dsymbol::toAlias2() 310{ 311 return toAlias(); 312} 313 314/** 315 * `pastMixin` returns the enclosing symbol if this is a template mixin. 316 * 317 * `pastMixinAndNspace` does likewise, additionally skipping over Nspaces that 318 * are mangleOnly. 319 * 320 * See also `parent`, `toParent`, `toParent2` and `toParent3`. 321 */ 322Dsymbol *Dsymbol::pastMixin() 323{ 324 //printf("Dsymbol::pastMixin() %s\n", toChars()); 325 if (!isTemplateMixin() && !isForwardingAttribDeclaration() && !isForwardingScopeDsymbol()) 326 return this; 327 if (!parent) 328 return NULL; 329 return parent->pastMixin(); 330} 331 332/// ditto 333Dsymbol *Dsymbol::pastMixinAndNspace() 334{ 335 //printf("Dsymbol::pastMixinAndNspace() %s\n", toChars()); 336 Nspace *ns = isNspace(); 337 if (!(ns && ns->mangleOnly) && 338 !isTemplateMixin() && !isForwardingAttribDeclaration() && !isForwardingScopeDsymbol()) 339 return this; 340 if (!parent) 341 return NULL; 342 return parent->pastMixinAndNspace(); 343} 344 345/********************************** 346 * `parent` field returns a lexically enclosing scope symbol this is a member of. 347 * 348 * `toParent()` returns a logically enclosing scope symbol this is a member of. 349 * It skips over TemplateMixin's and Nspaces that are mangleOnly. 350 * 351 * `toParent2()` returns an enclosing scope symbol this is living at runtime. 352 * It skips over both TemplateInstance's and TemplateMixin's. 353 * It's used when looking for the 'this' pointer of the enclosing function/class. 354 * 355 * `toParent3()` returns a logically enclosing scope symbol this is a member of. 356 * It skips over TemplateMixin's. 357 * 358 * Examples: 359 * module mod; 360 * template Foo(alias a) { mixin Bar!(); } 361 * mixin template Bar() { 362 * public { // ProtDeclaration 363 * void baz() { a = 2; } 364 * } 365 * } 366 * void test() { 367 * int v = 1; 368 * alias foo = Foo!(v); 369 * foo.baz(); 370 * assert(v == 2); 371 * } 372 * 373 * // s == FuncDeclaration('mod.test.Foo!().Bar!().baz()') 374 * // s.parent == TemplateMixin('mod.test.Foo!().Bar!()') 375 * // s.toParent() == TemplateInstance('mod.test.Foo!()') 376 * // s.toParent2() == FuncDeclaration('mod.test') 377 */ 378Dsymbol *Dsymbol::toParent() 379{ 380 return parent ? parent->pastMixinAndNspace() : NULL; 381} 382 383/// ditto 384Dsymbol *Dsymbol::toParent2() 385{ 386 if (!parent || 387 (!parent->isTemplateInstance() && 388 !parent->isForwardingAttribDeclaration() && 389 !parent->isForwardingScopeDsymbol())) 390 return parent; 391 return parent->toParent2(); 392} 393 394/// ditto 395Dsymbol *Dsymbol::toParent3() 396{ 397 return parent ? parent->pastMixin() : NULL; 398} 399 400TemplateInstance *Dsymbol::isInstantiated() 401{ 402 for (Dsymbol *s = parent; s; s = s->parent) 403 { 404 TemplateInstance *ti = s->isTemplateInstance(); 405 if (ti && !ti->isTemplateMixin()) 406 return ti; 407 } 408 return NULL; 409} 410 411// Check if this function is a member of a template which has only been 412// instantiated speculatively, eg from inside is(typeof()). 413// Return the speculative template instance it is part of, 414// or NULL if not speculative. 415TemplateInstance *Dsymbol::isSpeculative() 416{ 417 Dsymbol *par = parent; 418 while (par) 419 { 420 TemplateInstance *ti = par->isTemplateInstance(); 421 if (ti && ti->gagged) 422 return ti; 423 par = par->toParent(); 424 } 425 return NULL; 426} 427 428Ungag Dsymbol::ungagSpeculative() 429{ 430 unsigned oldgag = global.gag; 431 432 if (global.gag && !isSpeculative() && !toParent2()->isFuncDeclaration()) 433 global.gag = 0; 434 435 return Ungag(oldgag); 436} 437 438bool Dsymbol::isAnonymous() 439{ 440 return ident == NULL; 441} 442 443/************************************* 444 * Set scope for future semantic analysis so we can 445 * deal better with forward references. 446 */ 447 448void Dsymbol::setScope(Scope *sc) 449{ 450 //printf("Dsymbol::setScope() %p %s, %p stc = %llx\n", this, toChars(), sc, sc->stc); 451 if (!sc->nofree) 452 sc->setNoFree(); // may need it even after semantic() finishes 453 _scope = sc; 454 if (sc->depdecl) 455 depdecl = sc->depdecl; 456 457 if (!userAttribDecl) 458 userAttribDecl = sc->userAttribDecl; 459} 460 461void Dsymbol::importAll(Scope *) 462{ 463} 464 465/************************************* 466 * Does semantic analysis on the public face of declarations. 467 */ 468 469void Dsymbol::semantic(Scope *) 470{ 471 error("%p has no semantic routine", this); 472} 473 474/************************************* 475 * Does semantic analysis on initializers and members of aggregates. 476 */ 477 478void Dsymbol::semantic2(Scope *) 479{ 480 // Most Dsymbols have no further semantic analysis needed 481} 482 483/************************************* 484 * Does semantic analysis on function bodies. 485 */ 486 487void Dsymbol::semantic3(Scope *) 488{ 489 // Most Dsymbols have no further semantic analysis needed 490} 491 492/********************************************* 493 * Search for ident as member of s. 494 * Params: 495 * loc = location to print for error messages 496 * ident = identifier to search for 497 * flags = IgnoreXXXX 498 * Returns: 499 * NULL if not found 500 */ 501 502Dsymbol *Dsymbol::search(const Loc &, Identifier *, int) 503{ 504 //printf("Dsymbol::search(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars()); 505 return NULL; 506} 507 508/*************************************************** 509 * Search for symbol with correct spelling. 510 */ 511 512void *symbol_search_fp(void *arg, const char *seed, int *cost) 513{ 514 /* If not in the lexer's string table, it certainly isn't in the symbol table. 515 * Doing this first is a lot faster. 516 */ 517 size_t len = strlen(seed); 518 if (!len) 519 return NULL; 520 Identifier *id = Identifier::lookup(seed, len); 521 if (!id) 522 return NULL; 523 524 *cost = 0; 525 Dsymbol *s = (Dsymbol *)arg; 526 Module::clearCache(); 527 return (void *)s->search(Loc(), id, IgnoreErrors); 528} 529 530Dsymbol *Dsymbol::search_correct(Identifier *ident) 531{ 532 if (global.gag) 533 return NULL; // don't do it for speculative compiles; too time consuming 534 535 return (Dsymbol *)speller(ident->toChars(), &symbol_search_fp, (void *)this, idchars); 536} 537 538/*************************************** 539 * Search for identifier id as a member of 'this'. 540 * id may be a template instance. 541 * Returns: 542 * symbol found, NULL if not 543 */ 544Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, RootObject *id) 545{ 546 //printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars()); 547 Dsymbol *s = toAlias(); 548 Dsymbol *sm; 549 550 if (Declaration *d = s->isDeclaration()) 551 { 552 if (d->inuse) 553 { 554 ::error(loc, "circular reference to '%s'", d->toPrettyChars()); 555 return NULL; 556 } 557 } 558 559 switch (id->dyncast()) 560 { 561 case DYNCAST_IDENTIFIER: 562 sm = s->search(loc, (Identifier *)id); 563 break; 564 565 case DYNCAST_DSYMBOL: 566 { 567 // It's a template instance 568 //printf("\ttemplate instance id\n"); 569 Dsymbol *st = (Dsymbol *)id; 570 TemplateInstance *ti = st->isTemplateInstance(); 571 sm = s->search(loc, ti->name); 572 if (!sm) 573 { 574 sm = s->search_correct(ti->name); 575 if (sm) 576 ::error(loc, "template identifier '%s' is not a member of %s '%s', did you mean %s '%s'?", 577 ti->name->toChars(), s->kind(), s->toPrettyChars(), sm->kind(), sm->toChars()); 578 else 579 ::error(loc, "template identifier '%s' is not a member of %s '%s'", 580 ti->name->toChars(), s->kind(), s->toPrettyChars()); 581 return NULL; 582 } 583 sm = sm->toAlias(); 584 TemplateDeclaration *td = sm->isTemplateDeclaration(); 585 if (!td) 586 { 587 ::error(loc, "%s.%s is not a template, it is a %s", s->toPrettyChars(), ti->name->toChars(), sm->kind()); 588 return NULL; 589 } 590 ti->tempdecl = td; 591 if (!ti->semanticRun) 592 ti->semantic(sc); 593 sm = ti->toAlias(); 594 break; 595 } 596 597 case DYNCAST_TYPE: 598 case DYNCAST_EXPRESSION: 599 default: 600 assert(0); 601 } 602 return sm; 603} 604 605bool Dsymbol::overloadInsert(Dsymbol *) 606{ 607 //printf("Dsymbol::overloadInsert('%s')\n", s->toChars()); 608 return false; 609} 610 611d_uns64 Dsymbol::size(Loc) 612{ 613 error("Dsymbol '%s' has no size", toChars()); 614 return SIZE_INVALID; 615} 616 617bool Dsymbol::isforwardRef() 618{ 619 return false; 620} 621 622AggregateDeclaration *Dsymbol::isThis() 623{ 624 return NULL; 625} 626 627bool Dsymbol::isExport() const 628{ 629 return false; 630} 631 632bool Dsymbol::isImportedSymbol() const 633{ 634 return false; 635} 636 637bool Dsymbol::isDeprecated() 638{ 639 return false; 640} 641 642bool Dsymbol::isOverloadable() 643{ 644 return false; 645} 646 647LabelDsymbol *Dsymbol::isLabel() // is this a LabelDsymbol()? 648{ 649 return NULL; 650} 651 652/// Returns an AggregateDeclaration when toParent() is that. 653AggregateDeclaration *Dsymbol::isMember() 654{ 655 //printf("Dsymbol::isMember() %s\n", toChars()); 656 Dsymbol *parent = toParent(); 657 //printf("parent is %s %s\n", parent->kind(), parent->toChars()); 658 return parent ? parent->isAggregateDeclaration() : NULL; 659} 660 661/// Returns an AggregateDeclaration when toParent2() is that. 662AggregateDeclaration *Dsymbol::isMember2() 663{ 664 //printf("Dsymbol::isMember2() %s\n", toChars()); 665 Dsymbol *parent = toParent2(); 666 //printf("parent is %s %s\n", parent->kind(), parent->toChars()); 667 return parent ? parent->isAggregateDeclaration() : NULL; 668} 669 670// is this a member of a ClassDeclaration? 671ClassDeclaration *Dsymbol::isClassMember() 672{ 673 AggregateDeclaration *ad = isMember(); 674 return ad ? ad->isClassDeclaration() : NULL; 675} 676 677Type *Dsymbol::getType() 678{ 679 return NULL; 680} 681 682bool Dsymbol::needThis() 683{ 684 return false; 685} 686 687/********************************* 688 * Iterate this dsymbol or members of this scoped dsymbol, then 689 * call `fp` with the found symbol and `param`. 690 * Params: 691 * fp = function pointer to process the iterated symbol. 692 * If it returns nonzero, the iteration will be aborted. 693 * param = a parameter passed to fp. 694 * Returns: 695 * nonzero if the iteration is aborted by the return value of fp, 696 * or 0 if it's completed. 697 */ 698int Dsymbol::apply(Dsymbol_apply_ft_t fp, void *param) 699{ 700 return (*fp)(this, param); 701} 702 703void Dsymbol::addMember(Scope *, ScopeDsymbol *sds) 704{ 705 //printf("Dsymbol::addMember('%s')\n", toChars()); 706 //printf("Dsymbol::addMember(this = %p, '%s' scopesym = '%s')\n", this, toChars(), sds->toChars()); 707 //printf("Dsymbol::addMember(this = %p, '%s' sds = %p, sds->symtab = %p)\n", this, toChars(), sds, sds->symtab); 708 parent = sds; 709 if (!isAnonymous()) // no name, so can't add it to symbol table 710 { 711 if (!sds->symtabInsert(this)) // if name is already defined 712 { 713 Dsymbol *s2 = sds->symtabLookup(this, ident); 714 if (!s2->overloadInsert(this)) 715 { 716 sds->multiplyDefined(Loc(), this, s2); 717 errors = true; 718 } 719 } 720 if (sds->isAggregateDeclaration() || sds->isEnumDeclaration()) 721 { 722 if (ident == Id::__sizeof || ident == Id::__xalignof || ident == Id::_mangleof) 723 { 724 error(".%s property cannot be redefined", ident->toChars()); 725 errors = true; 726 } 727 } 728 } 729} 730 731void Dsymbol::error(const char *format, ...) 732{ 733 va_list ap; 734 va_start(ap, format); 735 ::verror(getLoc(), format, ap, kind(), toPrettyChars()); 736 va_end(ap); 737} 738 739void Dsymbol::error(Loc loc, const char *format, ...) 740{ 741 va_list ap; 742 va_start(ap, format); 743 ::verror(loc, format, ap, kind(), toPrettyChars()); 744 va_end(ap); 745} 746 747void Dsymbol::deprecation(Loc loc, const char *format, ...) 748{ 749 va_list ap; 750 va_start(ap, format); 751 ::vdeprecation(loc, format, ap, kind(), toPrettyChars()); 752 va_end(ap); 753} 754 755void Dsymbol::deprecation(const char *format, ...) 756{ 757 va_list ap; 758 va_start(ap, format); 759 ::vdeprecation(getLoc(), format, ap, kind(), toPrettyChars()); 760 va_end(ap); 761} 762 763void Dsymbol::checkDeprecated(Loc loc, Scope *sc) 764{ 765 if (global.params.useDeprecated != DIAGNOSTICoff && isDeprecated()) 766 { 767 // Don't complain if we're inside a deprecated symbol's scope 768 for (Dsymbol *sp = sc->parent; sp; sp = sp->parent) 769 { 770 if (sp->isDeprecated()) 771 goto L1; 772 } 773 774 for (Scope *sc2 = sc; sc2; sc2 = sc2->enclosing) 775 { 776 if (sc2->scopesym && sc2->scopesym->isDeprecated()) 777 goto L1; 778 779 // If inside a StorageClassDeclaration that is deprecated 780 if (sc2->stc & STCdeprecated) 781 goto L1; 782 } 783 784 const char *message = NULL; 785 for (Dsymbol *p = this; p; p = p->parent) 786 { 787 message = p->depdecl ? p->depdecl->getMessage() : NULL; 788 if (message) 789 break; 790 } 791 792 if (message) 793 deprecation(loc, "is deprecated - %s", message); 794 else 795 deprecation(loc, "is deprecated"); 796 } 797 798 L1: 799 Declaration *d = isDeclaration(); 800 if (d && d->storage_class & STCdisable) 801 { 802 if (!(sc->func && sc->func->storage_class & STCdisable)) 803 { 804 if (d->toParent() && d->isPostBlitDeclaration()) 805 d->toParent()->error(loc, "is not copyable because it is annotated with @disable"); 806 else 807 error(loc, "is not callable because it is annotated with @disable"); 808 } 809 } 810} 811 812/********************************** 813 * Determine which Module a Dsymbol is in. 814 */ 815 816Module *Dsymbol::getModule() 817{ 818 //printf("Dsymbol::getModule()\n"); 819 if (TemplateInstance *ti = isInstantiated()) 820 return ti->tempdecl->getModule(); 821 822 Dsymbol *s = this; 823 while (s) 824 { 825 //printf("\ts = %s '%s'\n", s->kind(), s->toPrettyChars()); 826 Module *m = s->isModule(); 827 if (m) 828 return m; 829 s = s->parent; 830 } 831 return NULL; 832} 833 834/********************************** 835 * Determine which Module a Dsymbol is in, as far as access rights go. 836 */ 837 838Module *Dsymbol::getAccessModule() 839{ 840 //printf("Dsymbol::getAccessModule()\n"); 841 if (TemplateInstance *ti = isInstantiated()) 842 return ti->tempdecl->getAccessModule(); 843 844 Dsymbol *s = this; 845 while (s) 846 { 847 //printf("\ts = %s '%s'\n", s->kind(), s->toPrettyChars()); 848 Module *m = s->isModule(); 849 if (m) 850 return m; 851 TemplateInstance *ti = s->isTemplateInstance(); 852 if (ti && ti->enclosing) 853 { 854 /* Because of local template instantiation, the parent isn't where the access 855 * rights come from - it's the template declaration 856 */ 857 s = ti->tempdecl; 858 } 859 else 860 s = s->parent; 861 } 862 return NULL; 863} 864 865/************************************* 866 */ 867 868Prot Dsymbol::prot() 869{ 870 return Prot(PROTpublic); 871} 872 873/************************************* 874 * Do syntax copy of an array of Dsymbol's. 875 */ 876 877Dsymbols *Dsymbol::arraySyntaxCopy(Dsymbols *a) 878{ 879 880 Dsymbols *b = NULL; 881 if (a) 882 { 883 b = a->copy(); 884 for (size_t i = 0; i < b->dim; i++) 885 { 886 (*b)[i] = (*b)[i]->syntaxCopy(NULL); 887 } 888 } 889 return b; 890} 891 892/**************************************** 893 * Add documentation comment to Dsymbol. 894 * Ignore NULL comments. 895 */ 896 897void Dsymbol::addComment(const utf8_t *comment) 898{ 899 //if (comment) 900 //printf("adding comment '%s' to symbol %p '%s'\n", comment, this, toChars()); 901 902 if (!this->comment) 903 this->comment = comment; 904 else if (comment && strcmp((const char *)comment, (const char *)this->comment) != 0) 905 { // Concatenate the two 906 this->comment = Lexer::combineComments(this->comment, comment); 907 } 908} 909 910/**************************************** 911 * Returns true if this symbol is defined in a non-root module without instantiation. 912 */ 913bool Dsymbol::inNonRoot() 914{ 915 Dsymbol *s = parent; 916 for (; s; s = s->toParent()) 917 { 918 if (s->isTemplateInstance()) 919 { 920 return false; 921 } 922 if (Module *m = s->isModule()) 923 { 924 if (!m->isRoot()) 925 return true; 926 break; 927 } 928 } 929 return false; 930} 931 932/********************************* OverloadSet ****************************/ 933 934OverloadSet::OverloadSet(Identifier *ident, OverloadSet *os) 935 : Dsymbol(ident) 936{ 937 if (os) 938 { 939 for (size_t i = 0; i < os->a.dim; i++) 940 { 941 a.push(os->a[i]); 942 } 943 } 944} 945 946void OverloadSet::push(Dsymbol *s) 947{ 948 a.push(s); 949} 950 951const char *OverloadSet::kind() const 952{ 953 return "overloadset"; 954} 955 956 957/********************************* ForwardingScopeDsymbol ******************/ 958 959ForwardingScopeDsymbol::ForwardingScopeDsymbol(ScopeDsymbol *forward) 960 : ScopeDsymbol() 961{ 962 this->forward = forward; 963} 964 965Dsymbol *ForwardingScopeDsymbol::symtabInsert(Dsymbol *s) 966{ 967 assert(forward); 968 if (Declaration *d = s->isDeclaration()) 969 { 970 if (d->storage_class & STClocal) 971 { 972 // Symbols with storage class STClocal are not 973 // forwarded, but stored in the local symbol 974 // table. (Those are the `static foreach` variables.) 975 if (!symtab) 976 { 977 symtab = new DsymbolTable(); 978 } 979 return ScopeDsymbol::symtabInsert(s); // insert locally 980 } 981 } 982 if (!forward->symtab) 983 { 984 forward->symtab = new DsymbolTable(); 985 } 986 // Non-STClocal symbols are forwarded to `forward`. 987 return forward->symtabInsert(s); 988} 989 990/************************ 991 * This override handles the following two cases: 992 * static foreach (i, i; [0]) { ... } 993 * and 994 * static foreach (i; [0]) { enum i = 2; } 995 */ 996Dsymbol *ForwardingScopeDsymbol::symtabLookup(Dsymbol *s, Identifier *id) 997{ 998 assert(forward); 999 // correctly diagnose clashing foreach loop variables. 1000 if (Declaration *d = s->isDeclaration()) 1001 { 1002 if (d->storage_class & STClocal) 1003 { 1004 if (!symtab) 1005 { 1006 symtab = new DsymbolTable(); 1007 } 1008 return ScopeDsymbol::symtabLookup(s,id); 1009 } 1010 } 1011 // Declarations within `static foreach` do not clash with 1012 // `static foreach` loop variables. 1013 if (!forward->symtab) 1014 { 1015 forward->symtab = new DsymbolTable(); 1016 } 1017 return forward->symtabLookup(s,id); 1018} 1019 1020void ForwardingScopeDsymbol::importScope(Dsymbol *s, Prot protection) 1021{ 1022 forward->importScope(s, protection); 1023} 1024 1025void ForwardingScopeDsymbol::semantic(Scope *) 1026{ 1027} 1028 1029const char *ForwardingScopeDsymbol::kind() const 1030{ 1031 return "local scope"; 1032} 1033 1034/********************************* ScopeDsymbol ****************************/ 1035 1036ScopeDsymbol::ScopeDsymbol() 1037 : Dsymbol() 1038{ 1039 members = NULL; 1040 symtab = NULL; 1041 endlinnum = 0; 1042 importedScopes = NULL; 1043 prots = NULL; 1044} 1045 1046ScopeDsymbol::ScopeDsymbol(Identifier *id) 1047 : Dsymbol(id) 1048{ 1049 members = NULL; 1050 symtab = NULL; 1051 endlinnum = 0; 1052 importedScopes = NULL; 1053 prots = NULL; 1054} 1055 1056Dsymbol *ScopeDsymbol::syntaxCopy(Dsymbol *s) 1057{ 1058 //printf("ScopeDsymbol::syntaxCopy('%s')\n", toChars()); 1059 ScopeDsymbol *sds = s ? (ScopeDsymbol *)s : new ScopeDsymbol(ident); 1060 sds->members = arraySyntaxCopy(members); 1061 sds->endlinnum = endlinnum; 1062 return sds; 1063} 1064 1065void ScopeDsymbol::semantic(Scope *) 1066{ 1067} 1068 1069/***************************************** 1070 * This function is #1 on the list of functions that eat cpu time. 1071 * Be very, very careful about slowing it down. 1072 */ 1073 1074Dsymbol *ScopeDsymbol::search(const Loc &loc, Identifier *ident, int flags) 1075{ 1076 //printf("%s->ScopeDsymbol::search(ident='%s', flags=x%x)\n", toChars(), ident->toChars(), flags); 1077 //if (strcmp(ident->toChars(),"c") == 0) *(char*)0=0; 1078 1079 // Look in symbols declared in this module 1080 if (symtab && !(flags & SearchImportsOnly)) 1081 { 1082 //printf(" look in locals\n"); 1083 Dsymbol *s1 = symtab->lookup(ident); 1084 if (s1) 1085 { 1086 //printf("\tfound in locals = '%s.%s'\n",toChars(),s1->toChars()); 1087 return s1; 1088 } 1089 } 1090 //printf(" not found in locals\n"); 1091 1092 // Look in imported scopes 1093 if (importedScopes) 1094 { 1095 //printf(" look in imports\n"); 1096 Dsymbol *s = NULL; 1097 OverloadSet *a = NULL; 1098 1099 // Look in imported modules 1100 for (size_t i = 0; i < importedScopes->dim; i++) 1101 { 1102 // If private import, don't search it 1103 if ((flags & IgnorePrivateImports) && prots[i] == PROTprivate) 1104 continue; 1105 1106 int sflags = flags & (IgnoreErrors | IgnoreAmbiguous | IgnoreSymbolVisibility); // remember these in recursive searches 1107 Dsymbol *ss = (*importedScopes)[i]; 1108 1109 //printf("\tscanning import '%s', prots = %d, isModule = %p, isImport = %p\n", ss->toChars(), prots[i], ss->isModule(), ss->isImport()); 1110 1111 if (ss->isModule()) 1112 { 1113 if (flags & SearchLocalsOnly) 1114 continue; 1115 } 1116 else // mixin template 1117 { 1118 if (flags & SearchImportsOnly) 1119 continue; 1120 // compatibility with -transition=import (Bugzilla 15925) 1121 // SearchLocalsOnly should always get set for new lookup rules 1122 sflags |= (flags & SearchLocalsOnly); 1123 } 1124 1125 /* Don't find private members if ss is a module 1126 */ 1127 Dsymbol *s2 = ss->search(loc, ident, sflags | (ss->isModule() ? IgnorePrivateImports : IgnoreNone)); 1128 if (!s2 || (!(flags & IgnoreSymbolVisibility) && !symbolIsVisible(this, s2))) 1129 continue; 1130 if (!s) 1131 { 1132 s = s2; 1133 if (s && s->isOverloadSet()) 1134 a = mergeOverloadSet(ident, a, s); 1135 } 1136 else if (s2 && s != s2) 1137 { 1138 if (s->toAlias() == s2->toAlias() || 1139 (s->getType() == s2->getType() && s->getType())) 1140 { 1141 /* After following aliases, we found the same 1142 * symbol, so it's not an ambiguity. But if one 1143 * alias is deprecated or less accessible, prefer 1144 * the other. 1145 */ 1146 if (s->isDeprecated() || 1147 (s->prot().isMoreRestrictiveThan(s2->prot()) && s2->prot().kind != PROTnone)) 1148 s = s2; 1149 } 1150 else 1151 { 1152 /* Two imports of the same module should be regarded as 1153 * the same. 1154 */ 1155 Import *i1 = s->isImport(); 1156 Import *i2 = s2->isImport(); 1157 if (!(i1 && i2 && 1158 (i1->mod == i2->mod || 1159 (!i1->parent->isImport() && !i2->parent->isImport() && 1160 i1->ident->equals(i2->ident)) 1161 ) 1162 ) 1163 ) 1164 { 1165 /* Bugzilla 8668: 1166 * Public selective import adds AliasDeclaration in module. 1167 * To make an overload set, resolve aliases in here and 1168 * get actual overload roots which accessible via s and s2. 1169 */ 1170 s = s->toAlias(); 1171 s2 = s2->toAlias(); 1172 1173 /* If both s2 and s are overloadable (though we only 1174 * need to check s once) 1175 */ 1176 if ((s2->isOverloadSet() || s2->isOverloadable()) && 1177 (a || s->isOverloadable())) 1178 { 1179 a = mergeOverloadSet(ident, a, s2); 1180 continue; 1181 } 1182 if (flags & IgnoreAmbiguous) // if return NULL on ambiguity 1183 return NULL; 1184 if (!(flags & IgnoreErrors)) 1185 ScopeDsymbol::multiplyDefined(loc, s, s2); 1186 break; 1187 } 1188 } 1189 } 1190 } 1191 1192 if (s) 1193 { 1194 /* Build special symbol if we had multiple finds 1195 */ 1196 if (a) 1197 { 1198 if (!s->isOverloadSet()) 1199 a = mergeOverloadSet(ident, a, s); 1200 s = a; 1201 } 1202 1203 // TODO: remove once private symbol visibility has been deprecated 1204 if (!(flags & IgnoreErrors) && s->prot().kind == PROTprivate && 1205 !s->isOverloadable() && !s->parent->isTemplateMixin() && !s->parent->isNspace()) 1206 { 1207 AliasDeclaration *ad; 1208 // accessing private selective and renamed imports is 1209 // deprecated by restricting the symbol visibility 1210 if (s->isImport() || ((ad = s->isAliasDeclaration()) != NULL && ad->_import != NULL)) 1211 {} 1212 else 1213 error(loc, "%s %s is private", s->kind(), s->toPrettyChars()); 1214 } 1215 //printf("\tfound in imports %s.%s\n", toChars(), s.toChars()); 1216 return s; 1217 } 1218 //printf(" not found in imports\n"); 1219 } 1220 1221 return NULL; 1222} 1223 1224OverloadSet *ScopeDsymbol::mergeOverloadSet(Identifier *ident, OverloadSet *os, Dsymbol *s) 1225{ 1226 if (!os) 1227 { 1228 os = new OverloadSet(ident); 1229 os->parent = this; 1230 } 1231 if (OverloadSet *os2 = s->isOverloadSet()) 1232 { 1233 // Merge the cross-module overload set 'os2' into 'os' 1234 if (os->a.dim == 0) 1235 { 1236 os->a.setDim(os2->a.dim); 1237 memcpy(os->a.tdata(), os2->a.tdata(), sizeof(os->a[0]) * os2->a.dim); 1238 } 1239 else 1240 { 1241 for (size_t i = 0; i < os2->a.dim; i++) 1242 { 1243 os = mergeOverloadSet(ident, os, os2->a[i]); 1244 } 1245 } 1246 } 1247 else 1248 { 1249 assert(s->isOverloadable()); 1250 1251 /* Don't add to os[] if s is alias of previous sym 1252 */ 1253 for (size_t j = 0; j < os->a.dim; j++) 1254 { 1255 Dsymbol *s2 = os->a[j]; 1256 if (s->toAlias() == s2->toAlias()) 1257 { 1258 if (s2->isDeprecated() || 1259 (s2->prot().isMoreRestrictiveThan(s->prot()) && 1260 s->prot().kind != PROTnone)) 1261 { 1262 os->a[j] = s; 1263 } 1264 goto Lcontinue; 1265 } 1266 } 1267 os->push(s); 1268 Lcontinue: 1269 ; 1270 } 1271 return os; 1272} 1273 1274void ScopeDsymbol::importScope(Dsymbol *s, Prot protection) 1275{ 1276 //printf("%s->ScopeDsymbol::importScope(%s, %d)\n", toChars(), s->toChars(), protection); 1277 1278 // No circular or redundant import's 1279 if (s != this) 1280 { 1281 if (!importedScopes) 1282 importedScopes = new Dsymbols(); 1283 else 1284 { 1285 for (size_t i = 0; i < importedScopes->dim; i++) 1286 { 1287 Dsymbol *ss = (*importedScopes)[i]; 1288 if (ss == s) // if already imported 1289 { 1290 if (protection.kind > prots[i]) 1291 prots[i] = protection.kind; // upgrade access 1292 return; 1293 } 1294 } 1295 } 1296 importedScopes->push(s); 1297 prots = (PROTKIND *)mem.xrealloc(prots, importedScopes->dim * sizeof(prots[0])); 1298 prots[importedScopes->dim - 1] = protection.kind; 1299 } 1300} 1301 1302#define BITS_PER_INDEX (sizeof(size_t) * CHAR_BIT) 1303 1304static void bitArraySet(BitArray *array, size_t idx) 1305{ 1306 array->ptr[idx / BITS_PER_INDEX] |= 1ULL << (idx % BITS_PER_INDEX); 1307} 1308 1309static bool bitArrayGet(BitArray *array, size_t idx) 1310{ 1311 const size_t boffset = idx % BITS_PER_INDEX; 1312 return (array->ptr[idx / BITS_PER_INDEX] & (1ULL << boffset)) >> boffset; 1313} 1314 1315static void bitArrayLength(BitArray *array, size_t len) 1316{ 1317 if (array->len < len) 1318 { 1319 const size_t obytes = (array->len + BITS_PER_INDEX - 1) / BITS_PER_INDEX; 1320 const size_t nbytes = (len + BITS_PER_INDEX - 1) / BITS_PER_INDEX; 1321 1322 if (!array->ptr) 1323 array->ptr = (size_t *)mem.xmalloc(nbytes * sizeof(size_t)); 1324 else 1325 array->ptr = (size_t *)mem.xrealloc(array->ptr, nbytes * sizeof(size_t)); 1326 1327 for (size_t i = obytes; i < nbytes; i++) 1328 array->ptr[i] = 0; 1329 1330 array->len = nbytes * BITS_PER_INDEX; 1331 } 1332} 1333 1334void ScopeDsymbol::addAccessiblePackage(Package *p, Prot protection) 1335{ 1336 BitArray *pary = protection.kind == PROTprivate ? &privateAccessiblePackages : &accessiblePackages; 1337 if (pary->len <= p->tag) 1338 bitArrayLength(pary, p->tag + 1); 1339 bitArraySet(pary, p->tag); 1340} 1341 1342bool ScopeDsymbol::isPackageAccessible(Package *p, Prot protection, int) 1343{ 1344 if ((p->tag < accessiblePackages.len && bitArrayGet(&accessiblePackages, p->tag)) || 1345 (protection.kind == PROTprivate && p->tag < privateAccessiblePackages.len && bitArrayGet(&privateAccessiblePackages, p->tag))) 1346 return true; 1347 if (importedScopes) 1348 { 1349 for (size_t i = 0; i < importedScopes->dim; i++) 1350 { 1351 // only search visible scopes && imported modules should ignore private imports 1352 Dsymbol *ss = (*importedScopes)[i]; 1353 if (protection.kind <= prots[i] && 1354 ss->isScopeDsymbol()->isPackageAccessible(p, protection, IgnorePrivateImports)) 1355 return true; 1356 } 1357 } 1358 return false; 1359} 1360 1361bool ScopeDsymbol::isforwardRef() 1362{ 1363 return (members == NULL); 1364} 1365 1366void ScopeDsymbol::multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2) 1367{ 1368 if (loc.filename) 1369 { ::error(loc, "%s at %s conflicts with %s at %s", 1370 s1->toPrettyChars(), 1371 s1->locToChars(), 1372 s2->toPrettyChars(), 1373 s2->locToChars()); 1374 } 1375 else 1376 { 1377 s1->error(s1->loc, "conflicts with %s %s at %s", 1378 s2->kind(), 1379 s2->toPrettyChars(), 1380 s2->locToChars()); 1381 } 1382} 1383 1384const char *ScopeDsymbol::kind() const 1385{ 1386 return "ScopeDsymbol"; 1387} 1388 1389Dsymbol *ScopeDsymbol::symtabInsert(Dsymbol *s) 1390{ 1391 return symtab->insert(s); 1392} 1393 1394/**************************************** 1395 * Look up identifier in symbol table. 1396 */ 1397 1398Dsymbol *ScopeDsymbol::symtabLookup(Dsymbol *, Identifier *id) 1399{ 1400 return symtab->lookup(id); 1401} 1402 1403/**************************************** 1404 * Return true if any of the members are static ctors or static dtors, or if 1405 * any members have members that are. 1406 */ 1407 1408bool ScopeDsymbol::hasStaticCtorOrDtor() 1409{ 1410 if (members) 1411 { 1412 for (size_t i = 0; i < members->dim; i++) 1413 { Dsymbol *member = (*members)[i]; 1414 1415 if (member->hasStaticCtorOrDtor()) 1416 return true; 1417 } 1418 } 1419 return false; 1420} 1421 1422/*************************************** 1423 * Determine number of Dsymbols, folding in AttribDeclaration members. 1424 */ 1425 1426static int dimDg(void *ctx, size_t, Dsymbol *) 1427{ 1428 ++*(size_t *)ctx; 1429 return 0; 1430} 1431 1432size_t ScopeDsymbol::dim(Dsymbols *members) 1433{ 1434 size_t n = 0; 1435 ScopeDsymbol_foreach(NULL, members, &dimDg, &n); 1436 return n; 1437} 1438 1439/*************************************** 1440 * Get nth Dsymbol, folding in AttribDeclaration members. 1441 * Returns: 1442 * Dsymbol* nth Dsymbol 1443 * NULL not found, *pn gets incremented by the number 1444 * of Dsymbols 1445 */ 1446 1447struct GetNthSymbolCtx 1448{ 1449 size_t nth; 1450 Dsymbol *sym; 1451}; 1452 1453static int getNthSymbolDg(void *ctx, size_t n, Dsymbol *sym) 1454{ 1455 GetNthSymbolCtx *p = (GetNthSymbolCtx *)ctx; 1456 if (n == p->nth) 1457 { p->sym = sym; 1458 return 1; 1459 } 1460 return 0; 1461} 1462 1463Dsymbol *ScopeDsymbol::getNth(Dsymbols *members, size_t nth, size_t *) 1464{ 1465 GetNthSymbolCtx ctx = { nth, NULL }; 1466 int res = ScopeDsymbol_foreach(NULL, members, &getNthSymbolDg, &ctx); 1467 return res ? ctx.sym : NULL; 1468} 1469 1470/*************************************** 1471 * Expands attribute declarations in members in depth first 1472 * order. Calls dg(void *ctx, size_t symidx, Dsymbol *sym) for each 1473 * member. 1474 * If dg returns !=0, stops and returns that value else returns 0. 1475 * Use this function to avoid the O(N + N^2/2) complexity of 1476 * calculating dim and calling N times getNth. 1477 */ 1478 1479int ScopeDsymbol_foreach(Scope *sc, Dsymbols *members, ForeachDg dg, void *ctx, size_t *pn) 1480{ 1481 assert(dg); 1482 if (!members) 1483 return 0; 1484 1485 size_t n = pn ? *pn : 0; // take over index 1486 int result = 0; 1487 for (size_t i = 0; i < members->dim; i++) 1488 { Dsymbol *s = (*members)[i]; 1489 1490 if (AttribDeclaration *a = s->isAttribDeclaration()) 1491 result = ScopeDsymbol_foreach(sc, a->include(sc, NULL), dg, ctx, &n); 1492 else if (TemplateMixin *tm = s->isTemplateMixin()) 1493 result = ScopeDsymbol_foreach(sc, tm->members, dg, ctx, &n); 1494 else if (s->isTemplateInstance()) 1495 ; 1496 else if (s->isUnitTestDeclaration()) 1497 ; 1498 else 1499 result = dg(ctx, n++, s); 1500 1501 if (result) 1502 break; 1503 } 1504 1505 if (pn) 1506 *pn = n; // update index 1507 return result; 1508} 1509 1510/******************************************* 1511 * Look for member of the form: 1512 * const(MemberInfo)[] getMembers(string); 1513 * Returns NULL if not found 1514 */ 1515 1516FuncDeclaration *ScopeDsymbol::findGetMembers() 1517{ 1518 Dsymbol *s = search_function(this, Id::getmembers); 1519 FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL; 1520 1521 if (fdx && fdx->isVirtual()) 1522 fdx = NULL; 1523 1524 return fdx; 1525} 1526 1527 1528/****************************** WithScopeSymbol ******************************/ 1529 1530WithScopeSymbol::WithScopeSymbol(WithStatement *withstate) 1531 : ScopeDsymbol() 1532{ 1533 this->withstate = withstate; 1534} 1535 1536Dsymbol *WithScopeSymbol::search(const Loc &loc, Identifier *ident, int flags) 1537{ 1538 //printf("WithScopeSymbol::search(%s)\n", ident->toChars()); 1539 if (flags & SearchImportsOnly) 1540 return NULL; 1541 1542 // Acts as proxy to the with class declaration 1543 Dsymbol *s = NULL; 1544 Expression *eold = NULL; 1545 for (Expression *e = withstate->exp; e != eold; e = resolveAliasThis(_scope, e)) 1546 { 1547 if (e->op == TOKscope) 1548 { 1549 s = ((ScopeExp *)e)->sds; 1550 } 1551 else if (e->op == TOKtype) 1552 { 1553 s = e->type->toDsymbol(NULL); 1554 } 1555 else 1556 { 1557 Type *t = e->type->toBasetype(); 1558 s = t->toDsymbol(NULL); 1559 } 1560 if (s) 1561 { 1562 s = s->search(loc, ident, flags); 1563 if (s) 1564 return s; 1565 } 1566 eold = e; 1567 } 1568 return NULL; 1569} 1570 1571/****************************** ArrayScopeSymbol ******************************/ 1572 1573ArrayScopeSymbol::ArrayScopeSymbol(Scope *sc, Expression *e) 1574 : ScopeDsymbol() 1575{ 1576 assert(e->op == TOKindex || e->op == TOKslice || e->op == TOKarray); 1577 exp = e; 1578 type = NULL; 1579 td = NULL; 1580 this->sc = sc; 1581} 1582 1583ArrayScopeSymbol::ArrayScopeSymbol(Scope *sc, TypeTuple *t) 1584 : ScopeDsymbol() 1585{ 1586 exp = NULL; 1587 type = t; 1588 td = NULL; 1589 this->sc = sc; 1590} 1591 1592ArrayScopeSymbol::ArrayScopeSymbol(Scope *sc, TupleDeclaration *s) 1593 : ScopeDsymbol() 1594{ 1595 exp = NULL; 1596 type = NULL; 1597 td = s; 1598 this->sc = sc; 1599} 1600 1601Dsymbol *ArrayScopeSymbol::search(const Loc &loc, Identifier *ident, int) 1602{ 1603 //printf("ArrayScopeSymbol::search('%s', flags = %d)\n", ident->toChars(), flags); 1604 if (ident == Id::dollar) 1605 { 1606 VarDeclaration **pvar; 1607 Expression *ce; 1608 1609 L1: 1610 if (td) 1611 { 1612 /* $ gives the number of elements in the tuple 1613 */ 1614 VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL); 1615 Expression *e = new IntegerExp(Loc(), td->objects->dim, Type::tsize_t); 1616 v->_init = new ExpInitializer(Loc(), e); 1617 v->storage_class |= STCtemp | STCstatic | STCconst; 1618 v->semantic(sc); 1619 return v; 1620 } 1621 1622 if (type) 1623 { 1624 /* $ gives the number of type entries in the type tuple 1625 */ 1626 VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL); 1627 Expression *e = new IntegerExp(Loc(), type->arguments->dim, Type::tsize_t); 1628 v->_init = new ExpInitializer(Loc(), e); 1629 v->storage_class |= STCtemp | STCstatic | STCconst; 1630 v->semantic(sc); 1631 return v; 1632 } 1633 1634 if (exp->op == TOKindex) 1635 { 1636 /* array[index] where index is some function of $ 1637 */ 1638 IndexExp *ie = (IndexExp *)exp; 1639 pvar = &ie->lengthVar; 1640 ce = ie->e1; 1641 } 1642 else if (exp->op == TOKslice) 1643 { 1644 /* array[lwr .. upr] where lwr or upr is some function of $ 1645 */ 1646 SliceExp *se = (SliceExp *)exp; 1647 pvar = &se->lengthVar; 1648 ce = se->e1; 1649 } 1650 else if (exp->op == TOKarray) 1651 { 1652 /* array[e0, e1, e2, e3] where e0, e1, e2 are some function of $ 1653 * $ is a opDollar!(dim)() where dim is the dimension(0,1,2,...) 1654 */ 1655 ArrayExp *ae = (ArrayExp *)exp; 1656 pvar = &ae->lengthVar; 1657 ce = ae->e1; 1658 } 1659 else 1660 { 1661 /* Didn't find $, look in enclosing scope(s). 1662 */ 1663 return NULL; 1664 } 1665 1666 while (ce->op == TOKcomma) 1667 ce = ((CommaExp *)ce)->e2; 1668 1669 /* If we are indexing into an array that is really a type 1670 * tuple, rewrite this as an index into a type tuple and 1671 * try again. 1672 */ 1673 if (ce->op == TOKtype) 1674 { 1675 Type *t = ((TypeExp *)ce)->type; 1676 if (t->ty == Ttuple) 1677 { 1678 type = (TypeTuple *)t; 1679 goto L1; 1680 } 1681 } 1682 1683 /* *pvar is lazily initialized, so if we refer to $ 1684 * multiple times, it gets set only once. 1685 */ 1686 if (!*pvar) // if not already initialized 1687 { 1688 /* Create variable v and set it to the value of $ 1689 */ 1690 VarDeclaration *v; 1691 Type *t; 1692 if (ce->op == TOKtuple) 1693 { 1694 /* It is for an expression tuple, so the 1695 * length will be a const. 1696 */ 1697 Expression *e = new IntegerExp(Loc(), ((TupleExp *)ce)->exps->dim, Type::tsize_t); 1698 v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, new ExpInitializer(Loc(), e)); 1699 v->storage_class |= STCtemp | STCstatic | STCconst; 1700 } 1701 else if (ce->type && (t = ce->type->toBasetype()) != NULL && 1702 (t->ty == Tstruct || t->ty == Tclass)) 1703 { 1704 // Look for opDollar 1705 assert(exp->op == TOKarray || exp->op == TOKslice); 1706 AggregateDeclaration *ad = isAggregate(t); 1707 assert(ad); 1708 1709 Dsymbol *s = ad->search(loc, Id::opDollar); 1710 if (!s) // no dollar exists -- search in higher scope 1711 return NULL; 1712 s = s->toAlias(); 1713 1714 Expression *e = NULL; 1715 // Check for multi-dimensional opDollar(dim) template. 1716 if (TemplateDeclaration *td = s->isTemplateDeclaration()) 1717 { 1718 dinteger_t dim = 0; 1719 if (exp->op == TOKarray) 1720 { 1721 dim = ((ArrayExp *)exp)->currentDimension; 1722 } 1723 else if (exp->op == TOKslice) 1724 { 1725 dim = 0; // slices are currently always one-dimensional 1726 } 1727 else 1728 { 1729 assert(0); 1730 } 1731 1732 Objects *tiargs = new Objects(); 1733 Expression *edim = new IntegerExp(Loc(), dim, Type::tsize_t); 1734 edim = ::semantic(edim, sc); 1735 tiargs->push(edim); 1736 e = new DotTemplateInstanceExp(loc, ce, td->ident, tiargs); 1737 } 1738 else 1739 { 1740 /* opDollar exists, but it's not a template. 1741 * This is acceptable ONLY for single-dimension indexing. 1742 * Note that it's impossible to have both template & function opDollar, 1743 * because both take no arguments. 1744 */ 1745 if (exp->op == TOKarray && ((ArrayExp *)exp)->arguments->dim != 1) 1746 { 1747 exp->error("%s only defines opDollar for one dimension", ad->toChars()); 1748 return NULL; 1749 } 1750 Declaration *d = s->isDeclaration(); 1751 assert(d); 1752 e = new DotVarExp(loc, ce, d); 1753 } 1754 e = ::semantic(e, sc); 1755 if (!e->type) 1756 exp->error("%s has no value", e->toChars()); 1757 t = e->type->toBasetype(); 1758 if (t && t->ty == Tfunction) 1759 e = new CallExp(e->loc, e); 1760 v = new VarDeclaration(loc, NULL, Id::dollar, new ExpInitializer(Loc(), e)); 1761 v->storage_class |= STCtemp | STCctfe | STCrvalue; 1762 } 1763 else 1764 { 1765 /* For arrays, $ will either be a compile-time constant 1766 * (in which case its value in set during constant-folding), 1767 * or a variable (in which case an expression is created in 1768 * toir.c). 1769 */ 1770 VoidInitializer *e = new VoidInitializer(Loc()); 1771 e->type = Type::tsize_t; 1772 v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, e); 1773 v->storage_class |= STCtemp | STCctfe; // it's never a true static variable 1774 } 1775 *pvar = v; 1776 } 1777 (*pvar)->semantic(sc); 1778 return (*pvar); 1779 } 1780 return NULL; 1781} 1782 1783 1784/****************************** DsymbolTable ******************************/ 1785 1786DsymbolTable::DsymbolTable() 1787{ 1788 tab = NULL; 1789} 1790 1791Dsymbol *DsymbolTable::lookup(Identifier const * const ident) 1792{ 1793 //printf("DsymbolTable::lookup(%s)\n", (char*)ident->string); 1794 return (Dsymbol *)dmd_aaGetRvalue(tab, const_cast<void *>((const void *)ident)); 1795} 1796 1797Dsymbol *DsymbolTable::insert(Dsymbol *s) 1798{ 1799 //printf("DsymbolTable::insert(this = %p, '%s')\n", this, s->ident->toChars()); 1800 Identifier *ident = s->ident; 1801 Dsymbol **ps = (Dsymbol **)dmd_aaGet(&tab, (void *)ident); 1802 if (*ps) 1803 return NULL; // already in table 1804 *ps = s; 1805 return s; 1806} 1807 1808Dsymbol *DsymbolTable::insert(Identifier const * const ident, Dsymbol *s) 1809{ 1810 //printf("DsymbolTable::insert()\n"); 1811 Dsymbol **ps = (Dsymbol **)dmd_aaGet(&tab, const_cast<void *>((const void *)ident)); 1812 if (*ps) 1813 return NULL; // already in table 1814 *ps = s; 1815 return s; 1816} 1817 1818Dsymbol *DsymbolTable::update(Dsymbol *s) 1819{ 1820 Identifier *ident = s->ident; 1821 Dsymbol **ps = (Dsymbol **)dmd_aaGet(&tab, (void *)ident); 1822 *ps = s; 1823 return s; 1824} 1825 1826/****************************** Prot ******************************/ 1827 1828Prot::Prot() 1829{ 1830 this->kind = PROTundefined; 1831 this->pkg = NULL; 1832} 1833 1834Prot::Prot(PROTKIND kind) 1835{ 1836 this->kind = kind; 1837 this->pkg = NULL; 1838} 1839 1840/** 1841 * Checks if `this` is superset of `other` restrictions. 1842 * For example, "protected" is more restrictive than "public". 1843 */ 1844bool Prot::isMoreRestrictiveThan(const Prot other) const 1845{ 1846 return this->kind < other.kind; 1847} 1848 1849/** 1850 * Checks if `this` is absolutely identical protection attribute to `other` 1851 */ 1852bool Prot::operator==(const Prot& other) const 1853{ 1854 if (this->kind == other.kind) 1855 { 1856 if (this->kind == PROTpackage) 1857 return this->pkg == other.pkg; 1858 return true; 1859 } 1860 return false; 1861} 1862 1863/** 1864 * Checks if parent defines different access restrictions than this one. 1865 * 1866 * Params: 1867 * parent = protection attribute for scope that hosts this one 1868 * 1869 * Returns: 1870 * 'true' if parent is already more restrictive than this one and thus 1871 * no differentiation is needed. 1872 */ 1873bool Prot::isSubsetOf(const Prot& parent) const 1874{ 1875 if (this->kind != parent.kind) 1876 return false; 1877 1878 if (this->kind == PROTpackage) 1879 { 1880 if (!this->pkg) 1881 return true; 1882 if (!parent.pkg) 1883 return false; 1884 if (parent.pkg->isAncestorPackageOf(this->pkg)) 1885 return true; 1886 } 1887 1888 return true; 1889} 1890