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