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