1 
2 // Compiler implementation of the D programming language
3 // Copyright: Copyright (C) 2014-2019 by The D Language Foundation, All Rights Reserved
4 // Authors: Walter Bright, http://www.digitalmars.com
5 // License: http://boost.org/LICENSE_1_0.txt
6 // Source: https://github.com/D-Programming-Language/dmd/blob/master/src/nspace.c
7 
8 
9 #include "root/dsystem.h"
10 
11 #include "mars.h"
12 #include "dsymbol.h"
13 #include "nspace.h"
14 #include "identifier.h"
15 #include "scope.h"
16 
17 /* This implements namespaces.
18  */
19 
Nspace(Loc loc,Identifier * ident,Dsymbols * members,bool mangleOnly)20 Nspace::Nspace(Loc loc, Identifier *ident, Dsymbols *members, bool mangleOnly)
21     : ScopeDsymbol(ident)
22 {
23     //printf("Nspace::Nspace(ident = %s)\n", ident->toChars());
24     this->loc = loc;
25     this->members = members;
26     // Determines whether the symbol for this namespace should be included in
27     // the symbol table.
28     this->mangleOnly = mangleOnly;
29 }
30 
syntaxCopy(Dsymbol *)31 Dsymbol *Nspace::syntaxCopy(Dsymbol *)
32 {
33     Nspace *ns = new Nspace(loc, ident, NULL, mangleOnly);
34     return ScopeDsymbol::syntaxCopy(ns);
35 }
36 
addMember(Scope * sc,ScopeDsymbol * sds)37 void Nspace::addMember(Scope *sc, ScopeDsymbol *sds)
38 {
39     if (mangleOnly)
40         parent = sds;
41     else
42         ScopeDsymbol::addMember(sc, sds);
43     if (members)
44     {
45         if (!symtab)
46             symtab = new DsymbolTable();
47         // The namespace becomes 'imported' into the enclosing scope
48         for (Scope *sce = sc; 1; sce = sce->enclosing)
49         {
50             ScopeDsymbol *sds2 = sce->scopesym;
51             if (sds2)
52             {
53                 sds2->importScope(this, Prot(PROTpublic));
54                 break;
55             }
56         }
57         assert(sc);
58         sc = sc->push(this);
59         sc->linkage = LINKcpp; // namespaces default to C++ linkage
60         sc->parent = this;
61         for (size_t i = 0; i < members->dim; i++)
62         {
63             Dsymbol *s = (*members)[i];
64             //printf("add %s to scope %s\n", s->toChars(), toChars());
65             s->addMember(sc, this);
66         }
67         sc->pop();
68     }
69 }
70 
setScope(Scope * sc)71 void Nspace::setScope(Scope *sc)
72 {
73     ScopeDsymbol::setScope(sc);
74     if (members)
75     {
76         assert(sc);
77         sc = sc->push(this);
78         sc->linkage = LINKcpp; // namespaces default to C++ linkage
79         sc->parent = this;
80         for (size_t i = 0; i < members->dim; i++)
81         {
82             Dsymbol *s = (*members)[i];
83             s->setScope(sc);
84         }
85         sc->pop();
86     }
87 }
88 
semantic(Scope * sc)89 void Nspace::semantic(Scope *sc)
90 {
91     if (semanticRun != PASSinit)
92         return;
93     if (_scope)
94     {
95         sc = _scope;
96         _scope = NULL;
97     }
98     if (!sc)
99         return;
100 
101     semanticRun = PASSsemantic;
102     parent = sc->parent;
103     if (members)
104     {
105         assert(sc);
106         sc = sc->push(this);
107         sc->linkage = LINKcpp;          // note that namespaces imply C++ linkage
108         sc->parent = this;
109 
110         for (size_t i = 0; i < members->dim; i++)
111         {
112             Dsymbol *s = (*members)[i];
113             s->importAll(sc);
114         }
115 
116         for (size_t i = 0; i < members->dim; i++)
117         {
118             Dsymbol *s = (*members)[i];
119             s->semantic(sc);
120         }
121         sc->pop();
122     }
123     semanticRun = PASSsemanticdone;
124 }
125 
semantic2(Scope * sc)126 void Nspace::semantic2(Scope *sc)
127 {
128     if (semanticRun >= PASSsemantic2)
129         return;
130     semanticRun = PASSsemantic2;
131     if (members)
132     {
133         assert(sc);
134         sc = sc->push(this);
135         sc->linkage = LINKcpp;
136         for (size_t i = 0; i < members->dim; i++)
137         {
138             Dsymbol *s = (*members)[i];
139             s->semantic2(sc);
140         }
141         sc->pop();
142     }
143 }
144 
semantic3(Scope * sc)145 void Nspace::semantic3(Scope *sc)
146 {
147     if (semanticRun >= PASSsemantic3)
148         return;
149     semanticRun = PASSsemantic3;
150     if (members)
151     {
152         sc = sc->push(this);
153         sc->linkage = LINKcpp;
154         for (size_t i = 0; i < members->dim; i++)
155         {
156             Dsymbol *s = (*members)[i];
157             s->semantic3(sc);
158         }
159         sc->pop();
160     }
161 }
162 
kind()163 const char *Nspace::kind() const
164 {
165     return "namespace";
166 }
167 
oneMember(Dsymbol ** ps,Identifier * ident)168 bool Nspace::oneMember(Dsymbol **ps, Identifier *ident)
169 {
170     return Dsymbol::oneMember(ps, ident);
171 }
172 
search(const Loc & loc,Identifier * ident,int flags)173 Dsymbol *Nspace::search(const Loc &loc, Identifier *ident, int flags)
174 {
175     //printf("%s::Nspace::search('%s')\n", toChars(), ident->toChars());
176     if (_scope && !symtab)
177         semantic(_scope);
178 
179     if (!members || !symtab) // opaque or semantic() is not yet called
180     {
181         error("is forward referenced when looking for '%s'", ident->toChars());
182         return NULL;
183     }
184 
185     return ScopeDsymbol::search(loc, ident, flags);
186 }
187 
apply(Dsymbol_apply_ft_t fp,void * param)188 int Nspace::apply(Dsymbol_apply_ft_t fp, void *param)
189 {
190     if (members)
191     {
192         for (size_t i = 0; i < members->dim; i++)
193         {
194             Dsymbol *s = (*members)[i];
195             if (s)
196             {
197                 if (s->apply(fp, param))
198                     return 1;
199             }
200         }
201     }
202     return 0;
203 }
204 
hasPointers()205 bool Nspace::hasPointers()
206 {
207     //printf("Nspace::hasPointers() %s\n", toChars());
208 
209     if (members)
210     {
211         for (size_t i = 0; i < members->dim; i++)
212         {
213             Dsymbol *s = (*members)[i];
214             //printf(" s = %s %s\n", s->kind(), s->toChars());
215             if (s->hasPointers())
216             {
217                 return true;
218             }
219         }
220     }
221     return false;
222 }
223 
setFieldOffset(AggregateDeclaration * ad,unsigned * poffset,bool isunion)224 void Nspace::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion)
225 {
226     //printf("Nspace::setFieldOffset() %s\n", toChars());
227     if (_scope)                  // if fwd reference
228         semantic(NULL);         // try to resolve it
229     if (members)
230     {
231         for (size_t i = 0; i < members->dim; i++)
232         {
233             Dsymbol *s = (*members)[i];
234             //printf("\t%s\n", s->toChars());
235             s->setFieldOffset(ad, poffset, isunion);
236         }
237     }
238 }
239