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