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