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