Fixed some lexing problems with DOS line-endings
[delight/core.git] / dmd2 / dsymbol.c
blob9b45e696bc4b663c83f7d11714ed877393bfa9d6
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 Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
646 //printf("%s->ScopeDsymbol::search(ident='%s', flags=x%x)\n", toChars(), ident->toChars(), flags);
648 // Look in symbols declared in this module
649 Dsymbol *s = symtab ? symtab->lookup(ident) : NULL;
650 if (s)
652 //printf("\ts = '%s.%s'\n",toChars(),s->toChars());
654 else if (imports)
656 OverloadSet *a = NULL;
658 // Look in imported modules
659 for (int i = 0; i < imports->dim; i++)
660 { ScopeDsymbol *ss = (ScopeDsymbol *)imports->data[i];
661 Dsymbol *s2;
663 // If private import, don't search it
664 if (flags & 1 && prots[i] == PROTprivate)
665 continue;
667 //printf("\tscanning import '%s', prots = %d, isModule = %p, isImport = %p\n", ss->toChars(), prots[i], ss->isModule(), ss->isImport());
668 /* Don't find private members if ss is a module
670 s2 = ss->search(loc, ident, ss->isModule() ? 1 : 0);
671 if (!s)
672 s = s2;
673 else if (s2 && s != s2)
675 if (s->toAlias() == s2->toAlias())
677 /* After following aliases, we found the same symbol,
678 * so it's not an ambiguity.
679 * But if one alias is deprecated, prefer the other.
681 if (s->isDeprecated())
682 s = s2;
684 else
686 /* Two imports of the same module should be regarded as
687 * the same.
689 Import *i1 = s->isImport();
690 Import *i2 = s2->isImport();
691 if (!(i1 && i2 &&
692 (i1->mod == i2->mod ||
693 (!i1->parent->isImport() && !i2->parent->isImport() &&
694 i1->ident->equals(i2->ident))
699 /* If both s2 and s are overloadable (though we only
700 * need to check s once)
702 if (s2->isOverloadable() && (a || s->isOverloadable()))
703 { if (!a)
704 a = new OverloadSet();
705 /* Don't add to a[] if s2 is alias of previous sym
707 for (int j = 0; j < a->a.dim; j++)
708 { Dsymbol *s3 = (Dsymbol *)a->a.data[j];
709 if (s2->toAlias() == s3->toAlias())
711 if (s3->isDeprecated())
712 a->a.data[j] = (void *)s2;
713 goto Lcontinue;
716 a->push(s2);
717 Lcontinue:
718 continue;
720 if (flags & 4) // if return NULL on ambiguity
721 return NULL;
722 if (!(flags & 2))
723 ss->multiplyDefined(loc, s, s2);
724 break;
730 /* Build special symbol if we had multiple finds
732 if (a)
733 { assert(s);
734 a->push(s);
735 s = a;
738 if (s)
740 Declaration *d = s->isDeclaration();
741 if (d && d->protection == PROTprivate &&
742 !d->parent->isTemplateMixin() &&
743 !(flags & 2))
744 error("%s is private", d->toPrettyChars());
747 return s;
750 void ScopeDsymbol::importScope(ScopeDsymbol *s, enum PROT protection)
752 //printf("%s->ScopeDsymbol::importScope(%s, %d)\n", toChars(), s->toChars(), protection);
754 // No circular or redundant import's
755 if (s != this)
757 if (!imports)
758 imports = new Array();
759 else
761 for (int i = 0; i < imports->dim; i++)
762 { ScopeDsymbol *ss;
764 ss = (ScopeDsymbol *) imports->data[i];
765 if (ss == s)
767 if (protection > prots[i])
768 prots[i] = protection; // upgrade access
769 return;
773 imports->push(s);
774 prots = (unsigned char *)mem.realloc(prots, imports->dim * sizeof(prots[0]));
775 prots[imports->dim - 1] = protection;
779 int ScopeDsymbol::isforwardRef()
781 return (members == NULL);
784 void ScopeDsymbol::defineRef(Dsymbol *s)
786 ScopeDsymbol *ss;
788 ss = s->isScopeDsymbol();
789 members = ss->members;
790 ss->members = NULL;
793 void ScopeDsymbol::multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2)
795 #if 0
796 printf("ScopeDsymbol::multiplyDefined()\n");
797 printf("s1 = %p, '%s' kind = '%s', parent = %s\n", s1, s1->toChars(), s1->kind(), s1->parent ? s1->parent->toChars() : "");
798 printf("s2 = %p, '%s' kind = '%s', parent = %s\n", s2, s2->toChars(), s2->kind(), s2->parent ? s2->parent->toChars() : "");
799 #endif
800 if (loc.filename)
801 { ::error(loc, "%s at %s conflicts with %s at %s",
802 s1->toPrettyChars(),
803 s1->locToChars(),
804 s2->toPrettyChars(),
805 s2->locToChars());
807 else
809 s1->error(loc, "conflicts with %s %s at %s",
810 s2->kind(),
811 s2->toPrettyChars(),
812 s2->locToChars());
814 halt();
817 Dsymbol *ScopeDsymbol::nameCollision(Dsymbol *s)
819 Dsymbol *sprev;
821 // Look to see if we are defining a forward referenced symbol
823 sprev = symtab->lookup(s->ident);
824 assert(sprev);
825 if (s->equals(sprev)) // if the same symbol
827 if (s->isforwardRef()) // if second declaration is a forward reference
828 return sprev;
829 if (sprev->isforwardRef())
831 sprev->defineRef(s); // copy data from s into sprev
832 return sprev;
835 multiplyDefined(0, s, sprev);
836 return sprev;
839 char *ScopeDsymbol::kind()
841 return "ScopeDsymbol";
845 /***************************************
846 * Determine number of Dsymbols, folding in AttribDeclaration members.
849 size_t ScopeDsymbol::dim(Array *members)
851 size_t n = 0;
852 if (members)
854 for (size_t i = 0; i < members->dim; i++)
855 { Dsymbol *s = (Dsymbol *)members->data[i];
856 AttribDeclaration *a = s->isAttribDeclaration();
858 if (a)
860 n += dim(a->decl);
862 else
863 n++;
866 return n;
869 /***************************************
870 * Get nth Dsymbol, folding in AttribDeclaration members.
871 * Returns:
872 * Dsymbol* nth Dsymbol
873 * NULL not found, *pn gets incremented by the number
874 * of Dsymbols
877 Dsymbol *ScopeDsymbol::getNth(Array *members, size_t nth, size_t *pn)
879 if (!members)
880 return NULL;
882 size_t n = 0;
883 for (size_t i = 0; i < members->dim; i++)
884 { Dsymbol *s = (Dsymbol *)members->data[i];
885 AttribDeclaration *a = s->isAttribDeclaration();
887 if (a)
889 s = getNth(a->decl, nth - n, &n);
890 if (s)
891 return s;
893 else if (n == nth)
894 return s;
895 else
896 n++;
899 if (pn)
900 *pn += n;
901 return NULL;
904 /*******************************************
905 * Look for member of the form:
906 * const(MemberInfo)[] getMembers(string);
907 * Returns NULL if not found
910 #if V2
911 FuncDeclaration *ScopeDsymbol::findGetMembers()
913 Dsymbol *s = search_function(this, Id::getmembers);
914 FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL;
916 #if 0 // Finish
917 static TypeFunction *tfgetmembers;
919 if (!tfgetmembers)
921 Scope sc;
922 Arguments *arguments = new Arguments;
923 Arguments *arg = new Argument(STCin, Type::tchar->constOf()->arrayOf(), NULL, NULL);
924 arguments->push(arg);
926 Type *tret = NULL;
927 tfgetmembers = new TypeFunction(arguments, tret, 0, LINKd);
928 tfgetmembers = (TypeFunction *)tfgetmembers->semantic(0, &sc);
930 if (fdx)
931 fdx = fdx->overloadExactMatch(tfgetmembers);
932 #endif
933 if (fdx && fdx->isVirtual())
934 fdx = NULL;
936 return fdx;
938 #endif
941 /****************************** WithScopeSymbol ******************************/
943 WithScopeSymbol::WithScopeSymbol(WithStatement *withstate)
944 : ScopeDsymbol()
946 this->withstate = withstate;
949 Dsymbol *WithScopeSymbol::search(Loc loc, Identifier *ident, int flags)
951 // Acts as proxy to the with class declaration
952 return withstate->exp->type->toDsymbol(NULL)->search(loc, ident, 0);
955 /****************************** ArrayScopeSymbol ******************************/
957 ArrayScopeSymbol::ArrayScopeSymbol(Scope *sc, Expression *e)
958 : ScopeDsymbol()
960 assert(e->op == TOKindex || e->op == TOKslice);
961 exp = e;
962 type = NULL;
963 td = NULL;
964 this->sc = sc;
967 ArrayScopeSymbol::ArrayScopeSymbol(Scope *sc, TypeTuple *t)
968 : ScopeDsymbol()
970 exp = NULL;
971 type = t;
972 td = NULL;
973 this->sc = sc;
976 ArrayScopeSymbol::ArrayScopeSymbol(Scope *sc, TupleDeclaration *s)
977 : ScopeDsymbol()
979 exp = NULL;
980 type = NULL;
981 td = s;
982 this->sc = sc;
985 Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
987 //printf("ArrayScopeSymbol::search('%s', flags = %d)\n", ident->toChars(), flags);
988 if (ident == Id::length || ident == Id::dollar)
989 { VarDeclaration **pvar;
990 Expression *ce;
994 if (td)
996 VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
997 Expression *e = new IntegerExp(0, td->objects->dim, Type::tsize_t);
998 v->init = new ExpInitializer(0, e);
999 v->storage_class |= STCstatic | STCconst;
1000 v->semantic(sc);
1001 return v;
1004 if (type)
1006 VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
1007 Expression *e = new IntegerExp(0, type->arguments->dim, Type::tsize_t);
1008 v->init = new ExpInitializer(0, e);
1009 v->storage_class |= STCstatic | STCconst;
1010 v->semantic(sc);
1011 return v;
1014 if (exp->op == TOKindex)
1016 IndexExp *ie = (IndexExp *)exp;
1018 pvar = &ie->lengthVar;
1019 ce = ie->e1;
1021 else if (exp->op == TOKslice)
1023 SliceExp *se = (SliceExp *)exp;
1025 pvar = &se->lengthVar;
1026 ce = se->e1;
1028 else
1029 return NULL;
1031 if (ce->op == TOKtype)
1033 Type *t = ((TypeExp *)ce)->type;
1034 if (t->ty == Ttuple)
1035 { type = (TypeTuple *)t;
1036 goto L1;
1040 if (!*pvar)
1042 VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
1044 if (ce->op == TOKvar)
1045 { // if ce is const, get its initializer
1046 ce = fromConstInitializer(WANTvalue | WANTinterpret, ce);
1049 if (ce->op == TOKstring)
1050 { /* It is for a string literal, so the
1051 * length will be a const.
1053 Expression *e = new IntegerExp(0, ((StringExp *)ce)->len, Type::tsize_t);
1054 v->init = new ExpInitializer(0, e);
1055 v->storage_class |= STCstatic | STCconst;
1057 else if (ce->op == TOKarrayliteral)
1058 { /* It is for an array literal, so the
1059 * length will be a const.
1061 Expression *e = new IntegerExp(0, ((ArrayLiteralExp *)ce)->elements->dim, Type::tsize_t);
1062 v->init = new ExpInitializer(0, e);
1063 v->storage_class |= STCstatic | STCconst;
1065 else if (ce->op == TOKtuple)
1066 { /* It is for an expression tuple, so the
1067 * length will be a const.
1069 Expression *e = new IntegerExp(0, ((TupleExp *)ce)->exps->dim, Type::tsize_t);
1070 v->init = new ExpInitializer(0, e);
1071 v->storage_class |= STCstatic | STCconst;
1073 *pvar = v;
1075 (*pvar)->semantic(sc);
1076 return (*pvar);
1078 return NULL;
1082 /****************************** DsymbolTable ******************************/
1084 DsymbolTable::DsymbolTable()
1086 tab = new StringTable;
1089 DsymbolTable::~DsymbolTable()
1091 delete tab;
1094 Dsymbol *DsymbolTable::lookup(Identifier *ident)
1095 { StringValue *sv;
1097 #ifdef DEBUG
1098 assert(ident);
1099 assert(tab);
1100 #endif
1101 sv = tab->lookup((char*)ident->string, ident->len);
1102 return (Dsymbol *)(sv ? sv->ptrvalue : NULL);
1105 Dsymbol *DsymbolTable::insert(Dsymbol *s)
1106 { StringValue *sv;
1107 Identifier *ident;
1109 //printf("DsymbolTable::insert(this = %p, '%s')\n", this, s->ident->toChars());
1110 ident = s->ident;
1111 #ifdef DEBUG
1112 assert(ident);
1113 assert(tab);
1114 #endif
1115 sv = tab->insert(ident->toChars(), ident->len);
1116 if (!sv)
1117 return NULL; // already in table
1118 sv->ptrvalue = s;
1119 return s;
1122 Dsymbol *DsymbolTable::insert(Identifier *ident, Dsymbol *s)
1123 { StringValue *sv;
1125 //printf("DsymbolTable::insert()\n");
1126 sv = tab->insert(ident->toChars(), ident->len);
1127 if (!sv)
1128 return NULL; // already in table
1129 sv->ptrvalue = s;
1130 return s;
1133 Dsymbol *DsymbolTable::update(Dsymbol *s)
1134 { StringValue *sv;
1135 Identifier *ident;
1137 ident = s->ident;
1138 sv = tab->update(ident->toChars(), ident->len);
1139 sv->ptrvalue = s;
1140 return s;