root/branches/dmdfe-2.0/dsymbol.c

Revision 914, 23.9 kB (checked in by Gregor, 3 months ago)

MERGE: DMD 2.019

Line 
1 // Compiler implementation of the D programming language
2 // Copyright (c) 1999-2008 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 "mem.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
32 /****************************** Dsymbol ******************************/
33
34 Dsymbol::Dsymbol()
35 {
36     //printf("Dsymbol::Dsymbol(%p)\n", this);
37     this->ident = NULL;
38     this->c_ident = NULL;
39     this->parent = NULL;
40     this->csym = NULL;
41     this->isym = NULL;
42     this->loc = 0;
43     this->comment = NULL;
44 }
45
46 Dsymbol::Dsymbol(Identifier *ident)
47 {
48     //printf("Dsymbol::Dsymbol(%p, ident)\n", this);
49     this->ident = ident;
50     this->c_ident = NULL;
51     this->parent = NULL;
52     this->csym = NULL;
53     this->isym = NULL;
54     this->loc = 0;
55     this->comment = NULL;
56 }
57
58 int Dsymbol::equals(Object *o)
59 {   Dsymbol *s;
60
61     if (this == o)
62     return TRUE;
63     s = (Dsymbol *)(o);
64     if (s && ident->equals(s->ident))
65     return TRUE;
66     return FALSE;
67 }
68
69 /**************************************
70  * Copy the syntax.
71  * Used for template instantiations.
72  * If s is NULL, allocate the new object, otherwise fill it in.
73  */
74
75 Dsymbol *Dsymbol::syntaxCopy(Dsymbol *s)
76 {
77     print();
78     printf("%s %s\n", kind(), toChars());
79     assert(0);
80     return NULL;
81 }
82
83 /**************************************
84  * Determine if this symbol is only one.
85  * Returns:
86  *  FALSE, *ps = NULL: There are 2 or more symbols
87  *  TRUE,  *ps = NULL: There are zero symbols
88  *  TRUE,  *ps = symbol: The one and only one symbol
89  */
90
91 int Dsymbol::oneMember(Dsymbol **ps)
92 {
93     //printf("Dsymbol::oneMember()\n");
94     *ps = this;
95     return TRUE;
96 }
97
98 /*****************************************
99  * Same as Dsymbol::oneMember(), but look at an array of Dsymbols.
100  */
101
102 int Dsymbol::oneMembers(Array *members, Dsymbol **ps)
103 {
104     //printf("Dsymbol::oneMembers() %d\n", members ? members->dim : 0);
105     Dsymbol *s = NULL;
106
107     if (members)
108     {
109     for (int i = 0; i < members->dim; i++)
110     {   Dsymbol *sx = (Dsymbol *)members->data[i];
111
112         int x = sx->oneMember(ps);
113         //printf("\t[%d] kind %s = %d, s = %p\n", i, sx->kind(), x, *ps);
114         if (!x)
115         {
116         //printf("\tfalse 1\n");
117         assert(*ps == NULL);
118         return FALSE;
119         }
120         if (*ps)
121         {
122         if (s)          // more than one symbol
123         {   *ps = NULL;
124             //printf("\tfalse 2\n");
125             return FALSE;
126         }
127         s = *ps;
128         }
129     }
130     }
131     *ps = s;        // s is the one symbol, NULL if none
132     //printf("\ttrue\n");
133     return TRUE;
134 }
135
136 /*****************************************
137  * Is Dsymbol a variable that contains pointers?
138  */
139
140 int Dsymbol::hasPointers()
141 {
142     //printf("Dsymbol::hasPointers() %s\n", toChars());
143     return 0;
144 }
145
146 char *Dsymbol::toChars()
147 {
148     return ident ? ident->toChars() : (char *)"__anonymous";
149 }
150
151 char *Dsymbol::toPrettyChars()
152 {   Dsymbol *p;
153     char *s;
154     char *q;
155     size_t len;
156
157     //printf("Dsymbol::toPrettyChars() '%s'\n", toChars());
158     if (!parent)
159     return toChars();
160
161     len = 0;
162     for (p = this; p; p = p->parent)
163     len += strlen(p->toChars()) + 1;
164
165     s = (char *)mem.malloc(len);
166     q = s + len - 1;
167     *q = 0;
168     for (p = this; p; p = p->parent)
169     {
170     char *t = p->toChars();
171     len = strlen(t);
172     q -= len;
173     memcpy(q, t, len);
174     if (q == s)
175         break;
176     q--;
177     *q = '.';
178     }
179     return s;
180 }
181
182 char *Dsymbol::locToChars()
183 {
184     OutBuffer buf;
185     char *p;
186
187     Module *m = getModule();
188
189     if (m && m->srcfile)
190     loc.filename = m->srcfile->toChars();
191     return loc.toChars();
192 }
193
194 const char *Dsymbol::kind()
195 {
196     return "symbol";
197 }
198
199 /*********************************
200  * If this symbol is really an alias for another,
201  * return that other.
202  */
203
204 Dsymbol *Dsymbol::toAlias()
205 {
206     return this;
207 }
208
209 Dsymbol *Dsymbol::toParent()
210 {
211     return parent ? parent->pastMixin() : NULL;
212 }
213
214 Dsymbol *Dsymbol::pastMixin()
215 {
216     Dsymbol *s = this;
217
218     //printf("Dsymbol::pastMixin() %s\n", toChars());
219     while (s && s->isTemplateMixin())
220     s = s->parent;
221     return s;
222 }
223
224 /**********************************
225  * Use this instead of toParent() when looking for the
226  * 'this' pointer of the enclosing function/class.
227  */
228
229 Dsymbol *Dsymbol::toParent2()
230 {
231     Dsymbol *s = parent;
232     while (s && s->isTemplateInstance())
233     s = s->parent;
234     return s;
235 }
236
237 TemplateInstance *Dsymbol::inTemplateInstance()
238 {
239     for (Dsymbol *parent = this->parent; parent; parent = parent->parent)
240     {
241     TemplateInstance *ti = parent->isTemplateInstance();
242     if (ti)
243         return ti;
244     }
245     return NULL;
246 }
247
248 int Dsymbol::isAnonymous()
249 {
250     return ident ? 0 : 1;
251 }
252
253 void Dsymbol::semantic(Scope *sc)
254 {
255     error("%p has no semantic routine", this);
256 }
257
258 void Dsymbol::semantic2(Scope *sc)
259 {
260     // Most Dsymbols have no further semantic analysis needed
261 }
262
263 void Dsymbol::semantic3(Scope *sc)
264 {
265     // Most Dsymbols have no further semantic analysis needed
266 }
267
268 void Dsymbol::inlineScan()
269 {
270     // Most Dsymbols have no further semantic analysis needed
271 }
272
273 /*********************************************
274  * Search for ident as member of s.
275  * Input:
276  *  flags:  1   don't find private members
277  *      2   don't give error messages
278  *      4   return NULL if ambiguous
279  * Returns:
280  *  NULL if not found
281  */
282
283 Dsymbol *Dsymbol::search(Loc loc, Identifier *ident, int flags)
284 {
285     //printf("Dsymbol::search(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars());
286     return NULL;
287 }
288
289 /***************************************
290  * Search for identifier id as a member of 'this'.
291  * id may be a template instance.
292  * Returns:
293  *  symbol found, NULL if not
294  */
295
296 Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, Identifier *id)
297 {
298     //printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars());
299     Dsymbol *s = toAlias();
300     Dsymbol *sm;
301
302     switch (id->dyncast())
303     {
304     case DYNCAST_IDENTIFIER:
305         sm = s->search(loc, id, 0);
306         break;
307
308     case DYNCAST_DSYMBOL:
309     {   // It's a template instance
310         //printf("\ttemplate instance id\n");
311         Dsymbol *st = (Dsymbol *)id;
312         TemplateInstance *ti = st->isTemplateInstance();
313         id = ti->name;
314         sm = s->search(loc, id, 0);
315         if (!sm)
316         {   error("template identifier %s is not a member of %s %s",
317             id->toChars(), s->kind(), s->toChars());
318         return NULL;
319         }
320         sm = sm->toAlias();
321         TemplateDeclaration *td = sm->isTemplateDeclaration();
322         if (!td)
323         {
324         error("%s is not a template, it is a %s", id->toChars(), sm->kind());
325         return NULL;
326         }
327         ti->tempdecl = td;
328         if (!ti->semanticdone)
329         ti->semantic(sc);
330         sm = ti->toAlias();
331         break;
332     }
333
334     default:
335         assert(0);
336     }
337     return sm;
338 }
339
340 int Dsymbol::overloadInsert(Dsymbol *s)
341 {
342     //printf("Dsymbol::overloadInsert('%s')\n", s->toChars());
343     return FALSE;
344 }
345
346 void Dsymbol::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
347 {
348     buf->writestring(toChars());
349 }
350
351 unsigned Dsymbol::size(Loc loc)
352 {
353     error("Dsymbol '%s' has no size\n", toChars());
354     return 0;
355 }
356
357 int Dsymbol::isforwardRef()
358 {
359     return FALSE;
360 }
361
362 AggregateDeclaration *Dsymbol::isThis()
363 {
364     return NULL;
365 }
366
367 ClassDeclaration *Dsymbol::isClassMember()  // are we a member of a class?
368 {
369     Dsymbol *parent = toParent();
370     if (parent && parent->isClassDeclaration())
371     return (ClassDeclaration *)parent;
372     return NULL;
373 }
374
375 void Dsymbol::defineRef(Dsymbol *s)
376 {
377     assert(0);
378 }
379
380 int Dsymbol::isExport()
381 {
382     return FALSE;
383 }
384
385 int Dsymbol::isImportedSymbol()
386 {
387     return FALSE;
388 }
389
390 int Dsymbol::isDeprecated()
391 {
392     return FALSE;
393 }
394
395 int Dsymbol::isOverloadable()
396 {
397     return 0;
398 }
399
400 LabelDsymbol *Dsymbol::isLabel()        // is this a LabelDsymbol()?
401 {
402     return NULL;
403 }
404
405 AggregateDeclaration *Dsymbol::isMember()   // is this a member of an AggregateDeclaration?
406 {
407     //printf("Dsymbol::isMember() %s\n", toChars());
408     Dsymbol *parent = toParent();
409     //printf("parent is %s %s\n", parent->kind(), parent->toChars());
410     return parent ? parent->isAggregateDeclaration() : NULL;
411 }
412
413 Type *Dsymbol::getType()
414 {
415     return NULL;
416 }
417
418 int Dsymbol::needThis()
419 {
420     return FALSE;
421 }
422
423 int Dsymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
424 {
425     //printf("Dsymbol::addMember('%s')\n", toChars());
426     //printf("Dsymbol::addMember(this = %p, '%s' scopesym = '%s')\n", this, toChars(), sd->toChars());
427     //printf("Dsymbol::addMember(this = %p, '%s' sd = %p, sd->symtab = %p)\n", this, toChars(), sd, sd->symtab);
428     parent = sd;
429     if (!isAnonymous())     // no name, so can't add it to symbol table
430     {
431     if (!sd->symtab->insert(this))  // if name is already defined
432     {
433         Dsymbol *s2;
434
435         s2 = sd->symtab->lookup(ident);
436         if (!s2->overloadInsert(this))
437         {
438         sd->multiplyDefined(0, this, s2);
439         }
440     }
441     if (sd->isAggregateDeclaration() || sd->isEnumDeclaration())
442     {
443         if (ident == Id::__sizeof || ident == Id::alignof || ident == Id::mangleof)
444         error(".%s property cannot be redefined", ident->toChars());
445     }
446     return 1;
447     }
448     return 0;
449 }
450
451 void Dsymbol::error(const char *format, ...)
452 {
453     //printf("Dsymbol::error()\n");
454     if (!global.gag)
455     {
456     char *p = locToChars();
457
458     if (*p)
459         fprintf(stdmsg, "%s: ", p);
460     mem.free(p);
461
462     if (isAnonymous())
463         fprintf(stdmsg, "%s ", kind());
464     else
465         fprintf(stdmsg, "%s %s ", kind(), toPrettyChars());
466
467     va_list ap;
468     va_start(ap, format);
469     vfprintf(stdmsg, format, ap);
470     va_end(ap);
471
472     fprintf(stdmsg, "\n");
473     fflush(stdmsg);
474     }
475     global.errors++;
476
477     //fatal();
478 }
479
480 void Dsymbol::error(Loc loc, const char *format, ...)
481 {
482     if (!global.gag)
483     {
484     char *p = loc.toChars();
485     if (!*p)
486         p = locToChars();
487
488     if (*p)
489         fprintf(stdmsg, "%s: ", p);
490     mem.free(p);
491
492     fprintf(stdmsg, "%s %s ", kind(), toPrettyChars());
493
494     va_list ap;
495     va_start(ap, format);
496     vfprintf(stdmsg, format, ap);
497     va_end(ap);
498
499     fprintf(stdmsg, "\n");
500     fflush(stdmsg);
501     }
502
503     global.errors++;
504
505     //fatal();
506 }
507
508 void Dsymbol::checkDeprecated(Loc loc, Scope *sc)
509 {
510     if (!global.params.useDeprecated && isDeprecated())
511     {
512     // Don't complain if we're inside a deprecated symbol's scope
513     for (Dsymbol *sp = sc->parent; sp; sp = sp->parent)
514     {   if (sp->isDeprecated())
515         return;
516     }
517
518     for (; sc; sc = sc->enclosing)
519     {
520         if (sc->scopesym && sc->scopesym->isDeprecated())
521         return;
522
523         // If inside a StorageClassDeclaration that is deprecated
524         if (sc->stc & STCdeprecated)
525         return;
526     }
527
528     error(loc, "is deprecated");
529     }
530 }
531
532 /**********************************
533  * Determine which Module a Dsymbol is in.
534  */
535
536 Module *Dsymbol::getModule()
537 {
538     Module *m;
539     Dsymbol *s;
540
541     //printf("Dsymbol::getModule()\n");
542     s = this;
543     while (s)
544     {
545     //printf("\ts = '%s'\n", s->toChars());
546     m = s->isModule();
547     if (m)
548         return m;
549     s = s->parent;
550     }
551     return NULL;
552 }
553
554 /*************************************
555  */
556
557 enum PROT Dsymbol::prot()
558 {
559     return PROTpublic;
560 }
561
562 /*************************************
563  * Do syntax copy of an array of Dsymbol's.
564  */
565
566
567 Array *Dsymbol::arraySyntaxCopy(Array *a)
568 {
569
570     Array *b = NULL;
571     if (a)
572     {
573     b = a->copy();
574     for (int i = 0; i < b->dim; i++)
575     {
576         Dsymbol *s = (Dsymbol *)b->data[i];
577
578         s = s->syntaxCopy(NULL);
579         b->data[i] = (void *)s;
580     }
581     }
582     return b;
583 }
584
585
586 /****************************************
587  * Add documentation comment to Dsymbol.
588  * Ignore NULL comments.
589  */
590
591 void Dsymbol::addComment(unsigned char *comment)
592 {
593     //if (comment)
594     //printf("adding comment '%s' to symbol %p '%s'\n", comment, this, toChars());
595
596     if (!this->comment)
597     this->comment = comment;
598 #if 1
599     else if (comment && strcmp((char *)comment, (char *)this->comment))
600     {   // Concatenate the two
601     this->comment = Lexer::combineComments(this->comment, comment);
602     }
603 #endif
604 }
605
606 /********************************* OverloadSet ****************************/
607
608 OverloadSet::OverloadSet()
609     : Dsymbol()
610 {
611 }
612
613 void OverloadSet::push(Dsymbol *s)
614 {
615     a.push(s);
616 }
617
618 const char *OverloadSet::kind()
619 {
620     return "overloadset";
621 }
622
623
624 /********************************* ScopeDsymbol ****************************/
625
626 ScopeDsymbol::ScopeDsymbol()
627     : Dsymbol()
628 {
629     members = NULL;
630     symtab = NULL;
631     imports = NULL;
632     prots = NULL;
633 }
634
635 ScopeDsymbol::ScopeDsymbol(Identifier *id)
636     : Dsymbol(id)
637 {
638     members = NULL;
639     symtab = NULL;
640     imports = NULL;
641     prots = NULL;
642 }
643
644 Dsymbol *ScopeDsymbol::syntaxCopy(Dsymbol *s)
645 {
646     //printf("ScopeDsymbol::syntaxCopy('%s')\n", toChars());
647
648     ScopeDsymbol *sd;
649     if (s)
650     sd = (ScopeDsymbol *)s;
651     else
652     sd = new ScopeDsymbol(ident);
653     sd->members = arraySyntaxCopy(members);
654     return sd;
655 }
656
657 Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
658 {
659     //printf("%s->ScopeDsymbol::search(ident='%s', flags=x%x)\n", toChars(), ident->toChars(), flags);
660
661     // Look in symbols declared in this module
662     Dsymbol *s = symtab ? symtab->lookup(ident) : NULL;
663     if (s)
664     {
665     //printf("\ts = '%s.%s'\n",toChars(),s->toChars());
666     }
667     else if (imports)
668     {
669     OverloadSet *a = NULL;
670
671     // Look in imported modules
672     for (int i = 0; i < imports->dim; i++)
673     {   ScopeDsymbol *ss = (ScopeDsymbol *)imports->data[i];
674         Dsymbol *s2;
675
676         // If private import, don't search it
677         if (flags & 1 && prots[i] == PROTprivate)
678         continue;
679
680         //printf("\tscanning import '%s', prots = %d, isModule = %p, isImport = %p\n", ss->toChars(), prots[i], ss->isModule(), ss->isImport());
681         /* Don't find private members if ss is a module
682          */
683         s2 = ss->search(loc, ident, ss->isModule() ? 1 : 0);
684         if (!s)
685         s = s2;
686         else if (s2 && s != s2)
687         {
688         if (s->toAlias() == s2->toAlias())
689         {
690             /* After following aliases, we found the same symbol,
691              * so it's not an ambiguity.
692              * But if one alias is deprecated, prefer the other.
693              */
694             if (s->isDeprecated())
695             s = s2;
696         }
697         else
698         {
699             /* Two imports of the same module should be regarded as
700              * the same.
701              */
702             Import *i1 = s->isImport();
703             Import *i2 = s2->isImport();
704             if (!(i1 && i2 &&
705               (i1->mod == i2->mod ||
706                (!i1->parent->isImport() && !i2->parent->isImport() &&
707                 i1->ident->equals(i2->ident))
708               )
709              )
710                )
711             {
712             /* If both s2 and s are overloadable (though we only
713              * need to check s once)
714              */
715             if (s2->isOverloadable() && (a || s->isOverloadable()))
716             {   if (!a)
717                 a = new OverloadSet();
718                 /* Don't add to a[] if s2 is alias of previous sym
719                  */
720                 for (int j = 0; j < a->a.dim; j++)
721                 {   Dsymbol *s3 = (Dsymbol *)a->a.data[j];
722                 if (s2->toAlias() == s3->toAlias())
723                 {
724                     if (s3->isDeprecated())
725                     a->a.data[j] = (void *)s2;
726                     goto Lcontinue;
727                 }
728                 }
729                 a->push(s2);
730             Lcontinue:
731                 continue;
732             }
733             if (flags & 4)      // if return NULL on ambiguity
734                 return NULL;
735       &