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