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