Mercurial > projects > ldc
comparison dmd/dsymbol.c @ 1:c53b6e3fe49a trunk
[svn r5] Initial commit. Most things are very rough.
author | lindquist |
---|---|
date | Sat, 01 Sep 2007 21:43:27 +0200 |
parents | |
children | 788401029ecf |
comparison
equal
deleted
inserted
replaced
0:a9e71648e74d | 1:c53b6e3fe49a |
---|---|
1 | |
2 // Compiler implementation of the D programming language | |
3 // Copyright (c) 1999-2007 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 | |
32 #include "../gen/enums.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->llvmInternal = LLVMnone; | |
47 this->llvmInternal1 = NULL; | |
48 this->llvmInternal2 = NULL; | |
49 this->llvmValue = NULL; | |
50 } | |
51 | |
52 Dsymbol::Dsymbol(Identifier *ident) | |
53 { | |
54 //printf("Dsymbol::Dsymbol(%p, ident)\n", this); | |
55 this->ident = ident; | |
56 this->c_ident = NULL; | |
57 this->parent = NULL; | |
58 this->csym = NULL; | |
59 this->isym = NULL; | |
60 this->loc = 0; | |
61 this->comment = NULL; | |
62 this->llvmInternal = LLVMnone; | |
63 this->llvmInternal1 = NULL; | |
64 this->llvmInternal2 = NULL; | |
65 this->llvmValue = NULL; | |
66 this->llvmDModule = NULL; | |
67 } | |
68 | |
69 int Dsymbol::equals(Object *o) | |
70 { Dsymbol *s; | |
71 | |
72 if (this == o) | |
73 return TRUE; | |
74 s = (Dsymbol *)(o); | |
75 if (s && ident->equals(s->ident)) | |
76 return TRUE; | |
77 return FALSE; | |
78 } | |
79 | |
80 /************************************** | |
81 * Copy the syntax. | |
82 * Used for template instantiations. | |
83 * If s is NULL, allocate the new object, otherwise fill it in. | |
84 */ | |
85 | |
86 Dsymbol *Dsymbol::syntaxCopy(Dsymbol *s) | |
87 { | |
88 print(); | |
89 printf("%s %s\n", kind(), toChars()); | |
90 assert(0); | |
91 return NULL; | |
92 } | |
93 | |
94 /************************************** | |
95 * Determine if this symbol is only one. | |
96 * Returns: | |
97 * FALSE, *ps = NULL: There are 2 or more symbols | |
98 * TRUE, *ps = NULL: There are zero symbols | |
99 * TRUE, *ps = symbol: The one and only one symbol | |
100 */ | |
101 | |
102 int Dsymbol::oneMember(Dsymbol **ps) | |
103 { | |
104 //printf("Dsymbol::oneMember()\n"); | |
105 *ps = this; | |
106 return TRUE; | |
107 } | |
108 | |
109 /***************************************** | |
110 * Same as Dsymbol::oneMember(), but look at an array of Dsymbols. | |
111 */ | |
112 | |
113 int Dsymbol::oneMembers(Array *members, Dsymbol **ps) | |
114 { | |
115 //printf("Dsymbol::oneMembers() %d\n", members ? members->dim : 0); | |
116 Dsymbol *s = NULL; | |
117 | |
118 if (members) | |
119 { | |
120 for (int i = 0; i < members->dim; i++) | |
121 { Dsymbol *sx = (Dsymbol *)members->data[i]; | |
122 | |
123 int x = sx->oneMember(ps); | |
124 //printf("\t[%d] kind %s = %d, s = %p\n", i, sx->kind(), x, *ps); | |
125 if (!x) | |
126 { | |
127 //printf("\tfalse 1\n"); | |
128 assert(*ps == NULL); | |
129 return FALSE; | |
130 } | |
131 if (*ps) | |
132 { | |
133 if (s) // more than one symbol | |
134 { *ps = NULL; | |
135 //printf("\tfalse 2\n"); | |
136 return FALSE; | |
137 } | |
138 s = *ps; | |
139 } | |
140 } | |
141 } | |
142 *ps = s; // s is the one symbol, NULL if none | |
143 //printf("\ttrue\n"); | |
144 return TRUE; | |
145 } | |
146 | |
147 /***************************************** | |
148 * Is Dsymbol a variable that contains pointers? | |
149 */ | |
150 | |
151 int Dsymbol::hasPointers() | |
152 { | |
153 //printf("Dsymbol::hasPointers() %s\n", toChars()); | |
154 return 0; | |
155 } | |
156 | |
157 char *Dsymbol::toChars() | |
158 { | |
159 return ident ? ident->toChars() : (char *)"__anonymous"; | |
160 } | |
161 | |
162 char *Dsymbol::toPrettyChars() | |
163 { Dsymbol *p; | |
164 char *s; | |
165 char *q; | |
166 size_t len; | |
167 | |
168 //printf("Dsymbol::toPrettyChars() '%s'\n", toChars()); | |
169 if (!parent) | |
170 return toChars(); | |
171 | |
172 len = 0; | |
173 for (p = this; p; p = p->parent) | |
174 len += strlen(p->toChars()) + 1; | |
175 | |
176 s = (char *)mem.malloc(len); | |
177 q = s + len - 1; | |
178 *q = 0; | |
179 for (p = this; p; p = p->parent) | |
180 { | |
181 char *t = p->toChars(); | |
182 len = strlen(t); | |
183 q -= len; | |
184 memcpy(q, t, len); | |
185 if (q == s) | |
186 break; | |
187 q--; | |
188 *q = '.'; | |
189 } | |
190 return s; | |
191 } | |
192 | |
193 char *Dsymbol::locToChars() | |
194 { | |
195 OutBuffer buf; | |
196 char *p; | |
197 | |
198 Module *m = getModule(); | |
199 | |
200 if (m && m->srcfile) | |
201 loc.filename = m->srcfile->toChars(); | |
202 return loc.toChars(); | |
203 } | |
204 | |
205 char *Dsymbol::kind() | |
206 { | |
207 return "symbol"; | |
208 } | |
209 | |
210 /********************************* | |
211 * If this symbol is really an alias for another, | |
212 * return that other. | |
213 */ | |
214 | |
215 Dsymbol *Dsymbol::toAlias() | |
216 { | |
217 return this; | |
218 } | |
219 | |
220 Dsymbol *Dsymbol::toParent() | |
221 { | |
222 return parent ? parent->pastMixin() : NULL; | |
223 } | |
224 | |
225 Dsymbol *Dsymbol::pastMixin() | |
226 { | |
227 Dsymbol *s = this; | |
228 | |
229 //printf("Dsymbol::pastMixin() %s\n", toChars()); | |
230 while (s && s->isTemplateMixin()) | |
231 s = s->parent; | |
232 return s; | |
233 } | |
234 | |
235 /********************************** | |
236 * Use this instead of toParent() when looking for the | |
237 * 'this' pointer of the enclosing function/class. | |
238 */ | |
239 | |
240 Dsymbol *Dsymbol::toParent2() | |
241 { | |
242 Dsymbol *s = parent; | |
243 while (s && s->isTemplateInstance()) | |
244 s = s->parent; | |
245 return s; | |
246 } | |
247 | |
248 | |
249 int Dsymbol::isAnonymous() | |
250 { | |
251 return ident ? 0 : 1; | |
252 } | |
253 | |
254 void Dsymbol::semantic(Scope *sc) | |
255 { | |
256 error("%p has no semantic routine", this); | |
257 } | |
258 | |
259 void Dsymbol::semantic2(Scope *sc) | |
260 { | |
261 // Most Dsymbols have no further semantic analysis needed | |
262 } | |
263 | |
264 void Dsymbol::semantic3(Scope *sc) | |
265 { | |
266 // Most Dsymbols have no further semantic analysis needed | |
267 } | |
268 | |
269 void Dsymbol::inlineScan() | |
270 { | |
271 // Most Dsymbols have no further semantic analysis needed | |
272 } | |
273 | |
274 Dsymbol *Dsymbol::search(Loc loc, Identifier *ident, int flags) | |
275 { | |
276 //printf("Dsymbol::search(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars()); | |
277 return NULL; | |
278 } | |
279 | |
280 /*************************************** | |
281 * Search for identifier id as a member of 'this'. | |
282 * id may be a template instance. | |
283 * Returns: | |
284 * symbol found, NULL if not | |
285 */ | |
286 | |
287 Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, Identifier *id) | |
288 { | |
289 //printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars()); | |
290 Dsymbol *s = toAlias(); | |
291 Dsymbol *sm; | |
292 | |
293 switch (id->dyncast()) | |
294 { | |
295 case DYNCAST_IDENTIFIER: | |
296 sm = s->search(loc, id, 0); | |
297 break; | |
298 | |
299 case DYNCAST_DSYMBOL: | |
300 { // It's a template instance | |
301 //printf("\ttemplate instance id\n"); | |
302 Dsymbol *st = (Dsymbol *)id; | |
303 TemplateInstance *ti = st->isTemplateInstance(); | |
304 id = ti->name; | |
305 sm = s->search(loc, id, 0); | |
306 if (!sm) | |
307 { error("template identifier %s is not a member of %s %s", | |
308 id->toChars(), s->kind(), s->toChars()); | |
309 return NULL; | |
310 } | |
311 sm = sm->toAlias(); | |
312 TemplateDeclaration *td = sm->isTemplateDeclaration(); | |
313 if (!td) | |
314 { | |
315 error("%s is not a template, it is a %s", id->toChars(), sm->kind()); | |
316 return NULL; | |
317 } | |
318 ti->tempdecl = td; | |
319 if (!ti->semanticdone) | |
320 ti->semantic(sc); | |
321 sm = ti->toAlias(); | |
322 break; | |
323 } | |
324 | |
325 default: | |
326 assert(0); | |
327 } | |
328 return sm; | |
329 } | |
330 | |
331 int Dsymbol::overloadInsert(Dsymbol *s) | |
332 { | |
333 //printf("Dsymbol::overloadInsert('%s')\n", s->toChars()); | |
334 return FALSE; | |
335 } | |
336 | |
337 void Dsymbol::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
338 { | |
339 buf->writestring(toChars()); | |
340 } | |
341 | |
342 unsigned Dsymbol::size(Loc loc) | |
343 { | |
344 error("Dsymbol '%s' has no size\n", toChars()); | |
345 return 0; | |
346 } | |
347 | |
348 int Dsymbol::isforwardRef() | |
349 { | |
350 return FALSE; | |
351 } | |
352 | |
353 AggregateDeclaration *Dsymbol::isThis() | |
354 { | |
355 return NULL; | |
356 } | |
357 | |
358 ClassDeclaration *Dsymbol::isClassMember() // are we a member of a class? | |
359 { | |
360 Dsymbol *parent = toParent(); | |
361 if (parent && parent->isClassDeclaration()) | |
362 return (ClassDeclaration *)parent; | |
363 return NULL; | |
364 } | |
365 | |
366 void Dsymbol::defineRef(Dsymbol *s) | |
367 { | |
368 assert(0); | |
369 } | |
370 | |
371 int Dsymbol::isExport() | |
372 { | |
373 return FALSE; | |
374 } | |
375 | |
376 int Dsymbol::isImportedSymbol() | |
377 { | |
378 return FALSE; | |
379 } | |
380 | |
381 int Dsymbol::isDeprecated() | |
382 { | |
383 return FALSE; | |
384 } | |
385 | |
386 LabelDsymbol *Dsymbol::isLabel() // is this a LabelDsymbol()? | |
387 { | |
388 return NULL; | |
389 } | |
390 | |
391 AggregateDeclaration *Dsymbol::isMember() // is this a member of an AggregateDeclaration? | |
392 { | |
393 Dsymbol *parent = toParent(); | |
394 return parent ? parent->isAggregateDeclaration() : NULL; | |
395 } | |
396 | |
397 Type *Dsymbol::getType() | |
398 { | |
399 return NULL; | |
400 } | |
401 | |
402 int Dsymbol::needThis() | |
403 { | |
404 return FALSE; | |
405 } | |
406 | |
407 int Dsymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) | |
408 { | |
409 //printf("Dsymbol::addMember('%s')\n", toChars()); | |
410 //printf("Dsymbol::addMember(this = %p, '%s' scopesym = '%s')\n", this, toChars(), sd->toChars()); | |
411 //printf("Dsymbol::addMember(this = %p, '%s' sd = %p, sd->symtab = %p)\n", this, toChars(), sd, sd->symtab); | |
412 parent = sd; | |
413 if (!isAnonymous()) // no name, so can't add it to symbol table | |
414 { | |
415 if (!sd->symtab->insert(this)) // if name is already defined | |
416 { | |
417 Dsymbol *s2; | |
418 | |
419 s2 = sd->symtab->lookup(ident); | |
420 if (!s2->overloadInsert(this)) | |
421 { | |
422 sd->multiplyDefined(0, this, s2); | |
423 } | |
424 } | |
425 if (sd->isAggregateDeclaration() || sd->isEnumDeclaration()) | |
426 { | |
427 if (ident == Id::__sizeof || ident == Id::alignof || ident == Id::mangleof) | |
428 error(".%s property cannot be redefined", ident->toChars()); | |
429 } | |
430 return 1; | |
431 } | |
432 return 0; | |
433 } | |
434 | |
435 void Dsymbol::error(const char *format, ...) | |
436 { | |
437 //printf("Dsymbol::error()\n"); | |
438 if (!global.gag) | |
439 { | |
440 char *p = locToChars(); | |
441 | |
442 if (*p) | |
443 fprintf(stdmsg, "%s: ", p); | |
444 mem.free(p); | |
445 | |
446 if (isAnonymous()) | |
447 fprintf(stdmsg, "%s ", kind()); | |
448 else | |
449 fprintf(stdmsg, "%s %s ", kind(), toPrettyChars()); | |
450 | |
451 va_list ap; | |
452 va_start(ap, format); | |
453 vfprintf(stdmsg, format, ap); | |
454 va_end(ap); | |
455 | |
456 fprintf(stdmsg, "\n"); | |
457 fflush(stdmsg); | |
458 } | |
459 global.errors++; | |
460 | |
461 //fatal(); | |
462 } | |
463 | |
464 void Dsymbol::error(Loc loc, const char *format, ...) | |
465 { | |
466 if (!global.gag) | |
467 { | |
468 char *p = loc.toChars(); | |
469 if (!*p) | |
470 p = locToChars(); | |
471 | |
472 if (*p) | |
473 fprintf(stdmsg, "%s: ", p); | |
474 mem.free(p); | |
475 | |
476 fprintf(stdmsg, "%s %s ", kind(), toPrettyChars()); | |
477 | |
478 va_list ap; | |
479 va_start(ap, format); | |
480 vfprintf(stdmsg, format, ap); | |
481 va_end(ap); | |
482 | |
483 fprintf(stdmsg, "\n"); | |
484 fflush(stdmsg); | |
485 } | |
486 | |
487 global.errors++; | |
488 | |
489 //fatal(); | |
490 } | |
491 | |
492 void Dsymbol::checkDeprecated(Loc loc, Scope *sc) | |
493 { | |
494 if (!global.params.useDeprecated && isDeprecated()) | |
495 { | |
496 // Don't complain if we're inside a deprecated symbol's scope | |
497 for (Dsymbol *sp = sc->parent; sp; sp = sp->parent) | |
498 { if (sp->isDeprecated()) | |
499 return; | |
500 } | |
501 | |
502 for (; sc; sc = sc->enclosing) | |
503 { | |
504 if (sc->scopesym && sc->scopesym->isDeprecated()) | |
505 return; | |
506 } | |
507 | |
508 error(loc, "is deprecated"); | |
509 } | |
510 } | |
511 | |
512 /********************************** | |
513 * Determine which Module a Dsymbol is in. | |
514 */ | |
515 | |
516 Module *Dsymbol::getModule() | |
517 { | |
518 Module *m; | |
519 Dsymbol *s; | |
520 | |
521 //printf("Dsymbol::getModule()\n"); | |
522 s = this; | |
523 while (s) | |
524 { | |
525 //printf("\ts = '%s'\n", s->toChars()); | |
526 m = s->isModule(); | |
527 if (m) | |
528 return m; | |
529 s = s->parent; | |
530 } | |
531 return NULL; | |
532 } | |
533 | |
534 /************************************* | |
535 */ | |
536 | |
537 enum PROT Dsymbol::prot() | |
538 { | |
539 return PROTpublic; | |
540 } | |
541 | |
542 /************************************* | |
543 * Do syntax copy of an array of Dsymbol's. | |
544 */ | |
545 | |
546 | |
547 Array *Dsymbol::arraySyntaxCopy(Array *a) | |
548 { | |
549 | |
550 Array *b = NULL; | |
551 if (a) | |
552 { | |
553 b = a->copy(); | |
554 for (int i = 0; i < b->dim; i++) | |
555 { | |
556 Dsymbol *s = (Dsymbol *)b->data[i]; | |
557 | |
558 s = s->syntaxCopy(NULL); | |
559 b->data[i] = (void *)s; | |
560 } | |
561 } | |
562 return b; | |
563 } | |
564 | |
565 | |
566 /**************************************** | |
567 * Add documentation comment to Dsymbol. | |
568 * Ignore NULL comments. | |
569 */ | |
570 | |
571 void Dsymbol::addComment(unsigned char *comment) | |
572 { | |
573 // if (comment) | |
574 // printf("adding comment '%s' to symbol %p '%s'\n", comment, this, toChars()); | |
575 | |
576 if (!this->comment) | |
577 this->comment = comment; | |
578 #if 1 | |
579 else if (comment && strcmp((char *)comment, (char *)this->comment)) | |
580 { // Concatenate the two | |
581 this->comment = Lexer::combineComments(this->comment, comment); | |
582 } | |
583 #endif | |
584 } | |
585 | |
586 | |
587 /********************************* ScopeDsymbol ****************************/ | |
588 | |
589 ScopeDsymbol::ScopeDsymbol() | |
590 : Dsymbol() | |
591 { | |
592 members = NULL; | |
593 symtab = NULL; | |
594 imports = NULL; | |
595 prots = NULL; | |
596 } | |
597 | |
598 ScopeDsymbol::ScopeDsymbol(Identifier *id) | |
599 : Dsymbol(id) | |
600 { | |
601 members = NULL; | |
602 symtab = NULL; | |
603 imports = NULL; | |
604 prots = NULL; | |
605 } | |
606 | |
607 Dsymbol *ScopeDsymbol::syntaxCopy(Dsymbol *s) | |
608 { | |
609 //printf("ScopeDsymbol::syntaxCopy('%s')\n", toChars()); | |
610 | |
611 ScopeDsymbol *sd; | |
612 if (s) | |
613 sd = (ScopeDsymbol *)s; | |
614 else | |
615 sd = new ScopeDsymbol(ident); | |
616 sd->members = arraySyntaxCopy(members); | |
617 return sd; | |
618 } | |
619 | |
620 Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags) | |
621 { Dsymbol *s; | |
622 int i; | |
623 | |
624 //printf("%s->ScopeDsymbol::search(ident='%s', flags=x%x)\n", toChars(), ident->toChars(), flags); | |
625 // Look in symbols declared in this module | |
626 s = symtab ? symtab->lookup(ident) : NULL; | |
627 if (s) | |
628 { | |
629 //printf("\ts = '%s.%s'\n",toChars(),s->toChars()); | |
630 } | |
631 else if (imports) | |
632 { | |
633 // Look in imported modules | |
634 for (i = 0; i < imports->dim; i++) | |
635 { ScopeDsymbol *ss = (ScopeDsymbol *)imports->data[i]; | |
636 Dsymbol *s2; | |
637 | |
638 // If private import, don't search it | |
639 if (flags & 1 && prots[i] == PROTprivate) | |
640 continue; | |
641 | |
642 //printf("\tscanning import '%s', prots = %d, isModule = %p, isImport = %p\n", ss->toChars(), prots[i], ss->isModule(), ss->isImport()); | |
643 s2 = ss->search(loc, ident, ss->isModule() ? 1 : 0); | |
644 if (!s) | |
645 s = s2; | |
646 else if (s2 && s != s2) | |
647 { | |
648 if (s->toAlias() == s2->toAlias()) | |
649 { | |
650 if (s->isDeprecated()) | |
651 s = s2; | |
652 } | |
653 else | |
654 { | |
655 /* Two imports of the same module should be regarded as | |
656 * the same. | |
657 */ | |
658 Import *i1 = s->isImport(); | |
659 Import *i2 = s2->isImport(); | |
660 if (!(i1 && i2 && | |
661 (i1->mod == i2->mod || | |
662 (!i1->parent->isImport() && !i2->parent->isImport() && | |
663 i1->ident->equals(i2->ident)) | |
664 ) | |
665 ) | |
666 ) | |
667 { | |
668 ss->multiplyDefined(loc, s, s2); | |
669 break; | |
670 } | |
671 } | |
672 } | |
673 } | |
674 if (s) | |
675 { | |
676 Declaration *d = s->isDeclaration(); | |
677 if (d && d->protection == PROTprivate && !d->parent->isTemplateMixin()) | |
678 error("%s is private", d->toPrettyChars()); | |
679 } | |
680 } | |
681 return s; | |
682 } | |
683 | |
684 void ScopeDsymbol::importScope(ScopeDsymbol *s, enum PROT protection) | |
685 { | |
686 //printf("%s->ScopeDsymbol::importScope(%s, %d)\n", toChars(), s->toChars(), protection); | |
687 | |
688 // No circular or redundant import's | |
689 if (s != this) | |
690 { | |
691 if (!imports) | |
692 imports = new Array(); | |
693 else | |
694 { | |
695 for (int i = 0; i < imports->dim; i++) | |
696 { ScopeDsymbol *ss; | |
697 | |
698 ss = (ScopeDsymbol *) imports->data[i]; | |
699 if (ss == s) | |
700 { | |
701 if (protection > prots[i]) | |
702 prots[i] = protection; // upgrade access | |
703 return; | |
704 } | |
705 } | |
706 } | |
707 imports->push(s); | |
708 prots = (unsigned char *)mem.realloc(prots, imports->dim * sizeof(prots[0])); | |
709 prots[imports->dim - 1] = protection; | |
710 } | |
711 } | |
712 | |
713 int ScopeDsymbol::isforwardRef() | |
714 { | |
715 return (members == NULL); | |
716 } | |
717 | |
718 void ScopeDsymbol::defineRef(Dsymbol *s) | |
719 { | |
720 ScopeDsymbol *ss; | |
721 | |
722 ss = s->isScopeDsymbol(); | |
723 members = ss->members; | |
724 ss->members = NULL; | |
725 } | |
726 | |
727 void ScopeDsymbol::multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2) | |
728 { | |
729 #if 0 | |
730 printf("ScopeDsymbol::multiplyDefined()\n"); | |
731 printf("s1 = %p, '%s' kind = '%s', parent = %s\n", s1, s1->toChars(), s1->kind(), s1->parent ? s1->parent->toChars() : ""); | |
732 printf("s2 = %p, '%s' kind = '%s', parent = %s\n", s2, s2->toChars(), s2->kind(), s2->parent ? s2->parent->toChars() : ""); | |
733 #endif | |
734 if (loc.filename) | |
735 { ::error(loc, "%s at %s conflicts with %s at %s", | |
736 s1->toPrettyChars(), | |
737 s1->locToChars(), | |
738 s2->toPrettyChars(), | |
739 s2->locToChars()); | |
740 } | |
741 else | |
742 { | |
743 s1->error(loc, "conflicts with %s %s at %s", | |
744 s2->kind(), | |
745 s2->toPrettyChars(), | |
746 s2->locToChars()); | |
747 } | |
748 } | |
749 | |
750 Dsymbol *ScopeDsymbol::nameCollision(Dsymbol *s) | |
751 { | |
752 Dsymbol *sprev; | |
753 | |
754 // Look to see if we are defining a forward referenced symbol | |
755 | |
756 sprev = symtab->lookup(s->ident); | |
757 assert(sprev); | |
758 if (s->equals(sprev)) // if the same symbol | |
759 { | |
760 if (s->isforwardRef()) // if second declaration is a forward reference | |
761 return sprev; | |
762 if (sprev->isforwardRef()) | |
763 { | |
764 sprev->defineRef(s); // copy data from s into sprev | |
765 return sprev; | |
766 } | |
767 } | |
768 multiplyDefined(0, s, sprev); | |
769 return sprev; | |
770 } | |
771 | |
772 char *ScopeDsymbol::kind() | |
773 { | |
774 return "ScopeDsymbol"; | |
775 } | |
776 | |
777 | |
778 /****************************** WithScopeSymbol ******************************/ | |
779 | |
780 WithScopeSymbol::WithScopeSymbol(WithStatement *withstate) | |
781 : ScopeDsymbol() | |
782 { | |
783 this->withstate = withstate; | |
784 } | |
785 | |
786 Dsymbol *WithScopeSymbol::search(Loc loc, Identifier *ident, int flags) | |
787 { | |
788 // Acts as proxy to the with class declaration | |
789 return withstate->exp->type->toDsymbol(NULL)->search(loc, ident, 0); | |
790 } | |
791 | |
792 /****************************** ArrayScopeSymbol ******************************/ | |
793 | |
794 ArrayScopeSymbol::ArrayScopeSymbol(Expression *e) | |
795 : ScopeDsymbol() | |
796 { | |
797 assert(e->op == TOKindex || e->op == TOKslice); | |
798 exp = e; | |
799 type = NULL; | |
800 td = NULL; | |
801 } | |
802 | |
803 ArrayScopeSymbol::ArrayScopeSymbol(TypeTuple *t) | |
804 : ScopeDsymbol() | |
805 { | |
806 exp = NULL; | |
807 type = t; | |
808 td = NULL; | |
809 } | |
810 | |
811 ArrayScopeSymbol::ArrayScopeSymbol(TupleDeclaration *s) | |
812 : ScopeDsymbol() | |
813 { | |
814 exp = NULL; | |
815 type = NULL; | |
816 td = s; | |
817 } | |
818 | |
819 Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags) | |
820 { | |
821 //printf("ArrayScopeSymbol::search('%s', flags = %d)\n", ident->toChars(), flags); | |
822 if (ident == Id::length || ident == Id::dollar) | |
823 { VarDeclaration **pvar; | |
824 Expression *ce; | |
825 | |
826 L1: | |
827 | |
828 if (td) | |
829 { | |
830 VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL); | |
831 Expression *e = new IntegerExp(0, td->objects->dim, Type::tsize_t); | |
832 v->init = new ExpInitializer(0, e); | |
833 v->storage_class |= STCconst; | |
834 return v; | |
835 } | |
836 | |
837 if (type) | |
838 { | |
839 VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL); | |
840 Expression *e = new IntegerExp(0, type->arguments->dim, Type::tsize_t); | |
841 v->init = new ExpInitializer(0, e); | |
842 v->storage_class |= STCconst; | |
843 return v; | |
844 } | |
845 | |
846 if (exp->op == TOKindex) | |
847 { | |
848 IndexExp *ie = (IndexExp *)exp; | |
849 | |
850 pvar = &ie->lengthVar; | |
851 ce = ie->e1; | |
852 } | |
853 else if (exp->op == TOKslice) | |
854 { | |
855 SliceExp *se = (SliceExp *)exp; | |
856 | |
857 pvar = &se->lengthVar; | |
858 ce = se->e1; | |
859 } | |
860 else | |
861 return NULL; | |
862 | |
863 if (ce->op == TOKtype) | |
864 { | |
865 Type *t = ((TypeExp *)ce)->type; | |
866 if (t->ty == Ttuple) | |
867 { type = (TypeTuple *)t; | |
868 goto L1; | |
869 } | |
870 } | |
871 | |
872 if (!*pvar) | |
873 { | |
874 VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL); | |
875 | |
876 if (ce->op == TOKstring) | |
877 { /* It is for a string literal, so the | |
878 * length will be a const. | |
879 */ | |
880 Expression *e = new IntegerExp(0, ((StringExp *)ce)->len, Type::tsize_t); | |
881 v->init = new ExpInitializer(0, e); | |
882 v->storage_class |= STCconst; | |
883 } | |
884 else if (ce->op == TOKarrayliteral) | |
885 { /* It is for an array literal, so the | |
886 * length will be a const. | |
887 */ | |
888 Expression *e = new IntegerExp(0, ((ArrayLiteralExp *)ce)->elements->dim, Type::tsize_t); | |
889 v->init = new ExpInitializer(0, e); | |
890 v->storage_class |= STCconst; | |
891 } | |
892 else if (ce->op == TOKtuple) | |
893 { /* It is for an expression tuple, so the | |
894 * length will be a const. | |
895 */ | |
896 Expression *e = new IntegerExp(0, ((TupleExp *)ce)->exps->dim, Type::tsize_t); | |
897 v->init = new ExpInitializer(0, e); | |
898 v->storage_class |= STCconst; | |
899 } | |
900 *pvar = v; | |
901 } | |
902 return (*pvar); | |
903 } | |
904 return NULL; | |
905 } | |
906 | |
907 | |
908 /****************************** DsymbolTable ******************************/ | |
909 | |
910 DsymbolTable::DsymbolTable() | |
911 { | |
912 tab = new StringTable; | |
913 } | |
914 | |
915 DsymbolTable::~DsymbolTable() | |
916 { | |
917 delete tab; | |
918 } | |
919 | |
920 Dsymbol *DsymbolTable::lookup(Identifier *ident) | |
921 { StringValue *sv; | |
922 | |
923 #ifdef DEBUG | |
924 assert(ident); | |
925 assert(tab); | |
926 #endif | |
927 sv = tab->lookup((char*)ident->string, ident->len); | |
928 return (Dsymbol *)(sv ? sv->ptrvalue : NULL); | |
929 } | |
930 | |
931 Dsymbol *DsymbolTable::insert(Dsymbol *s) | |
932 { StringValue *sv; | |
933 Identifier *ident; | |
934 | |
935 //printf("DsymbolTable::insert(this = %p, '%s')\n", this, s->ident->toChars()); | |
936 ident = s->ident; | |
937 #ifdef DEBUG | |
938 assert(ident); | |
939 assert(tab); | |
940 #endif | |
941 sv = tab->insert(ident->toChars(), ident->len); | |
942 if (!sv) | |
943 return NULL; // already in table | |
944 sv->ptrvalue = s; | |
945 return s; | |
946 } | |
947 | |
948 Dsymbol *DsymbolTable::insert(Identifier *ident, Dsymbol *s) | |
949 { StringValue *sv; | |
950 | |
951 //printf("DsymbolTable::insert()\n"); | |
952 sv = tab->insert(ident->toChars(), ident->len); | |
953 if (!sv) | |
954 return NULL; // already in table | |
955 sv->ptrvalue = s; | |
956 return s; | |
957 } | |
958 | |
959 Dsymbol *DsymbolTable::update(Dsymbol *s) | |
960 { StringValue *sv; | |
961 Identifier *ident; | |
962 | |
963 ident = s->ident; | |
964 sv = tab->update(ident->toChars(), ident->len); | |
965 sv->ptrvalue = s; | |
966 return s; | |
967 } | |
968 | |
969 | |
970 | |
971 |