root/trunk/src/dsymbol.c

Revision 583, 31.8 kB (checked in by walter, 2 years ago)

workaround for another fwd reference anonymous enum bug

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