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