Scan dynamic libraries for GC roots
[delight/core.git] / dmd2 / dsymbol.c
blob28b4f54bdda23231cbb2479d2cf6af575d2813ae
2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2008 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.
11 #include <stdio.h>
12 #include <string.h>
13 #include <assert.h>
15 #include "mem.h"
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 #include "attrib.h"
33 /****************************** Dsymbol ******************************/
35 Dsymbol::Dsymbol()
37 //printf("Dsymbol::Dsymbol(%p)\n", this);
38 this->ident = NULL;
39 this->c_ident = NULL;
40 this->parent = NULL;
41 this->csym = NULL;
42 this->isym = NULL;
43 this->loc = 0;
44 this->comment = NULL;
47 Dsymbol::Dsymbol(Identifier *ident)
49 //printf("Dsymbol::Dsymbol(%p, ident)\n", this);
50 this->ident = ident;
51 this->c_ident = NULL;
52 this->parent = NULL;
53 this->csym = NULL;
54 this->isym = NULL;
55 this->loc = 0;
56 this->comment = NULL;
59 int Dsymbol::equals(Object *o)
60 { Dsymbol *s;
62 if (this == o)
63 return TRUE;
64 s = (Dsymbol *)(o);
65 if (s && ident->equals(s->ident))
66 return TRUE;
67 return FALSE;
70 /**************************************
71 * Copy the syntax.
72 * Used for template instantiations.
73 * If s is NULL, allocate the new object, otherwise fill it in.
76 Dsymbol *Dsymbol::syntaxCopy(Dsymbol *s)
78 print();
79 printf("%s %s\n", kind(), toChars());
80 assert(0);
81 return NULL;
84 /**************************************
85 * Determine if this symbol is only one.
86 * Returns:
87 * FALSE, *ps = NULL: There are 2 or more symbols
88 * TRUE, *ps = NULL: There are zero symbols
89 * TRUE, *ps = symbol: The one and only one symbol
92 int Dsymbol::oneMember(Dsymbol **ps)
94 //printf("Dsymbol::oneMember()\n");
95 *ps = this;
96 return TRUE;
99 /*****************************************
100 * Same as Dsymbol::oneMember(), but look at an array of Dsymbols.
103 int Dsymbol::oneMembers(Array *members, Dsymbol **ps)
105 //printf("Dsymbol::oneMembers() %d\n", members ? members->dim : 0);
106 Dsymbol *s = NULL;
108 if (members)
110 for (int i = 0; i < members->dim; i++)
111 { Dsymbol *sx = (Dsymbol *)members->data[i];
113 int x = sx->oneMember(ps);
114 //printf("\t[%d] kind %s = %d, s = %p\n", i, sx->kind(), x, *ps);
115 if (!x)
117 //printf("\tfalse 1\n");
118 assert(*ps == NULL);
119 return FALSE;
121 if (*ps)
123 if (s) // more than one symbol
124 { *ps = NULL;
125 //printf("\tfalse 2\n");
126 return FALSE;
128 s = *ps;
132 *ps = s; // s is the one symbol, NULL if none
133 //printf("\ttrue\n");
134 return TRUE;
137 /*****************************************
138 * Is Dsymbol a variable that contains pointers?
141 int Dsymbol::hasPointers()
143 //printf("Dsymbol::hasPointers() %s\n", toChars());
144 return 0;
147 char *Dsymbol::toChars()
149 return ident ? ident->toChars() : (char *)"__anonymous";
152 char *Dsymbol::toPrettyChars()
153 { Dsymbol *p;
154 char *s;
155 char *q;
156 size_t len;
158 //printf("Dsymbol::toPrettyChars() '%s'\n", toChars());
159 if (!parent)
160 return toChars();
162 len = 0;
163 for (p = this; p; p = p->parent)
164 len += strlen(p->toChars()) + 1;
166 s = (char *)mem.malloc(len);
167 q = s + len - 1;
168 *q = 0;
169 for (p = this; p; p = p->parent)
171 char *t = p->toChars();
172 len = strlen(t);
173 q -= len;
174 memcpy(q, t, len);
175 if (q == s)
176 break;
177 q--;
178 *q = '.';
180 return s;
183 char *Dsymbol::locToChars()
185 OutBuffer buf;
186 char *p;
188 Module *m = getModule();
190 if (m && m->srcfile)
191 loc.filename = m->srcfile->toChars();
192 return loc.toChars();
195 char *Dsymbol::kind()
197 return "symbol";
200 /*********************************
201 * If this symbol is really an alias for another,
202 * return that other.
205 Dsymbol *Dsymbol::toAlias()
207 return this;
210 Dsymbol *Dsymbol::toParent()
212 return parent ? parent->pastMixin() : NULL;
215 Dsymbol *Dsymbol::pastMixin()
217 Dsymbol *s = this;
219 //printf("Dsymbol::pastMixin() %s\n", toChars());
220 while (s && s->isTemplateMixin())
221 s = s->parent;
222 return s;
225 /**********************************
226 * Use this instead of toParent() when looking for the
227 * 'this' pointer of the enclosing function/class.
230 Dsymbol *Dsymbol::toParent2()
232 Dsymbol *s = parent;
233 while (s && s->isTemplateInstance())
234 s = s->parent;
235 return s;
239 int Dsymbol::isAnonymous()
241 return ident ? 0 : 1;
244 void Dsymbol::semantic(Scope *sc)
246 error("%p has no semantic routine", this);
249 void Dsymbol::semantic2(Scope *sc)
251 // Most Dsymbols have no further semantic analysis needed
254 void Dsymbol::semantic3(Scope *sc)
256 // Most Dsymbols have no further semantic analysis needed
259 void Dsymbol::inlineScan()
261 // Most Dsymbols have no further semantic analysis needed
264 /*********************************************
265 * Search for ident as member of s.
266 * Input:
267 * flags: 1 don't find private members
268 * 2 don't give error messages
269 * 4 return NULL if ambiguous
270 * Returns:
271 * NULL if not found
274 Dsymbol *Dsymbol::search(Loc loc, Identifier *ident, int flags)
276 //printf("Dsymbol::search(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars());
277 return NULL;
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
287 Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, Identifier *id)
289 //printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars());
290 Dsymbol *s = toAlias();
291 Dsymbol *sm;
293 switch (id->dyncast())
295 case DYNCAST_IDENTIFIER:
296 sm = s->search(loc, id, 0);
297 break;
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;
311 sm = sm->toAlias();
312 TemplateDeclaration *td = sm->isTemplateDeclaration();
313 if (!td)
315 error("%s is not a template, it is a %s", id->toChars(), sm->kind());
316 return NULL;
318 ti->tempdecl = td;
319 if (!ti->semanticdone)
320 ti->semantic(sc);
321 sm = ti->toAlias();
322 break;
325 default:
326 assert(0);
328 return sm;
331 int Dsymbol::overloadInsert(Dsymbol *s)
333 //printf("Dsymbol::overloadInsert('%s')\n", s->toChars());
334 return FALSE;
337 void Dsymbol::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
339 buf->writestring(toChars());
342 target_size_t Dsymbol::size(Loc loc)
344 error("Dsymbol '%s' has no size\n", toChars());
345 return 0;
348 int Dsymbol::isforwardRef()
350 return FALSE;
353 AggregateDeclaration *Dsymbol::isThis()
355 return NULL;
358 ClassDeclaration *Dsymbol::isClassMember() // are we a member of a class?
360 Dsymbol *parent = toParent();
361 if (parent && parent->isClassDeclaration())
362 return (ClassDeclaration *)parent;
363 return NULL;
366 void Dsymbol::defineRef(Dsymbol *s)
368 assert(0);
371 int Dsymbol::isExport()
373 return FALSE;
376 int Dsymbol::isImportedSymbol()
378 return FALSE;
381 int Dsymbol::isDeprecated()
383 return FALSE;
386 int Dsymbol::isOverloadable()
388 return 0;
391 LabelDsymbol *Dsymbol::isLabel() // is this a LabelDsymbol()?
393 return NULL;
396 AggregateDeclaration *Dsymbol::isMember() // is this a member of an AggregateDeclaration?
398 //printf("Dsymbol::isMember() %s\n", toChars());
399 Dsymbol *parent = toParent();
400 //printf("parent is %s %s\n", parent->kind(), parent->toChars());
401 return parent ? parent->isAggregateDeclaration() : NULL;
404 Type *Dsymbol::getType()
406 return NULL;
409 int Dsymbol::needThis()
411 return FALSE;
414 int Dsymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
416 //printf("Dsymbol::addMember('%s')\n", toChars());
417 //printf("Dsymbol::addMember(this = %p, '%s' scopesym = '%s')\n", this, toChars(), sd->toChars());
418 //printf("Dsymbol::addMember(this = %p, '%s' sd = %p, sd->symtab = %p)\n", this, toChars(), sd, sd->symtab);
419 parent = sd;
420 if (!isAnonymous()) // no name, so can't add it to symbol table
422 if (!sd->symtab->insert(this)) // if name is already defined
424 Dsymbol *s2;
426 s2 = sd->symtab->lookup(ident);
427 if (!s2->overloadInsert(this))
429 sd->multiplyDefined(0, this, s2);
432 if (sd->isAggregateDeclaration() || sd->isEnumDeclaration())
434 if (ident == Id::__sizeof || ident == Id::alignof || ident == Id::mangleof)
435 error(".%s property cannot be redefined", ident->toChars());
437 return 1;
439 return 0;
442 void Dsymbol::error(const char *format, ...)
444 //printf("Dsymbol::error()\n");
445 if (!global.gag)
447 char *p = locToChars();
449 if (*p)
450 fprintf(stdmsg, "%s: ", p);
451 mem.free(p);
453 if (isAnonymous())
454 fprintf(stdmsg, "%s ", kind());
455 else
456 fprintf(stdmsg, "%s %s ", kind(), toPrettyChars());
458 va_list ap;
459 va_start(ap, format);
460 vfprintf(stdmsg, format, ap);
461 va_end(ap);
463 fprintf(stdmsg, "\n");
464 fflush(stdmsg);
466 global.errors++;
468 //fatal();
471 void Dsymbol::error(Loc loc, const char *format, ...)
473 if (!global.gag)
475 char *p = loc.toChars();
476 if (!*p)
477 p = locToChars();
479 if (*p)
480 fprintf(stdmsg, "%s: ", p);
481 mem.free(p);
483 fprintf(stdmsg, "%s %s ", kind(), toPrettyChars());
485 va_list ap;
486 va_start(ap, format);
487 vfprintf(stdmsg, format, ap);
488 va_end(ap);
490 fprintf(stdmsg, "\n");
491 fflush(stdmsg);
494 global.errors++;
496 //fatal();
499 void Dsymbol::checkDeprecated(Loc loc, Scope *sc)
501 if (!global.params.useDeprecated && isDeprecated())
503 // Don't complain if we're inside a deprecated symbol's scope
504 for (Dsymbol *sp = sc->parent; sp; sp = sp->parent)
505 { if (sp->isDeprecated())
506 return;
509 for (; sc; sc = sc->enclosing)
511 if (sc->scopesym && sc->scopesym->isDeprecated())
512 return;
515 error(loc, "is deprecated");
519 /**********************************
520 * Determine which Module a Dsymbol is in.
523 Module *Dsymbol::getModule()
525 Module *m;
526 Dsymbol *s;
528 //printf("Dsymbol::getModule()\n");
529 s = this;
530 while (s)
532 //printf("\ts = '%s'\n", s->toChars());
533 m = s->isModule();
534 if (m)
535 return m;
536 s = s->parent;
538 return NULL;
541 /*************************************
544 enum PROT Dsymbol::prot()
546 return PROTpublic;
549 /*************************************
550 * Do syntax copy of an array of Dsymbol's.
554 Array *Dsymbol::arraySyntaxCopy(Array *a)
557 Array *b = NULL;
558 if (a)
560 b = a->copy();
561 for (int i = 0; i < b->dim; i++)
563 Dsymbol *s = (Dsymbol *)b->data[i];
565 s = s->syntaxCopy(NULL);
566 b->data[i] = (void *)s;
569 return b;
573 /****************************************
574 * Add documentation comment to Dsymbol.
575 * Ignore NULL comments.
578 void Dsymbol::addComment(unsigned char *comment)
580 // if (comment)
581 // printf("adding comment '%s' to symbol %p '%s'\n", comment, this, toChars());
583 if (!this->comment)
584 this->comment = comment;
585 #if 1
586 else if (comment && strcmp((char *)comment, (char *)this->comment))
587 { // Concatenate the two
588 this->comment = Lexer::combineComments(this->comment, comment);
590 #endif
593 /********************************* OverloadSet ****************************/
595 OverloadSet::OverloadSet()
596 : Dsymbol()
600 void OverloadSet::push(Dsymbol *s)
602 a.push(s);
605 char *OverloadSet::kind()
607 return "overloadset";
611 /********************************* ScopeDsymbol ****************************/
613 ScopeDsymbol::ScopeDsymbol()
614 : Dsymbol()
616 members = NULL;
617 symtab = NULL;
618 imports = NULL;
619 prots = NULL;
622 ScopeDsymbol::ScopeDsymbol(Identifier *id)
623 : Dsymbol(id)
625 members = NULL;
626 symtab = NULL;
627 imports = NULL;
628 prots = NULL;
631 Dsymbol *ScopeDsymbol::syntaxCopy(Dsymbol *s)
633 //printf("ScopeDsymbol::syntaxCopy('%s')\n", toChars());
635 ScopeDsymbol *sd;
636 if (s)
637 sd = (ScopeDsymbol *)s;
638 else
639 sd = new ScopeDsymbol(ident);
640 sd->members = arraySyntaxCopy(members);
641 return sd;
644 // flags:
645 // 1 => skip private imports
646 // 2 => don't call multiplyDefined
647 // 4 => return NULL if ambiguous
648 Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
650 //printf("%s->ScopeDsymbol::search(ident='%s', flags=x%x)\n", toChars(), ident->toChars(), flags);
652 // Look in symbols declared in this module
653 Dsymbol *s = symtab ? symtab->lookup(ident) : NULL;
655 // hide private nonlocal symbols
656 // THIS IS PROBABLY BROKEN: at the end of the function
657 // something similar is done for declarations and that
658 // contains a special case for template mixins
659 if (s && flags & 1 && s->prot() == PROTprivate)
660 s = NULL;
662 if (s)
664 //printf("\ts = '%s.%s'\n",toChars(),s->toChars());
666 else if (imports)
668 OverloadSet *a = NULL;
670 // Look in imported modules
671 for (int i = 0; i < imports->dim; i++)
672 { ScopeDsymbol *ss = (ScopeDsymbol *)imports->data[i];
673 Dsymbol *s2;
675 // If private import, don't search it
676 if (flags & 1 && prots[i] == PROTprivate)
677 continue;
679 //printf("\tscanning import '%s', prots = %d, isModule = %p, isImport = %p\n", ss->toChars(), prots[i], ss->isModule(), ss->isImport());
680 /* Don't find private members if ss is a module
682 s2 = ss->search(loc, ident, ss->isModule() ? 1 : 0);
683 if (!s)
684 s = s2;
685 else if (s2 && s != s2)
687 if (s->toAlias() == s2->toAlias())
689 /* After following aliases, we found the same symbol,
690 * so it's not an ambiguity.
691 * But if one alias is deprecated, prefer the other.
693 if (s->isDeprecated())
694 s = s2;
696 else
698 /* Two imports of the same module should be regarded as
699 * the same.
701 Import *i1 = s->isImport();
702 Import *i2 = s2->isImport();
703 if (!(i1 && i2 &&
704 (i1->mod == i2->mod ||
705 (!i1->parent->isImport() && !i2->parent->isImport() &&
706 i1->ident->equals(i2->ident))
711 /* If both s2 and s are overloadable (though we only
712 * need to check s once)
714 if (s2->isOverloadable() && (a || s->isOverloadable()))
715 { if (!a)
716 a = new OverloadSet();
717 /* Don't add to a[] if s2 is alias of previous sym
719 for (int j = 0; j < a->a.dim; j++)
720 { Dsymbol *s3 = (Dsymbol *)a->a.data[j];
721 if (s2->toAlias() == s3->toAlias())
723 if (s3->isDeprecated())
724 a->a.data[j] = (void *)s2;
725 goto Lcontinue;
728 a->push(s2);
729 Lcontinue:
730 continue;
732 if (flags & 4) // if return NULL on ambiguity
733 return NULL;
734 if (!(flags & 2))
735 ss->multiplyDefined(loc, s, s2);
736 break;
742 /* Build special symbol if we had multiple finds
744 if (a)
745 { assert(s);
746 a->push(s);
747 s = a;
750 if (s)
752 Declaration *d = s->isDeclaration();
753 if (d && d->protection == PROTprivate &&
754 !d->parent->isTemplateMixin() &&
755 !(flags & 2))
756 error("%s is private", d->toPrettyChars());
759 return s;
762 void ScopeDsymbol::importScope(ScopeDsymbol *s, enum PROT protection)
764 //printf("%s->ScopeDsymbol::importScope(%s, %d)\n", toChars(), s->toChars(), protection);
766 // No circular or redundant import's
767 if (s != this)
769 if (!imports)
770 imports = new Array();
771 else
773 for (int i = 0; i < imports->dim; i++)
774 { ScopeDsymbol *ss;
776 ss = (ScopeDsymbol *) imports->data[i];
777 if (ss == s)
779 if (protection > prots[i])
780 prots[i] = protection; // upgrade access
781 return;
785 imports->push(s);
786 prots = (unsigned char *)mem.realloc(prots, imports->dim * sizeof(prots[0]));
787 prots[imports->dim - 1] = protection;
791 int ScopeDsymbol::isforwardRef()
793 return (members == NULL);
796 void ScopeDsymbol::defineRef(Dsymbol *s)
798 ScopeDsymbol *ss;
800 ss = s->isScopeDsymbol();
801 members = ss->members;
802 ss->members = NULL;
805 void ScopeDsymbol::multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2)
807 #if 0
808 printf("ScopeDsymbol::multiplyDefined()\n");
809 printf("s1 = %p, '%s' kind = '%s', parent = %s\n", s1, s1->toChars(), s1->kind(), s1->parent ? s1->parent->toChars() : "");
810 printf("s2 = %p, '%s' kind = '%s', parent = %s\n", s2, s2->toChars(), s2->kind(), s2->parent ? s2->parent->toChars() : "");
811 #endif
812 if (loc.filename)
813 { ::error(loc, "%s at %s conflicts with %s at %s",
814 s1->toPrettyChars(),
815 s1->locToChars(),
816 s2->toPrettyChars(),
817 s2->locToChars());
819 else
821 s1->error(loc, "conflicts with %s %s at %s",
822 s2->kind(),
823 s2->toPrettyChars(),
824 s2->locToChars());
826 halt();
829 Dsymbol *ScopeDsymbol::nameCollision(Dsymbol *s)
831 Dsymbol *sprev;
833 // Look to see if we are defining a forward referenced symbol
835 sprev = symtab->lookup(s->ident);
836 assert(sprev);
837 if (s->equals(sprev)) // if the same symbol
839 if (s->isforwardRef()) // if second declaration is a forward reference
840 return sprev;
841 if (sprev->isforwardRef())
843 sprev->defineRef(s); // copy data from s into sprev
844 return sprev;
847 multiplyDefined(0, s, sprev);
848 return sprev;
851 char *ScopeDsymbol::kind()
853 return "ScopeDsymbol";
857 /***************************************
858 * Determine number of Dsymbols, folding in AttribDeclaration members.
861 size_t ScopeDsymbol::dim(Array *members)
863 size_t n = 0;
864 if (members)
866 for (size_t i = 0; i < members->dim; i++)
867 { Dsymbol *s = (Dsymbol *)members->data[i];
868 AttribDeclaration *a = s->isAttribDeclaration();
870 if (a)
872 n += dim(a->decl);
874 else
875 n++;
878 return n;
881 /***************************************
882 * Get nth Dsymbol, folding in AttribDeclaration members.
883 * Returns:
884 * Dsymbol* nth Dsymbol
885 * NULL not found, *pn gets incremented by the number
886 * of Dsymbols
889 Dsymbol *ScopeDsymbol::getNth(Array *members, size_t nth, size_t *pn)
891 if (!members)
892 return NULL;
894 size_t n = 0;
895 for (size_t i = 0; i < members->dim; i++)
896 { Dsymbol *s = (Dsymbol *)members->data[i];
897 AttribDeclaration *a = s->isAttribDeclaration();
899 if (a)
901 s = getNth(a->decl, nth - n, &n);
902 if (s)
903 return s;
905 else if (n == nth)
906 return s;
907 else
908 n++;
911 if (pn)
912 *pn += n;
913 return NULL;
916 /*******************************************
917 * Look for member of the form:
918 * const(MemberInfo)[] getMembers(string);
919 * Returns NULL if not found
922 #if V2
923 FuncDeclaration *ScopeDsymbol::findGetMembers()
925 Dsymbol *s = search_function(this, Id::getmembers);
926 FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL;
928 #if 0 // Finish
929 static TypeFunction *tfgetmembers;
931 if (!tfgetmembers)
933 Scope sc;
934 Arguments *arguments = new Arguments;
935 Arguments *arg = new Argument(STCin, Type::tchar->constOf()->arrayOf(), NULL, NULL);
936 arguments->push(arg);
938 Type *tret = NULL;
939 tfgetmembers = new TypeFunction(arguments, tret, 0, LINKd);
940 tfgetmembers = (TypeFunction *)tfgetmembers->semantic(0, &sc);
942 if (fdx)
943 fdx = fdx->overloadExactMatch(tfgetmembers);
944 #endif
945 if (fdx && fdx->isVirtual())
946 fdx = NULL;
948 return fdx;
950 #endif
953 /****************************** WithScopeSymbol ******************************/
955 WithScopeSymbol::WithScopeSymbol(WithStatement *withstate)
956 : ScopeDsymbol()
958 this->withstate = withstate;
961 Dsymbol *WithScopeSymbol::search(Loc loc, Identifier *ident, int flags)
963 // Acts as proxy to the with class declaration
964 return withstate->exp->type->toDsymbol(NULL)->search(loc, ident, 0);
967 /****************************** ArrayScopeSymbol ******************************/
969 ArrayScopeSymbol::ArrayScopeSymbol(Scope *sc, Expression *e)
970 : ScopeDsymbol()
972 assert(e->op == TOKindex || e->op == TOKslice);
973 exp = e;
974 type = NULL;
975 td = NULL;
976 this->sc = sc;
979 ArrayScopeSymbol::ArrayScopeSymbol(Scope *sc, TypeTuple *t)
980 : ScopeDsymbol()
982 exp = NULL;
983 type = t;
984 td = NULL;
985 this->sc = sc;
988 ArrayScopeSymbol::ArrayScopeSymbol(Scope *sc, TupleDeclaration *s)
989 : ScopeDsymbol()
991 exp = NULL;
992 type = NULL;
993 td = s;
994 this->sc = sc;
997 Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
999 //printf("ArrayScopeSymbol::search('%s', flags = %d)\n", ident->toChars(), flags);
1000 if (ident == Id::length || ident == Id::dollar)
1001 { VarDeclaration **pvar;
1002 Expression *ce;
1006 if (td)
1008 VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
1009 Expression *e = new IntegerExp(0, td->objects->dim, Type::tsize_t);
1010 v->init = new ExpInitializer(0, e);
1011 v->storage_class |= STCstatic | STCconst;
1012 v->semantic(sc);
1013 return v;
1016 if (type)
1018 VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
1019 Expression *e = new IntegerExp(0, type->arguments->dim, Type::tsize_t);
1020 v->init = new ExpInitializer(0, e);
1021 v->storage_class |= STCstatic | STCconst;
1022 v->semantic(sc);
1023 return v;
1026 if (exp->op == TOKindex)
1028 IndexExp *ie = (IndexExp *)exp;
1030 pvar = &ie->lengthVar;
1031 ce = ie->e1;
1033 else if (exp->op == TOKslice)
1035 SliceExp *se = (SliceExp *)exp;
1037 pvar = &se->lengthVar;
1038 ce = se->e1;
1040 else
1041 return NULL;
1043 if (ce->op == TOKtype)
1045 Type *t = ((TypeExp *)ce)->type;
1046 if (t->ty == Ttuple)
1047 { type = (TypeTuple *)t;
1048 goto L1;
1052 if (!*pvar)
1054 VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
1056 if (ce->op == TOKvar)
1057 { // if ce is const, get its initializer
1058 ce = fromConstInitializer(WANTvalue | WANTinterpret, ce);
1061 if (ce->op == TOKstring)
1062 { /* It is for a string literal, so the
1063 * length will be a const.
1065 Expression *e = new IntegerExp(0, ((StringExp *)ce)->len, Type::tsize_t);
1066 v->init = new ExpInitializer(0, e);
1067 v->storage_class |= STCstatic | STCconst;
1069 else if (ce->op == TOKarrayliteral)
1070 { /* It is for an array literal, so the
1071 * length will be a const.
1073 Expression *e = new IntegerExp(0, ((ArrayLiteralExp *)ce)->elements->dim, Type::tsize_t);
1074 v->init = new ExpInitializer(0, e);
1075 v->storage_class |= STCstatic | STCconst;
1077 else if (ce->op == TOKtuple)
1078 { /* It is for an expression tuple, so the
1079 * length will be a const.
1081 Expression *e = new IntegerExp(0, ((TupleExp *)ce)->exps->dim, Type::tsize_t);
1082 v->init = new ExpInitializer(0, e);
1083 v->storage_class |= STCstatic | STCconst;
1085 *pvar = v;
1087 (*pvar)->semantic(sc);
1088 return (*pvar);
1090 return NULL;
1094 /****************************** DsymbolTable ******************************/
1096 DsymbolTable::DsymbolTable()
1098 tab = new StringTable;
1101 DsymbolTable::~DsymbolTable()
1103 delete tab;
1106 Dsymbol *DsymbolTable::lookup(Identifier *ident)
1107 { StringValue *sv;
1109 #ifdef DEBUG
1110 assert(ident);
1111 assert(tab);
1112 #endif
1113 sv = tab->lookup((char*)ident->string, ident->len);
1114 return (Dsymbol *)(sv ? sv->ptrvalue : NULL);
1117 Dsymbol *DsymbolTable::insert(Dsymbol *s)
1118 { StringValue *sv;
1119 Identifier *ident;
1121 //printf("DsymbolTable::insert(this = %p, '%s')\n", this, s->ident->toChars());
1122 ident = s->ident;
1123 #ifdef DEBUG
1124 assert(ident);
1125 assert(tab);
1126 #endif
1127 sv = tab->insert(ident->toChars(), ident->len);
1128 if (!sv)
1129 return NULL; // already in table
1130 sv->ptrvalue = s;
1131 return s;
1134 Dsymbol *DsymbolTable::insert(Identifier *ident, Dsymbol *s)
1135 { StringValue *sv;
1137 //printf("DsymbolTable::insert()\n");
1138 sv = tab->insert(ident->toChars(), ident->len);
1139 if (!sv)
1140 return NULL; // already in table
1141 sv->ptrvalue = s;
1142 return s;
1145 Dsymbol *DsymbolTable::update(Dsymbol *s)
1146 { StringValue *sv;
1147 Identifier *ident;
1149 ident = s->ident;
1150 sv = tab->update(ident->toChars(), ident->len);
1151 sv->ptrvalue = s;
1152 return s;