2 /* Compiler implementation of the D programming language
3 * Copyright (C) 1999-2018 by The D Language Foundation, All Rights Reserved
4 * written by Walter Bright
5 * http://www.digitalmars.com
6 * Distributed under the Boost Software License, Version 1.0.
7 * http://www.boost.org/LICENSE_1_0.txt
8 * https://github.com/D-Programming-Language/dmd/blob/master/src/dsymbol.c
11 #include "root/dsystem.h"
12 #include "root/rmem.h"
13 #include "root/speller.h"
18 #include "aggregate.h"
19 #include "identifier.h"
22 #include "expression.h"
23 #include "statement.h"
24 #include "declaration.h"
34 bool symbolIsVisible(Dsymbol
*origin
, Dsymbol
*s
);
35 typedef int (*ForeachDg
)(void *ctx
, size_t idx
, Dsymbol
*s
);
36 int ScopeDsymbol_foreach(Scope
*sc
, Dsymbols
*members
, ForeachDg dg
, void *ctx
, size_t *pn
= NULL
);
37 Expression
*semantic(Expression
*e
, Scope
*sc
);
40 /****************************** Dsymbol ******************************/
44 //printf("Dsymbol::Dsymbol(%p)\n", this);
52 this->prettystring
= NULL
;
53 this->semanticRun
= PASSinit
;
56 this->userAttribDecl
= NULL
;
57 this->ddocUnittest
= NULL
;
60 Dsymbol::Dsymbol(Identifier
*ident
)
62 //printf("Dsymbol::Dsymbol(%p, ident)\n", this);
70 this->prettystring
= NULL
;
71 this->semanticRun
= PASSinit
;
74 this->userAttribDecl
= NULL
;
75 this->ddocUnittest
= NULL
;
78 Dsymbol
*Dsymbol::create(Identifier
*ident
)
80 return new Dsymbol(ident
);
83 bool Dsymbol::equals(RootObject
*o
)
87 Dsymbol
*s
= (Dsymbol
*)(o
);
88 // Overload sets don't have an ident
89 if (s
&& ident
&& s
->ident
&& ident
->equals(s
->ident
))
94 /**************************************
96 * Used for template instantiations.
97 * If s is NULL, allocate the new object, otherwise fill it in.
100 Dsymbol
*Dsymbol::syntaxCopy(Dsymbol
*)
103 printf("%s %s\n", kind(), toChars());
108 /**************************************
109 * Determine if this symbol is only one.
111 * false, *ps = NULL: There are 2 or more symbols
112 * true, *ps = NULL: There are zero symbols
113 * true, *ps = symbol: The one and only one symbol
116 bool Dsymbol::oneMember(Dsymbol
**ps
, Identifier
*)
118 //printf("Dsymbol::oneMember()\n");
123 /*****************************************
124 * Same as Dsymbol::oneMember(), but look at an array of Dsymbols.
127 bool Dsymbol::oneMembers(Dsymbols
*members
, Dsymbol
**ps
, Identifier
*ident
)
129 //printf("Dsymbol::oneMembers() %d\n", members ? members->dim : 0);
134 for (size_t i
= 0; i
< members
->dim
; i
++)
136 Dsymbol
*sx
= (*members
)[i
];
137 bool x
= sx
->oneMember(ps
, ident
);
138 //printf("\t[%d] kind %s = %d, s = %p\n", i, sx->kind(), x, *ps);
141 //printf("\tfalse 1\n");
148 if (!(*ps
)->ident
|| !(*ps
)->ident
->equals(ident
))
152 else if (s
->isOverloadable() && (*ps
)->isOverloadable())
154 // keep head of overload set
155 FuncDeclaration
*f1
= s
->isFuncDeclaration();
156 FuncDeclaration
*f2
= (*ps
)->isFuncDeclaration();
159 assert(!f1
->isFuncAliasDeclaration());
160 assert(!f2
->isFuncAliasDeclaration());
161 for (; f1
!= f2
; f1
= f1
->overnext0
)
163 if (f1
->overnext0
== NULL
)
171 else // more than one symbol
174 //printf("\tfalse 2\n");
180 *ps
= s
; // s is the one symbol, NULL if none
181 //printf("\ttrue\n");
185 /*****************************************
186 * Is Dsymbol a variable that contains pointers?
189 bool Dsymbol::hasPointers()
191 //printf("Dsymbol::hasPointers() %s\n", toChars());
195 bool Dsymbol::hasStaticCtorOrDtor()
197 //printf("Dsymbol::hasStaticCtorOrDtor() %s\n", toChars());
201 void Dsymbol::setFieldOffset(AggregateDeclaration
*, unsigned *, bool)
205 Identifier
*Dsymbol::getIdent()
210 const char *Dsymbol::toChars()
212 return ident
? ident
->toChars() : "__anonymous";
215 const char *Dsymbol::toPrettyCharsHelper()
220 const char *Dsymbol::toPrettyChars(bool QualifyTypes
)
222 if (prettystring
&& !QualifyTypes
)
223 return (const char *)prettystring
;
225 //printf("Dsymbol::toPrettyChars() '%s'\n", toChars());
228 const char *s
= toChars();
230 prettystring
= (const utf8_t
*)s
;
234 // Computer number of components
235 size_t complength
= 0;
236 for (Dsymbol
*p
= this; p
; p
= p
->parent
)
239 // Allocate temporary array comp[]
240 const char **comp
= (const char **)mem
.xmalloc(complength
* sizeof(char**));
242 // Fill in comp[] and compute length of final result
245 for (Dsymbol
*p
= this; p
; p
= p
->parent
)
247 const char *s
= QualifyTypes
? p
->toPrettyCharsHelper() : p
->toChars();
248 const size_t len
= strlen(s
);
254 char *s
= (char *)mem
.xmalloc(length
);
255 char *q
= s
+ length
- 1;
257 for (size_t j
= 0; j
< complength
; j
++)
259 const char *t
= comp
[j
];
260 const size_t len
= strlen(t
);
269 prettystring
= (utf8_t
*)s
;
273 Loc
& Dsymbol::getLoc()
275 if (!loc
.filename
) // avoid bug 5861.
277 Module
*m
= getModule();
280 loc
.filename
= m
->srcfile
->toChars();
285 const char *Dsymbol::locToChars()
287 return getLoc().toChars();
290 const char *Dsymbol::kind() const
295 /*********************************
296 * If this symbol is really an alias for another,
298 * If needed, semantic() is invoked due to resolve forward reference.
300 Dsymbol
*Dsymbol::toAlias()
305 /*********************************
306 * Resolve recursive tuple expansion in eponymous template.
308 Dsymbol
*Dsymbol::toAlias2()
313 Dsymbol
*Dsymbol::pastMixin()
317 //printf("Dsymbol::pastMixin() %s\n", toChars());
318 while (s
&& s
->isTemplateMixin())
323 /**********************************
324 * `parent` field returns a lexically enclosing scope symbol this is a member of.
326 * `toParent()` returns a logically enclosing scope symbol this is a member of.
327 * It skips over TemplateMixin's.
329 * `toParent2()` returns an enclosing scope symbol this is living at runtime.
330 * It skips over both TemplateInstance's and TemplateMixin's.
331 * It's used when looking for the 'this' pointer of the enclosing function/class.
335 * template Foo(alias a) { mixin Bar!(); }
336 * mixin template Bar() {
337 * public { // ProtDeclaration
338 * void baz() { a = 2; }
343 * alias foo = Foo!(v);
348 * // s == FuncDeclaration('mod.test.Foo!().Bar!().baz()')
349 * // s.parent == TemplateMixin('mod.test.Foo!().Bar!()')
350 * // s.toParent() == TemplateInstance('mod.test.Foo!()')
351 * // s.toParent2() == FuncDeclaration('mod.test')
353 Dsymbol
*Dsymbol::toParent()
355 return parent
? parent
->pastMixin() : NULL
;
359 Dsymbol
*Dsymbol::toParent2()
362 while (s
&& s
->isTemplateInstance())
367 TemplateInstance
*Dsymbol::isInstantiated()
369 for (Dsymbol
*s
= parent
; s
; s
= s
->parent
)
371 TemplateInstance
*ti
= s
->isTemplateInstance();
372 if (ti
&& !ti
->isTemplateMixin())
378 // Check if this function is a member of a template which has only been
379 // instantiated speculatively, eg from inside is(typeof()).
380 // Return the speculative template instance it is part of,
381 // or NULL if not speculative.
382 TemplateInstance
*Dsymbol::isSpeculative()
384 Dsymbol
*par
= parent
;
387 TemplateInstance
*ti
= par
->isTemplateInstance();
388 if (ti
&& ti
->gagged
)
390 par
= par
->toParent();
395 Ungag
Dsymbol::ungagSpeculative()
397 unsigned oldgag
= global
.gag
;
399 if (global
.gag
&& !isSpeculative() && !toParent2()->isFuncDeclaration())
402 return Ungag(oldgag
);
405 bool Dsymbol::isAnonymous()
407 return ident
== NULL
;
410 /*************************************
411 * Set scope for future semantic analysis so we can
412 * deal better with forward references.
415 void Dsymbol::setScope(Scope
*sc
)
417 //printf("Dsymbol::setScope() %p %s, %p stc = %llx\n", this, toChars(), sc, sc->stc);
419 sc
->setNoFree(); // may need it even after semantic() finishes
422 depdecl
= sc
->depdecl
;
425 userAttribDecl
= sc
->userAttribDecl
;
428 void Dsymbol::importAll(Scope
*)
432 /*************************************
433 * Does semantic analysis on the public face of declarations.
436 void Dsymbol::semantic(Scope
*)
438 error("%p has no semantic routine", this);
441 /*************************************
442 * Does semantic analysis on initializers and members of aggregates.
445 void Dsymbol::semantic2(Scope
*)
447 // Most Dsymbols have no further semantic analysis needed
450 /*************************************
451 * Does semantic analysis on function bodies.
454 void Dsymbol::semantic3(Scope
*)
456 // Most Dsymbols have no further semantic analysis needed
459 /*********************************************
460 * Search for ident as member of s.
462 * loc = location to print for error messages
463 * ident = identifier to search for
469 Dsymbol
*Dsymbol::search(const Loc
&, Identifier
*, int)
471 //printf("Dsymbol::search(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars());
475 /***************************************************
476 * Search for symbol with correct spelling.
479 void *symbol_search_fp(void *arg
, const char *seed
, int *cost
)
481 /* If not in the lexer's string table, it certainly isn't in the symbol table.
482 * Doing this first is a lot faster.
484 size_t len
= strlen(seed
);
487 Identifier
*id
= Identifier::lookup(seed
, len
);
492 Dsymbol
*s
= (Dsymbol
*)arg
;
493 Module::clearCache();
494 return (void *)s
->search(Loc(), id
, IgnoreErrors
);
497 Dsymbol
*Dsymbol::search_correct(Identifier
*ident
)
500 return NULL
; // don't do it for speculative compiles; too time consuming
502 return (Dsymbol
*)speller(ident
->toChars(), &symbol_search_fp
, (void *)this, idchars
);
505 /***************************************
506 * Search for identifier id as a member of 'this'.
507 * id may be a template instance.
509 * symbol found, NULL if not
511 Dsymbol
*Dsymbol::searchX(Loc loc
, Scope
*sc
, RootObject
*id
)
513 //printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars());
514 Dsymbol
*s
= toAlias();
517 if (Declaration
*d
= s
->isDeclaration())
521 ::error(loc
, "circular reference to '%s'", d
->toPrettyChars());
526 switch (id
->dyncast())
528 case DYNCAST_IDENTIFIER
:
529 sm
= s
->search(loc
, (Identifier
*)id
);
532 case DYNCAST_DSYMBOL
:
534 // It's a template instance
535 //printf("\ttemplate instance id\n");
536 Dsymbol
*st
= (Dsymbol
*)id
;
537 TemplateInstance
*ti
= st
->isTemplateInstance();
538 sm
= s
->search(loc
, ti
->name
);
541 sm
= s
->search_correct(ti
->name
);
543 ::error(loc
, "template identifier '%s' is not a member of %s '%s', did you mean %s '%s'?",
544 ti
->name
->toChars(), s
->kind(), s
->toPrettyChars(), sm
->kind(), sm
->toChars());
546 ::error(loc
, "template identifier '%s' is not a member of %s '%s'",
547 ti
->name
->toChars(), s
->kind(), s
->toPrettyChars());
551 TemplateDeclaration
*td
= sm
->isTemplateDeclaration();
554 ::error(loc
, "%s.%s is not a template, it is a %s", s
->toPrettyChars(), ti
->name
->toChars(), sm
->kind());
558 if (!ti
->semanticRun
)
565 case DYNCAST_EXPRESSION
:
572 bool Dsymbol::overloadInsert(Dsymbol
*)
574 //printf("Dsymbol::overloadInsert('%s')\n", s->toChars());
578 d_uns64
Dsymbol::size(Loc
)
580 error("Dsymbol '%s' has no size", toChars());
584 bool Dsymbol::isforwardRef()
589 AggregateDeclaration
*Dsymbol::isThis()
594 bool Dsymbol::isExport() const
599 bool Dsymbol::isImportedSymbol() const
604 bool Dsymbol::isDeprecated()
609 bool Dsymbol::isOverloadable()
614 LabelDsymbol
*Dsymbol::isLabel() // is this a LabelDsymbol()?
619 /// Returns an AggregateDeclaration when toParent() is that.
620 AggregateDeclaration
*Dsymbol::isMember()
622 //printf("Dsymbol::isMember() %s\n", toChars());
623 Dsymbol
*parent
= toParent();
624 //printf("parent is %s %s\n", parent->kind(), parent->toChars());
625 return parent
? parent
->isAggregateDeclaration() : NULL
;
628 /// Returns an AggregateDeclaration when toParent2() is that.
629 AggregateDeclaration
*Dsymbol::isMember2()
631 //printf("Dsymbol::isMember2() %s\n", toChars());
632 Dsymbol
*parent
= toParent2();
633 //printf("parent is %s %s\n", parent->kind(), parent->toChars());
634 return parent
? parent
->isAggregateDeclaration() : NULL
;
637 // is this a member of a ClassDeclaration?
638 ClassDeclaration
*Dsymbol::isClassMember()
640 AggregateDeclaration
*ad
= isMember();
641 return ad
? ad
->isClassDeclaration() : NULL
;
644 Type
*Dsymbol::getType()
649 bool Dsymbol::needThis()
654 /*********************************
655 * Iterate this dsymbol or members of this scoped dsymbol, then
656 * call `fp` with the found symbol and `param`.
658 * fp = function pointer to process the iterated symbol.
659 * If it returns nonzero, the iteration will be aborted.
660 * param = a parameter passed to fp.
662 * nonzero if the iteration is aborted by the return value of fp,
663 * or 0 if it's completed.
665 int Dsymbol::apply(Dsymbol_apply_ft_t fp
, void *param
)
667 return (*fp
)(this, param
);
670 void Dsymbol::addMember(Scope
*, ScopeDsymbol
*sds
)
672 //printf("Dsymbol::addMember('%s')\n", toChars());
673 //printf("Dsymbol::addMember(this = %p, '%s' scopesym = '%s')\n", this, toChars(), sds->toChars());
674 //printf("Dsymbol::addMember(this = %p, '%s' sds = %p, sds->symtab = %p)\n", this, toChars(), sds, sds->symtab);
676 if (!isAnonymous()) // no name, so can't add it to symbol table
678 if (!sds
->symtabInsert(this)) // if name is already defined
680 Dsymbol
*s2
= sds
->symtabLookup(this, ident
);
681 if (!s2
->overloadInsert(this))
683 sds
->multiplyDefined(Loc(), this, s2
);
687 if (sds
->isAggregateDeclaration() || sds
->isEnumDeclaration())
689 if (ident
== Id::__sizeof
|| ident
== Id::__xalignof
|| ident
== Id::_mangleof
)
691 error(".%s property cannot be redefined", ident
->toChars());
698 void Dsymbol::error(const char *format
, ...)
701 va_start(ap
, format
);
702 ::verror(getLoc(), format
, ap
, kind(), toPrettyChars());
706 void Dsymbol::error(Loc loc
, const char *format
, ...)
709 va_start(ap
, format
);
710 ::verror(loc
, format
, ap
, kind(), toPrettyChars());
714 void Dsymbol::deprecation(Loc loc
, const char *format
, ...)
717 va_start(ap
, format
);
718 ::vdeprecation(loc
, format
, ap
, kind(), toPrettyChars());
722 void Dsymbol::deprecation(const char *format
, ...)
725 va_start(ap
, format
);
726 ::vdeprecation(getLoc(), format
, ap
, kind(), toPrettyChars());
730 void Dsymbol::checkDeprecated(Loc loc
, Scope
*sc
)
732 if (global
.params
.useDeprecated
!= DIAGNOSTICoff
&& isDeprecated())
734 // Don't complain if we're inside a deprecated symbol's scope
735 for (Dsymbol
*sp
= sc
->parent
; sp
; sp
= sp
->parent
)
737 if (sp
->isDeprecated())
741 for (Scope
*sc2
= sc
; sc2
; sc2
= sc2
->enclosing
)
743 if (sc2
->scopesym
&& sc2
->scopesym
->isDeprecated())
746 // If inside a StorageClassDeclaration that is deprecated
747 if (sc2
->stc
& STCdeprecated
)
751 const char *message
= NULL
;
752 for (Dsymbol
*p
= this; p
; p
= p
->parent
)
754 message
= p
->depdecl
? p
->depdecl
->getMessage() : NULL
;
760 deprecation(loc
, "is deprecated - %s", message
);
762 deprecation(loc
, "is deprecated");
766 Declaration
*d
= isDeclaration();
767 if (d
&& d
->storage_class
& STCdisable
)
769 if (!(sc
->func
&& sc
->func
->storage_class
& STCdisable
))
771 if (d
->toParent() && d
->isPostBlitDeclaration())
772 d
->toParent()->error(loc
, "is not copyable because it is annotated with @disable");
774 error(loc
, "is not callable because it is annotated with @disable");
779 /**********************************
780 * Determine which Module a Dsymbol is in.
783 Module
*Dsymbol::getModule()
785 //printf("Dsymbol::getModule()\n");
786 if (TemplateInstance
*ti
= isInstantiated())
787 return ti
->tempdecl
->getModule();
792 //printf("\ts = %s '%s'\n", s->kind(), s->toPrettyChars());
793 Module
*m
= s
->isModule();
801 /**********************************
802 * Determine which Module a Dsymbol is in, as far as access rights go.
805 Module
*Dsymbol::getAccessModule()
807 //printf("Dsymbol::getAccessModule()\n");
808 if (TemplateInstance
*ti
= isInstantiated())
809 return ti
->tempdecl
->getAccessModule();
814 //printf("\ts = %s '%s'\n", s->kind(), s->toPrettyChars());
815 Module
*m
= s
->isModule();
818 TemplateInstance
*ti
= s
->isTemplateInstance();
819 if (ti
&& ti
->enclosing
)
821 /* Because of local template instantiation, the parent isn't where the access
822 * rights come from - it's the template declaration
832 /*************************************
837 return Prot(PROTpublic
);
840 /*************************************
841 * Do syntax copy of an array of Dsymbol's.
844 Dsymbols
*Dsymbol::arraySyntaxCopy(Dsymbols
*a
)
851 for (size_t i
= 0; i
< b
->dim
; i
++)
853 (*b
)[i
] = (*b
)[i
]->syntaxCopy(NULL
);
859 /****************************************
860 * Add documentation comment to Dsymbol.
861 * Ignore NULL comments.
864 void Dsymbol::addComment(const utf8_t
*comment
)
867 //printf("adding comment '%s' to symbol %p '%s'\n", comment, this, toChars());
870 this->comment
= comment
;
871 else if (comment
&& strcmp((const char *)comment
, (const char *)this->comment
) != 0)
872 { // Concatenate the two
873 this->comment
= Lexer::combineComments(this->comment
, comment
);
877 /****************************************
878 * Returns true if this symbol is defined in a non-root module without instantiation.
880 bool Dsymbol::inNonRoot()
883 for (; s
; s
= s
->toParent())
885 if (s
->isTemplateInstance())
889 if (Module
*m
= s
->isModule())
899 /********************************* OverloadSet ****************************/
901 OverloadSet::OverloadSet(Identifier
*ident
, OverloadSet
*os
)
906 for (size_t i
= 0; i
< os
->a
.dim
; i
++)
913 void OverloadSet::push(Dsymbol
*s
)
918 const char *OverloadSet::kind() const
920 return "overloadset";
924 /********************************* ScopeDsymbol ****************************/
926 ScopeDsymbol::ScopeDsymbol()
932 importedScopes
= NULL
;
936 ScopeDsymbol::ScopeDsymbol(Identifier
*id
)
942 importedScopes
= NULL
;
946 Dsymbol
*ScopeDsymbol::syntaxCopy(Dsymbol
*s
)
948 //printf("ScopeDsymbol::syntaxCopy('%s')\n", toChars());
949 ScopeDsymbol
*sds
= s
? (ScopeDsymbol
*)s
: new ScopeDsymbol(ident
);
950 sds
->members
= arraySyntaxCopy(members
);
951 sds
->endlinnum
= endlinnum
;
955 void ScopeDsymbol::semantic(Scope
*)
959 /*****************************************
960 * This function is #1 on the list of functions that eat cpu time.
961 * Be very, very careful about slowing it down.
964 Dsymbol
*ScopeDsymbol::search(const Loc
&loc
, Identifier
*ident
, int flags
)
966 //printf("%s->ScopeDsymbol::search(ident='%s', flags=x%x)\n", toChars(), ident->toChars(), flags);
967 //if (strcmp(ident->toChars(),"c") == 0) *(char*)0=0;
969 // Look in symbols declared in this module
970 if (symtab
&& !(flags
& SearchImportsOnly
))
972 //printf(" look in locals\n");
973 Dsymbol
*s1
= symtab
->lookup(ident
);
976 //printf("\tfound in locals = '%s.%s'\n",toChars(),s1->toChars());
980 //printf(" not found in locals\n");
982 // Look in imported scopes
985 //printf(" look in imports\n");
987 OverloadSet
*a
= NULL
;
989 // Look in imported modules
990 for (size_t i
= 0; i
< importedScopes
->dim
; i
++)
992 // If private import, don't search it
993 if ((flags
& IgnorePrivateImports
) && prots
[i
] == PROTprivate
)
996 int sflags
= flags
& (IgnoreErrors
| IgnoreAmbiguous
| IgnoreSymbolVisibility
); // remember these in recursive searches
997 Dsymbol
*ss
= (*importedScopes
)[i
];
999 //printf("\tscanning import '%s', prots = %d, isModule = %p, isImport = %p\n", ss->toChars(), prots[i], ss->isModule(), ss->isImport());
1003 if (flags
& SearchLocalsOnly
)
1006 else // mixin template
1008 if (flags
& SearchImportsOnly
)
1010 // compatibility with -transition=import (Bugzilla 15925)
1011 // SearchLocalsOnly should always get set for new lookup rules
1012 sflags
|= (flags
& SearchLocalsOnly
);
1015 /* Don't find private members if ss is a module
1017 Dsymbol
*s2
= ss
->search(loc
, ident
, sflags
| (ss
->isModule() ? IgnorePrivateImports
: IgnoreNone
));
1018 if (!s2
|| (!(flags
& IgnoreSymbolVisibility
) && !symbolIsVisible(this, s2
)))
1023 if (s
&& s
->isOverloadSet())
1024 a
= mergeOverloadSet(ident
, a
, s
);
1026 else if (s2
&& s
!= s2
)
1028 if (s
->toAlias() == s2
->toAlias() ||
1029 (s
->getType() == s2
->getType() && s
->getType()))
1031 /* After following aliases, we found the same
1032 * symbol, so it's not an ambiguity. But if one
1033 * alias is deprecated or less accessible, prefer
1036 if (s
->isDeprecated() ||
1037 (s
->prot().isMoreRestrictiveThan(s2
->prot()) && s2
->prot().kind
!= PROTnone
))
1042 /* Two imports of the same module should be regarded as
1045 Import
*i1
= s
->isImport();
1046 Import
*i2
= s2
->isImport();
1048 (i1
->mod
== i2
->mod
||
1049 (!i1
->parent
->isImport() && !i2
->parent
->isImport() &&
1050 i1
->ident
->equals(i2
->ident
))
1056 * Public selective import adds AliasDeclaration in module.
1057 * To make an overload set, resolve aliases in here and
1058 * get actual overload roots which accessible via s and s2.
1063 /* If both s2 and s are overloadable (though we only
1064 * need to check s once)
1066 if ((s2
->isOverloadSet() || s2
->isOverloadable()) &&
1067 (a
|| s
->isOverloadable()))
1069 a
= mergeOverloadSet(ident
, a
, s2
);
1072 if (flags
& IgnoreAmbiguous
) // if return NULL on ambiguity
1074 if (!(flags
& IgnoreErrors
))
1075 ScopeDsymbol::multiplyDefined(loc
, s
, s2
);
1084 /* Build special symbol if we had multiple finds
1088 if (!s
->isOverloadSet())
1089 a
= mergeOverloadSet(ident
, a
, s
);
1093 // TODO: remove once private symbol visibility has been deprecated
1094 if (!(flags
& IgnoreErrors
) && s
->prot().kind
== PROTprivate
&&
1095 !s
->isOverloadable() && !s
->parent
->isTemplateMixin() && !s
->parent
->isNspace())
1097 AliasDeclaration
*ad
;
1098 // accessing private selective and renamed imports is
1099 // deprecated by restricting the symbol visibility
1100 if (s
->isImport() || ((ad
= s
->isAliasDeclaration()) != NULL
&& ad
->_import
!= NULL
))
1103 error(loc
, "%s %s is private", s
->kind(), s
->toPrettyChars());
1105 //printf("\tfound in imports %s.%s\n", toChars(), s.toChars());
1108 //printf(" not found in imports\n");
1114 OverloadSet
*ScopeDsymbol::mergeOverloadSet(Identifier
*ident
, OverloadSet
*os
, Dsymbol
*s
)
1118 os
= new OverloadSet(ident
);
1121 if (OverloadSet
*os2
= s
->isOverloadSet())
1123 // Merge the cross-module overload set 'os2' into 'os'
1126 os
->a
.setDim(os2
->a
.dim
);
1127 memcpy(os
->a
.tdata(), os2
->a
.tdata(), sizeof(os
->a
[0]) * os2
->a
.dim
);
1131 for (size_t i
= 0; i
< os2
->a
.dim
; i
++)
1133 os
= mergeOverloadSet(ident
, os
, os2
->a
[i
]);
1139 assert(s
->isOverloadable());
1141 /* Don't add to os[] if s is alias of previous sym
1143 for (size_t j
= 0; j
< os
->a
.dim
; j
++)
1145 Dsymbol
*s2
= os
->a
[j
];
1146 if (s
->toAlias() == s2
->toAlias())
1148 if (s2
->isDeprecated() ||
1149 (s2
->prot().isMoreRestrictiveThan(s
->prot()) &&
1150 s
->prot().kind
!= PROTnone
))
1164 void ScopeDsymbol::importScope(Dsymbol
*s
, Prot protection
)
1166 //printf("%s->ScopeDsymbol::importScope(%s, %d)\n", toChars(), s->toChars(), protection);
1168 // No circular or redundant import's
1171 if (!importedScopes
)
1172 importedScopes
= new Dsymbols();
1175 for (size_t i
= 0; i
< importedScopes
->dim
; i
++)
1177 Dsymbol
*ss
= (*importedScopes
)[i
];
1178 if (ss
== s
) // if already imported
1180 if (protection
.kind
> prots
[i
])
1181 prots
[i
] = protection
.kind
; // upgrade access
1186 importedScopes
->push(s
);
1187 prots
= (PROTKIND
*)mem
.xrealloc(prots
, importedScopes
->dim
* sizeof(prots
[0]));
1188 prots
[importedScopes
->dim
- 1] = protection
.kind
;
1192 static void bitArraySet(BitArray
*array
, size_t idx
)
1194 array
->ptr
[idx
/ (sizeof(size_t) * CHAR_BIT
)] |= 1ULL << (idx
& (sizeof(size_t) * CHAR_BIT
- 1));
1197 static bool bitArrayGet(BitArray
*array
, size_t idx
)
1199 return (array
->ptr
[idx
/ (sizeof(size_t) * CHAR_BIT
)] & (1ULL << (idx
& (sizeof(size_t) * CHAR_BIT
- 1)))) != 0;
1202 static void bitArrayLength(BitArray
*array
, size_t len
)
1204 size_t obytes
= (array
->len
+ CHAR_BIT
- 1) / CHAR_BIT
;
1205 size_t nbytes
= (len
+ CHAR_BIT
- 1) / CHAR_BIT
;
1207 if (obytes
< nbytes
)
1210 array
->ptr
= (size_t *)mem
.xmalloc(nbytes
* sizeof(size_t));
1212 array
->ptr
= (size_t *)mem
.xrealloc(array
->ptr
, nbytes
* sizeof(size_t));
1214 for (size_t i
= obytes
; i
< nbytes
; i
++)
1220 void ScopeDsymbol::addAccessiblePackage(Package
*p
, Prot protection
)
1222 BitArray
*pary
= protection
.kind
== PROTprivate
? &privateAccessiblePackages
: &accessiblePackages
;
1223 if (pary
->len
<= p
->tag
)
1224 bitArrayLength(pary
, p
->tag
+ 1);
1225 bitArraySet(pary
, p
->tag
);
1228 bool ScopeDsymbol::isPackageAccessible(Package
*p
, Prot protection
, int)
1230 if ((p
->tag
< accessiblePackages
.len
&& bitArrayGet(&accessiblePackages
, p
->tag
)) ||
1231 (protection
.kind
== PROTprivate
&& p
->tag
< privateAccessiblePackages
.len
&& bitArrayGet(&privateAccessiblePackages
, p
->tag
)))
1235 for (size_t i
= 0; i
< importedScopes
->dim
; i
++)
1237 // only search visible scopes && imported modules should ignore private imports
1238 Dsymbol
*ss
= (*importedScopes
)[i
];
1239 if (protection
.kind
<= prots
[i
] &&
1240 ss
->isScopeDsymbol()->isPackageAccessible(p
, protection
, IgnorePrivateImports
))
1247 bool ScopeDsymbol::isforwardRef()
1249 return (members
== NULL
);
1252 void ScopeDsymbol::multiplyDefined(Loc loc
, Dsymbol
*s1
, Dsymbol
*s2
)
1255 { ::error(loc
, "%s at %s conflicts with %s at %s",
1256 s1
->toPrettyChars(),
1258 s2
->toPrettyChars(),
1263 s1
->error(s1
->loc
, "conflicts with %s %s at %s",
1265 s2
->toPrettyChars(),
1270 const char *ScopeDsymbol::kind() const
1272 return "ScopeDsymbol";
1275 Dsymbol
*ScopeDsymbol::symtabInsert(Dsymbol
*s
)
1277 return symtab
->insert(s
);
1280 /****************************************
1281 * Look up identifier in symbol table.
1284 Dsymbol
*ScopeDsymbol::symtabLookup(Dsymbol
*, Identifier
*id
)
1286 return symtab
->lookup(id
);
1289 /****************************************
1290 * Return true if any of the members are static ctors or static dtors, or if
1291 * any members have members that are.
1294 bool ScopeDsymbol::hasStaticCtorOrDtor()
1298 for (size_t i
= 0; i
< members
->dim
; i
++)
1299 { Dsymbol
*member
= (*members
)[i
];
1301 if (member
->hasStaticCtorOrDtor())
1308 /***************************************
1309 * Determine number of Dsymbols, folding in AttribDeclaration members.
1312 static int dimDg(void *ctx
, size_t, Dsymbol
*)
1318 size_t ScopeDsymbol::dim(Dsymbols
*members
)
1321 ScopeDsymbol_foreach(NULL
, members
, &dimDg
, &n
);
1325 /***************************************
1326 * Get nth Dsymbol, folding in AttribDeclaration members.
1328 * Dsymbol* nth Dsymbol
1329 * NULL not found, *pn gets incremented by the number
1333 struct GetNthSymbolCtx
1339 static int getNthSymbolDg(void *ctx
, size_t n
, Dsymbol
*sym
)
1341 GetNthSymbolCtx
*p
= (GetNthSymbolCtx
*)ctx
;
1349 Dsymbol
*ScopeDsymbol::getNth(Dsymbols
*members
, size_t nth
, size_t *)
1351 GetNthSymbolCtx ctx
= { nth
, NULL
};
1352 int res
= ScopeDsymbol_foreach(NULL
, members
, &getNthSymbolDg
, &ctx
);
1353 return res
? ctx
.sym
: NULL
;
1356 /***************************************
1357 * Expands attribute declarations in members in depth first
1358 * order. Calls dg(void *ctx, size_t symidx, Dsymbol *sym) for each
1360 * If dg returns !=0, stops and returns that value else returns 0.
1361 * Use this function to avoid the O(N + N^2/2) complexity of
1362 * calculating dim and calling N times getNth.
1365 int ScopeDsymbol_foreach(Scope
*sc
, Dsymbols
*members
, ForeachDg dg
, void *ctx
, size_t *pn
)
1371 size_t n
= pn
? *pn
: 0; // take over index
1373 for (size_t i
= 0; i
< members
->dim
; i
++)
1374 { Dsymbol
*s
= (*members
)[i
];
1376 if (AttribDeclaration
*a
= s
->isAttribDeclaration())
1377 result
= ScopeDsymbol_foreach(sc
, a
->include(sc
, NULL
), dg
, ctx
, &n
);
1378 else if (TemplateMixin
*tm
= s
->isTemplateMixin())
1379 result
= ScopeDsymbol_foreach(sc
, tm
->members
, dg
, ctx
, &n
);
1380 else if (s
->isTemplateInstance())
1382 else if (s
->isUnitTestDeclaration())
1385 result
= dg(ctx
, n
++, s
);
1392 *pn
= n
; // update index
1396 /*******************************************
1397 * Look for member of the form:
1398 * const(MemberInfo)[] getMembers(string);
1399 * Returns NULL if not found
1402 FuncDeclaration
*ScopeDsymbol::findGetMembers()
1404 Dsymbol
*s
= search_function(this, Id::getmembers
);
1405 FuncDeclaration
*fdx
= s
? s
->isFuncDeclaration() : NULL
;
1407 if (fdx
&& fdx
->isVirtual())
1414 /****************************** WithScopeSymbol ******************************/
1416 WithScopeSymbol::WithScopeSymbol(WithStatement
*withstate
)
1419 this->withstate
= withstate
;
1422 Dsymbol
*WithScopeSymbol::search(const Loc
&loc
, Identifier
*ident
, int flags
)
1424 //printf("WithScopeSymbol::search(%s)\n", ident->toChars());
1425 if (flags
& SearchImportsOnly
)
1428 // Acts as proxy to the with class declaration
1430 Expression
*eold
= NULL
;
1431 for (Expression
*e
= withstate
->exp
; e
!= eold
; e
= resolveAliasThis(_scope
, e
))
1433 if (e
->op
== TOKscope
)
1435 s
= ((ScopeExp
*)e
)->sds
;
1437 else if (e
->op
== TOKtype
)
1439 s
= e
->type
->toDsymbol(NULL
);
1443 Type
*t
= e
->type
->toBasetype();
1444 s
= t
->toDsymbol(NULL
);
1448 s
= s
->search(loc
, ident
, flags
);
1457 /****************************** ArrayScopeSymbol ******************************/
1459 ArrayScopeSymbol::ArrayScopeSymbol(Scope
*sc
, Expression
*e
)
1462 assert(e
->op
== TOKindex
|| e
->op
== TOKslice
|| e
->op
== TOKarray
);
1469 ArrayScopeSymbol::ArrayScopeSymbol(Scope
*sc
, TypeTuple
*t
)
1478 ArrayScopeSymbol::ArrayScopeSymbol(Scope
*sc
, TupleDeclaration
*s
)
1487 Dsymbol
*ArrayScopeSymbol::search(const Loc
&loc
, Identifier
*ident
, int)
1489 //printf("ArrayScopeSymbol::search('%s', flags = %d)\n", ident->toChars(), flags);
1490 if (ident
== Id::dollar
)
1492 VarDeclaration
**pvar
;
1498 /* $ gives the number of elements in the tuple
1500 VarDeclaration
*v
= new VarDeclaration(loc
, Type::tsize_t
, Id::dollar
, NULL
);
1501 Expression
*e
= new IntegerExp(Loc(), td
->objects
->dim
, Type::tsize_t
);
1502 v
->_init
= new ExpInitializer(Loc(), e
);
1503 v
->storage_class
|= STCtemp
| STCstatic
| STCconst
;
1510 /* $ gives the number of type entries in the type tuple
1512 VarDeclaration
*v
= new VarDeclaration(loc
, Type::tsize_t
, Id::dollar
, NULL
);
1513 Expression
*e
= new IntegerExp(Loc(), type
->arguments
->dim
, Type::tsize_t
);
1514 v
->_init
= new ExpInitializer(Loc(), e
);
1515 v
->storage_class
|= STCtemp
| STCstatic
| STCconst
;
1520 if (exp
->op
== TOKindex
)
1522 /* array[index] where index is some function of $
1524 IndexExp
*ie
= (IndexExp
*)exp
;
1525 pvar
= &ie
->lengthVar
;
1528 else if (exp
->op
== TOKslice
)
1530 /* array[lwr .. upr] where lwr or upr is some function of $
1532 SliceExp
*se
= (SliceExp
*)exp
;
1533 pvar
= &se
->lengthVar
;
1536 else if (exp
->op
== TOKarray
)
1538 /* array[e0, e1, e2, e3] where e0, e1, e2 are some function of $
1539 * $ is a opDollar!(dim)() where dim is the dimension(0,1,2,...)
1541 ArrayExp
*ae
= (ArrayExp
*)exp
;
1542 pvar
= &ae
->lengthVar
;
1547 /* Didn't find $, look in enclosing scope(s).
1552 while (ce
->op
== TOKcomma
)
1553 ce
= ((CommaExp
*)ce
)->e2
;
1555 /* If we are indexing into an array that is really a type
1556 * tuple, rewrite this as an index into a type tuple and
1559 if (ce
->op
== TOKtype
)
1561 Type
*t
= ((TypeExp
*)ce
)->type
;
1562 if (t
->ty
== Ttuple
)
1564 type
= (TypeTuple
*)t
;
1569 /* *pvar is lazily initialized, so if we refer to $
1570 * multiple times, it gets set only once.
1572 if (!*pvar
) // if not already initialized
1574 /* Create variable v and set it to the value of $
1578 if (ce
->op
== TOKtuple
)
1580 /* It is for an expression tuple, so the
1581 * length will be a const.
1583 Expression
*e
= new IntegerExp(Loc(), ((TupleExp
*)ce
)->exps
->dim
, Type::tsize_t
);
1584 v
= new VarDeclaration(loc
, Type::tsize_t
, Id::dollar
, new ExpInitializer(Loc(), e
));
1585 v
->storage_class
|= STCtemp
| STCstatic
| STCconst
;
1587 else if (ce
->type
&& (t
= ce
->type
->toBasetype()) != NULL
&&
1588 (t
->ty
== Tstruct
|| t
->ty
== Tclass
))
1590 // Look for opDollar
1591 assert(exp
->op
== TOKarray
|| exp
->op
== TOKslice
);
1592 AggregateDeclaration
*ad
= isAggregate(t
);
1595 Dsymbol
*s
= ad
->search(loc
, Id::opDollar
);
1596 if (!s
) // no dollar exists -- search in higher scope
1600 Expression
*e
= NULL
;
1601 // Check for multi-dimensional opDollar(dim) template.
1602 if (TemplateDeclaration
*td
= s
->isTemplateDeclaration())
1605 if (exp
->op
== TOKarray
)
1607 dim
= ((ArrayExp
*)exp
)->currentDimension
;
1609 else if (exp
->op
== TOKslice
)
1611 dim
= 0; // slices are currently always one-dimensional
1618 Objects
*tiargs
= new Objects();
1619 Expression
*edim
= new IntegerExp(Loc(), dim
, Type::tsize_t
);
1620 edim
= ::semantic(edim
, sc
);
1622 e
= new DotTemplateInstanceExp(loc
, ce
, td
->ident
, tiargs
);
1626 /* opDollar exists, but it's not a template.
1627 * This is acceptable ONLY for single-dimension indexing.
1628 * Note that it's impossible to have both template & function opDollar,
1629 * because both take no arguments.
1631 if (exp
->op
== TOKarray
&& ((ArrayExp
*)exp
)->arguments
->dim
!= 1)
1633 exp
->error("%s only defines opDollar for one dimension", ad
->toChars());
1636 Declaration
*d
= s
->isDeclaration();
1638 e
= new DotVarExp(loc
, ce
, d
);
1640 e
= ::semantic(e
, sc
);
1642 exp
->error("%s has no value", e
->toChars());
1643 t
= e
->type
->toBasetype();
1644 if (t
&& t
->ty
== Tfunction
)
1645 e
= new CallExp(e
->loc
, e
);
1646 v
= new VarDeclaration(loc
, NULL
, Id::dollar
, new ExpInitializer(Loc(), e
));
1647 v
->storage_class
|= STCtemp
| STCctfe
| STCrvalue
;
1651 /* For arrays, $ will either be a compile-time constant
1652 * (in which case its value in set during constant-folding),
1653 * or a variable (in which case an expression is created in
1656 VoidInitializer
*e
= new VoidInitializer(Loc());
1657 e
->type
= Type::tsize_t
;
1658 v
= new VarDeclaration(loc
, Type::tsize_t
, Id::dollar
, e
);
1659 v
->storage_class
|= STCtemp
| STCctfe
; // it's never a true static variable
1663 (*pvar
)->semantic(sc
);
1670 /****************************** DsymbolTable ******************************/
1672 DsymbolTable::DsymbolTable()
1677 Dsymbol
*DsymbolTable::lookup(Identifier
const * const ident
)
1679 //printf("DsymbolTable::lookup(%s)\n", (char*)ident->string);
1680 return (Dsymbol
*)dmd_aaGetRvalue(tab
, const_cast<void *>((const void *)ident
));
1683 Dsymbol
*DsymbolTable::insert(Dsymbol
*s
)
1685 //printf("DsymbolTable::insert(this = %p, '%s')\n", this, s->ident->toChars());
1686 Identifier
*ident
= s
->ident
;
1687 Dsymbol
**ps
= (Dsymbol
**)dmd_aaGet(&tab
, (void *)ident
);
1689 return NULL
; // already in table
1694 Dsymbol
*DsymbolTable::insert(Identifier
const * const ident
, Dsymbol
*s
)
1696 //printf("DsymbolTable::insert()\n");
1697 Dsymbol
**ps
= (Dsymbol
**)dmd_aaGet(&tab
, const_cast<void *>((const void *)ident
));
1699 return NULL
; // already in table
1704 Dsymbol
*DsymbolTable::update(Dsymbol
*s
)
1706 Identifier
*ident
= s
->ident
;
1707 Dsymbol
**ps
= (Dsymbol
**)dmd_aaGet(&tab
, (void *)ident
);
1712 /****************************** Prot ******************************/
1716 this->kind
= PROTundefined
;
1720 Prot::Prot(PROTKIND kind
)
1727 * Checks if `this` is superset of `other` restrictions.
1728 * For example, "protected" is more restrictive than "public".
1730 bool Prot::isMoreRestrictiveThan(const Prot other
) const
1732 return this->kind
< other
.kind
;
1736 * Checks if `this` is absolutely identical protection attribute to `other`
1738 bool Prot::operator==(const Prot
& other
) const
1740 if (this->kind
== other
.kind
)
1742 if (this->kind
== PROTpackage
)
1743 return this->pkg
== other
.pkg
;
1750 * Checks if parent defines different access restrictions than this one.
1753 * parent = protection attribute for scope that hosts this one
1756 * 'true' if parent is already more restrictive than this one and thus
1757 * no differentiation is needed.
1759 bool Prot::isSubsetOf(const Prot
& parent
) const
1761 if (this->kind
!= parent
.kind
)
1764 if (this->kind
== PROTpackage
)
1770 if (parent
.pkg
->isAncestorPackageOf(this->pkg
))