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