root/branches/dmdfe/dsymbol.c

Revision 659, 19.6 kB (checked in by Gregor, 1 year ago)

MERGE: DMD 1.018

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