2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2008 by Digital Mars
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.
19 #include "aggregate.h"
20 #include "identifier.h"
23 #include "expression.h"
24 #include "statement.h"
25 #include "declaration.h"
33 /****************************** Dsymbol ******************************/
37 //printf("Dsymbol::Dsymbol(%p)\n", this);
47 Dsymbol::Dsymbol(Identifier
*ident
)
49 //printf("Dsymbol::Dsymbol(%p, ident)\n", this);
59 int Dsymbol::equals(Object
*o
)
65 if (s
&& ident
->equals(s
->ident
))
70 /**************************************
72 * Used for template instantiations.
73 * If s is NULL, allocate the new object, otherwise fill it in.
76 Dsymbol
*Dsymbol::syntaxCopy(Dsymbol
*s
)
79 printf("%s %s\n", kind(), toChars());
84 /**************************************
85 * Determine if this symbol is only one.
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");
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);
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);
117 //printf("\tfalse 1\n");
123 if (s
) // more than one symbol
125 //printf("\tfalse 2\n");
132 *ps
= s
; // s is the one symbol, NULL if none
133 //printf("\ttrue\n");
137 /*****************************************
138 * Is Dsymbol a variable that contains pointers?
141 int Dsymbol::hasPointers()
143 //printf("Dsymbol::hasPointers() %s\n", toChars());
147 char *Dsymbol::toChars()
149 return ident
? ident
->toChars() : (char *)"__anonymous";
152 char *Dsymbol::toPrettyChars()
158 //printf("Dsymbol::toPrettyChars() '%s'\n", toChars());
163 for (p
= this; p
; p
= p
->parent
)
164 len
+= strlen(p
->toChars()) + 1;
166 s
= (char *)mem
.malloc(len
);
169 for (p
= this; p
; p
= p
->parent
)
171 char *t
= p
->toChars();
183 char *Dsymbol::locToChars()
188 Module
*m
= getModule();
191 loc
.filename
= m
->srcfile
->toChars();
192 return loc
.toChars();
195 char *Dsymbol::kind()
200 /*********************************
201 * If this symbol is really an alias for another,
205 Dsymbol
*Dsymbol::toAlias()
210 Dsymbol
*Dsymbol::toParent()
212 return parent
? parent
->pastMixin() : NULL
;
215 Dsymbol
*Dsymbol::pastMixin()
219 //printf("Dsymbol::pastMixin() %s\n", toChars());
220 while (s
&& s
->isTemplateMixin())
225 /**********************************
226 * Use this instead of toParent() when looking for the
227 * 'this' pointer of the enclosing function/class.
230 Dsymbol
*Dsymbol::toParent2()
233 while (s
&& s
->isTemplateInstance())
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.
267 * flags: 1 don't find private members
268 * 2 don't give error messages
269 * 4 return NULL if ambiguous
274 Dsymbol
*Dsymbol::search(Loc loc
, Identifier
*ident
, int flags
)
276 //printf("Dsymbol::search(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars());
280 /***************************************
281 * Search for identifier id as a member of 'this'.
282 * id may be a template instance.
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();
293 switch (id
->dyncast())
295 case DYNCAST_IDENTIFIER
:
296 sm
= s
->search(loc
, id
, 0);
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();
305 sm
= s
->search(loc
, id
, 0);
307 { error("template identifier %s is not a member of %s %s",
308 id
->toChars(), s
->kind(), s
->toChars());
312 TemplateDeclaration
*td
= sm
->isTemplateDeclaration();
315 error("%s is not a template, it is a %s", id
->toChars(), sm
->kind());
319 if (!ti
->semanticdone
)
331 int Dsymbol::overloadInsert(Dsymbol
*s
)
333 //printf("Dsymbol::overloadInsert('%s')\n", s->toChars());
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());
348 int Dsymbol::isforwardRef()
353 AggregateDeclaration
*Dsymbol::isThis()
358 ClassDeclaration
*Dsymbol::isClassMember() // are we a member of a class?
360 Dsymbol
*parent
= toParent();
361 if (parent
&& parent
->isClassDeclaration())
362 return (ClassDeclaration
*)parent
;
366 void Dsymbol::defineRef(Dsymbol
*s
)
371 int Dsymbol::isExport()
376 int Dsymbol::isImportedSymbol()
381 int Dsymbol::isDeprecated()
386 int Dsymbol::isOverloadable()
391 LabelDsymbol
*Dsymbol::isLabel() // is this a LabelDsymbol()?
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()
409 int Dsymbol::needThis()
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);
420 if (!isAnonymous()) // no name, so can't add it to symbol table
422 if (!sd
->symtab
->insert(this)) // if name is already defined
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());
442 void Dsymbol::error(const char *format
, ...)
444 //printf("Dsymbol::error()\n");
447 char *p
= locToChars();
450 fprintf(stdmsg
, "%s: ", p
);
454 fprintf(stdmsg
, "%s ", kind());
456 fprintf(stdmsg
, "%s %s ", kind(), toPrettyChars());
459 va_start(ap
, format
);
460 vfprintf(stdmsg
, format
, ap
);
463 fprintf(stdmsg
, "\n");
471 void Dsymbol::error(Loc loc
, const char *format
, ...)
475 char *p
= loc
.toChars();
480 fprintf(stdmsg
, "%s: ", p
);
483 fprintf(stdmsg
, "%s %s ", kind(), toPrettyChars());
486 va_start(ap
, format
);
487 vfprintf(stdmsg
, format
, ap
);
490 fprintf(stdmsg
, "\n");
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())
509 for (; sc
; sc
= sc
->enclosing
)
511 if (sc
->scopesym
&& sc
->scopesym
->isDeprecated())
515 error(loc
, "is deprecated");
519 /**********************************
520 * Determine which Module a Dsymbol is in.
523 Module
*Dsymbol::getModule()
528 //printf("Dsymbol::getModule()\n");
532 //printf("\ts = '%s'\n", s->toChars());
541 /*************************************
544 enum PROT
Dsymbol::prot()
549 /*************************************
550 * Do syntax copy of an array of Dsymbol's.
554 Array
*Dsymbol::arraySyntaxCopy(Array
*a
)
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
;
573 /****************************************
574 * Add documentation comment to Dsymbol.
575 * Ignore NULL comments.
578 void Dsymbol::addComment(unsigned char *comment
)
581 // printf("adding comment '%s' to symbol %p '%s'\n", comment, this, toChars());
584 this->comment
= comment
;
586 else if (comment
&& strcmp((char *)comment
, (char *)this->comment
))
587 { // Concatenate the two
588 this->comment
= Lexer::combineComments(this->comment
, comment
);
593 /********************************* OverloadSet ****************************/
595 OverloadSet::OverloadSet()
600 void OverloadSet::push(Dsymbol
*s
)
605 char *OverloadSet::kind()
607 return "overloadset";
611 /********************************* ScopeDsymbol ****************************/
613 ScopeDsymbol::ScopeDsymbol()
622 ScopeDsymbol::ScopeDsymbol(Identifier
*id
)
631 Dsymbol
*ScopeDsymbol::syntaxCopy(Dsymbol
*s
)
633 //printf("ScopeDsymbol::syntaxCopy('%s')\n", toChars());
637 sd
= (ScopeDsymbol
*)s
;
639 sd
= new ScopeDsymbol(ident
);
640 sd
->members
= arraySyntaxCopy(members
);
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
;
652 //printf("\ts = '%s.%s'\n",toChars(),s->toChars());
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
];
663 // If private import, don't search it
664 if (flags
& 1 && prots
[i
] == PROTprivate
)
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);
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())
686 /* Two imports of the same module should be regarded as
689 Import
*i1
= s
->isImport();
690 Import
*i2
= s2
->isImport();
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()))
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
;
720 if (flags
& 4) // if return NULL on ambiguity
723 ss
->multiplyDefined(loc
, s
, s2
);
730 /* Build special symbol if we had multiple finds
740 Declaration
*d
= s
->isDeclaration();
741 if (d
&& d
->protection
== PROTprivate
&&
742 !d
->parent
->isTemplateMixin() &&
744 error("%s is private", d
->toPrettyChars());
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
758 imports
= new Array();
761 for (int i
= 0; i
< imports
->dim
; i
++)
764 ss
= (ScopeDsymbol
*) imports
->data
[i
];
767 if (protection
> prots
[i
])
768 prots
[i
] = protection
; // upgrade access
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
)
788 ss
= s
->isScopeDsymbol();
789 members
= ss
->members
;
793 void ScopeDsymbol::multiplyDefined(Loc loc
, Dsymbol
*s1
, Dsymbol
*s2
)
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() : "");
801 { ::error(loc
, "%s at %s conflicts with %s at %s",
809 s1
->error(loc
, "conflicts with %s %s at %s",
817 Dsymbol
*ScopeDsymbol::nameCollision(Dsymbol
*s
)
821 // Look to see if we are defining a forward referenced symbol
823 sprev
= symtab
->lookup(s
->ident
);
825 if (s
->equals(sprev
)) // if the same symbol
827 if (s
->isforwardRef()) // if second declaration is a forward reference
829 if (sprev
->isforwardRef())
831 sprev
->defineRef(s
); // copy data from s into sprev
835 multiplyDefined(0, s
, 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
)
854 for (size_t i
= 0; i
< members
->dim
; i
++)
855 { Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
856 AttribDeclaration
*a
= s
->isAttribDeclaration();
869 /***************************************
870 * Get nth Dsymbol, folding in AttribDeclaration members.
872 * Dsymbol* nth Dsymbol
873 * NULL not found, *pn gets incremented by the number
877 Dsymbol
*ScopeDsymbol::getNth(Array
*members
, size_t nth
, size_t *pn
)
883 for (size_t i
= 0; i
< members
->dim
; i
++)
884 { Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
885 AttribDeclaration
*a
= s
->isAttribDeclaration();
889 s
= getNth(a
->decl
, nth
- n
, &n
);
904 /*******************************************
905 * Look for member of the form:
906 * const(MemberInfo)[] getMembers(string);
907 * Returns NULL if not found
911 FuncDeclaration
*ScopeDsymbol::findGetMembers()
913 Dsymbol
*s
= search_function(this, Id::getmembers
);
914 FuncDeclaration
*fdx
= s
? s
->isFuncDeclaration() : NULL
;
917 static TypeFunction
*tfgetmembers
;
922 Arguments
*arguments
= new Arguments
;
923 Arguments
*arg
= new Argument(STCin
, Type::tchar
->constOf()->arrayOf(), NULL
, NULL
);
924 arguments
->push(arg
);
927 tfgetmembers
= new TypeFunction(arguments
, tret
, 0, LINKd
);
928 tfgetmembers
= (TypeFunction
*)tfgetmembers
->semantic(0, &sc
);
931 fdx
= fdx
->overloadExactMatch(tfgetmembers
);
933 if (fdx
&& fdx
->isVirtual())
941 /****************************** WithScopeSymbol ******************************/
943 WithScopeSymbol::WithScopeSymbol(WithStatement
*withstate
)
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
)
960 assert(e
->op
== TOKindex
|| e
->op
== TOKslice
);
967 ArrayScopeSymbol::ArrayScopeSymbol(Scope
*sc
, TypeTuple
*t
)
976 ArrayScopeSymbol::ArrayScopeSymbol(Scope
*sc
, TupleDeclaration
*s
)
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
;
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
;
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
;
1014 if (exp
->op
== TOKindex
)
1016 IndexExp
*ie
= (IndexExp
*)exp
;
1018 pvar
= &ie
->lengthVar
;
1021 else if (exp
->op
== TOKslice
)
1023 SliceExp
*se
= (SliceExp
*)exp
;
1025 pvar
= &se
->lengthVar
;
1031 if (ce
->op
== TOKtype
)
1033 Type
*t
= ((TypeExp
*)ce
)->type
;
1034 if (t
->ty
== Ttuple
)
1035 { type
= (TypeTuple
*)t
;
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
;
1075 (*pvar
)->semantic(sc
);
1082 /****************************** DsymbolTable ******************************/
1084 DsymbolTable::DsymbolTable()
1086 tab
= new StringTable
;
1089 DsymbolTable::~DsymbolTable()
1094 Dsymbol
*DsymbolTable::lookup(Identifier
*ident
)
1101 sv
= tab
->lookup((char*)ident
->string
, ident
->len
);
1102 return (Dsymbol
*)(sv
? sv
->ptrvalue
: NULL
);
1105 Dsymbol
*DsymbolTable::insert(Dsymbol
*s
)
1109 //printf("DsymbolTable::insert(this = %p, '%s')\n", this, s->ident->toChars());
1115 sv
= tab
->insert(ident
->toChars(), ident
->len
);
1117 return NULL
; // already in table
1122 Dsymbol
*DsymbolTable::insert(Identifier
*ident
, Dsymbol
*s
)
1125 //printf("DsymbolTable::insert()\n");
1126 sv
= tab
->insert(ident
->toChars(), ident
->len
);
1128 return NULL
; // already in table
1133 Dsymbol
*DsymbolTable::update(Dsymbol
*s
)
1138 sv
= tab
->update(ident
->toChars(), ident
->len
);