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