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