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
11 #include "root/dsystem.h"
12 #include "root/rmem.h"
13 #include "root/speller.h"
18 #include "aggregate.h"
19 #include "identifier.h"
22 #include "expression.h"
23 #include "statement.h"
24 #include "declaration.h"
34 bool symbolIsVisible(Dsymbol *origin, Dsymbol *s);
35 typedef int (*ForeachDg)(void *ctx, size_t idx, Dsymbol *s);
36 int ScopeDsymbol_foreach(Scope *sc, Dsymbols *members, ForeachDg dg, void *ctx, size_t *pn = NULL);
37 Expression *semantic(Expression *e, Scope *sc);
40 /****************************** Dsymbol ******************************/
44 //printf("Dsymbol::Dsymbol(%p)\n", this);
52 this->prettystring = NULL;
53 this->semanticRun = PASSinit;
56 this->userAttribDecl = NULL;
57 this->ddocUnittest = NULL;
60 Dsymbol::Dsymbol(Identifier *ident)
62 //printf("Dsymbol::Dsymbol(%p, ident)\n", this);
70 this->prettystring = NULL;
71 this->semanticRun = PASSinit;
74 this->userAttribDecl = NULL;
75 this->ddocUnittest = NULL;
78 Dsymbol *Dsymbol::create(Identifier *ident)
80 return new Dsymbol(ident);
83 bool Dsymbol::equals(RootObject *o)
87 Dsymbol *s = (Dsymbol *)(o);
88 // Overload sets don't have an ident
89 if (s && ident && s->ident && ident->equals(s->ident))
94 /**************************************
96 * Used for template instantiations.
97 * If s is NULL, allocate the new object, otherwise fill it in.
100 Dsymbol *Dsymbol::syntaxCopy(Dsymbol *)
103 printf("%s %s\n", kind(), toChars());
108 /**************************************
109 * Determine if this symbol is only one.
111 * false, *ps = NULL: There are 2 or more symbols
112 * true, *ps = NULL: There are zero symbols
113 * true, *ps = symbol: The one and only one symbol
116 bool Dsymbol::oneMember(Dsymbol **ps, Identifier *)
118 //printf("Dsymbol::oneMember()\n");
123 /*****************************************
124 * Same as Dsymbol::oneMember(), but look at an array of Dsymbols.
127 bool Dsymbol::oneMembers(Dsymbols *members, Dsymbol **ps, Identifier *ident)
129 //printf("Dsymbol::oneMembers() %d\n", members ? members->dim : 0);
134 for (size_t i = 0; i < members->dim; i++)
136 Dsymbol *sx = (*members)[i];
137 bool x = sx->oneMember(ps, ident);
138 //printf("\t[%d] kind %s = %d, s = %p\n", i, sx->kind(), x, *ps);
141 //printf("\tfalse 1\n");
148 if (!(*ps)->ident || !(*ps)->ident->equals(ident))
152 else if (s->isOverloadable() && (*ps)->isOverloadable())
154 // keep head of overload set
155 FuncDeclaration *f1 = s->isFuncDeclaration();
156 FuncDeclaration *f2 = (*ps)->isFuncDeclaration();
159 assert(!f1->isFuncAliasDeclaration());
160 assert(!f2->isFuncAliasDeclaration());
161 for (; f1 != f2; f1 = f1->overnext0)
163 if (f1->overnext0 == NULL)
171 else // more than one symbol
174 //printf("\tfalse 2\n");
180 *ps = s; // s is the one symbol, NULL if none
181 //printf("\ttrue\n");
185 /*****************************************
186 * Is Dsymbol a variable that contains pointers?
189 bool Dsymbol::hasPointers()
191 //printf("Dsymbol::hasPointers() %s\n", toChars());
195 bool Dsymbol::hasStaticCtorOrDtor()
197 //printf("Dsymbol::hasStaticCtorOrDtor() %s\n", toChars());
201 void Dsymbol::setFieldOffset(AggregateDeclaration *, unsigned *, bool)
205 Identifier *Dsymbol::getIdent()
210 const char *Dsymbol::toChars()
212 return ident ? ident->toChars() : "__anonymous";
215 const char *Dsymbol::toPrettyCharsHelper()
220 const char *Dsymbol::toPrettyChars(bool QualifyTypes)
222 if (prettystring && !QualifyTypes)
223 return (const char *)prettystring;
225 //printf("Dsymbol::toPrettyChars() '%s'\n", toChars());
228 const char *s = toChars();
230 prettystring = (const utf8_t *)s;
234 // Computer number of components
235 size_t complength = 0;
236 for (Dsymbol *p = this; p; p = p->parent)
239 // Allocate temporary array comp[]
240 const char **comp = (const char **)mem.xmalloc(complength * sizeof(char**));
242 // Fill in comp[] and compute length of final result
245 for (Dsymbol *p = this; p; p = p->parent)
247 const char *s = QualifyTypes ? p->toPrettyCharsHelper() : p->toChars();
248 const size_t len = strlen(s);
254 char *s = (char *)mem.xmalloc(length);
255 char *q = s + length - 1;
257 for (size_t j = 0; j < complength; j++)
259 const char *t = comp[j];
260 const size_t len = strlen(t);
269 prettystring = (utf8_t *)s;
273 Loc& Dsymbol::getLoc()
275 if (!loc.filename) // avoid bug 5861.
277 Module *m = getModule();
280 loc.filename = m->srcfile->toChars();
285 const char *Dsymbol::locToChars()
287 return getLoc().toChars();
290 const char *Dsymbol::kind() const
295 /*********************************
296 * If this symbol is really an alias for another,
298 * If needed, semantic() is invoked due to resolve forward reference.
300 Dsymbol *Dsymbol::toAlias()
305 /*********************************
306 * Resolve recursive tuple expansion in eponymous template.
308 Dsymbol *Dsymbol::toAlias2()
313 Dsymbol *Dsymbol::pastMixin()
317 //printf("Dsymbol::pastMixin() %s\n", toChars());
318 while (s && s->isTemplateMixin())
323 /**********************************
324 * `parent` field returns a lexically enclosing scope symbol this is a member of.
326 * `toParent()` returns a logically enclosing scope symbol this is a member of.
327 * It skips over TemplateMixin's.
329 * `toParent2()` returns an enclosing scope symbol this is living at runtime.
330 * It skips over both TemplateInstance's and TemplateMixin's.
331 * It's used when looking for the 'this' pointer of the enclosing function/class.
335 * template Foo(alias a) { mixin Bar!(); }
336 * mixin template Bar() {
337 * public { // ProtDeclaration
338 * void baz() { a = 2; }
343 * alias foo = Foo!(v);
348 * // s == FuncDeclaration('mod.test.Foo!().Bar!().baz()')
349 * // s.parent == TemplateMixin('mod.test.Foo!().Bar!()')
350 * // s.toParent() == TemplateInstance('mod.test.Foo!()')
351 * // s.toParent2() == FuncDeclaration('mod.test')
353 Dsymbol *Dsymbol::toParent()
355 return parent ? parent->pastMixin() : NULL;
359 Dsymbol *Dsymbol::toParent2()
362 while (s && s->isTemplateInstance())
367 TemplateInstance *Dsymbol::isInstantiated()
369 for (Dsymbol *s = parent; s; s = s->parent)
371 TemplateInstance *ti = s->isTemplateInstance();
372 if (ti && !ti->isTemplateMixin())
378 // Check if this function is a member of a template which has only been
379 // instantiated speculatively, eg from inside is(typeof()).
380 // Return the speculative template instance it is part of,
381 // or NULL if not speculative.
382 TemplateInstance *Dsymbol::isSpeculative()
384 Dsymbol *par = parent;
387 TemplateInstance *ti = par->isTemplateInstance();
388 if (ti && ti->gagged)
390 par = par->toParent();
395 Ungag Dsymbol::ungagSpeculative()
397 unsigned oldgag = global.gag;
399 if (global.gag && !isSpeculative() && !toParent2()->isFuncDeclaration())
402 return Ungag(oldgag);
405 bool Dsymbol::isAnonymous()
407 return ident == NULL;
410 /*************************************
411 * Set scope for future semantic analysis so we can
412 * deal better with forward references.
415 void Dsymbol::setScope(Scope *sc)
417 //printf("Dsymbol::setScope() %p %s, %p stc = %llx\n", this, toChars(), sc, sc->stc);
419 sc->setNoFree(); // may need it even after semantic() finishes
422 depdecl = sc->depdecl;
425 userAttribDecl = sc->userAttribDecl;
428 void Dsymbol::importAll(Scope *)
432 /*************************************
433 * Does semantic analysis on the public face of declarations.
436 void Dsymbol::semantic(Scope *)
438 error("%p has no semantic routine", this);
441 /*************************************
442 * Does semantic analysis on initializers and members of aggregates.
445 void Dsymbol::semantic2(Scope *)
447 // Most Dsymbols have no further semantic analysis needed
450 /*************************************
451 * Does semantic analysis on function bodies.
454 void Dsymbol::semantic3(Scope *)
456 // Most Dsymbols have no further semantic analysis needed
459 /*********************************************
460 * Search for ident as member of s.
462 * loc = location to print for error messages
463 * ident = identifier to search for
469 Dsymbol *Dsymbol::search(const Loc &, Identifier *, int)
471 //printf("Dsymbol::search(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars());
475 /***************************************************
476 * Search for symbol with correct spelling.
479 void *symbol_search_fp(void *arg, const char *seed, int *cost)
481 /* If not in the lexer's string table, it certainly isn't in the symbol table.
482 * Doing this first is a lot faster.
484 size_t len = strlen(seed);
487 Identifier *id = Identifier::lookup(seed, len);
492 Dsymbol *s = (Dsymbol *)arg;
493 Module::clearCache();
494 return (void *)s->search(Loc(), id, IgnoreErrors);
497 Dsymbol *Dsymbol::search_correct(Identifier *ident)
500 return NULL; // don't do it for speculative compiles; too time consuming
502 return (Dsymbol *)speller(ident->toChars(), &symbol_search_fp, (void *)this, idchars);
505 /***************************************
506 * Search for identifier id as a member of 'this'.
507 * id may be a template instance.
509 * symbol found, NULL if not
511 Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, RootObject *id)
513 //printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars());
514 Dsymbol *s = toAlias();
517 if (Declaration *d = s->isDeclaration())
521 ::error(loc, "circular reference to '%s'", d->toPrettyChars());
526 switch (id->dyncast())
528 case DYNCAST_IDENTIFIER:
529 sm = s->search(loc, (Identifier *)id);
532 case DYNCAST_DSYMBOL:
534 // It's a template instance
535 //printf("\ttemplate instance id\n");
536 Dsymbol *st = (Dsymbol *)id;
537 TemplateInstance *ti = st->isTemplateInstance();
538 sm = s->search(loc, ti->name);
541 sm = s->search_correct(ti->name);
543 ::error(loc, "template identifier '%s' is not a member of %s '%s', did you mean %s '%s'?",
544 ti->name->toChars(), s->kind(), s->toPrettyChars(), sm->kind(), sm->toChars());
546 ::error(loc, "template identifier '%s' is not a member of %s '%s'",
547 ti->name->toChars(), s->kind(), s->toPrettyChars());
551 TemplateDeclaration *td = sm->isTemplateDeclaration();
554 ::error(loc, "%s.%s is not a template, it is a %s", s->toPrettyChars(), ti->name->toChars(), sm->kind());
558 if (!ti->semanticRun)
565 case DYNCAST_EXPRESSION:
572 bool Dsymbol::overloadInsert(Dsymbol *)
574 //printf("Dsymbol::overloadInsert('%s')\n", s->toChars());
578 d_uns64 Dsymbol::size(Loc)
580 error("Dsymbol '%s' has no size", toChars());
584 bool Dsymbol::isforwardRef()
589 AggregateDeclaration *Dsymbol::isThis()
594 bool Dsymbol::isExport() const
599 bool Dsymbol::isImportedSymbol() const
604 bool Dsymbol::isDeprecated()
609 bool Dsymbol::isOverloadable()
614 LabelDsymbol *Dsymbol::isLabel() // is this a LabelDsymbol()?
619 /// Returns an AggregateDeclaration when toParent() is that.
620 AggregateDeclaration *Dsymbol::isMember()
622 //printf("Dsymbol::isMember() %s\n", toChars());
623 Dsymbol *parent = toParent();
624 //printf("parent is %s %s\n", parent->kind(), parent->toChars());
625 return parent ? parent->isAggregateDeclaration() : NULL;
628 /// Returns an AggregateDeclaration when toParent2() is that.
629 AggregateDeclaration *Dsymbol::isMember2()
631 //printf("Dsymbol::isMember2() %s\n", toChars());
632 Dsymbol *parent = toParent2();
633 //printf("parent is %s %s\n", parent->kind(), parent->toChars());
634 return parent ? parent->isAggregateDeclaration() : NULL;
637 // is this a member of a ClassDeclaration?
638 ClassDeclaration *Dsymbol::isClassMember()
640 AggregateDeclaration *ad = isMember();
641 return ad ? ad->isClassDeclaration() : NULL;
644 Type *Dsymbol::getType()
649 bool Dsymbol::needThis()
654 /*********************************
655 * Iterate this dsymbol or members of this scoped dsymbol, then
656 * call `fp` with the found symbol and `param`.
658 * fp = function pointer to process the iterated symbol.
659 * If it returns nonzero, the iteration will be aborted.
660 * param = a parameter passed to fp.
662 * nonzero if the iteration is aborted by the return value of fp,
663 * or 0 if it's completed.
665 int Dsymbol::apply(Dsymbol_apply_ft_t fp, void *param)
667 return (*fp)(this, param);
670 void Dsymbol::addMember(Scope *, ScopeDsymbol *sds)
672 //printf("Dsymbol::addMember('%s')\n", toChars());
673 //printf("Dsymbol::addMember(this = %p, '%s' scopesym = '%s')\n", this, toChars(), sds->toChars());
674 //printf("Dsymbol::addMember(this = %p, '%s' sds = %p, sds->symtab = %p)\n", this, toChars(), sds, sds->symtab);
676 if (!isAnonymous()) // no name, so can't add it to symbol table
678 if (!sds->symtabInsert(this)) // if name is already defined
680 Dsymbol *s2 = sds->symtabLookup(this, ident);
681 if (!s2->overloadInsert(this))
683 sds->multiplyDefined(Loc(), this, s2);
687 if (sds->isAggregateDeclaration() || sds->isEnumDeclaration())
689 if (ident == Id::__sizeof || ident == Id::__xalignof || ident == Id::_mangleof)
691 error(".%s property cannot be redefined", ident->toChars());
698 void Dsymbol::error(const char *format, ...)
701 va_start(ap, format);
702 ::verror(getLoc(), format, ap, kind(), toPrettyChars());
706 void Dsymbol::error(Loc loc, const char *format, ...)
709 va_start(ap, format);
710 ::verror(loc, format, ap, kind(), toPrettyChars());
714 void Dsymbol::deprecation(Loc loc, const char *format, ...)
717 va_start(ap, format);
718 ::vdeprecation(loc, format, ap, kind(), toPrettyChars());
722 void Dsymbol::deprecation(const char *format, ...)
725 va_start(ap, format);
726 ::vdeprecation(getLoc(), format, ap, kind(), toPrettyChars());
730 void Dsymbol::checkDeprecated(Loc loc, Scope *sc)
732 if (global.params.useDeprecated != DIAGNOSTICoff && isDeprecated())
734 // Don't complain if we're inside a deprecated symbol's scope
735 for (Dsymbol *sp = sc->parent; sp; sp = sp->parent)
737 if (sp->isDeprecated())
741 for (Scope *sc2 = sc; sc2; sc2 = sc2->enclosing)
743 if (sc2->scopesym && sc2->scopesym->isDeprecated())
746 // If inside a StorageClassDeclaration that is deprecated
747 if (sc2->stc & STCdeprecated)
751 const char *message = NULL;
752 for (Dsymbol *p = this; p; p = p->parent)
754 message = p->depdecl ? p->depdecl->getMessage() : NULL;
760 deprecation(loc, "is deprecated - %s", message);
762 deprecation(loc, "is deprecated");
766 Declaration *d = isDeclaration();
767 if (d && d->storage_class & STCdisable)
769 if (!(sc->func && sc->func->storage_class & STCdisable))
771 if (d->toParent() && d->isPostBlitDeclaration())
772 d->toParent()->error(loc, "is not copyable because it is annotated with @disable");
774 error(loc, "is not callable because it is annotated with @disable");
779 /**********************************
780 * Determine which Module a Dsymbol is in.
783 Module *Dsymbol::getModule()
785 //printf("Dsymbol::getModule()\n");
786 if (TemplateInstance *ti = isInstantiated())
787 return ti->tempdecl->getModule();
792 //printf("\ts = %s '%s'\n", s->kind(), s->toPrettyChars());
793 Module *m = s->isModule();
801 /**********************************
802 * Determine which Module a Dsymbol is in, as far as access rights go.
805 Module *Dsymbol::getAccessModule()
807 //printf("Dsymbol::getAccessModule()\n");
808 if (TemplateInstance *ti = isInstantiated())
809 return ti->tempdecl->getAccessModule();
814 //printf("\ts = %s '%s'\n", s->kind(), s->toPrettyChars());
815 Module *m = s->isModule();
818 TemplateInstance *ti = s->isTemplateInstance();
819 if (ti && ti->enclosing)
821 /* Because of local template instantiation, the parent isn't where the access
822 * rights come from - it's the template declaration
832 /*************************************
837 return Prot(PROTpublic);
840 /*************************************
841 * Do syntax copy of an array of Dsymbol's.
844 Dsymbols *Dsymbol::arraySyntaxCopy(Dsymbols *a)
851 for (size_t i = 0; i < b->dim; i++)
853 (*b)[i] = (*b)[i]->syntaxCopy(NULL);
859 /****************************************
860 * Add documentation comment to Dsymbol.
861 * Ignore NULL comments.
864 void Dsymbol::addComment(const utf8_t *comment)
867 //printf("adding comment '%s' to symbol %p '%s'\n", comment, this, toChars());
870 this->comment = comment;
871 else if (comment && strcmp((const char *)comment, (const char *)this->comment) != 0)
872 { // Concatenate the two
873 this->comment = Lexer::combineComments(this->comment, comment);
877 /****************************************
878 * Returns true if this symbol is defined in a non-root module without instantiation.
880 bool Dsymbol::inNonRoot()
883 for (; s; s = s->toParent())
885 if (s->isTemplateInstance())
889 if (Module *m = s->isModule())
899 /********************************* OverloadSet ****************************/
901 OverloadSet::OverloadSet(Identifier *ident, OverloadSet *os)
906 for (size_t i = 0; i < os->a.dim; i++)
913 void OverloadSet::push(Dsymbol *s)
918 const char *OverloadSet::kind() const
920 return "overloadset";
924 /********************************* ScopeDsymbol ****************************/
926 ScopeDsymbol::ScopeDsymbol()
932 importedScopes = NULL;
936 ScopeDsymbol::ScopeDsymbol(Identifier *id)
942 importedScopes = NULL;
946 Dsymbol *ScopeDsymbol::syntaxCopy(Dsymbol *s)
948 //printf("ScopeDsymbol::syntaxCopy('%s')\n", toChars());
949 ScopeDsymbol *sds = s ? (ScopeDsymbol *)s : new ScopeDsymbol(ident);
950 sds->members = arraySyntaxCopy(members);
951 sds->endlinnum = endlinnum;
955 void ScopeDsymbol::semantic(Scope *)
959 /*****************************************
960 * This function is #1 on the list of functions that eat cpu time.
961 * Be very, very careful about slowing it down.
964 Dsymbol *ScopeDsymbol::search(const Loc &loc, Identifier *ident, int flags)
966 //printf("%s->ScopeDsymbol::search(ident='%s', flags=x%x)\n", toChars(), ident->toChars(), flags);
967 //if (strcmp(ident->toChars(),"c") == 0) *(char*)0=0;
969 // Look in symbols declared in this module
970 if (symtab && !(flags & SearchImportsOnly))
972 //printf(" look in locals\n");
973 Dsymbol *s1 = symtab->lookup(ident);
976 //printf("\tfound in locals = '%s.%s'\n",toChars(),s1->toChars());
980 //printf(" not found in locals\n");
982 // Look in imported scopes
985 //printf(" look in imports\n");
987 OverloadSet *a = NULL;
989 // Look in imported modules
990 for (size_t i = 0; i < importedScopes->dim; i++)
992 // If private import, don't search it
993 if ((flags & IgnorePrivateImports) && prots[i] == PROTprivate)
996 int sflags = flags & (IgnoreErrors | IgnoreAmbiguous | IgnoreSymbolVisibility); // remember these in recursive searches
997 Dsymbol *ss = (*importedScopes)[i];
999 //printf("\tscanning import '%s', prots = %d, isModule = %p, isImport = %p\n", ss->toChars(), prots[i], ss->isModule(), ss->isImport());
1003 if (flags & SearchLocalsOnly)
1006 else // mixin template
1008 if (flags & SearchImportsOnly)
1010 // compatibility with -transition=import (Bugzilla 15925)
1011 // SearchLocalsOnly should always get set for new lookup rules
1012 sflags |= (flags & SearchLocalsOnly);
1015 /* Don't find private members if ss is a module
1017 Dsymbol *s2 = ss->search(loc, ident, sflags | (ss->isModule() ? IgnorePrivateImports : IgnoreNone));
1018 if (!s2 || (!(flags & IgnoreSymbolVisibility) && !symbolIsVisible(this, s2)))
1023 if (s && s->isOverloadSet())
1024 a = mergeOverloadSet(ident, a, s);
1026 else if (s2 && s != s2)
1028 if (s->toAlias() == s2->toAlias() ||
1029 (s->getType() == s2->getType() && s->getType()))
1031 /* After following aliases, we found the same
1032 * symbol, so it's not an ambiguity. But if one
1033 * alias is deprecated or less accessible, prefer
1036 if (s->isDeprecated() ||
1037 (s->prot().isMoreRestrictiveThan(s2->prot()) && s2->prot().kind != PROTnone))
1042 /* Two imports of the same module should be regarded as
1045 Import *i1 = s->isImport();
1046 Import *i2 = s2->isImport();
1048 (i1->mod == i2->mod ||
1049 (!i1->parent->isImport() && !i2->parent->isImport() &&
1050 i1->ident->equals(i2->ident))
1056 * Public selective import adds AliasDeclaration in module.
1057 * To make an overload set, resolve aliases in here and
1058 * get actual overload roots which accessible via s and s2.
1063 /* If both s2 and s are overloadable (though we only
1064 * need to check s once)
1066 if ((s2->isOverloadSet() || s2->isOverloadable()) &&
1067 (a || s->isOverloadable()))
1069 a = mergeOverloadSet(ident, a, s2);
1072 if (flags & IgnoreAmbiguous) // if return NULL on ambiguity
1074 if (!(flags & IgnoreErrors))
1075 ScopeDsymbol::multiplyDefined(loc, s, s2);
1084 /* Build special symbol if we had multiple finds
1088 if (!s->isOverloadSet())
1089 a = mergeOverloadSet(ident, a, s);
1093 // TODO: remove once private symbol visibility has been deprecated
1094 if (!(flags & IgnoreErrors) && s->prot().kind == PROTprivate &&
1095 !s->isOverloadable() && !s->parent->isTemplateMixin() && !s->parent->isNspace())
1097 AliasDeclaration *ad;
1098 // accessing private selective and renamed imports is
1099 // deprecated by restricting the symbol visibility
1100 if (s->isImport() || ((ad = s->isAliasDeclaration()) != NULL && ad->_import != NULL))
1103 error(loc, "%s %s is private", s->kind(), s->toPrettyChars());
1105 //printf("\tfound in imports %s.%s\n", toChars(), s.toChars());
1108 //printf(" not found in imports\n");
1114 OverloadSet *ScopeDsymbol::mergeOverloadSet(Identifier *ident, OverloadSet *os, Dsymbol *s)
1118 os = new OverloadSet(ident);
1121 if (OverloadSet *os2 = s->isOverloadSet())
1123 // Merge the cross-module overload set 'os2' into 'os'
1126 os->a.setDim(os2->a.dim);
1127 memcpy(os->a.tdata(), os2->a.tdata(), sizeof(os->a[0]) * os2->a.dim);
1131 for (size_t i = 0; i < os2->a.dim; i++)
1133 os = mergeOverloadSet(ident, os, os2->a[i]);
1139 assert(s->isOverloadable());
1141 /* Don't add to os[] if s is alias of previous sym
1143 for (size_t j = 0; j < os->a.dim; j++)
1145 Dsymbol *s2 = os->a[j];
1146 if (s->toAlias() == s2->toAlias())
1148 if (s2->isDeprecated() ||
1149 (s2->prot().isMoreRestrictiveThan(s->prot()) &&
1150 s->prot().kind != PROTnone))
1164 void ScopeDsymbol::importScope(Dsymbol *s, Prot protection)
1166 //printf("%s->ScopeDsymbol::importScope(%s, %d)\n", toChars(), s->toChars(), protection);
1168 // No circular or redundant import's
1171 if (!importedScopes)
1172 importedScopes = new Dsymbols();
1175 for (size_t i = 0; i < importedScopes->dim; i++)
1177 Dsymbol *ss = (*importedScopes)[i];
1178 if (ss == s) // if already imported
1180 if (protection.kind > prots[i])
1181 prots[i] = protection.kind; // upgrade access
1186 importedScopes->push(s);
1187 prots = (PROTKIND *)mem.xrealloc(prots, importedScopes->dim * sizeof(prots[0]));
1188 prots[importedScopes->dim - 1] = protection.kind;
1192 #define BITS_PER_INDEX (sizeof(size_t) * CHAR_BIT)
1194 static void bitArraySet(BitArray *array, size_t idx)
1196 array->ptr[idx / BITS_PER_INDEX] |= 1ULL << (idx % BITS_PER_INDEX);
1199 static bool bitArrayGet(BitArray *array, size_t idx)
1201 const size_t boffset = idx % BITS_PER_INDEX;
1202 return (array->ptr[idx / BITS_PER_INDEX] & (1ULL << boffset)) >> boffset;
1205 static void bitArrayLength(BitArray *array, size_t len)
1207 if (array->len < len)
1209 const size_t obytes = (array->len + BITS_PER_INDEX - 1) / BITS_PER_INDEX;
1210 const size_t nbytes = (len + BITS_PER_INDEX - 1) / BITS_PER_INDEX;
1213 array->ptr = (size_t *)mem.xmalloc(nbytes * sizeof(size_t));
1215 array->ptr = (size_t *)mem.xrealloc(array->ptr, nbytes * sizeof(size_t));
1217 for (size_t i = obytes; i < nbytes; i++)
1220 array->len = nbytes * BITS_PER_INDEX;
1224 void ScopeDsymbol::addAccessiblePackage(Package *p, Prot protection)
1226 BitArray *pary = protection.kind == PROTprivate ? &privateAccessiblePackages : &accessiblePackages;
1227 if (pary->len <= p->tag)
1228 bitArrayLength(pary, p->tag + 1);
1229 bitArraySet(pary, p->tag);
1232 bool ScopeDsymbol::isPackageAccessible(Package *p, Prot protection, int)
1234 if ((p->tag < accessiblePackages.len && bitArrayGet(&accessiblePackages, p->tag)) ||
1235 (protection.kind == PROTprivate && p->tag < privateAccessiblePackages.len && bitArrayGet(&privateAccessiblePackages, p->tag)))
1239 for (size_t i = 0; i < importedScopes->dim; i++)
1241 // only search visible scopes && imported modules should ignore private imports
1242 Dsymbol *ss = (*importedScopes)[i];
1243 if (protection.kind <= prots[i] &&
1244 ss->isScopeDsymbol()->isPackageAccessible(p, protection, IgnorePrivateImports))
1251 bool ScopeDsymbol::isforwardRef()
1253 return (members == NULL);
1256 void ScopeDsymbol::multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2)
1259 { ::error(loc, "%s at %s conflicts with %s at %s",
1260 s1->toPrettyChars(),
1262 s2->toPrettyChars(),
1267 s1->error(s1->loc, "conflicts with %s %s at %s",
1269 s2->toPrettyChars(),
1274 const char *ScopeDsymbol::kind() const
1276 return "ScopeDsymbol";
1279 Dsymbol *ScopeDsymbol::symtabInsert(Dsymbol *s)
1281 return symtab->insert(s);
1284 /****************************************
1285 * Look up identifier in symbol table.
1288 Dsymbol *ScopeDsymbol::symtabLookup(Dsymbol *, Identifier *id)
1290 return symtab->lookup(id);
1293 /****************************************
1294 * Return true if any of the members are static ctors or static dtors, or if
1295 * any members have members that are.
1298 bool ScopeDsymbol::hasStaticCtorOrDtor()
1302 for (size_t i = 0; i < members->dim; i++)
1303 { Dsymbol *member = (*members)[i];
1305 if (member->hasStaticCtorOrDtor())
1312 /***************************************
1313 * Determine number of Dsymbols, folding in AttribDeclaration members.
1316 static int dimDg(void *ctx, size_t, Dsymbol *)
1322 size_t ScopeDsymbol::dim(Dsymbols *members)
1325 ScopeDsymbol_foreach(NULL, members, &dimDg, &n);
1329 /***************************************
1330 * Get nth Dsymbol, folding in AttribDeclaration members.
1332 * Dsymbol* nth Dsymbol
1333 * NULL not found, *pn gets incremented by the number
1337 struct GetNthSymbolCtx
1343 static int getNthSymbolDg(void *ctx, size_t n, Dsymbol *sym)
1345 GetNthSymbolCtx *p = (GetNthSymbolCtx *)ctx;
1353 Dsymbol *ScopeDsymbol::getNth(Dsymbols *members, size_t nth, size_t *)
1355 GetNthSymbolCtx ctx = { nth, NULL };
1356 int res = ScopeDsymbol_foreach(NULL, members, &getNthSymbolDg, &ctx);
1357 return res ? ctx.sym : NULL;
1360 /***************************************
1361 * Expands attribute declarations in members in depth first
1362 * order. Calls dg(void *ctx, size_t symidx, Dsymbol *sym) for each
1364 * If dg returns !=0, stops and returns that value else returns 0.
1365 * Use this function to avoid the O(N + N^2/2) complexity of
1366 * calculating dim and calling N times getNth.
1369 int ScopeDsymbol_foreach(Scope *sc, Dsymbols *members, ForeachDg dg, void *ctx, size_t *pn)
1375 size_t n = pn ? *pn : 0; // take over index
1377 for (size_t i = 0; i < members->dim; i++)
1378 { Dsymbol *s = (*members)[i];
1380 if (AttribDeclaration *a = s->isAttribDeclaration())
1381 result = ScopeDsymbol_foreach(sc, a->include(sc, NULL), dg, ctx, &n);
1382 else if (TemplateMixin *tm = s->isTemplateMixin())
1383 result = ScopeDsymbol_foreach(sc, tm->members, dg, ctx, &n);
1384 else if (s->isTemplateInstance())
1386 else if (s->isUnitTestDeclaration())
1389 result = dg(ctx, n++, s);
1396 *pn = n; // update index
1400 /*******************************************
1401 * Look for member of the form:
1402 * const(MemberInfo)[] getMembers(string);
1403 * Returns NULL if not found
1406 FuncDeclaration *ScopeDsymbol::findGetMembers()
1408 Dsymbol *s = search_function(this, Id::getmembers);
1409 FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL;
1411 if (fdx && fdx->isVirtual())
1418 /****************************** WithScopeSymbol ******************************/
1420 WithScopeSymbol::WithScopeSymbol(WithStatement *withstate)
1423 this->withstate = withstate;
1426 Dsymbol *WithScopeSymbol::search(const Loc &loc, Identifier *ident, int flags)
1428 //printf("WithScopeSymbol::search(%s)\n", ident->toChars());
1429 if (flags & SearchImportsOnly)
1432 // Acts as proxy to the with class declaration
1434 Expression *eold = NULL;
1435 for (Expression *e = withstate->exp; e != eold; e = resolveAliasThis(_scope, e))
1437 if (e->op == TOKscope)
1439 s = ((ScopeExp *)e)->sds;
1441 else if (e->op == TOKtype)
1443 s = e->type->toDsymbol(NULL);
1447 Type *t = e->type->toBasetype();
1448 s = t->toDsymbol(NULL);
1452 s = s->search(loc, ident, flags);
1461 /****************************** ArrayScopeSymbol ******************************/
1463 ArrayScopeSymbol::ArrayScopeSymbol(Scope *sc, Expression *e)
1466 assert(e->op == TOKindex || e->op == TOKslice || e->op == TOKarray);
1473 ArrayScopeSymbol::ArrayScopeSymbol(Scope *sc, TypeTuple *t)
1482 ArrayScopeSymbol::ArrayScopeSymbol(Scope *sc, TupleDeclaration *s)
1491 Dsymbol *ArrayScopeSymbol::search(const Loc &loc, Identifier *ident, int)
1493 //printf("ArrayScopeSymbol::search('%s', flags = %d)\n", ident->toChars(), flags);
1494 if (ident == Id::dollar)
1496 VarDeclaration **pvar;
1502 /* $ gives the number of elements in the tuple
1504 VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
1505 Expression *e = new IntegerExp(Loc(), td->objects->dim, Type::tsize_t);
1506 v->_init = new ExpInitializer(Loc(), e);
1507 v->storage_class |= STCtemp | STCstatic | STCconst;
1514 /* $ gives the number of type entries in the type tuple
1516 VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
1517 Expression *e = new IntegerExp(Loc(), type->arguments->dim, Type::tsize_t);
1518 v->_init = new ExpInitializer(Loc(), e);
1519 v->storage_class |= STCtemp | STCstatic | STCconst;
1524 if (exp->op == TOKindex)
1526 /* array[index] where index is some function of $
1528 IndexExp *ie = (IndexExp *)exp;
1529 pvar = &ie->lengthVar;
1532 else if (exp->op == TOKslice)
1534 /* array[lwr .. upr] where lwr or upr is some function of $
1536 SliceExp *se = (SliceExp *)exp;
1537 pvar = &se->lengthVar;
1540 else if (exp->op == TOKarray)
1542 /* array[e0, e1, e2, e3] where e0, e1, e2 are some function of $
1543 * $ is a opDollar!(dim)() where dim is the dimension(0,1,2,...)
1545 ArrayExp *ae = (ArrayExp *)exp;
1546 pvar = &ae->lengthVar;
1551 /* Didn't find $, look in enclosing scope(s).
1556 while (ce->op == TOKcomma)
1557 ce = ((CommaExp *)ce)->e2;
1559 /* If we are indexing into an array that is really a type
1560 * tuple, rewrite this as an index into a type tuple and
1563 if (ce->op == TOKtype)
1565 Type *t = ((TypeExp *)ce)->type;
1566 if (t->ty == Ttuple)
1568 type = (TypeTuple *)t;
1573 /* *pvar is lazily initialized, so if we refer to $
1574 * multiple times, it gets set only once.
1576 if (!*pvar) // if not already initialized
1578 /* Create variable v and set it to the value of $
1582 if (ce->op == TOKtuple)
1584 /* It is for an expression tuple, so the
1585 * length will be a const.
1587 Expression *e = new IntegerExp(Loc(), ((TupleExp *)ce)->exps->dim, Type::tsize_t);
1588 v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, new ExpInitializer(Loc(), e));
1589 v->storage_class |= STCtemp | STCstatic | STCconst;
1591 else if (ce->type && (t = ce->type->toBasetype()) != NULL &&
1592 (t->ty == Tstruct || t->ty == Tclass))
1594 // Look for opDollar
1595 assert(exp->op == TOKarray || exp->op == TOKslice);
1596 AggregateDeclaration *ad = isAggregate(t);
1599 Dsymbol *s = ad->search(loc, Id::opDollar);
1600 if (!s) // no dollar exists -- search in higher scope
1604 Expression *e = NULL;
1605 // Check for multi-dimensional opDollar(dim) template.
1606 if (TemplateDeclaration *td = s->isTemplateDeclaration())
1609 if (exp->op == TOKarray)
1611 dim = ((ArrayExp *)exp)->currentDimension;
1613 else if (exp->op == TOKslice)
1615 dim = 0; // slices are currently always one-dimensional
1622 Objects *tiargs = new Objects();
1623 Expression *edim = new IntegerExp(Loc(), dim, Type::tsize_t);
1624 edim = ::semantic(edim, sc);
1626 e = new DotTemplateInstanceExp(loc, ce, td->ident, tiargs);
1630 /* opDollar exists, but it's not a template.
1631 * This is acceptable ONLY for single-dimension indexing.
1632 * Note that it's impossible to have both template & function opDollar,
1633 * because both take no arguments.
1635 if (exp->op == TOKarray && ((ArrayExp *)exp)->arguments->dim != 1)
1637 exp->error("%s only defines opDollar for one dimension", ad->toChars());
1640 Declaration *d = s->isDeclaration();
1642 e = new DotVarExp(loc, ce, d);
1644 e = ::semantic(e, sc);
1646 exp->error("%s has no value", e->toChars());
1647 t = e->type->toBasetype();
1648 if (t && t->ty == Tfunction)
1649 e = new CallExp(e->loc, e);
1650 v = new VarDeclaration(loc, NULL, Id::dollar, new ExpInitializer(Loc(), e));
1651 v->storage_class |= STCtemp | STCctfe | STCrvalue;
1655 /* For arrays, $ will either be a compile-time constant
1656 * (in which case its value in set during constant-folding),
1657 * or a variable (in which case an expression is created in
1660 VoidInitializer *e = new VoidInitializer(Loc());
1661 e->type = Type::tsize_t;
1662 v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, e);
1663 v->storage_class |= STCtemp | STCctfe; // it's never a true static variable
1667 (*pvar)->semantic(sc);
1674 /****************************** DsymbolTable ******************************/
1676 DsymbolTable::DsymbolTable()
1681 Dsymbol *DsymbolTable::lookup(Identifier const * const ident)
1683 //printf("DsymbolTable::lookup(%s)\n", (char*)ident->string);
1684 return (Dsymbol *)dmd_aaGetRvalue(tab, const_cast<void *>((const void *)ident));
1687 Dsymbol *DsymbolTable::insert(Dsymbol *s)
1689 //printf("DsymbolTable::insert(this = %p, '%s')\n", this, s->ident->toChars());
1690 Identifier *ident = s->ident;
1691 Dsymbol **ps = (Dsymbol **)dmd_aaGet(&tab, (void *)ident);
1693 return NULL; // already in table
1698 Dsymbol *DsymbolTable::insert(Identifier const * const ident, Dsymbol *s)
1700 //printf("DsymbolTable::insert()\n");
1701 Dsymbol **ps = (Dsymbol **)dmd_aaGet(&tab, const_cast<void *>((const void *)ident));
1703 return NULL; // already in table
1708 Dsymbol *DsymbolTable::update(Dsymbol *s)
1710 Identifier *ident = s->ident;
1711 Dsymbol **ps = (Dsymbol **)dmd_aaGet(&tab, (void *)ident);
1716 /****************************** Prot ******************************/
1720 this->kind = PROTundefined;
1724 Prot::Prot(PROTKIND kind)
1731 * Checks if `this` is superset of `other` restrictions.
1732 * For example, "protected" is more restrictive than "public".
1734 bool Prot::isMoreRestrictiveThan(const Prot other) const
1736 return this->kind < other.kind;
1740 * Checks if `this` is absolutely identical protection attribute to `other`
1742 bool Prot::operator==(const Prot& other) const
1744 if (this->kind == other.kind)
1746 if (this->kind == PROTpackage)
1747 return this->pkg == other.pkg;
1754 * Checks if parent defines different access restrictions than this one.
1757 * parent = protection attribute for scope that hosts this one
1760 * 'true' if parent is already more restrictive than this one and thus
1761 * no differentiation is needed.
1763 bool Prot::isSubsetOf(const Prot& parent) const
1765 if (this->kind != parent.kind)
1768 if (this->kind == PROTpackage)
1774 if (parent.pkg->isAncestorPackageOf(this->pkg))