dsymbol.d revision 1.1.1.1 1 1.1 mrg /**
2 1.1 mrg * The base class for a D symbol, which can be a module, variable, function, enum, etc.
3 1.1 mrg *
4 1.1 mrg * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved
5 1.1 mrg * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright)
6 1.1 mrg * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
7 1.1 mrg * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dsymbol.d, _dsymbol.d)
8 1.1 mrg * Documentation: https://dlang.org/phobos/dmd_dsymbol.html
9 1.1 mrg * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dsymbol.d
10 1.1 mrg */
11 1.1 mrg
12 1.1 mrg module dmd.dsymbol;
13 1.1 mrg
14 1.1 mrg import core.stdc.stdarg;
15 1.1 mrg import core.stdc.stdio;
16 1.1 mrg import core.stdc.string;
17 1.1 mrg import core.stdc.stdlib;
18 1.1 mrg
19 1.1 mrg import dmd.aggregate;
20 1.1 mrg import dmd.aliasthis;
21 1.1 mrg import dmd.arraytypes;
22 1.1 mrg import dmd.attrib;
23 1.1 mrg import dmd.astenums;
24 1.1 mrg import dmd.ast_node;
25 1.1 mrg import dmd.gluelayer;
26 1.1 mrg import dmd.dclass;
27 1.1 mrg import dmd.declaration;
28 1.1 mrg import dmd.denum;
29 1.1 mrg import dmd.dimport;
30 1.1 mrg import dmd.dmodule;
31 1.1 mrg import dmd.dversion;
32 1.1 mrg import dmd.dscope;
33 1.1 mrg import dmd.dstruct;
34 1.1 mrg import dmd.dsymbolsem;
35 1.1 mrg import dmd.dtemplate;
36 1.1 mrg import dmd.errors;
37 1.1 mrg import dmd.expression;
38 1.1 mrg import dmd.expressionsem;
39 1.1 mrg import dmd.func;
40 1.1 mrg import dmd.globals;
41 1.1 mrg import dmd.id;
42 1.1 mrg import dmd.identifier;
43 1.1 mrg import dmd.init;
44 1.1 mrg import dmd.lexer;
45 1.1 mrg import dmd.mtype;
46 1.1 mrg import dmd.nspace;
47 1.1 mrg import dmd.opover;
48 1.1 mrg import dmd.root.aav;
49 1.1 mrg import dmd.root.rmem;
50 1.1 mrg import dmd.root.rootobject;
51 1.1 mrg import dmd.root.speller;
52 1.1 mrg import dmd.root.string;
53 1.1 mrg import dmd.statement;
54 1.1 mrg import dmd.staticassert;
55 1.1 mrg import dmd.tokens;
56 1.1 mrg import dmd.visitor;
57 1.1 mrg
58 1.1 mrg /***************************************
59 1.1 mrg * Calls dg(Dsymbol *sym) for each Dsymbol.
60 1.1 mrg * If dg returns !=0, stops and returns that value else returns 0.
61 1.1 mrg * Params:
62 1.1 mrg * symbols = Dsymbols
63 1.1 mrg * dg = delegate to call for each Dsymbol
64 1.1 mrg * Returns:
65 1.1 mrg * last value returned by dg()
66 1.1 mrg *
67 1.1 mrg * See_Also: $(REF each, dmd, root, array)
68 1.1 mrg */
69 1.1 mrg int foreachDsymbol(Dsymbols* symbols, scope int delegate(Dsymbol) dg)
70 1.1 mrg {
71 1.1 mrg assert(dg);
72 1.1 mrg if (symbols)
73 1.1 mrg {
74 1.1 mrg /* Do not use foreach, as the size of the array may expand during iteration
75 1.1 mrg */
76 1.1 mrg for (size_t i = 0; i < symbols.dim; ++i)
77 1.1 mrg {
78 1.1 mrg Dsymbol s = (*symbols)[i];
79 1.1 mrg const result = dg(s);
80 1.1 mrg if (result)
81 1.1 mrg return result;
82 1.1 mrg }
83 1.1 mrg }
84 1.1 mrg return 0;
85 1.1 mrg }
86 1.1 mrg
87 1.1 mrg /***************************************
88 1.1 mrg * Calls dg(Dsymbol *sym) for each Dsymbol.
89 1.1 mrg * Params:
90 1.1 mrg * symbols = Dsymbols
91 1.1 mrg * dg = delegate to call for each Dsymbol
92 1.1 mrg *
93 1.1 mrg * See_Also: $(REF each, dmd, root, array)
94 1.1 mrg */
95 1.1 mrg void foreachDsymbol(Dsymbols* symbols, scope void delegate(Dsymbol) dg)
96 1.1 mrg {
97 1.1 mrg assert(dg);
98 1.1 mrg if (symbols)
99 1.1 mrg {
100 1.1 mrg /* Do not use foreach, as the size of the array may expand during iteration
101 1.1 mrg */
102 1.1 mrg for (size_t i = 0; i < symbols.dim; ++i)
103 1.1 mrg {
104 1.1 mrg Dsymbol s = (*symbols)[i];
105 1.1 mrg dg(s);
106 1.1 mrg }
107 1.1 mrg }
108 1.1 mrg }
109 1.1 mrg
110 1.1 mrg
111 1.1 mrg struct Ungag
112 1.1 mrg {
113 1.1 mrg uint oldgag;
114 1.1 mrg
115 1.1 mrg extern (D) this(uint old) nothrow
116 1.1 mrg {
117 1.1 mrg this.oldgag = old;
118 1.1 mrg }
119 1.1 mrg
120 1.1 mrg extern (C++) ~this() nothrow
121 1.1 mrg {
122 1.1 mrg global.gag = oldgag;
123 1.1 mrg }
124 1.1 mrg }
125 1.1 mrg
126 1.1 mrg struct Visibility
127 1.1 mrg {
128 1.1 mrg ///
129 1.1 mrg enum Kind : ubyte
130 1.1 mrg {
131 1.1 mrg undefined,
132 1.1 mrg none, // no access
133 1.1 mrg private_,
134 1.1 mrg package_,
135 1.1 mrg protected_,
136 1.1 mrg public_,
137 1.1 mrg export_,
138 1.1 mrg }
139 1.1 mrg
140 1.1 mrg Kind kind;
141 1.1 mrg Package pkg;
142 1.1 mrg
143 1.1 mrg extern (D):
144 1.1 mrg
145 1.1 mrg this(Visibility.Kind kind) pure nothrow @nogc @safe
146 1.1 mrg {
147 1.1 mrg this.kind = kind;
148 1.1 mrg }
149 1.1 mrg
150 1.1 mrg /**
151 1.1 mrg * Checks if `this` is less or more visible than `other`
152 1.1 mrg *
153 1.1 mrg * Params:
154 1.1 mrg * other = Visibility to compare `this` to.
155 1.1 mrg *
156 1.1 mrg * Returns:
157 1.1 mrg * A value `< 0` if `this` is less visible than `other`,
158 1.1 mrg * a value `> 0` if `this` is more visible than `other`,
159 1.1 mrg * and `0` if they are at the same level.
160 1.1 mrg * Note that `package` visibility with different packages
161 1.1 mrg * will also return `0`.
162 1.1 mrg */
163 1.1 mrg int opCmp(const Visibility other) const pure nothrow @nogc @safe
164 1.1 mrg {
165 1.1 mrg return this.kind - other.kind;
166 1.1 mrg }
167 1.1 mrg
168 1.1 mrg ///
169 1.1 mrg unittest
170 1.1 mrg {
171 1.1 mrg assert(Visibility(Visibility.Kind.public_) > Visibility(Visibility.Kind.private_));
172 1.1 mrg assert(Visibility(Visibility.Kind.private_) < Visibility(Visibility.Kind.protected_));
173 1.1 mrg assert(Visibility(Visibility.Kind.package_) >= Visibility(Visibility.Kind.package_));
174 1.1 mrg }
175 1.1 mrg
176 1.1 mrg /**
177 1.1 mrg * Checks if `this` is absolutely identical visibility attribute to `other`
178 1.1 mrg */
179 1.1 mrg bool opEquals(ref const Visibility other) const
180 1.1 mrg {
181 1.1 mrg if (this.kind == other.kind)
182 1.1 mrg {
183 1.1 mrg if (this.kind == Visibility.Kind.package_)
184 1.1 mrg return this.pkg == other.pkg;
185 1.1 mrg return true;
186 1.1 mrg }
187 1.1 mrg return false;
188 1.1 mrg }
189 1.1 mrg }
190 1.1 mrg
191 1.1 mrg enum PASS : ubyte
192 1.1 mrg {
193 1.1 mrg initial, // initial state
194 1.1 mrg semantic, // semantic() started
195 1.1 mrg semanticdone, // semantic() done
196 1.1 mrg semantic2, // semantic2() started
197 1.1 mrg semantic2done, // semantic2() done
198 1.1 mrg semantic3, // semantic3() started
199 1.1 mrg semantic3done, // semantic3() done
200 1.1 mrg inline, // inline started
201 1.1 mrg inlinedone, // inline done
202 1.1 mrg obj, // toObjFile() run
203 1.1 mrg }
204 1.1 mrg
205 1.1 mrg // Search options
206 1.1 mrg enum : int
207 1.1 mrg {
208 1.1 mrg IgnoreNone = 0x00, // default
209 1.1 mrg IgnorePrivateImports = 0x01, // don't search private imports
210 1.1 mrg IgnoreErrors = 0x02, // don't give error messages
211 1.1 mrg IgnoreAmbiguous = 0x04, // return NULL if ambiguous
212 1.1 mrg SearchLocalsOnly = 0x08, // only look at locals (don't search imports)
213 1.1 mrg SearchImportsOnly = 0x10, // only look in imports
214 1.1 mrg SearchUnqualifiedModule = 0x20, // the module scope search is unqualified,
215 1.1 mrg // meaning don't search imports in that scope,
216 1.1 mrg // because qualified module searches search
217 1.1 mrg // their imports
218 1.1 mrg IgnoreSymbolVisibility = 0x80, // also find private and package protected symbols
219 1.1 mrg TagNameSpace = 0x100, // search ImportC tag symbol table
220 1.1 mrg }
221 1.1 mrg
222 1.1 mrg /***********************************************************
223 1.1 mrg * Struct/Class/Union field state.
224 1.1 mrg * Used for transitory information when setting field offsets, such
225 1.1 mrg * as bit fields.
226 1.1 mrg */
227 1.1 mrg struct FieldState
228 1.1 mrg {
229 1.1 mrg uint offset; /// byte offset for next field
230 1.1 mrg
231 1.1 mrg uint fieldOffset; /// byte offset for the start of the bit field
232 1.1 mrg uint fieldSize; /// byte size of field
233 1.1 mrg uint fieldAlign; /// byte alignment of field
234 1.1 mrg uint bitOffset; /// bit offset for field
235 1.1 mrg
236 1.1 mrg bool inFlight; /// bit field is in flight
237 1.1 mrg }
238 1.1 mrg
239 1.1 mrg /***********************************************************
240 1.1 mrg */
241 1.1 mrg extern (C++) class Dsymbol : ASTNode
242 1.1 mrg {
243 1.1 mrg Identifier ident;
244 1.1 mrg Dsymbol parent;
245 1.1 mrg /// C++ namespace this symbol belongs to
246 1.1 mrg CPPNamespaceDeclaration cppnamespace;
247 1.1 mrg Symbol* csym; // symbol for code generator
248 1.1 mrg const Loc loc; // where defined
249 1.1 mrg Scope* _scope; // !=null means context to use for semantic()
250 1.1 mrg const(char)* prettystring; // cached value of toPrettyChars()
251 1.1 mrg bool errors; // this symbol failed to pass semantic()
252 1.1 mrg PASS semanticRun = PASS.initial;
253 1.1 mrg ushort localNum; /// perturb mangled name to avoid collisions with those in FuncDeclaration.localsymtab
254 1.1 mrg
255 1.1 mrg DeprecatedDeclaration depdecl; // customized deprecation message
256 1.1 mrg UserAttributeDeclaration userAttribDecl; // user defined attributes
257 1.1 mrg
258 1.1 mrg final extern (D) this() nothrow
259 1.1 mrg {
260 1.1 mrg //printf("Dsymbol::Dsymbol(%p)\n", this);
261 1.1 mrg loc = Loc(null, 0, 0);
262 1.1 mrg }
263 1.1 mrg
264 1.1 mrg final extern (D) this(Identifier ident) nothrow
265 1.1 mrg {
266 1.1 mrg //printf("Dsymbol::Dsymbol(%p, ident)\n", this);
267 1.1 mrg this.loc = Loc(null, 0, 0);
268 1.1 mrg this.ident = ident;
269 1.1 mrg }
270 1.1 mrg
271 1.1 mrg final extern (D) this(const ref Loc loc, Identifier ident) nothrow
272 1.1 mrg {
273 1.1 mrg //printf("Dsymbol::Dsymbol(%p, ident)\n", this);
274 1.1 mrg this.loc = loc;
275 1.1 mrg this.ident = ident;
276 1.1 mrg }
277 1.1 mrg
278 1.1 mrg static Dsymbol create(Identifier ident) nothrow
279 1.1 mrg {
280 1.1 mrg return new Dsymbol(ident);
281 1.1 mrg }
282 1.1 mrg
283 1.1 mrg override const(char)* toChars() const
284 1.1 mrg {
285 1.1 mrg return ident ? ident.toChars() : "__anonymous";
286 1.1 mrg }
287 1.1 mrg
288 1.1 mrg // helper to print fully qualified (template) arguments
289 1.1 mrg const(char)* toPrettyCharsHelper()
290 1.1 mrg {
291 1.1 mrg return toChars();
292 1.1 mrg }
293 1.1 mrg
294 1.1 mrg final const(Loc) getLoc()
295 1.1 mrg {
296 1.1 mrg if (!loc.isValid()) // avoid bug 5861.
297 1.1 mrg if (const m = getModule())
298 1.1 mrg return Loc(m.srcfile.toChars(), 0, 0);
299 1.1 mrg return loc;
300 1.1 mrg }
301 1.1 mrg
302 1.1 mrg final const(char)* locToChars()
303 1.1 mrg {
304 1.1 mrg return getLoc().toChars();
305 1.1 mrg }
306 1.1 mrg
307 1.1 mrg override bool equals(const RootObject o) const
308 1.1 mrg {
309 1.1 mrg if (this == o)
310 1.1 mrg return true;
311 1.1 mrg if (o.dyncast() != DYNCAST.dsymbol)
312 1.1 mrg return false;
313 1.1 mrg auto s = cast(Dsymbol)o;
314 1.1 mrg // Overload sets don't have an ident
315 1.1 mrg // Function-local declarations may have identical names
316 1.1 mrg // if they are declared in different scopes
317 1.1 mrg if (s && ident && s.ident && ident.equals(s.ident) && localNum == s.localNum)
318 1.1 mrg return true;
319 1.1 mrg return false;
320 1.1 mrg }
321 1.1 mrg
322 1.1 mrg final bool isAnonymous() const
323 1.1 mrg {
324 1.1 mrg return ident is null || ident.isAnonymous;
325 1.1 mrg }
326 1.1 mrg
327 1.1 mrg extern(D) private const(char)[] prettyFormatHelper()
328 1.1 mrg {
329 1.1 mrg const cstr = toPrettyChars();
330 1.1 mrg return '`' ~ cstr.toDString() ~ "`\0";
331 1.1 mrg }
332 1.1 mrg
333 1.1 mrg static if (__VERSION__ < 2092)
334 1.1 mrg {
335 1.1 mrg final void error(const ref Loc loc, const(char)* format, ...)
336 1.1 mrg {
337 1.1 mrg va_list ap;
338 1.1 mrg va_start(ap, format);
339 1.1 mrg .verror(loc, format, ap, kind(), prettyFormatHelper().ptr);
340 1.1 mrg va_end(ap);
341 1.1 mrg }
342 1.1 mrg
343 1.1 mrg final void error(const(char)* format, ...)
344 1.1 mrg {
345 1.1 mrg va_list ap;
346 1.1 mrg va_start(ap, format);
347 1.1 mrg const loc = getLoc();
348 1.1 mrg .verror(loc, format, ap, kind(), prettyFormatHelper().ptr);
349 1.1 mrg va_end(ap);
350 1.1 mrg }
351 1.1 mrg
352 1.1 mrg final void deprecation(const ref Loc loc, const(char)* format, ...)
353 1.1 mrg {
354 1.1 mrg va_list ap;
355 1.1 mrg va_start(ap, format);
356 1.1 mrg .vdeprecation(loc, format, ap, kind(), prettyFormatHelper().ptr);
357 1.1 mrg va_end(ap);
358 1.1 mrg }
359 1.1 mrg
360 1.1 mrg final void deprecation(const(char)* format, ...)
361 1.1 mrg {
362 1.1 mrg va_list ap;
363 1.1 mrg va_start(ap, format);
364 1.1 mrg const loc = getLoc();
365 1.1 mrg .vdeprecation(loc, format, ap, kind(), prettyFormatHelper().ptr);
366 1.1 mrg va_end(ap);
367 1.1 mrg }
368 1.1 mrg }
369 1.1 mrg else
370 1.1 mrg {
371 1.1 mrg pragma(printf) final void error(const ref Loc loc, const(char)* format, ...)
372 1.1 mrg {
373 1.1 mrg va_list ap;
374 1.1 mrg va_start(ap, format);
375 1.1 mrg .verror(loc, format, ap, kind(), prettyFormatHelper().ptr);
376 1.1 mrg va_end(ap);
377 1.1 mrg }
378 1.1 mrg
379 1.1 mrg pragma(printf) final void error(const(char)* format, ...)
380 1.1 mrg {
381 1.1 mrg va_list ap;
382 1.1 mrg va_start(ap, format);
383 1.1 mrg const loc = getLoc();
384 1.1 mrg .verror(loc, format, ap, kind(), prettyFormatHelper().ptr);
385 1.1 mrg va_end(ap);
386 1.1 mrg }
387 1.1 mrg
388 1.1 mrg pragma(printf) final void deprecation(const ref Loc loc, const(char)* format, ...)
389 1.1 mrg {
390 1.1 mrg va_list ap;
391 1.1 mrg va_start(ap, format);
392 1.1 mrg .vdeprecation(loc, format, ap, kind(), prettyFormatHelper().ptr);
393 1.1 mrg va_end(ap);
394 1.1 mrg }
395 1.1 mrg
396 1.1 mrg pragma(printf) final void deprecation(const(char)* format, ...)
397 1.1 mrg {
398 1.1 mrg va_list ap;
399 1.1 mrg va_start(ap, format);
400 1.1 mrg const loc = getLoc();
401 1.1 mrg .vdeprecation(loc, format, ap, kind(), prettyFormatHelper().ptr);
402 1.1 mrg va_end(ap);
403 1.1 mrg }
404 1.1 mrg }
405 1.1 mrg
406 1.1 mrg final bool checkDeprecated(const ref Loc loc, Scope* sc)
407 1.1 mrg {
408 1.1 mrg if (global.params.useDeprecated == DiagnosticReporting.off)
409 1.1 mrg return false;
410 1.1 mrg if (!this.isDeprecated())
411 1.1 mrg return false;
412 1.1 mrg // Don't complain if we're inside a deprecated symbol's scope
413 1.1 mrg if (sc.isDeprecated())
414 1.1 mrg return false;
415 1.1 mrg // Don't complain if we're inside a template constraint
416 1.1 mrg // https://issues.dlang.org/show_bug.cgi?id=21831
417 1.1 mrg if (sc.flags & SCOPE.constraint)
418 1.1 mrg return false;
419 1.1 mrg
420 1.1 mrg const(char)* message = null;
421 1.1 mrg for (Dsymbol p = this; p; p = p.parent)
422 1.1 mrg {
423 1.1 mrg message = p.depdecl ? p.depdecl.getMessage() : null;
424 1.1 mrg if (message)
425 1.1 mrg break;
426 1.1 mrg }
427 1.1 mrg if (message)
428 1.1 mrg deprecation(loc, "is deprecated - %s", message);
429 1.1 mrg else
430 1.1 mrg deprecation(loc, "is deprecated");
431 1.1 mrg
432 1.1 mrg if (auto ti = sc.parent ? sc.parent.isInstantiated() : null)
433 1.1 mrg ti.printInstantiationTrace(Classification.deprecation);
434 1.1 mrg else if (auto ti = sc.parent ? sc.parent.isTemplateInstance() : null)
435 1.1 mrg ti.printInstantiationTrace(Classification.deprecation);
436 1.1 mrg
437 1.1 mrg return true;
438 1.1 mrg }
439 1.1 mrg
440 1.1 mrg /**********************************
441 1.1 mrg * Determine which Module a Dsymbol is in.
442 1.1 mrg */
443 1.1 mrg final Module getModule()
444 1.1 mrg {
445 1.1 mrg //printf("Dsymbol::getModule()\n");
446 1.1 mrg if (TemplateInstance ti = isInstantiated())
447 1.1 mrg return ti.tempdecl.getModule();
448 1.1 mrg Dsymbol s = this;
449 1.1 mrg while (s)
450 1.1 mrg {
451 1.1 mrg //printf("\ts = %s '%s'\n", s.kind(), s.toPrettyChars());
452 1.1 mrg Module m = s.isModule();
453 1.1 mrg if (m)
454 1.1 mrg return m;
455 1.1 mrg s = s.parent;
456 1.1 mrg }
457 1.1 mrg return null;
458 1.1 mrg }
459 1.1 mrg
460 1.1 mrg /**************************************
461 1.1 mrg * Does this Dsymbol come from a C file?
462 1.1 mrg * Returns:
463 1.1 mrg * true if it does
464 1.1 mrg */
465 1.1 mrg final bool isCsymbol()
466 1.1 mrg {
467 1.1 mrg if (Module m = getModule())
468 1.1 mrg return m.filetype == FileType.c;
469 1.1 mrg return false;
470 1.1 mrg }
471 1.1 mrg
472 1.1 mrg /**********************************
473 1.1 mrg * Determine which Module a Dsymbol is in, as far as access rights go.
474 1.1 mrg */
475 1.1 mrg final Module getAccessModule()
476 1.1 mrg {
477 1.1 mrg //printf("Dsymbol::getAccessModule()\n");
478 1.1 mrg if (TemplateInstance ti = isInstantiated())
479 1.1 mrg return ti.tempdecl.getAccessModule();
480 1.1 mrg Dsymbol s = this;
481 1.1 mrg while (s)
482 1.1 mrg {
483 1.1 mrg //printf("\ts = %s '%s'\n", s.kind(), s.toPrettyChars());
484 1.1 mrg Module m = s.isModule();
485 1.1 mrg if (m)
486 1.1 mrg return m;
487 1.1 mrg TemplateInstance ti = s.isTemplateInstance();
488 1.1 mrg if (ti && ti.enclosing)
489 1.1 mrg {
490 1.1 mrg /* Because of local template instantiation, the parent isn't where the access
491 1.1 mrg * rights come from - it's the template declaration
492 1.1 mrg */
493 1.1 mrg s = ti.tempdecl;
494 1.1 mrg }
495 1.1 mrg else
496 1.1 mrg s = s.parent;
497 1.1 mrg }
498 1.1 mrg return null;
499 1.1 mrg }
500 1.1 mrg
501 1.1 mrg /**
502 1.1 mrg * `pastMixin` returns the enclosing symbol if this is a template mixin.
503 1.1 mrg *
504 1.1 mrg * `pastMixinAndNspace` does likewise, additionally skipping over Nspaces that
505 1.1 mrg * are mangleOnly.
506 1.1 mrg *
507 1.1 mrg * See also `parent`, `toParent` and `toParent2`.
508 1.1 mrg */
509 1.1 mrg final inout(Dsymbol) pastMixin() inout
510 1.1 mrg {
511 1.1 mrg //printf("Dsymbol::pastMixin() %s\n", toChars());
512 1.1 mrg if (!isTemplateMixin() && !isForwardingAttribDeclaration() && !isForwardingScopeDsymbol())
513 1.1 mrg return this;
514 1.1 mrg if (!parent)
515 1.1 mrg return null;
516 1.1 mrg return parent.pastMixin();
517 1.1 mrg }
518 1.1 mrg
519 1.1 mrg /**********************************
520 1.1 mrg * `parent` field returns a lexically enclosing scope symbol this is a member of.
521 1.1 mrg *
522 1.1 mrg * `toParent()` returns a logically enclosing scope symbol this is a member of.
523 1.1 mrg * It skips over TemplateMixin's.
524 1.1 mrg *
525 1.1 mrg * `toParent2()` returns an enclosing scope symbol this is living at runtime.
526 1.1 mrg * It skips over both TemplateInstance's and TemplateMixin's.
527 1.1 mrg * It's used when looking for the 'this' pointer of the enclosing function/class.
528 1.1 mrg *
529 1.1 mrg * `toParentDecl()` similar to `toParent2()` but always follows the template declaration scope
530 1.1 mrg * instead of the instantiation scope.
531 1.1 mrg *
532 1.1 mrg * `toParentLocal()` similar to `toParentDecl()` but follows the instantiation scope
533 1.1 mrg * if a template declaration is non-local i.e. global or static.
534 1.1 mrg *
535 1.1 mrg * Examples:
536 1.1 mrg * ---
537 1.1 mrg * module mod;
538 1.1 mrg * template Foo(alias a) { mixin Bar!(); }
539 1.1 mrg * mixin template Bar() {
540 1.1 mrg * public { // VisibilityDeclaration
541 1.1 mrg * void baz() { a = 2; }
542 1.1 mrg * }
543 1.1 mrg * }
544 1.1 mrg * void test() {
545 1.1 mrg * int v = 1;
546 1.1 mrg * alias foo = Foo!(v);
547 1.1 mrg * foo.baz();
548 1.1 mrg * assert(v == 2);
549 1.1 mrg * }
550 1.1 mrg *
551 1.1 mrg * // s == FuncDeclaration('mod.test.Foo!().Bar!().baz()')
552 1.1 mrg * // s.parent == TemplateMixin('mod.test.Foo!().Bar!()')
553 1.1 mrg * // s.toParent() == TemplateInstance('mod.test.Foo!()')
554 1.1 mrg * // s.toParent2() == FuncDeclaration('mod.test')
555 1.1 mrg * // s.toParentDecl() == Module('mod')
556 1.1 mrg * // s.toParentLocal() == FuncDeclaration('mod.test')
557 1.1 mrg * ---
558 1.1 mrg */
559 1.1 mrg final inout(Dsymbol) toParent() inout
560 1.1 mrg {
561 1.1 mrg return parent ? parent.pastMixin() : null;
562 1.1 mrg }
563 1.1 mrg
564 1.1 mrg /// ditto
565 1.1 mrg final inout(Dsymbol) toParent2() inout
566 1.1 mrg {
567 1.1 mrg if (!parent || !parent.isTemplateInstance && !parent.isForwardingAttribDeclaration() && !parent.isForwardingScopeDsymbol())
568 1.1 mrg return parent;
569 1.1 mrg return parent.toParent2;
570 1.1 mrg }
571 1.1 mrg
572 1.1 mrg /// ditto
573 1.1 mrg final inout(Dsymbol) toParentDecl() inout
574 1.1 mrg {
575 1.1 mrg return toParentDeclImpl(false);
576 1.1 mrg }
577 1.1 mrg
578 1.1 mrg /// ditto
579 1.1 mrg final inout(Dsymbol) toParentLocal() inout
580 1.1 mrg {
581 1.1 mrg return toParentDeclImpl(true);
582 1.1 mrg }
583 1.1 mrg
584 1.1 mrg private inout(Dsymbol) toParentDeclImpl(bool localOnly) inout
585 1.1 mrg {
586 1.1 mrg auto p = toParent();
587 1.1 mrg if (!p || !p.isTemplateInstance())
588 1.1 mrg return p;
589 1.1 mrg auto ti = p.isTemplateInstance();
590 1.1 mrg if (ti.tempdecl && (!localOnly || !(cast(TemplateDeclaration)ti.tempdecl).isstatic))
591 1.1 mrg return ti.tempdecl.toParentDeclImpl(localOnly);
592 1.1 mrg return parent.toParentDeclImpl(localOnly);
593 1.1 mrg }
594 1.1 mrg
595 1.1 mrg /**
596 1.1 mrg * Returns the declaration scope scope of `this` unless any of the symbols
597 1.1 mrg * `p1` or `p2` resides in its enclosing instantiation scope then the
598 1.1 mrg * latter is returned.
599 1.1 mrg */
600 1.1 mrg final Dsymbol toParentP(Dsymbol p1, Dsymbol p2 = null)
601 1.1 mrg {
602 1.1 mrg return followInstantiationContext(p1, p2) ? toParent2() : toParentLocal();
603 1.1 mrg }
604 1.1 mrg
605 1.1 mrg final inout(TemplateInstance) isInstantiated() inout
606 1.1 mrg {
607 1.1 mrg if (!parent)
608 1.1 mrg return null;
609 1.1 mrg auto ti = parent.isTemplateInstance();
610 1.1 mrg if (ti && !ti.isTemplateMixin())
611 1.1 mrg return ti;
612 1.1 mrg return parent.isInstantiated();
613 1.1 mrg }
614 1.1 mrg
615 1.1 mrg /***
616 1.1 mrg * Returns true if any of the symbols `p1` or `p2` resides in the enclosing
617 1.1 mrg * instantiation scope of `this`.
618 1.1 mrg */
619 1.1 mrg final bool followInstantiationContext(Dsymbol p1, Dsymbol p2 = null)
620 1.1 mrg {
621 1.1 mrg static bool has2This(Dsymbol s)
622 1.1 mrg {
623 1.1 mrg if (auto f = s.isFuncDeclaration())
624 1.1 mrg return f.hasDualContext();
625 1.1 mrg if (auto ad = s.isAggregateDeclaration())
626 1.1 mrg return ad.vthis2 !is null;
627 1.1 mrg return false;
628 1.1 mrg }
629 1.1 mrg
630 1.1 mrg if (has2This(this))
631 1.1 mrg {
632 1.1 mrg assert(p1);
633 1.1 mrg auto outer = toParent();
634 1.1 mrg while (outer)
635 1.1 mrg {
636 1.1 mrg auto ti = outer.isTemplateInstance();
637 1.1 mrg if (!ti)
638 1.1 mrg break;
639 1.1 mrg foreach (oarg; *ti.tiargs)
640 1.1 mrg {
641 1.1 mrg auto sa = getDsymbol(oarg);
642 1.1 mrg if (!sa)
643 1.1 mrg continue;
644 1.1 mrg sa = sa.toAlias().toParent2();
645 1.1 mrg if (!sa)
646 1.1 mrg continue;
647 1.1 mrg if (sa == p1)
648 1.1 mrg return true;
649 1.1 mrg else if (p2 && sa == p2)
650 1.1 mrg return true;
651 1.1 mrg }
652 1.1 mrg outer = ti.tempdecl.toParent();
653 1.1 mrg }
654 1.1 mrg return false;
655 1.1 mrg }
656 1.1 mrg return false;
657 1.1 mrg }
658 1.1 mrg
659 1.1 mrg // Check if this function is a member of a template which has only been
660 1.1 mrg // instantiated speculatively, eg from inside is(typeof()).
661 1.1 mrg // Return the speculative template instance it is part of,
662 1.1 mrg // or NULL if not speculative.
663 1.1 mrg final inout(TemplateInstance) isSpeculative() inout
664 1.1 mrg {
665 1.1 mrg if (!parent)
666 1.1 mrg return null;
667 1.1 mrg auto ti = parent.isTemplateInstance();
668 1.1 mrg if (ti && ti.gagged)
669 1.1 mrg return ti;
670 1.1 mrg if (!parent.toParent())
671 1.1 mrg return null;
672 1.1 mrg return parent.isSpeculative();
673 1.1 mrg }
674 1.1 mrg
675 1.1 mrg final Ungag ungagSpeculative() const
676 1.1 mrg {
677 1.1 mrg uint oldgag = global.gag;
678 1.1 mrg if (global.gag && !isSpeculative() && !toParent2().isFuncDeclaration())
679 1.1 mrg global.gag = 0;
680 1.1 mrg return Ungag(oldgag);
681 1.1 mrg }
682 1.1 mrg
683 1.1 mrg // kludge for template.isSymbol()
684 1.1 mrg override final DYNCAST dyncast() const
685 1.1 mrg {
686 1.1 mrg return DYNCAST.dsymbol;
687 1.1 mrg }
688 1.1 mrg
689 1.1 mrg /*************************************
690 1.1 mrg * Do syntax copy of an array of Dsymbol's.
691 1.1 mrg */
692 1.1 mrg extern (D) static Dsymbols* arraySyntaxCopy(Dsymbols* a)
693 1.1 mrg {
694 1.1 mrg Dsymbols* b = null;
695 1.1 mrg if (a)
696 1.1 mrg {
697 1.1 mrg b = a.copy();
698 1.1 mrg for (size_t i = 0; i < b.dim; i++)
699 1.1 mrg {
700 1.1 mrg (*b)[i] = (*b)[i].syntaxCopy(null);
701 1.1 mrg }
702 1.1 mrg }
703 1.1 mrg return b;
704 1.1 mrg }
705 1.1 mrg
706 1.1 mrg Identifier getIdent()
707 1.1 mrg {
708 1.1 mrg return ident;
709 1.1 mrg }
710 1.1 mrg
711 1.1 mrg const(char)* toPrettyChars(bool QualifyTypes = false)
712 1.1 mrg {
713 1.1 mrg if (prettystring && !QualifyTypes)
714 1.1 mrg return prettystring;
715 1.1 mrg
716 1.1 mrg //printf("Dsymbol::toPrettyChars() '%s'\n", toChars());
717 1.1 mrg if (!parent)
718 1.1 mrg {
719 1.1 mrg auto s = toChars();
720 1.1 mrg if (!QualifyTypes)
721 1.1 mrg prettystring = s;
722 1.1 mrg return s;
723 1.1 mrg }
724 1.1 mrg
725 1.1 mrg // Computer number of components
726 1.1 mrg size_t complength = 0;
727 1.1 mrg for (Dsymbol p = this; p; p = p.parent)
728 1.1 mrg ++complength;
729 1.1 mrg
730 1.1 mrg // Allocate temporary array comp[]
731 1.1 mrg alias T = const(char)[];
732 1.1 mrg auto compptr = cast(T*)Mem.check(malloc(complength * T.sizeof));
733 1.1 mrg auto comp = compptr[0 .. complength];
734 1.1 mrg
735 1.1 mrg // Fill in comp[] and compute length of final result
736 1.1 mrg size_t length = 0;
737 1.1 mrg int i;
738 1.1 mrg for (Dsymbol p = this; p; p = p.parent)
739 1.1 mrg {
740 1.1 mrg const s = QualifyTypes ? p.toPrettyCharsHelper() : p.toChars();
741 1.1 mrg const len = strlen(s);
742 1.1 mrg comp[i] = s[0 .. len];
743 1.1 mrg ++i;
744 1.1 mrg length += len + 1;
745 1.1 mrg }
746 1.1 mrg
747 1.1 mrg auto s = cast(char*)mem.xmalloc_noscan(length);
748 1.1 mrg auto q = s + length - 1;
749 1.1 mrg *q = 0;
750 1.1 mrg foreach (j; 0 .. complength)
751 1.1 mrg {
752 1.1 mrg const t = comp[j].ptr;
753 1.1 mrg const len = comp[j].length;
754 1.1 mrg q -= len;
755 1.1 mrg memcpy(q, t, len);
756 1.1 mrg if (q == s)
757 1.1 mrg break;
758 1.1 mrg *--q = '.';
759 1.1 mrg }
760 1.1 mrg free(comp.ptr);
761 1.1 mrg if (!QualifyTypes)
762 1.1 mrg prettystring = s;
763 1.1 mrg return s;
764 1.1 mrg }
765 1.1 mrg
766 1.1 mrg const(char)* kind() const pure nothrow @nogc @safe
767 1.1 mrg {
768 1.1 mrg return "symbol";
769 1.1 mrg }
770 1.1 mrg
771 1.1 mrg /*********************************
772 1.1 mrg * If this symbol is really an alias for another,
773 1.1 mrg * return that other.
774 1.1 mrg * If needed, semantic() is invoked due to resolve forward reference.
775 1.1 mrg */
776 1.1 mrg Dsymbol toAlias()
777 1.1 mrg {
778 1.1 mrg return this;
779 1.1 mrg }
780 1.1 mrg
781 1.1 mrg /*********************************
782 1.1 mrg * Resolve recursive tuple expansion in eponymous template.
783 1.1 mrg */
784 1.1 mrg Dsymbol toAlias2()
785 1.1 mrg {
786 1.1 mrg return toAlias();
787 1.1 mrg }
788 1.1 mrg
789 1.1 mrg void addMember(Scope* sc, ScopeDsymbol sds)
790 1.1 mrg {
791 1.1 mrg //printf("Dsymbol::addMember('%s')\n", toChars());
792 1.1 mrg //printf("Dsymbol::addMember(this = %p, '%s' scopesym = '%s')\n", this, toChars(), sds.toChars());
793 1.1 mrg //printf("Dsymbol::addMember(this = %p, '%s' sds = %p, sds.symtab = %p)\n", this, toChars(), sds, sds.symtab);
794 1.1 mrg parent = sds;
795 1.1 mrg if (isAnonymous()) // no name, so can't add it to symbol table
796 1.1 mrg return;
797 1.1 mrg
798 1.1 mrg if (!sds.symtabInsert(this)) // if name is already defined
799 1.1 mrg {
800 1.1 mrg if (isAliasDeclaration() && !_scope)
801 1.1 mrg setScope(sc);
802 1.1 mrg Dsymbol s2 = sds.symtabLookup(this,ident);
803 1.1 mrg /* https://issues.dlang.org/show_bug.cgi?id=17434
804 1.1 mrg *
805 1.1 mrg * If we are trying to add an import to the symbol table
806 1.1 mrg * that has already been introduced, then keep the one with
807 1.1 mrg * larger visibility. This is fine for imports because if
808 1.1 mrg * we have multiple imports of the same file, if a single one
809 1.1 mrg * is public then the symbol is reachable.
810 1.1 mrg */
811 1.1 mrg if (auto i1 = isImport())
812 1.1 mrg {
813 1.1 mrg if (auto i2 = s2.isImport())
814 1.1 mrg {
815 1.1 mrg if (sc.explicitVisibility && sc.visibility > i2.visibility)
816 1.1 mrg sds.symtab.update(this);
817 1.1 mrg }
818 1.1 mrg }
819 1.1 mrg
820 1.1 mrg // If using C tag/prototype/forward declaration rules
821 1.1 mrg if (sc.flags & SCOPE.Cfile && !this.isImport())
822 1.1 mrg {
823 1.1 mrg if (handleTagSymbols(*sc, this, s2, sds))
824 1.1 mrg return;
825 1.1 mrg if (handleSymbolRedeclarations(*sc, this, s2, sds))
826 1.1 mrg return;
827 1.1 mrg
828 1.1 mrg sds.multiplyDefined(Loc.initial, this, s2); // ImportC doesn't allow overloading
829 1.1 mrg errors = true;
830 1.1 mrg return;
831 1.1 mrg }
832 1.1 mrg
833 1.1 mrg if (!s2.overloadInsert(this))
834 1.1 mrg {
835 1.1 mrg sds.multiplyDefined(Loc.initial, this, s2);
836 1.1 mrg errors = true;
837 1.1 mrg }
838 1.1 mrg }
839 1.1 mrg if (sds.isAggregateDeclaration() || sds.isEnumDeclaration())
840 1.1 mrg {
841 1.1 mrg if (ident == Id.__sizeof ||
842 1.1 mrg !(sc && sc.flags & SCOPE.Cfile) && (ident == Id.__xalignof || ident == Id._mangleof))
843 1.1 mrg {
844 1.1 mrg error("`.%s` property cannot be redefined", ident.toChars());
845 1.1 mrg errors = true;
846 1.1 mrg }
847 1.1 mrg }
848 1.1 mrg }
849 1.1 mrg
850 1.1 mrg /*************************************
851 1.1 mrg * Set scope for future semantic analysis so we can
852 1.1 mrg * deal better with forward references.
853 1.1 mrg */
854 1.1 mrg void setScope(Scope* sc)
855 1.1 mrg {
856 1.1 mrg //printf("Dsymbol::setScope() %p %s, %p stc = %llx\n", this, toChars(), sc, sc.stc);
857 1.1 mrg if (!sc.nofree)
858 1.1 mrg sc.setNoFree(); // may need it even after semantic() finishes
859 1.1 mrg _scope = sc;
860 1.1 mrg if (sc.depdecl)
861 1.1 mrg depdecl = sc.depdecl;
862 1.1 mrg if (!userAttribDecl)
863 1.1 mrg userAttribDecl = sc.userAttribDecl;
864 1.1 mrg }
865 1.1 mrg
866 1.1 mrg void importAll(Scope* sc)
867 1.1 mrg {
868 1.1 mrg }
869 1.1 mrg
870 1.1 mrg /*********************************************
871 1.1 mrg * Search for ident as member of s.
872 1.1 mrg * Params:
873 1.1 mrg * loc = location to print for error messages
874 1.1 mrg * ident = identifier to search for
875 1.1 mrg * flags = IgnoreXXXX
876 1.1 mrg * Returns:
877 1.1 mrg * null if not found
878 1.1 mrg */
879 1.1 mrg Dsymbol search(const ref Loc loc, Identifier ident, int flags = IgnoreNone)
880 1.1 mrg {
881 1.1 mrg //printf("Dsymbol::search(this=%p,%s, ident='%s')\n", this, toChars(), ident.toChars());
882 1.1 mrg return null;
883 1.1 mrg }
884 1.1 mrg
885 1.1 mrg extern (D) final Dsymbol search_correct(Identifier ident)
886 1.1 mrg {
887 1.1 mrg /***************************************************
888 1.1 mrg * Search for symbol with correct spelling.
889 1.1 mrg */
890 1.1 mrg extern (D) Dsymbol symbol_search_fp(const(char)[] seed, out int cost)
891 1.1 mrg {
892 1.1 mrg /* If not in the lexer's string table, it certainly isn't in the symbol table.
893 1.1 mrg * Doing this first is a lot faster.
894 1.1 mrg */
895 1.1 mrg if (!seed.length)
896 1.1 mrg return null;
897 1.1 mrg Identifier id = Identifier.lookup(seed);
898 1.1 mrg if (!id)
899 1.1 mrg return null;
900 1.1 mrg cost = 0; // all the same cost
901 1.1 mrg Dsymbol s = this;
902 1.1 mrg Module.clearCache();
903 1.1 mrg return s.search(Loc.initial, id, IgnoreErrors);
904 1.1 mrg }
905 1.1 mrg
906 1.1 mrg if (global.gag)
907 1.1 mrg return null; // don't do it for speculative compiles; too time consuming
908 1.1 mrg // search for exact name first
909 1.1 mrg if (auto s = search(Loc.initial, ident, IgnoreErrors))
910 1.1 mrg return s;
911 1.1 mrg return speller!symbol_search_fp(ident.toString());
912 1.1 mrg }
913 1.1 mrg
914 1.1 mrg /***************************************
915 1.1 mrg * Search for identifier id as a member of `this`.
916 1.1 mrg * `id` may be a template instance.
917 1.1 mrg *
918 1.1 mrg * Params:
919 1.1 mrg * loc = location to print the error messages
920 1.1 mrg * sc = the scope where the symbol is located
921 1.1 mrg * id = the id of the symbol
922 1.1 mrg * flags = the search flags which can be `SearchLocalsOnly` or `IgnorePrivateImports`
923 1.1 mrg *
924 1.1 mrg * Returns:
925 1.1 mrg * symbol found, NULL if not
926 1.1 mrg */
927 1.1 mrg extern (D) final Dsymbol searchX(const ref Loc loc, Scope* sc, RootObject id, int flags)
928 1.1 mrg {
929 1.1 mrg //printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident.toChars());
930 1.1 mrg Dsymbol s = toAlias();
931 1.1 mrg Dsymbol sm;
932 1.1 mrg if (Declaration d = s.isDeclaration())
933 1.1 mrg {
934 1.1 mrg if (d.inuse)
935 1.1 mrg {
936 1.1 mrg .error(loc, "circular reference to `%s`", d.toPrettyChars());
937 1.1 mrg return null;
938 1.1 mrg }
939 1.1 mrg }
940 1.1 mrg switch (id.dyncast())
941 1.1 mrg {
942 1.1 mrg case DYNCAST.identifier:
943 1.1 mrg sm = s.search(loc, cast(Identifier)id, flags);
944 1.1 mrg break;
945 1.1 mrg case DYNCAST.dsymbol:
946 1.1 mrg {
947 1.1 mrg // It's a template instance
948 1.1 mrg //printf("\ttemplate instance id\n");
949 1.1 mrg Dsymbol st = cast(Dsymbol)id;
950 1.1 mrg TemplateInstance ti = st.isTemplateInstance();
951 1.1 mrg sm = s.search(loc, ti.name);
952 1.1 mrg if (!sm)
953 1.1 mrg return null;
954 1.1 mrg sm = sm.toAlias();
955 1.1 mrg TemplateDeclaration td = sm.isTemplateDeclaration();
956 1.1 mrg if (!td)
957 1.1 mrg {
958 1.1 mrg .error(loc, "`%s.%s` is not a template, it is a %s", s.toPrettyChars(), ti.name.toChars(), sm.kind());
959 1.1 mrg return null;
960 1.1 mrg }
961 1.1 mrg ti.tempdecl = td;
962 1.1 mrg if (!ti.semanticRun)
963 1.1 mrg ti.dsymbolSemantic(sc);
964 1.1 mrg sm = ti.toAlias();
965 1.1 mrg break;
966 1.1 mrg }
967 1.1 mrg case DYNCAST.type:
968 1.1 mrg case DYNCAST.expression:
969 1.1 mrg default:
970 1.1 mrg assert(0);
971 1.1 mrg }
972 1.1 mrg return sm;
973 1.1 mrg }
974 1.1 mrg
975 1.1 mrg bool overloadInsert(Dsymbol s)
976 1.1 mrg {
977 1.1 mrg //printf("Dsymbol::overloadInsert('%s')\n", s.toChars());
978 1.1 mrg return false;
979 1.1 mrg }
980 1.1 mrg
981 1.1 mrg /*********************************
982 1.1 mrg * Returns:
983 1.1 mrg * SIZE_INVALID when the size cannot be determined
984 1.1 mrg */
985 1.1 mrg uinteger_t size(const ref Loc loc)
986 1.1 mrg {
987 1.1 mrg error("Dsymbol `%s` has no size", toChars());
988 1.1 mrg return SIZE_INVALID;
989 1.1 mrg }
990 1.1 mrg
991 1.1 mrg bool isforwardRef()
992 1.1 mrg {
993 1.1 mrg return false;
994 1.1 mrg }
995 1.1 mrg
996 1.1 mrg // is a 'this' required to access the member
997 1.1 mrg inout(AggregateDeclaration) isThis() inout
998 1.1 mrg {
999 1.1 mrg return null;
1000 1.1 mrg }
1001 1.1 mrg
1002 1.1 mrg // is Dsymbol exported?
1003 1.1 mrg bool isExport() const
1004 1.1 mrg {
1005 1.1 mrg return false;
1006 1.1 mrg }
1007 1.1 mrg
1008 1.1 mrg // is Dsymbol imported?
1009 1.1 mrg bool isImportedSymbol() const
1010 1.1 mrg {
1011 1.1 mrg return false;
1012 1.1 mrg }
1013 1.1 mrg
1014 1.1 mrg // is Dsymbol deprecated?
1015 1.1 mrg bool isDeprecated() @safe @nogc pure nothrow const
1016 1.1 mrg {
1017 1.1 mrg return false;
1018 1.1 mrg }
1019 1.1 mrg
1020 1.1 mrg bool isOverloadable() const
1021 1.1 mrg {
1022 1.1 mrg return false;
1023 1.1 mrg }
1024 1.1 mrg
1025 1.1 mrg // is this a LabelDsymbol()?
1026 1.1 mrg LabelDsymbol isLabel()
1027 1.1 mrg {
1028 1.1 mrg return null;
1029 1.1 mrg }
1030 1.1 mrg
1031 1.1 mrg /// Returns an AggregateDeclaration when toParent() is that.
1032 1.1 mrg final inout(AggregateDeclaration) isMember() inout
1033 1.1 mrg {
1034 1.1 mrg //printf("Dsymbol::isMember() %s\n", toChars());
1035 1.1 mrg auto p = toParent();
1036 1.1 mrg //printf("parent is %s %s\n", p.kind(), p.toChars());
1037 1.1 mrg return p ? p.isAggregateDeclaration() : null;
1038 1.1 mrg }
1039 1.1 mrg
1040 1.1 mrg /// Returns an AggregateDeclaration when toParent2() is that.
1041 1.1 mrg final inout(AggregateDeclaration) isMember2() inout
1042 1.1 mrg {
1043 1.1 mrg //printf("Dsymbol::isMember2() '%s'\n", toChars());
1044 1.1 mrg auto p = toParent2();
1045 1.1 mrg //printf("parent is %s %s\n", p.kind(), p.toChars());
1046 1.1 mrg return p ? p.isAggregateDeclaration() : null;
1047 1.1 mrg }
1048 1.1 mrg
1049 1.1 mrg /// Returns an AggregateDeclaration when toParentDecl() is that.
1050 1.1 mrg final inout(AggregateDeclaration) isMemberDecl() inout
1051 1.1 mrg {
1052 1.1 mrg //printf("Dsymbol::isMemberDecl() '%s'\n", toChars());
1053 1.1 mrg auto p = toParentDecl();
1054 1.1 mrg //printf("parent is %s %s\n", p.kind(), p.toChars());
1055 1.1 mrg return p ? p.isAggregateDeclaration() : null;
1056 1.1 mrg }
1057 1.1 mrg
1058 1.1 mrg /// Returns an AggregateDeclaration when toParentLocal() is that.
1059 1.1 mrg final inout(AggregateDeclaration) isMemberLocal() inout
1060 1.1 mrg {
1061 1.1 mrg //printf("Dsymbol::isMemberLocal() '%s'\n", toChars());
1062 1.1 mrg auto p = toParentLocal();
1063 1.1 mrg //printf("parent is %s %s\n", p.kind(), p.toChars());
1064 1.1 mrg return p ? p.isAggregateDeclaration() : null;
1065 1.1 mrg }
1066 1.1 mrg
1067 1.1 mrg // is this a member of a ClassDeclaration?
1068 1.1 mrg final ClassDeclaration isClassMember()
1069 1.1 mrg {
1070 1.1 mrg auto ad = isMember();
1071 1.1 mrg return ad ? ad.isClassDeclaration() : null;
1072 1.1 mrg }
1073 1.1 mrg
1074 1.1 mrg // is this a type?
1075 1.1 mrg Type getType()
1076 1.1 mrg {
1077 1.1 mrg return null;
1078 1.1 mrg }
1079 1.1 mrg
1080 1.1 mrg // need a 'this' pointer?
1081 1.1 mrg bool needThis()
1082 1.1 mrg {
1083 1.1 mrg return false;
1084 1.1 mrg }
1085 1.1 mrg
1086 1.1 mrg /*************************************
1087 1.1 mrg */
1088 1.1 mrg Visibility visible() pure nothrow @nogc @safe
1089 1.1 mrg {
1090 1.1 mrg return Visibility(Visibility.Kind.public_);
1091 1.1 mrg }
1092 1.1 mrg
1093 1.1 mrg /**************************************
1094 1.1 mrg * Copy the syntax.
1095 1.1 mrg * Used for template instantiations.
1096 1.1 mrg * If s is NULL, allocate the new object, otherwise fill it in.
1097 1.1 mrg */
1098 1.1 mrg Dsymbol syntaxCopy(Dsymbol s)
1099 1.1 mrg {
1100 1.1 mrg printf("%s %s\n", kind(), toChars());
1101 1.1 mrg assert(0);
1102 1.1 mrg }
1103 1.1 mrg
1104 1.1 mrg /**************************************
1105 1.1 mrg * Determine if this symbol is only one.
1106 1.1 mrg * Returns:
1107 1.1 mrg * false, *ps = NULL: There are 2 or more symbols
1108 1.1 mrg * true, *ps = NULL: There are zero symbols
1109 1.1 mrg * true, *ps = symbol: The one and only one symbol
1110 1.1 mrg */
1111 1.1 mrg bool oneMember(Dsymbol* ps, Identifier ident)
1112 1.1 mrg {
1113 1.1 mrg //printf("Dsymbol::oneMember()\n");
1114 1.1 mrg *ps = this;
1115 1.1 mrg return true;
1116 1.1 mrg }
1117 1.1 mrg
1118 1.1 mrg /*****************************************
1119 1.1 mrg * Same as Dsymbol::oneMember(), but look at an array of Dsymbols.
1120 1.1 mrg */
1121 1.1 mrg extern (D) static bool oneMembers(Dsymbols* members, Dsymbol* ps, Identifier ident)
1122 1.1 mrg {
1123 1.1 mrg //printf("Dsymbol::oneMembers() %d\n", members ? members.dim : 0);
1124 1.1 mrg Dsymbol s = null;
1125 1.1 mrg if (!members)
1126 1.1 mrg {
1127 1.1 mrg *ps = null;
1128 1.1 mrg return true;
1129 1.1 mrg }
1130 1.1 mrg
1131 1.1 mrg for (size_t i = 0; i < members.dim; i++)
1132 1.1 mrg {
1133 1.1 mrg Dsymbol sx = (*members)[i];
1134 1.1 mrg bool x = sx.oneMember(ps, ident);
1135 1.1 mrg //printf("\t[%d] kind %s = %d, s = %p\n", i, sx.kind(), x, *ps);
1136 1.1 mrg if (!x)
1137 1.1 mrg {
1138 1.1 mrg //printf("\tfalse 1\n");
1139 1.1 mrg assert(*ps is null);
1140 1.1 mrg return false;
1141 1.1 mrg }
1142 1.1 mrg if (*ps)
1143 1.1 mrg {
1144 1.1 mrg assert(ident);
1145 1.1 mrg if (!(*ps).ident || !(*ps).ident.equals(ident))
1146 1.1 mrg continue;
1147 1.1 mrg if (!s)
1148 1.1 mrg s = *ps;
1149 1.1 mrg else if (s.isOverloadable() && (*ps).isOverloadable())
1150 1.1 mrg {
1151 1.1 mrg // keep head of overload set
1152 1.1 mrg FuncDeclaration f1 = s.isFuncDeclaration();
1153 1.1 mrg FuncDeclaration f2 = (*ps).isFuncDeclaration();
1154 1.1 mrg if (f1 && f2)
1155 1.1 mrg {
1156 1.1 mrg assert(!f1.isFuncAliasDeclaration());
1157 1.1 mrg assert(!f2.isFuncAliasDeclaration());
1158 1.1 mrg for (; f1 != f2; f1 = f1.overnext0)
1159 1.1 mrg {
1160 1.1 mrg if (f1.overnext0 is null)
1161 1.1 mrg {
1162 1.1 mrg f1.overnext0 = f2;
1163 1.1 mrg break;
1164 1.1 mrg }
1165 1.1 mrg }
1166 1.1 mrg }
1167 1.1 mrg }
1168 1.1 mrg else // more than one symbol
1169 1.1 mrg {
1170 1.1 mrg *ps = null;
1171 1.1 mrg //printf("\tfalse 2\n");
1172 1.1 mrg return false;
1173 1.1 mrg }
1174 1.1 mrg }
1175 1.1 mrg }
1176 1.1 mrg *ps = s; // s is the one symbol, null if none
1177 1.1 mrg //printf("\ttrue\n");
1178 1.1 mrg return true;
1179 1.1 mrg }
1180 1.1 mrg
1181 1.1 mrg void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion)
1182 1.1 mrg {
1183 1.1 mrg }
1184 1.1 mrg
1185 1.1 mrg /*****************************************
1186 1.1 mrg * Is Dsymbol a variable that contains pointers?
1187 1.1 mrg */
1188 1.1 mrg bool hasPointers()
1189 1.1 mrg {
1190 1.1 mrg //printf("Dsymbol::hasPointers() %s\n", toChars());
1191 1.1 mrg return false;
1192 1.1 mrg }
1193 1.1 mrg
1194 1.1 mrg bool hasStaticCtorOrDtor()
1195 1.1 mrg {
1196 1.1 mrg //printf("Dsymbol::hasStaticCtorOrDtor() %s\n", toChars());
1197 1.1 mrg return false;
1198 1.1 mrg }
1199 1.1 mrg
1200 1.1 mrg void addLocalClass(ClassDeclarations*)
1201 1.1 mrg {
1202 1.1 mrg }
1203 1.1 mrg
1204 1.1 mrg void addObjcSymbols(ClassDeclarations* classes, ClassDeclarations* categories)
1205 1.1 mrg {
1206 1.1 mrg }
1207 1.1 mrg
1208 1.1 mrg void checkCtorConstInit()
1209 1.1 mrg {
1210 1.1 mrg }
1211 1.1 mrg
1212 1.1 mrg /****************************************
1213 1.1 mrg * Add documentation comment to Dsymbol.
1214 1.1 mrg * Ignore NULL comments.
1215 1.1 mrg */
1216 1.1 mrg void addComment(const(char)* comment)
1217 1.1 mrg {
1218 1.1 mrg if (!comment || !*comment)
1219 1.1 mrg return;
1220 1.1 mrg
1221 1.1 mrg //printf("addComment '%s' to Dsymbol %p '%s'\n", comment, this, toChars());
1222 1.1 mrg void* h = cast(void*)this; // just the pointer is the key
1223 1.1 mrg auto p = h in commentHashTable;
1224 1.1 mrg if (!p)
1225 1.1 mrg {
1226 1.1 mrg commentHashTable[h] = comment;
1227 1.1 mrg return;
1228 1.1 mrg }
1229 1.1 mrg if (strcmp(*p, comment) != 0)
1230 1.1 mrg {
1231 1.1 mrg // Concatenate the two
1232 1.1 mrg *p = Lexer.combineComments((*p).toDString(), comment.toDString(), true);
1233 1.1 mrg }
1234 1.1 mrg }
1235 1.1 mrg
1236 1.1 mrg /// get documentation comment for this Dsymbol
1237 1.1 mrg final const(char)* comment()
1238 1.1 mrg {
1239 1.1 mrg //printf("getcomment: %p '%s'\n", this, this.toChars());
1240 1.1 mrg if (auto p = cast(void*)this in commentHashTable)
1241 1.1 mrg {
1242 1.1 mrg //printf("comment: '%s'\n", *p);
1243 1.1 mrg return *p;
1244 1.1 mrg }
1245 1.1 mrg return null;
1246 1.1 mrg }
1247 1.1 mrg
1248 1.1 mrg /* Shell around addComment() to avoid disruption for the moment */
1249 1.1 mrg final void comment(const(char)* comment) { addComment(comment); }
1250 1.1 mrg
1251 1.1 mrg private extern (D) __gshared const(char)*[void*] commentHashTable;
1252 1.1 mrg
1253 1.1 mrg
1254 1.1 mrg /**********************************
1255 1.1 mrg * Get ddoc unittest associated with this symbol.
1256 1.1 mrg * (only use this with ddoc)
1257 1.1 mrg * Returns: ddoc unittest, null if none
1258 1.1 mrg */
1259 1.1 mrg final UnitTestDeclaration ddocUnittest()
1260 1.1 mrg {
1261 1.1 mrg if (auto p = cast(void*)this in ddocUnittestHashTable)
1262 1.1 mrg return *p;
1263 1.1 mrg return null;
1264 1.1 mrg }
1265 1.1 mrg
1266 1.1 mrg /**********************************
1267 1.1 mrg * Set ddoc unittest associated with this symbol.
1268 1.1 mrg */
1269 1.1 mrg final void ddocUnittest(UnitTestDeclaration utd)
1270 1.1 mrg {
1271 1.1 mrg ddocUnittestHashTable[cast(void*)this] = utd;
1272 1.1 mrg }
1273 1.1 mrg
1274 1.1 mrg private extern (D) __gshared UnitTestDeclaration[void*] ddocUnittestHashTable;
1275 1.1 mrg
1276 1.1 mrg
1277 1.1 mrg /****************************************
1278 1.1 mrg * Returns true if this symbol is defined in a non-root module without instantiation.
1279 1.1 mrg */
1280 1.1 mrg final bool inNonRoot()
1281 1.1 mrg {
1282 1.1 mrg Dsymbol s = parent;
1283 1.1 mrg for (; s; s = s.toParent())
1284 1.1 mrg {
1285 1.1 mrg if (auto ti = s.isTemplateInstance())
1286 1.1 mrg {
1287 1.1 mrg return false;
1288 1.1 mrg }
1289 1.1 mrg if (auto m = s.isModule())
1290 1.1 mrg {
1291 1.1 mrg if (!m.isRoot())
1292 1.1 mrg return true;
1293 1.1 mrg break;
1294 1.1 mrg }
1295 1.1 mrg }
1296 1.1 mrg return false;
1297 1.1 mrg }
1298 1.1 mrg
1299 1.1 mrg /**
1300 1.1 mrg * Deinitializes the global state of the compiler.
1301 1.1 mrg *
1302 1.1 mrg * This can be used to restore the state set by `_init` to its original
1303 1.1 mrg * state.
1304 1.1 mrg */
1305 1.1 mrg static void deinitialize()
1306 1.1 mrg {
1307 1.1 mrg commentHashTable = commentHashTable.init;
1308 1.1 mrg ddocUnittestHashTable = ddocUnittestHashTable.init;
1309 1.1 mrg }
1310 1.1 mrg
1311 1.1 mrg /************
1312 1.1 mrg */
1313 1.1 mrg override void accept(Visitor v)
1314 1.1 mrg {
1315 1.1 mrg v.visit(this);
1316 1.1 mrg }
1317 1.1 mrg
1318 1.1 mrg pure nothrow @safe @nogc:
1319 1.1 mrg
1320 1.1 mrg // Eliminate need for dynamic_cast
1321 1.1 mrg inout(Package) isPackage() inout { return null; }
1322 1.1 mrg inout(Module) isModule() inout { return null; }
1323 1.1 mrg inout(EnumMember) isEnumMember() inout { return null; }
1324 1.1 mrg inout(TemplateDeclaration) isTemplateDeclaration() inout { return null; }
1325 1.1 mrg inout(TemplateInstance) isTemplateInstance() inout { return null; }
1326 1.1 mrg inout(TemplateMixin) isTemplateMixin() inout { return null; }
1327 1.1 mrg inout(ForwardingAttribDeclaration) isForwardingAttribDeclaration() inout { return null; }
1328 1.1 mrg inout(Nspace) isNspace() inout { return null; }
1329 1.1 mrg inout(Declaration) isDeclaration() inout { return null; }
1330 1.1 mrg inout(StorageClassDeclaration) isStorageClassDeclaration() inout { return null; }
1331 1.1 mrg inout(ExpressionDsymbol) isExpressionDsymbol() inout { return null; }
1332 1.1 mrg inout(AliasAssign) isAliasAssign() inout { return null; }
1333 1.1 mrg inout(ThisDeclaration) isThisDeclaration() inout { return null; }
1334 1.1 mrg inout(BitFieldDeclaration) isBitFieldDeclaration() inout { return null; }
1335 1.1 mrg inout(TypeInfoDeclaration) isTypeInfoDeclaration() inout { return null; }
1336 1.1 mrg inout(TupleDeclaration) isTupleDeclaration() inout { return null; }
1337 1.1 mrg inout(AliasDeclaration) isAliasDeclaration() inout { return null; }
1338 1.1 mrg inout(AggregateDeclaration) isAggregateDeclaration() inout { return null; }
1339 1.1 mrg inout(FuncDeclaration) isFuncDeclaration() inout { return null; }
1340 1.1 mrg inout(FuncAliasDeclaration) isFuncAliasDeclaration() inout { return null; }
1341 1.1 mrg inout(OverDeclaration) isOverDeclaration() inout { return null; }
1342 1.1 mrg inout(FuncLiteralDeclaration) isFuncLiteralDeclaration() inout { return null; }
1343 1.1 mrg inout(CtorDeclaration) isCtorDeclaration() inout { return null; }
1344 1.1 mrg inout(PostBlitDeclaration) isPostBlitDeclaration() inout { return null; }
1345 1.1 mrg inout(DtorDeclaration) isDtorDeclaration() inout { return null; }
1346 1.1 mrg inout(StaticCtorDeclaration) isStaticCtorDeclaration() inout { return null; }
1347 1.1 mrg inout(StaticDtorDeclaration) isStaticDtorDeclaration() inout { return null; }
1348 1.1 mrg inout(SharedStaticCtorDeclaration) isSharedStaticCtorDeclaration() inout { return null; }
1349 1.1 mrg inout(SharedStaticDtorDeclaration) isSharedStaticDtorDeclaration() inout { return null; }
1350 1.1 mrg inout(InvariantDeclaration) isInvariantDeclaration() inout { return null; }
1351 1.1 mrg inout(UnitTestDeclaration) isUnitTestDeclaration() inout { return null; }
1352 1.1 mrg inout(NewDeclaration) isNewDeclaration() inout { return null; }
1353 1.1 mrg inout(VarDeclaration) isVarDeclaration() inout { return null; }
1354 1.1 mrg inout(VersionSymbol) isVersionSymbol() inout { return null; }
1355 1.1 mrg inout(DebugSymbol) isDebugSymbol() inout { return null; }
1356 1.1 mrg inout(ClassDeclaration) isClassDeclaration() inout { return null; }
1357 1.1 mrg inout(StructDeclaration) isStructDeclaration() inout { return null; }
1358 1.1 mrg inout(UnionDeclaration) isUnionDeclaration() inout { return null; }
1359 1.1 mrg inout(InterfaceDeclaration) isInterfaceDeclaration() inout { return null; }
1360 1.1 mrg inout(ScopeDsymbol) isScopeDsymbol() inout { return null; }
1361 1.1 mrg inout(ForwardingScopeDsymbol) isForwardingScopeDsymbol() inout { return null; }
1362 1.1 mrg inout(WithScopeSymbol) isWithScopeSymbol() inout { return null; }
1363 1.1 mrg inout(ArrayScopeSymbol) isArrayScopeSymbol() inout { return null; }
1364 1.1 mrg inout(Import) isImport() inout { return null; }
1365 1.1 mrg inout(EnumDeclaration) isEnumDeclaration() inout { return null; }
1366 1.1 mrg inout(SymbolDeclaration) isSymbolDeclaration() inout { return null; }
1367 1.1 mrg inout(AttribDeclaration) isAttribDeclaration() inout { return null; }
1368 1.1 mrg inout(AnonDeclaration) isAnonDeclaration() inout { return null; }
1369 1.1 mrg inout(CPPNamespaceDeclaration) isCPPNamespaceDeclaration() inout { return null; }
1370 1.1 mrg inout(VisibilityDeclaration) isVisibilityDeclaration() inout { return null; }
1371 1.1 mrg inout(OverloadSet) isOverloadSet() inout { return null; }
1372 1.1 mrg inout(CompileDeclaration) isCompileDeclaration() inout { return null; }
1373 1.1 mrg inout(StaticAssert) isStaticAssert() inout { return null; }
1374 1.1 mrg }
1375 1.1 mrg
1376 1.1 mrg /***********************************************************
1377 1.1 mrg * Dsymbol that generates a scope
1378 1.1 mrg */
1379 1.1 mrg extern (C++) class ScopeDsymbol : Dsymbol
1380 1.1 mrg {
1381 1.1 mrg Dsymbols* members; // all Dsymbol's in this scope
1382 1.1 mrg DsymbolTable symtab; // members[] sorted into table
1383 1.1 mrg uint endlinnum; // the linnumber of the statement after the scope (0 if unknown)
1384 1.1 mrg
1385 1.1 mrg private:
1386 1.1 mrg /// symbols whose members have been imported, i.e. imported modules and template mixins
1387 1.1 mrg Dsymbols* importedScopes;
1388 1.1 mrg Visibility.Kind* visibilities; // array of Visibility.Kind, one for each import
1389 1.1 mrg
1390 1.1 mrg import dmd.root.bitarray;
1391 1.1 mrg BitArray accessiblePackages, privateAccessiblePackages;// whitelists of accessible (imported) packages
1392 1.1 mrg
1393 1.1 mrg public:
1394 1.1 mrg final extern (D) this() nothrow
1395 1.1 mrg {
1396 1.1 mrg }
1397 1.1 mrg
1398 1.1 mrg final extern (D) this(Identifier ident) nothrow
1399 1.1 mrg {
1400 1.1 mrg super(ident);
1401 1.1 mrg }
1402 1.1 mrg
1403 1.1 mrg final extern (D) this(const ref Loc loc, Identifier ident) nothrow
1404 1.1 mrg {
1405 1.1 mrg super(loc, ident);
1406 1.1 mrg }
1407 1.1 mrg
1408 1.1 mrg override ScopeDsymbol syntaxCopy(Dsymbol s)
1409 1.1 mrg {
1410 1.1 mrg //printf("ScopeDsymbol::syntaxCopy('%s')\n", toChars());
1411 1.1 mrg ScopeDsymbol sds = s ? cast(ScopeDsymbol)s : new ScopeDsymbol(ident);
1412 1.1 mrg sds.comment = comment;
1413 1.1 mrg sds.members = arraySyntaxCopy(members);
1414 1.1 mrg sds.endlinnum = endlinnum;
1415 1.1 mrg return sds;
1416 1.1 mrg }
1417 1.1 mrg
1418 1.1 mrg /*****************************************
1419 1.1 mrg * This function is #1 on the list of functions that eat cpu time.
1420 1.1 mrg * Be very, very careful about slowing it down.
1421 1.1 mrg */
1422 1.1 mrg override Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
1423 1.1 mrg {
1424 1.1 mrg //printf("%s.ScopeDsymbol::search(ident='%s', flags=x%x)\n", toChars(), ident.toChars(), flags);
1425 1.1 mrg //if (strcmp(ident.toChars(),"c") == 0) *(char*)0=0;
1426 1.1 mrg
1427 1.1 mrg // Look in symbols declared in this module
1428 1.1 mrg if (symtab && !(flags & SearchImportsOnly))
1429 1.1 mrg {
1430 1.1 mrg //printf(" look in locals\n");
1431 1.1 mrg auto s1 = symtab.lookup(ident);
1432 1.1 mrg if (s1)
1433 1.1 mrg {
1434 1.1 mrg //printf("\tfound in locals = '%s.%s'\n",toChars(),s1.toChars());
1435 1.1 mrg return s1;
1436 1.1 mrg }
1437 1.1 mrg }
1438 1.1 mrg //printf(" not found in locals\n");
1439 1.1 mrg
1440 1.1 mrg // Look in imported scopes
1441 1.1 mrg if (!importedScopes)
1442 1.1 mrg return null;
1443 1.1 mrg
1444 1.1 mrg //printf(" look in imports\n");
1445 1.1 mrg Dsymbol s = null;
1446 1.1 mrg OverloadSet a = null;
1447 1.1 mrg // Look in imported modules
1448 1.1 mrg for (size_t i = 0; i < importedScopes.dim; i++)
1449 1.1 mrg {
1450 1.1 mrg // If private import, don't search it
1451 1.1 mrg if ((flags & IgnorePrivateImports) && visibilities[i] == Visibility.Kind.private_)
1452 1.1 mrg continue;
1453 1.1 mrg int sflags = flags & (IgnoreErrors | IgnoreAmbiguous); // remember these in recursive searches
1454 1.1 mrg Dsymbol ss = (*importedScopes)[i];
1455 1.1 mrg //printf("\tscanning import '%s', visibilities = %d, isModule = %p, isImport = %p\n", ss.toChars(), visibilities[i], ss.isModule(), ss.isImport());
1456 1.1 mrg
1457 1.1 mrg if (ss.isModule())
1458 1.1 mrg {
1459 1.1 mrg if (flags & SearchLocalsOnly)
1460 1.1 mrg continue;
1461 1.1 mrg }
1462 1.1 mrg else // mixin template
1463 1.1 mrg {
1464 1.1 mrg if (flags & SearchImportsOnly)
1465 1.1 mrg continue;
1466 1.1 mrg
1467 1.1 mrg sflags |= SearchLocalsOnly;
1468 1.1 mrg }
1469 1.1 mrg
1470 1.1 mrg /* Don't find private members if ss is a module
1471 1.1 mrg */
1472 1.1 mrg Dsymbol s2 = ss.search(loc, ident, sflags | (ss.isModule() ? IgnorePrivateImports : IgnoreNone));
1473 1.1 mrg import dmd.access : symbolIsVisible;
1474 1.1 mrg if (!s2 || !(flags & IgnoreSymbolVisibility) && !symbolIsVisible(this, s2))
1475 1.1 mrg continue;
1476 1.1 mrg if (!s)
1477 1.1 mrg {
1478 1.1 mrg s = s2;
1479 1.1 mrg if (s && s.isOverloadSet())
1480 1.1 mrg a = mergeOverloadSet(ident, a, s);
1481 1.1 mrg }
1482 1.1 mrg else if (s2 && s != s2)
1483 1.1 mrg {
1484 1.1 mrg if (s.toAlias() == s2.toAlias() || s.getType() == s2.getType() && s.getType())
1485 1.1 mrg {
1486 1.1 mrg /* After following aliases, we found the same
1487 1.1 mrg * symbol, so it's not an ambiguity. But if one
1488 1.1 mrg * alias is deprecated or less accessible, prefer
1489 1.1 mrg * the other.
1490 1.1 mrg */
1491 1.1 mrg if (s.isDeprecated() || s.visible() < s2.visible() && s2.visible().kind != Visibility.Kind.none)
1492 1.1 mrg s = s2;
1493 1.1 mrg }
1494 1.1 mrg else
1495 1.1 mrg {
1496 1.1 mrg /* Two imports of the same module should be regarded as
1497 1.1 mrg * the same.
1498 1.1 mrg */
1499 1.1 mrg Import i1 = s.isImport();
1500 1.1 mrg Import i2 = s2.isImport();
1501 1.1 mrg if (!(i1 && i2 && (i1.mod == i2.mod || (!i1.parent.isImport() && !i2.parent.isImport() && i1.ident.equals(i2.ident)))))
1502 1.1 mrg {
1503 1.1 mrg /* https://issues.dlang.org/show_bug.cgi?id=8668
1504 1.1 mrg * Public selective import adds AliasDeclaration in module.
1505 1.1 mrg * To make an overload set, resolve aliases in here and
1506 1.1 mrg * get actual overload roots which accessible via s and s2.
1507 1.1 mrg */
1508 1.1 mrg s = s.toAlias();
1509 1.1 mrg s2 = s2.toAlias();
1510 1.1 mrg /* If both s2 and s are overloadable (though we only
1511 1.1 mrg * need to check s once)
1512 1.1 mrg */
1513 1.1 mrg
1514 1.1 mrg auto so2 = s2.isOverloadSet();
1515 1.1 mrg if ((so2 || s2.isOverloadable()) && (a || s.isOverloadable()))
1516 1.1 mrg {
1517 1.1 mrg if (symbolIsVisible(this, s2))
1518 1.1 mrg {
1519 1.1 mrg a = mergeOverloadSet(ident, a, s2);
1520 1.1 mrg }
1521 1.1 mrg if (!symbolIsVisible(this, s))
1522 1.1 mrg s = s2;
1523 1.1 mrg continue;
1524 1.1 mrg }
1525 1.1 mrg
1526 1.1 mrg /* Two different overflow sets can have the same members
1527 1.1 mrg * https://issues.dlang.org/show_bug.cgi?id=16709
1528 1.1 mrg */
1529 1.1 mrg auto so = s.isOverloadSet();
1530 1.1 mrg if (so && so2)
1531 1.1 mrg {
1532 1.1 mrg if (so.a.length == so2.a.length)
1533 1.1 mrg {
1534 1.1 mrg foreach (j; 0 .. so.a.length)
1535 1.1 mrg {
1536 1.1 mrg if (so.a[j] !is so2.a[j])
1537 1.1 mrg goto L1;
1538 1.1 mrg }
1539 1.1 mrg continue; // the same
1540 1.1 mrg L1:
1541 1.1 mrg { } // different
1542 1.1 mrg }
1543 1.1 mrg }
1544 1.1 mrg
1545 1.1 mrg if (flags & IgnoreAmbiguous) // if return NULL on ambiguity
1546 1.1 mrg return null;
1547 1.1 mrg if (!(flags & IgnoreErrors))
1548 1.1 mrg ScopeDsymbol.multiplyDefined(loc, s, s2);
1549 1.1 mrg break;
1550 1.1 mrg }
1551 1.1 mrg }
1552 1.1 mrg }
1553 1.1 mrg }
1554 1.1 mrg if (s)
1555 1.1 mrg {
1556 1.1 mrg /* Build special symbol if we had multiple finds
1557 1.1 mrg */
1558 1.1 mrg if (a)
1559 1.1 mrg {
1560 1.1 mrg if (!s.isOverloadSet())
1561 1.1 mrg a = mergeOverloadSet(ident, a, s);
1562 1.1 mrg s = a;
1563 1.1 mrg }
1564 1.1 mrg //printf("\tfound in imports %s.%s\n", toChars(), s.toChars());
1565 1.1 mrg return s;
1566 1.1 mrg }
1567 1.1 mrg //printf(" not found in imports\n");
1568 1.1 mrg return null;
1569 1.1 mrg }
1570 1.1 mrg
1571 1.1 mrg extern (D) private OverloadSet mergeOverloadSet(Identifier ident, OverloadSet os, Dsymbol s)
1572 1.1 mrg {
1573 1.1 mrg if (!os)
1574 1.1 mrg {
1575 1.1 mrg os = new OverloadSet(ident);
1576 1.1 mrg os.parent = this;
1577 1.1 mrg }
1578 1.1 mrg if (OverloadSet os2 = s.isOverloadSet())
1579 1.1 mrg {
1580 1.1 mrg // Merge the cross-module overload set 'os2' into 'os'
1581 1.1 mrg if (os.a.dim == 0)
1582 1.1 mrg {
1583 1.1 mrg os.a.setDim(os2.a.dim);
1584 1.1 mrg memcpy(os.a.tdata(), os2.a.tdata(), (os.a[0]).sizeof * os2.a.dim);
1585 1.1 mrg }
1586 1.1 mrg else
1587 1.1 mrg {
1588 1.1 mrg for (size_t i = 0; i < os2.a.dim; i++)
1589 1.1 mrg {
1590 1.1 mrg os = mergeOverloadSet(ident, os, os2.a[i]);
1591 1.1 mrg }
1592 1.1 mrg }
1593 1.1 mrg }
1594 1.1 mrg else
1595 1.1 mrg {
1596 1.1 mrg assert(s.isOverloadable());
1597 1.1 mrg /* Don't add to os[] if s is alias of previous sym
1598 1.1 mrg */
1599 1.1 mrg for (size_t j = 0; j < os.a.dim; j++)
1600 1.1 mrg {
1601 1.1 mrg Dsymbol s2 = os.a[j];
1602 1.1 mrg if (s.toAlias() == s2.toAlias())
1603 1.1 mrg {
1604 1.1 mrg if (s2.isDeprecated() || (s2.visible() < s.visible() && s.visible().kind != Visibility.Kind.none))
1605 1.1 mrg {
1606 1.1 mrg os.a[j] = s;
1607 1.1 mrg }
1608 1.1 mrg goto Lcontinue;
1609 1.1 mrg }
1610 1.1 mrg }
1611 1.1 mrg os.push(s);
1612 1.1 mrg Lcontinue:
1613 1.1 mrg }
1614 1.1 mrg return os;
1615 1.1 mrg }
1616 1.1 mrg
1617 1.1 mrg void importScope(Dsymbol s, Visibility visibility) nothrow
1618 1.1 mrg {
1619 1.1 mrg //printf("%s.ScopeDsymbol::importScope(%s, %d)\n", toChars(), s.toChars(), visibility);
1620 1.1 mrg // No circular or redundant import's
1621 1.1 mrg if (s != this)
1622 1.1 mrg {
1623 1.1 mrg if (!importedScopes)
1624 1.1 mrg importedScopes = new Dsymbols();
1625 1.1 mrg else
1626 1.1 mrg {
1627 1.1 mrg for (size_t i = 0; i < importedScopes.dim; i++)
1628 1.1 mrg {
1629 1.1 mrg Dsymbol ss = (*importedScopes)[i];
1630 1.1 mrg if (ss == s) // if already imported
1631 1.1 mrg {
1632 1.1 mrg if (visibility.kind > visibilities[i])
1633 1.1 mrg visibilities[i] = visibility.kind; // upgrade access
1634 1.1 mrg return;
1635 1.1 mrg }
1636 1.1 mrg }
1637 1.1 mrg }
1638 1.1 mrg importedScopes.push(s);
1639 1.1 mrg visibilities = cast(Visibility.Kind*)mem.xrealloc(visibilities, importedScopes.dim * (visibilities[0]).sizeof);
1640 1.1 mrg visibilities[importedScopes.dim - 1] = visibility.kind;
1641 1.1 mrg }
1642 1.1 mrg }
1643 1.1 mrg
1644 1.1 mrg extern (D) final void addAccessiblePackage(Package p, Visibility visibility) nothrow
1645 1.1 mrg {
1646 1.1 mrg auto pary = visibility.kind == Visibility.Kind.private_ ? &privateAccessiblePackages : &accessiblePackages;
1647 1.1 mrg if (pary.length <= p.tag)
1648 1.1 mrg pary.length = p.tag + 1;
1649 1.1 mrg (*pary)[p.tag] = true;
1650 1.1 mrg }
1651 1.1 mrg
1652 1.1 mrg bool isPackageAccessible(Package p, Visibility visibility, int flags = 0) nothrow
1653 1.1 mrg {
1654 1.1 mrg if (p.tag < accessiblePackages.length && accessiblePackages[p.tag] ||
1655 1.1 mrg visibility.kind == Visibility.Kind.private_ && p.tag < privateAccessiblePackages.length && privateAccessiblePackages[p.tag])
1656 1.1 mrg return true;
1657 1.1 mrg foreach (i, ss; importedScopes ? (*importedScopes)[] : null)
1658 1.1 mrg {
1659 1.1 mrg // only search visible scopes && imported modules should ignore private imports
1660 1.1 mrg if (visibility.kind <= visibilities[i] &&
1661 1.1 mrg ss.isScopeDsymbol.isPackageAccessible(p, visibility, IgnorePrivateImports))
1662 1.1 mrg return true;
1663 1.1 mrg }
1664 1.1 mrg return false;
1665 1.1 mrg }
1666 1.1 mrg
1667 1.1 mrg override final bool isforwardRef() nothrow
1668 1.1 mrg {
1669 1.1 mrg return (members is null);
1670 1.1 mrg }
1671 1.1 mrg
1672 1.1 mrg static void multiplyDefined(const ref Loc loc, Dsymbol s1, Dsymbol s2)
1673 1.1 mrg {
1674 1.1 mrg version (none)
1675 1.1 mrg {
1676 1.1 mrg printf("ScopeDsymbol::multiplyDefined()\n");
1677 1.1 mrg printf("s1 = %p, '%s' kind = '%s', parent = %s\n", s1, s1.toChars(), s1.kind(), s1.parent ? s1.parent.toChars() : "");
1678 1.1 mrg printf("s2 = %p, '%s' kind = '%s', parent = %s\n", s2, s2.toChars(), s2.kind(), s2.parent ? s2.parent.toChars() : "");
1679 1.1 mrg }
1680 1.1 mrg if (loc.isValid())
1681 1.1 mrg {
1682 1.1 mrg .error(loc, "%s `%s` at %s conflicts with %s `%s` at %s",
1683 1.1 mrg s1.kind(), s1.toPrettyChars(), s1.locToChars(),
1684 1.1 mrg s2.kind(), s2.toPrettyChars(), s2.locToChars());
1685 1.1 mrg
1686 1.1 mrg static if (0)
1687 1.1 mrg {
1688 1.1 mrg if (auto so = s1.isOverloadSet())
1689 1.1 mrg {
1690 1.1 mrg printf("first %p:\n", so);
1691 1.1 mrg foreach (s; so.a[])
1692 1.1 mrg {
1693 1.1 mrg printf(" %p %s `%s` at %s\n", s, s.kind(), s.toPrettyChars(), s.locToChars());
1694 1.1 mrg }
1695 1.1 mrg }
1696 1.1 mrg if (auto so = s2.isOverloadSet())
1697 1.1 mrg {
1698 1.1 mrg printf("second %p:\n", so);
1699 1.1 mrg foreach (s; so.a[])
1700 1.1 mrg {
1701 1.1 mrg printf(" %p %s `%s` at %s\n", s, s.kind(), s.toPrettyChars(), s.locToChars());
1702 1.1 mrg }
1703 1.1 mrg }
1704 1.1 mrg }
1705 1.1 mrg }
1706 1.1 mrg else
1707 1.1 mrg {
1708 1.1 mrg s1.error(s1.loc, "conflicts with %s `%s` at %s", s2.kind(), s2.toPrettyChars(), s2.locToChars());
1709 1.1 mrg }
1710 1.1 mrg }
1711 1.1 mrg
1712 1.1 mrg override const(char)* kind() const
1713 1.1 mrg {
1714 1.1 mrg return "ScopeDsymbol";
1715 1.1 mrg }
1716 1.1 mrg
1717 1.1 mrg /*******************************************
1718 1.1 mrg * Look for member of the form:
1719 1.1 mrg * const(MemberInfo)[] getMembers(string);
1720 1.1 mrg * Returns NULL if not found
1721 1.1 mrg */
1722 1.1 mrg final FuncDeclaration findGetMembers()
1723 1.1 mrg {
1724 1.1 mrg Dsymbol s = search_function(this, Id.getmembers);
1725 1.1 mrg FuncDeclaration fdx = s ? s.isFuncDeclaration() : null;
1726 1.1 mrg version (none)
1727 1.1 mrg {
1728 1.1 mrg // Finish
1729 1.1 mrg __gshared TypeFunction tfgetmembers;
1730 1.1 mrg if (!tfgetmembers)
1731 1.1 mrg {
1732 1.1 mrg Scope sc;
1733 1.1 mrg auto parameters = new Parameters();
1734 1.1 mrg Parameters* p = new Parameter(STC.in_, Type.tchar.constOf().arrayOf(), null, null);
1735 1.1 mrg parameters.push(p);
1736 1.1 mrg Type tret = null;
1737 1.1 mrg tfgetmembers = new TypeFunction(parameters, tret, VarArg.none, LINK.d);
1738 1.1 mrg tfgetmembers = cast(TypeFunction)tfgetmembers.dsymbolSemantic(Loc.initial, &sc);
1739 1.1 mrg }
1740 1.1 mrg if (fdx)
1741 1.1 mrg fdx = fdx.overloadExactMatch(tfgetmembers);
1742 1.1 mrg }
1743 1.1 mrg if (fdx && fdx.isVirtual())
1744 1.1 mrg fdx = null;
1745 1.1 mrg return fdx;
1746 1.1 mrg }
1747 1.1 mrg
1748 1.1 mrg /********************************
1749 1.1 mrg * Insert Dsymbol in table.
1750 1.1 mrg * Params:
1751 1.1 mrg * s = symbol to add
1752 1.1 mrg * Returns:
1753 1.1 mrg * null if already in table, `s` if inserted
1754 1.1 mrg */
1755 1.1 mrg Dsymbol symtabInsert(Dsymbol s) nothrow
1756 1.1 mrg {
1757 1.1 mrg return symtab.insert(s);
1758 1.1 mrg }
1759 1.1 mrg
1760 1.1 mrg /****************************************
1761 1.1 mrg * Look up identifier in symbol table.
1762 1.1 mrg * Params:
1763 1.1 mrg * s = symbol
1764 1.1 mrg * id = identifier to look up
1765 1.1 mrg * Returns:
1766 1.1 mrg * Dsymbol if found, null if not
1767 1.1 mrg */
1768 1.1 mrg Dsymbol symtabLookup(Dsymbol s, Identifier id) nothrow
1769 1.1 mrg {
1770 1.1 mrg return symtab.lookup(id);
1771 1.1 mrg }
1772 1.1 mrg
1773 1.1 mrg /****************************************
1774 1.1 mrg * Return true if any of the members are static ctors or static dtors, or if
1775 1.1 mrg * any members have members that are.
1776 1.1 mrg */
1777 1.1 mrg override bool hasStaticCtorOrDtor()
1778 1.1 mrg {
1779 1.1 mrg if (members)
1780 1.1 mrg {
1781 1.1 mrg for (size_t i = 0; i < members.dim; i++)
1782 1.1 mrg {
1783 1.1 mrg Dsymbol member = (*members)[i];
1784 1.1 mrg if (member.hasStaticCtorOrDtor())
1785 1.1 mrg return true;
1786 1.1 mrg }
1787 1.1 mrg }
1788 1.1 mrg return false;
1789 1.1 mrg }
1790 1.1 mrg
1791 1.1 mrg extern (D) alias ForeachDg = int delegate(size_t idx, Dsymbol s);
1792 1.1 mrg
1793 1.1 mrg /***************************************
1794 1.1 mrg * Expands attribute declarations in members in depth first
1795 1.1 mrg * order. Calls dg(size_t symidx, Dsymbol *sym) for each
1796 1.1 mrg * member.
1797 1.1 mrg * If dg returns !=0, stops and returns that value else returns 0.
1798 1.1 mrg * Use this function to avoid the O(N + N^2/2) complexity of
1799 1.1 mrg * calculating dim and calling N times getNth.
1800 1.1 mrg * Returns:
1801 1.1 mrg * last value returned by dg()
1802 1.1 mrg */
1803 1.1 mrg extern (D) static int _foreach(Scope* sc, Dsymbols* members, scope ForeachDg dg, size_t* pn = null)
1804 1.1 mrg {
1805 1.1 mrg assert(dg);
1806 1.1 mrg if (!members)
1807 1.1 mrg return 0;
1808 1.1 mrg size_t n = pn ? *pn : 0; // take over index
1809 1.1 mrg int result = 0;
1810 1.1 mrg foreach (size_t i; 0 .. members.dim)
1811 1.1 mrg {
1812 1.1 mrg Dsymbol s = (*members)[i];
1813 1.1 mrg if (AttribDeclaration a = s.isAttribDeclaration())
1814 1.1 mrg result = _foreach(sc, a.include(sc), dg, &n);
1815 1.1 mrg else if (TemplateMixin tm = s.isTemplateMixin())
1816 1.1 mrg result = _foreach(sc, tm.members, dg, &n);
1817 1.1 mrg else if (s.isTemplateInstance())
1818 1.1 mrg {
1819 1.1 mrg }
1820 1.1 mrg else if (s.isUnitTestDeclaration())
1821 1.1 mrg {
1822 1.1 mrg }
1823 1.1 mrg else
1824 1.1 mrg result = dg(n++, s);
1825 1.1 mrg if (result)
1826 1.1 mrg break;
1827 1.1 mrg }
1828 1.1 mrg if (pn)
1829 1.1 mrg *pn = n; // update index
1830 1.1 mrg return result;
1831 1.1 mrg }
1832 1.1 mrg
1833 1.1 mrg override final inout(ScopeDsymbol) isScopeDsymbol() inout
1834 1.1 mrg {
1835 1.1 mrg return this;
1836 1.1 mrg }
1837 1.1 mrg
1838 1.1 mrg override void accept(Visitor v)
1839 1.1 mrg {
1840 1.1 mrg v.visit(this);
1841 1.1 mrg }
1842 1.1 mrg }
1843 1.1 mrg
1844 1.1 mrg /***********************************************************
1845 1.1 mrg * With statement scope
1846 1.1 mrg */
1847 1.1 mrg extern (C++) final class WithScopeSymbol : ScopeDsymbol
1848 1.1 mrg {
1849 1.1 mrg WithStatement withstate;
1850 1.1 mrg
1851 1.1 mrg extern (D) this(WithStatement withstate) nothrow
1852 1.1 mrg {
1853 1.1 mrg this.withstate = withstate;
1854 1.1 mrg }
1855 1.1 mrg
1856 1.1 mrg override Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
1857 1.1 mrg {
1858 1.1 mrg //printf("WithScopeSymbol.search(%s)\n", ident.toChars());
1859 1.1 mrg if (flags & SearchImportsOnly)
1860 1.1 mrg return null;
1861 1.1 mrg // Acts as proxy to the with class declaration
1862 1.1 mrg Dsymbol s = null;
1863 1.1 mrg Expression eold = null;
1864 1.1 mrg for (Expression e = withstate.exp; e && e != eold; e = resolveAliasThis(_scope, e, true))
1865 1.1 mrg {
1866 1.1 mrg if (e.op == EXP.scope_)
1867 1.1 mrg {
1868 1.1 mrg s = (cast(ScopeExp)e).sds;
1869 1.1 mrg }
1870 1.1 mrg else if (e.op == EXP.type)
1871 1.1 mrg {
1872 1.1 mrg s = e.type.toDsymbol(null);
1873 1.1 mrg }
1874 1.1 mrg else
1875 1.1 mrg {
1876 1.1 mrg Type t = e.type.toBasetype();
1877 1.1 mrg s = t.toDsymbol(null);
1878 1.1 mrg }
1879 1.1 mrg if (s)
1880 1.1 mrg {
1881 1.1 mrg s = s.search(loc, ident, flags);
1882 1.1 mrg if (s)
1883 1.1 mrg return s;
1884 1.1 mrg }
1885 1.1 mrg eold = e;
1886 1.1 mrg }
1887 1.1 mrg return null;
1888 1.1 mrg }
1889 1.1 mrg
1890 1.1 mrg override inout(WithScopeSymbol) isWithScopeSymbol() inout
1891 1.1 mrg {
1892 1.1 mrg return this;
1893 1.1 mrg }
1894 1.1 mrg
1895 1.1 mrg override void accept(Visitor v)
1896 1.1 mrg {
1897 1.1 mrg v.visit(this);
1898 1.1 mrg }
1899 1.1 mrg }
1900 1.1 mrg
1901 1.1 mrg /***********************************************************
1902 1.1 mrg * Array Index/Slice scope
1903 1.1 mrg */
1904 1.1 mrg extern (C++) final class ArrayScopeSymbol : ScopeDsymbol
1905 1.1 mrg {
1906 1.1 mrg // either a SliceExp, an IndexExp, an ArrayExp, a TypeTuple or a TupleDeclaration.
1907 1.1 mrg // Discriminated using DYNCAST and, for expressions, also EXP
1908 1.1 mrg private RootObject arrayContent;
1909 1.1 mrg Scope* sc;
1910 1.1 mrg
1911 1.1 mrg extern (D) this(Scope* sc, Expression exp) nothrow
1912 1.1 mrg {
1913 1.1 mrg super(exp.loc, null);
1914 1.1 mrg assert(exp.op == EXP.index || exp.op == EXP.slice || exp.op == EXP.array);
1915 1.1 mrg this.sc = sc;
1916 1.1 mrg this.arrayContent = exp;
1917 1.1 mrg }
1918 1.1 mrg
1919 1.1 mrg extern (D) this(Scope* sc, TypeTuple type) nothrow
1920 1.1 mrg {
1921 1.1 mrg this.sc = sc;
1922 1.1 mrg this.arrayContent = type;
1923 1.1 mrg }
1924 1.1 mrg
1925 1.1 mrg extern (D) this(Scope* sc, TupleDeclaration td) nothrow
1926 1.1 mrg {
1927 1.1 mrg this.sc = sc;
1928 1.1 mrg this.arrayContent = td;
1929 1.1 mrg }
1930 1.1 mrg
1931 1.1 mrg /// This override is used to solve `$`
1932 1.1 mrg override Dsymbol search(const ref Loc loc, Identifier ident, int flags = IgnoreNone)
1933 1.1 mrg {
1934 1.1 mrg //printf("ArrayScopeSymbol::search('%s', flags = %d)\n", ident.toChars(), flags);
1935 1.1 mrg if (ident != Id.dollar)
1936 1.1 mrg return null;
1937 1.1 mrg
1938 1.1 mrg VarDeclaration* pvar;
1939 1.1 mrg Expression ce;
1940 1.1 mrg
1941 1.1 mrg static Dsymbol dollarFromTypeTuple(const ref Loc loc, TypeTuple tt, Scope* sc)
1942 1.1 mrg {
1943 1.1 mrg
1944 1.1 mrg /* $ gives the number of type entries in the type tuple
1945 1.1 mrg */
1946 1.1 mrg auto v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, null);
1947 1.1 mrg Expression e = new IntegerExp(Loc.initial, tt.arguments.dim, Type.tsize_t);
1948 1.1 mrg v._init = new ExpInitializer(Loc.initial, e);
1949 1.1 mrg v.storage_class |= STC.temp | STC.static_ | STC.const_;
1950 1.1 mrg v.dsymbolSemantic(sc);
1951 1.1 mrg return v;
1952 1.1 mrg }
1953 1.1 mrg
1954 1.1 mrg const DYNCAST kind = arrayContent.dyncast();
1955 1.1 mrg if (kind == DYNCAST.dsymbol)
1956 1.1 mrg {
1957 1.1 mrg TupleDeclaration td = cast(TupleDeclaration) arrayContent;
1958 1.1 mrg /* $ gives the number of elements in the tuple
1959 1.1 mrg */
1960 1.1 mrg auto v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, null);
1961 1.1 mrg Expression e = new IntegerExp(Loc.initial, td.objects.dim, Type.tsize_t);
1962 1.1 mrg v._init = new ExpInitializer(Loc.initial, e);
1963 1.1 mrg v.storage_class |= STC.temp | STC.static_ | STC.const_;
1964 1.1 mrg v.dsymbolSemantic(sc);
1965 1.1 mrg return v;
1966 1.1 mrg }
1967 1.1 mrg if (kind == DYNCAST.type)
1968 1.1 mrg {
1969 1.1 mrg return dollarFromTypeTuple(loc, cast(TypeTuple) arrayContent, sc);
1970 1.1 mrg }
1971 1.1 mrg Expression exp = cast(Expression) arrayContent;
1972 1.1 mrg if (auto ie = exp.isIndexExp())
1973 1.1 mrg {
1974 1.1 mrg /* array[index] where index is some function of $
1975 1.1 mrg */
1976 1.1 mrg pvar = &ie.lengthVar;
1977 1.1 mrg ce = ie.e1;
1978 1.1 mrg }
1979 1.1 mrg else if (auto se = exp.isSliceExp())
1980 1.1 mrg {
1981 1.1 mrg /* array[lwr .. upr] where lwr or upr is some function of $
1982 1.1 mrg */
1983 1.1 mrg pvar = &se.lengthVar;
1984 1.1 mrg ce = se.e1;
1985 1.1 mrg }
1986 1.1 mrg else if (auto ae = exp.isArrayExp())
1987 1.1 mrg {
1988 1.1 mrg /* array[e0, e1, e2, e3] where e0, e1, e2 are some function of $
1989 1.1 mrg * $ is a opDollar!(dim)() where dim is the dimension(0,1,2,...)
1990 1.1 mrg */
1991 1.1 mrg pvar = &ae.lengthVar;
1992 1.1 mrg ce = ae.e1;
1993 1.1 mrg }
1994 1.1 mrg else
1995 1.1 mrg {
1996 1.1 mrg /* Didn't find $, look in enclosing scope(s).
1997 1.1 mrg */
1998 1.1 mrg return null;
1999 1.1 mrg }
2000 1.1 mrg ce = ce.lastComma();
2001 1.1 mrg /* If we are indexing into an array that is really a type
2002 1.1 mrg * tuple, rewrite this as an index into a type tuple and
2003 1.1 mrg * try again.
2004 1.1 mrg */
2005 1.1 mrg if (auto te = ce.isTypeExp())
2006 1.1 mrg {
2007 1.1 mrg if (auto ttp = te.type.isTypeTuple())
2008 1.1 mrg return dollarFromTypeTuple(loc, ttp, sc);
2009 1.1 mrg }
2010 1.1 mrg /* *pvar is lazily initialized, so if we refer to $
2011 1.1 mrg * multiple times, it gets set only once.
2012 1.1 mrg */
2013 1.1 mrg if (!*pvar) // if not already initialized
2014 1.1 mrg {
2015 1.1 mrg /* Create variable v and set it to the value of $
2016 1.1 mrg */
2017 1.1 mrg VarDeclaration v;
2018 1.1 mrg Type t;
2019 1.1 mrg if (auto tupexp = ce.isTupleExp())
2020 1.1 mrg {
2021 1.1 mrg /* It is for an expression tuple, so the
2022 1.1 mrg * length will be a const.
2023 1.1 mrg */
2024 1.1 mrg Expression e = new IntegerExp(Loc.initial, tupexp.exps.dim, Type.tsize_t);
2025 1.1 mrg v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, new ExpInitializer(Loc.initial, e));
2026 1.1 mrg v.storage_class |= STC.temp | STC.static_ | STC.const_;
2027 1.1 mrg }
2028 1.1 mrg else if (ce.type && (t = ce.type.toBasetype()) !is null && (t.ty == Tstruct || t.ty == Tclass))
2029 1.1 mrg {
2030 1.1 mrg // Look for opDollar
2031 1.1 mrg assert(exp.op == EXP.array || exp.op == EXP.slice);
2032 1.1 mrg AggregateDeclaration ad = isAggregate(t);
2033 1.1 mrg assert(ad);
2034 1.1 mrg Dsymbol s = ad.search(loc, Id.opDollar);
2035 1.1 mrg if (!s) // no dollar exists -- search in higher scope
2036 1.1 mrg return null;
2037 1.1 mrg s = s.toAlias();
2038 1.1 mrg Expression e = null;
2039 1.1 mrg // Check for multi-dimensional opDollar(dim) template.
2040 1.1 mrg if (TemplateDeclaration td = s.isTemplateDeclaration())
2041 1.1 mrg {
2042 1.1 mrg dinteger_t dim = 0;
2043 1.1 mrg if (exp.op == EXP.array)
2044 1.1 mrg {
2045 1.1 mrg dim = (cast(ArrayExp)exp).currentDimension;
2046 1.1 mrg }
2047 1.1 mrg else if (exp.op == EXP.slice)
2048 1.1 mrg {
2049 1.1 mrg dim = 0; // slices are currently always one-dimensional
2050 1.1 mrg }
2051 1.1 mrg else
2052 1.1 mrg {
2053 1.1 mrg assert(0);
2054 1.1 mrg }
2055 1.1 mrg auto tiargs = new Objects();
2056 1.1 mrg Expression edim = new IntegerExp(Loc.initial, dim, Type.tsize_t);
2057 1.1 mrg edim = edim.expressionSemantic(sc);
2058 1.1 mrg tiargs.push(edim);
2059 1.1 mrg e = new DotTemplateInstanceExp(loc, ce, td.ident, tiargs);
2060 1.1 mrg }
2061 1.1 mrg else
2062 1.1 mrg {
2063 1.1 mrg /* opDollar exists, but it's not a template.
2064 1.1 mrg * This is acceptable ONLY for single-dimension indexing.
2065 1.1 mrg * Note that it's impossible to have both template & function opDollar,
2066 1.1 mrg * because both take no arguments.
2067 1.1 mrg */
2068 1.1 mrg if (exp.op == EXP.array && (cast(ArrayExp)exp).arguments.dim != 1)
2069 1.1 mrg {
2070 1.1 mrg exp.error("`%s` only defines opDollar for one dimension", ad.toChars());
2071 1.1 mrg return null;
2072 1.1 mrg }
2073 1.1 mrg Declaration d = s.isDeclaration();
2074 1.1 mrg assert(d);
2075 1.1 mrg e = new DotVarExp(loc, ce, d);
2076 1.1 mrg }
2077 1.1 mrg e = e.expressionSemantic(sc);
2078 1.1 mrg if (!e.type)
2079 1.1 mrg exp.error("`%s` has no value", e.toChars());
2080 1.1 mrg t = e.type.toBasetype();
2081 1.1 mrg if (t && t.ty == Tfunction)
2082 1.1 mrg e = new CallExp(e.loc, e);
2083 1.1 mrg v = new VarDeclaration(loc, null, Id.dollar, new ExpInitializer(Loc.initial, e));
2084 1.1 mrg v.storage_class |= STC.temp | STC.ctfe | STC.rvalue;
2085 1.1 mrg }
2086 1.1 mrg else
2087 1.1 mrg {
2088 1.1 mrg /* For arrays, $ will either be a compile-time constant
2089 1.1 mrg * (in which case its value in set during constant-folding),
2090 1.1 mrg * or a variable (in which case an expression is created in
2091 1.1 mrg * toir.c).
2092 1.1 mrg */
2093 1.1 mrg auto e = new VoidInitializer(Loc.initial);
2094 1.1 mrg e.type = Type.tsize_t;
2095 1.1 mrg v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, e);
2096 1.1 mrg v.storage_class |= STC.temp | STC.ctfe; // it's never a true static variable
2097 1.1 mrg }
2098 1.1 mrg *pvar = v;
2099 1.1 mrg }
2100 1.1 mrg (*pvar).dsymbolSemantic(sc);
2101 1.1 mrg return (*pvar);
2102 1.1 mrg }
2103 1.1 mrg
2104 1.1 mrg override inout(ArrayScopeSymbol) isArrayScopeSymbol() inout
2105 1.1 mrg {
2106 1.1 mrg return this;
2107 1.1 mrg }
2108 1.1 mrg
2109 1.1 mrg override void accept(Visitor v)
2110 1.1 mrg {
2111 1.1 mrg v.visit(this);
2112 1.1 mrg }
2113 1.1 mrg }
2114 1.1 mrg
2115 1.1 mrg /***********************************************************
2116 1.1 mrg * Overload Sets
2117 1.1 mrg */
2118 1.1 mrg extern (C++) final class OverloadSet : Dsymbol
2119 1.1 mrg {
2120 1.1 mrg Dsymbols a; // array of Dsymbols
2121 1.1 mrg
2122 1.1 mrg extern (D) this(Identifier ident, OverloadSet os = null) nothrow
2123 1.1 mrg {
2124 1.1 mrg super(ident);
2125 1.1 mrg if (os)
2126 1.1 mrg {
2127 1.1 mrg a.pushSlice(os.a[]);
2128 1.1 mrg }
2129 1.1 mrg }
2130 1.1 mrg
2131 1.1 mrg void push(Dsymbol s) nothrow
2132 1.1 mrg {
2133 1.1 mrg a.push(s);
2134 1.1 mrg }
2135 1.1 mrg
2136 1.1 mrg override inout(OverloadSet) isOverloadSet() inout
2137 1.1 mrg {
2138 1.1 mrg return this;
2139 1.1 mrg }
2140 1.1 mrg
2141 1.1 mrg override const(char)* kind() const
2142 1.1 mrg {
2143 1.1 mrg return "overloadset";
2144 1.1 mrg }
2145 1.1 mrg
2146 1.1 mrg override void accept(Visitor v)
2147 1.1 mrg {
2148 1.1 mrg v.visit(this);
2149 1.1 mrg }
2150 1.1 mrg }
2151 1.1 mrg
2152 1.1 mrg /***********************************************************
2153 1.1 mrg * Forwarding ScopeDsymbol. Used by ForwardingAttribDeclaration and
2154 1.1 mrg * ForwardingScopeDeclaration to forward symbol insertions to another
2155 1.1 mrg * scope. See `dmd.attrib.ForwardingAttribDeclaration` for more
2156 1.1 mrg * details.
2157 1.1 mrg */
2158 1.1 mrg extern (C++) final class ForwardingScopeDsymbol : ScopeDsymbol
2159 1.1 mrg {
2160 1.1 mrg /*************************
2161 1.1 mrg * Symbol to forward insertions to.
2162 1.1 mrg * Can be `null` before being lazily initialized.
2163 1.1 mrg */
2164 1.1 mrg ScopeDsymbol forward;
2165 1.1 mrg extern (D) this(ScopeDsymbol forward) nothrow
2166 1.1 mrg {
2167 1.1 mrg super(null);
2168 1.1 mrg this.forward = forward;
2169 1.1 mrg }
2170 1.1 mrg
2171 1.1 mrg override Dsymbol symtabInsert(Dsymbol s) nothrow
2172 1.1 mrg {
2173 1.1 mrg assert(forward);
2174 1.1 mrg if (auto d = s.isDeclaration())
2175 1.1 mrg {
2176 1.1 mrg if (d.storage_class & STC.local)
2177 1.1 mrg {
2178 1.1 mrg // Symbols with storage class STC.local are not
2179 1.1 mrg // forwarded, but stored in the local symbol
2180 1.1 mrg // table. (Those are the `static foreach` variables.)
2181 1.1 mrg if (!symtab)
2182 1.1 mrg {
2183 1.1 mrg symtab = new DsymbolTable();
2184 1.1 mrg }
2185 1.1 mrg return super.symtabInsert(s); // insert locally
2186 1.1 mrg }
2187 1.1 mrg }
2188 1.1 mrg if (!forward.symtab)
2189 1.1 mrg {
2190 1.1 mrg forward.symtab = new DsymbolTable();
2191 1.1 mrg }
2192 1.1 mrg // Non-STC.local symbols are forwarded to `forward`.
2193 1.1 mrg return forward.symtabInsert(s);
2194 1.1 mrg }
2195 1.1 mrg
2196 1.1 mrg /************************
2197 1.1 mrg * This override handles the following two cases:
2198 1.1 mrg * static foreach (i, i; [0]) { ... }
2199 1.1 mrg * and
2200 1.1 mrg * static foreach (i; [0]) { enum i = 2; }
2201 1.1 mrg */
2202 1.1 mrg override Dsymbol symtabLookup(Dsymbol s, Identifier id) nothrow
2203 1.1 mrg {
2204 1.1 mrg assert(forward);
2205 1.1 mrg // correctly diagnose clashing foreach loop variables.
2206 1.1 mrg if (auto d = s.isDeclaration())
2207 1.1 mrg {
2208 1.1 mrg if (d.storage_class & STC.local)
2209 1.1 mrg {
2210 1.1 mrg if (!symtab)
2211 1.1 mrg {
2212 1.1 mrg symtab = new DsymbolTable();
2213 1.1 mrg }
2214 1.1 mrg return super.symtabLookup(s,id);
2215 1.1 mrg }
2216 1.1 mrg }
2217 1.1 mrg // Declarations within `static foreach` do not clash with
2218 1.1 mrg // `static foreach` loop variables.
2219 1.1 mrg if (!forward.symtab)
2220 1.1 mrg {
2221 1.1 mrg forward.symtab = new DsymbolTable();
2222 1.1 mrg }
2223 1.1 mrg return forward.symtabLookup(s,id);
2224 1.1 mrg }
2225 1.1 mrg
2226 1.1 mrg override void importScope(Dsymbol s, Visibility visibility)
2227 1.1 mrg {
2228 1.1 mrg forward.importScope(s, visibility);
2229 1.1 mrg }
2230 1.1 mrg
2231 1.1 mrg override const(char)* kind()const{ return "local scope"; }
2232 1.1 mrg
2233 1.1 mrg override inout(ForwardingScopeDsymbol) isForwardingScopeDsymbol() inout nothrow
2234 1.1 mrg {
2235 1.1 mrg return this;
2236 1.1 mrg }
2237 1.1 mrg
2238 1.1 mrg }
2239 1.1 mrg
2240 1.1 mrg /**
2241 1.1 mrg * Class that holds an expression in a Dsymbol wrapper.
2242 1.1 mrg * This is not an AST node, but a class used to pass
2243 1.1 mrg * an expression as a function parameter of type Dsymbol.
2244 1.1 mrg */
2245 1.1 mrg extern (C++) final class ExpressionDsymbol : Dsymbol
2246 1.1 mrg {
2247 1.1 mrg Expression exp;
2248 1.1 mrg this(Expression exp) nothrow
2249 1.1 mrg {
2250 1.1 mrg super();
2251 1.1 mrg this.exp = exp;
2252 1.1 mrg }
2253 1.1 mrg
2254 1.1 mrg override inout(ExpressionDsymbol) isExpressionDsymbol() inout nothrow
2255 1.1 mrg {
2256 1.1 mrg return this;
2257 1.1 mrg }
2258 1.1 mrg }
2259 1.1 mrg
2260 1.1 mrg /**********************************************
2261 1.1 mrg * Encapsulate assigning to an alias:
2262 1.1 mrg * `identifier = type;`
2263 1.1 mrg * `identifier = symbol;`
2264 1.1 mrg * where `identifier` is an AliasDeclaration in scope.
2265 1.1 mrg */
2266 1.1 mrg extern (C++) final class AliasAssign : Dsymbol
2267 1.1 mrg {
2268 1.1 mrg Identifier ident; /// Dsymbol's ident will be null, as this class is anonymous
2269 1.1 mrg Type type; /// replace previous RHS of AliasDeclaration with `type`
2270 1.1 mrg Dsymbol aliassym; /// replace previous RHS of AliasDeclaration with `aliassym`
2271 1.1 mrg /// only one of type and aliassym can be != null
2272 1.1 mrg
2273 1.1 mrg extern (D) this(const ref Loc loc, Identifier ident, Type type, Dsymbol aliassym) nothrow
2274 1.1 mrg {
2275 1.1 mrg super(loc, null);
2276 1.1 mrg this.ident = ident;
2277 1.1 mrg this.type = type;
2278 1.1 mrg this.aliassym = aliassym;
2279 1.1 mrg }
2280 1.1 mrg
2281 1.1 mrg override AliasAssign syntaxCopy(Dsymbol s)
2282 1.1 mrg {
2283 1.1 mrg assert(!s);
2284 1.1 mrg AliasAssign aa = new AliasAssign(loc, ident,
2285 1.1 mrg type ? type.syntaxCopy() : null,
2286 1.1 mrg aliassym ? aliassym.syntaxCopy(null) : null);
2287 1.1 mrg return aa;
2288 1.1 mrg }
2289 1.1 mrg
2290 1.1 mrg override inout(AliasAssign) isAliasAssign() inout
2291 1.1 mrg {
2292 1.1 mrg return this;
2293 1.1 mrg }
2294 1.1 mrg
2295 1.1 mrg override const(char)* kind() const
2296 1.1 mrg {
2297 1.1 mrg return "alias assignment";
2298 1.1 mrg }
2299 1.1 mrg
2300 1.1 mrg override void accept(Visitor v)
2301 1.1 mrg {
2302 1.1 mrg v.visit(this);
2303 1.1 mrg }
2304 1.1 mrg }
2305 1.1 mrg
2306 1.1 mrg /***********************************************************
2307 1.1 mrg * Table of Dsymbol's
2308 1.1 mrg */
2309 1.1 mrg extern (C++) final class DsymbolTable : RootObject
2310 1.1 mrg {
2311 1.1 mrg AssocArray!(Identifier, Dsymbol) tab;
2312 1.1 mrg
2313 1.1 mrg nothrow:
2314 1.1 mrg
2315 1.1 mrg /***************************
2316 1.1 mrg * Look up Identifier in symbol table
2317 1.1 mrg * Params:
2318 1.1 mrg * ident = identifer to look up
2319 1.1 mrg * Returns:
2320 1.1 mrg * Dsymbol if found, null if not
2321 1.1 mrg */
2322 1.1 mrg Dsymbol lookup(const Identifier ident)
2323 1.1 mrg {
2324 1.1 mrg //printf("DsymbolTable::lookup(%s)\n", ident.toChars());
2325 1.1 mrg return tab[ident];
2326 1.1 mrg }
2327 1.1 mrg
2328 1.1 mrg /**********
2329 1.1 mrg * Replace existing symbol in symbol table with `s`.
2330 1.1 mrg * If it's not there, add it.
2331 1.1 mrg * Params:
2332 1.1 mrg * s = replacement symbol with same identifier
2333 1.1 mrg */
2334 1.1 mrg void update(Dsymbol s)
2335 1.1 mrg {
2336 1.1 mrg *tab.getLvalue(s.ident) = s;
2337 1.1 mrg }
2338 1.1 mrg
2339 1.1 mrg /**************************
2340 1.1 mrg * Insert Dsymbol in table.
2341 1.1 mrg * Params:
2342 1.1 mrg * s = symbol to add
2343 1.1 mrg * Returns:
2344 1.1 mrg * null if already in table, `s` if inserted
2345 1.1 mrg */
2346 1.1 mrg Dsymbol insert(Dsymbol s)
2347 1.1 mrg {
2348 1.1 mrg return insert(s.ident, s);
2349 1.1 mrg }
2350 1.1 mrg
2351 1.1 mrg /**************************
2352 1.1 mrg * Insert Dsymbol in table.
2353 1.1 mrg * Params:
2354 1.1 mrg * ident = identifier to serve as index
2355 1.1 mrg * s = symbol to add
2356 1.1 mrg * Returns:
2357 1.1 mrg * null if already in table, `s` if inserted
2358 1.1 mrg */
2359 1.1 mrg Dsymbol insert(const Identifier ident, Dsymbol s)
2360 1.1 mrg {
2361 1.1 mrg //printf("DsymbolTable.insert(this = %p, '%s')\n", this, s.ident.toChars());
2362 1.1 mrg Dsymbol* ps = tab.getLvalue(ident);
2363 1.1 mrg if (*ps)
2364 1.1 mrg return null; // already in table
2365 1.1 mrg *ps = s;
2366 1.1 mrg return s;
2367 1.1 mrg }
2368 1.1 mrg
2369 1.1 mrg /*****************
2370 1.1 mrg * Returns:
2371 1.1 mrg * number of symbols in symbol table
2372 1.1 mrg */
2373 1.1 mrg size_t length() const pure
2374 1.1 mrg {
2375 1.1 mrg return tab.length;
2376 1.1 mrg }
2377 1.1 mrg }
2378 1.1 mrg
2379 1.1 mrg /**********************************************
2380 1.1 mrg * ImportC tag symbols sit in a parallel symbol table,
2381 1.1 mrg * so that this C code works:
2382 1.1 mrg * ---
2383 1.1 mrg * struct S { a; };
2384 1.1 mrg * int S;
2385 1.1 mrg * struct S s;
2386 1.1 mrg * ---
2387 1.1 mrg * But there are relatively few such tag symbols, so that would be
2388 1.1 mrg * a waste of memory and complexity. An additional problem is we'd like the D side
2389 1.1 mrg * to find the tag symbols with ordinary lookup, not lookup in both
2390 1.1 mrg * tables, if the tag symbol is not conflicting with an ordinary symbol.
2391 1.1 mrg * The solution is to put the tag symbols that conflict into an associative
2392 1.1 mrg * array, indexed by the address of the ordinary symbol that conflicts with it.
2393 1.1 mrg * C has no modules, so this associative array is tagSymTab[] in ModuleDeclaration.
2394 1.1 mrg * A side effect of our approach is that D code cannot access a tag symbol that is
2395 1.1 mrg * hidden by an ordinary symbol. This is more of a theoretical problem, as nobody
2396 1.1 mrg * has mentioned it when importing C headers. If someone wants to do it,
2397 1.1 mrg * too bad so sad. Change the C code.
2398 1.1 mrg * This function fixes up the symbol table when faced with adding a new symbol
2399 1.1 mrg * `s` when there is an existing symbol `s2` with the same name.
2400 1.1 mrg * C also allows forward and prototype declarations of tag symbols,
2401 1.1 mrg * this function merges those.
2402 1.1 mrg * Params:
2403 1.1 mrg * sc = context
2404 1.1 mrg * s = symbol to add to symbol table
2405 1.1 mrg * s2 = existing declaration
2406 1.1 mrg * sds = symbol table
2407 1.1 mrg * Returns:
2408 1.1 mrg * if s and s2 are successfully put in symbol table then return the merged symbol,
2409 1.1 mrg * null if they conflict
2410 1.1 mrg */
2411 1.1 mrg Dsymbol handleTagSymbols(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsymbol sds)
2412 1.1 mrg {
2413 1.1 mrg enum log = false;
2414 1.1 mrg if (log) printf("handleTagSymbols('%s') add %p existing %p\n", s.toChars(), s, s2);
2415 1.1 mrg if (log) printf(" add %s %s, existing %s %s\n", s.kind(), s.toChars(), s2.kind(), s2.toChars());
2416 1.1 mrg auto sd = s.isScopeDsymbol(); // new declaration
2417 1.1 mrg auto sd2 = s2.isScopeDsymbol(); // existing declaration
2418 1.1 mrg
2419 1.1 mrg if (!sd2)
2420 1.1 mrg {
2421 1.1 mrg /* Look in tag table
2422 1.1 mrg */
2423 1.1 mrg if (log) printf(" look in tag table\n");
2424 1.1 mrg if (auto p = cast(void*)s2 in sc._module.tagSymTab)
2425 1.1 mrg {
2426 1.1 mrg Dsymbol s2tag = *p;
2427 1.1 mrg sd2 = s2tag.isScopeDsymbol();
2428 1.1 mrg assert(sd2); // only tags allowed in tag symbol table
2429 1.1 mrg }
2430 1.1 mrg }
2431 1.1 mrg
2432 1.1 mrg if (sd && sd2) // `s` is a tag, `sd2` is the same tag
2433 1.1 mrg {
2434 1.1 mrg if (log) printf(" tag is already defined\n");
2435 1.1 mrg
2436 1.1 mrg if (sd.kind() != sd2.kind()) // being enum/struct/union must match
2437 1.1 mrg return null; // conflict
2438 1.1 mrg
2439 1.1 mrg /* Not a redeclaration if one is a forward declaration.
2440 1.1 mrg * Move members to the first declared type, which is sd2.
2441 1.1 mrg */
2442 1.1 mrg if (sd2.members)
2443 1.1 mrg {
2444 1.1 mrg if (!sd.members)
2445 1.1 mrg return sd2; // ignore the sd redeclaration
2446 1.1 mrg }
2447 1.1 mrg else if (sd.members)
2448 1.1 mrg {
2449 1.1 mrg sd2.members = sd.members; // transfer definition to sd2
2450 1.1 mrg sd.members = null;
2451 1.1 mrg return sd2;
2452 1.1 mrg }
2453 1.1 mrg else
2454 1.1 mrg return sd2; // ignore redeclaration
2455 1.1 mrg }
2456 1.1 mrg else if (sd) // `s` is a tag, `s2` is not
2457 1.1 mrg {
2458 1.1 mrg if (log) printf(" s is tag, s2 is not\n");
2459 1.1 mrg /* add `s` as tag indexed by s2
2460 1.1 mrg */
2461 1.1 mrg sc._module.tagSymTab[cast(void*)s2] = s;
2462 1.1 mrg return s;
2463 1.1 mrg }
2464 1.1 mrg else if (s2 is sd2) // `s2` is a tag, `s` is not
2465 1.1 mrg {
2466 1.1 mrg if (log) printf(" s2 is tag, s is not\n");
2467 1.1 mrg /* replace `s2` in symbol table with `s`,
2468 1.1 mrg * then add `s2` as tag indexed by `s`
2469 1.1 mrg */
2470 1.1 mrg sds.symtab.update(s);
2471 1.1 mrg sc._module.tagSymTab[cast(void*)s] = s2;
2472 1.1 mrg return s;
2473 1.1 mrg }
2474 1.1 mrg // neither s2 nor s is a tag
2475 1.1 mrg if (log) printf(" collision\n");
2476 1.1 mrg return null;
2477 1.1 mrg }
2478 1.1 mrg
2479 1.1 mrg
2480 1.1 mrg /**********************************************
2481 1.1 mrg * ImportC allows redeclarations of C variables, functions and typedefs.
2482 1.1 mrg * extern int x;
2483 1.1 mrg * int x = 3;
2484 1.1 mrg * and:
2485 1.1 mrg * extern void f();
2486 1.1 mrg * void f() { }
2487 1.1 mrg * Attempt to merge them.
2488 1.1 mrg * Params:
2489 1.1 mrg * sc = context
2490 1.1 mrg * s = symbol to add to symbol table
2491 1.1 mrg * s2 = existing declaration
2492 1.1 mrg * sds = symbol table
2493 1.1 mrg * Returns:
2494 1.1 mrg * if s and s2 are successfully put in symbol table then return the merged symbol,
2495 1.1 mrg * null if they conflict
2496 1.1 mrg */
2497 1.1 mrg Dsymbol handleSymbolRedeclarations(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsymbol sds)
2498 1.1 mrg {
2499 1.1 mrg enum log = false;
2500 1.1 mrg if (log) printf("handleSymbolRedeclarations('%s')\n", s.toChars());
2501 1.1 mrg if (log) printf(" add %s %s, existing %s %s\n", s.kind(), s.toChars(), s2.kind(), s2.toChars());
2502 1.1 mrg
2503 1.1 mrg static Dsymbol collision()
2504 1.1 mrg {
2505 1.1 mrg if (log) printf(" collision\n");
2506 1.1 mrg return null;
2507 1.1 mrg }
2508 1.1 mrg
2509 1.1 mrg auto vd = s.isVarDeclaration(); // new declaration
2510 1.1 mrg auto vd2 = s2.isVarDeclaration(); // existing declaration
2511 1.1 mrg if (vd && vd2)
2512 1.1 mrg {
2513 1.1 mrg /* if one is `static` and the other isn't, the result is undefined
2514 1.1 mrg * behavior, C11 6.2.2.7
2515 1.1 mrg */
2516 1.1 mrg if ((vd.storage_class ^ vd2.storage_class) & STC.static_)
2517 1.1 mrg return collision();
2518 1.1 mrg
2519 1.1 mrg const i1 = vd._init && ! vd._init.isVoidInitializer();
2520 1.1 mrg const i2 = vd2._init && !vd2._init.isVoidInitializer();
2521 1.1 mrg
2522 1.1 mrg if (i1 && i2)
2523 1.1 mrg return collision(); // can't both have initializers
2524 1.1 mrg
2525 1.1 mrg if (i1) // vd is the definition
2526 1.1 mrg {
2527 1.1 mrg vd2.storage_class |= STC.extern_; // so toObjFile() won't emit it
2528 1.1 mrg sds.symtab.update(vd); // replace vd2 with the definition
2529 1.1 mrg return vd;
2530 1.1 mrg }
2531 1.1 mrg
2532 1.1 mrg /* BUG: the types should match, which needs semantic() to be run on it
2533 1.1 mrg * extern int x;
2534 1.1 mrg * int x; // match
2535 1.1 mrg * typedef int INT;
2536 1.1 mrg * INT x; // match
2537 1.1 mrg * long x; // collision
2538 1.1 mrg * We incorrectly ignore these collisions
2539 1.1 mrg */
2540 1.1 mrg return vd2;
2541 1.1 mrg }
2542 1.1 mrg
2543 1.1 mrg auto fd = s.isFuncDeclaration(); // new declaration
2544 1.1 mrg auto fd2 = s2.isFuncDeclaration(); // existing declaration
2545 1.1 mrg if (fd && fd2)
2546 1.1 mrg {
2547 1.1 mrg /* if one is `static` and the other isn't, the result is undefined
2548 1.1 mrg * behavior, C11 6.2.2.7
2549 1.1 mrg * However, match what gcc allows:
2550 1.1 mrg * static int sun1(); int sun1() { return 0; }
2551 1.1 mrg * and:
2552 1.1 mrg * static int sun2() { return 0; } int sun2();
2553 1.1 mrg * Both produce a static function.
2554 1.1 mrg *
2555 1.1 mrg * Both of these should fail:
2556 1.1 mrg * int sun3(); static int sun3() { return 0; }
2557 1.1 mrg * and:
2558 1.1 mrg * int sun4() { return 0; } static int sun4();
2559 1.1 mrg */
2560 1.1 mrg // if adding `static`
2561 1.1 mrg if ( fd.storage_class & STC.static_ &&
2562 1.1 mrg !(fd2.storage_class & STC.static_))
2563 1.1 mrg {
2564 1.1 mrg return collision();
2565 1.1 mrg }
2566 1.1 mrg
2567 1.1 mrg if (fd.fbody && fd2.fbody)
2568 1.1 mrg return collision(); // can't both have bodies
2569 1.1 mrg
2570 1.1 mrg if (fd.fbody) // fd is the definition
2571 1.1 mrg {
2572 1.1 mrg if (log) printf(" replace existing with new\n");
2573 1.1 mrg sds.symtab.update(fd); // replace fd2 in symbol table with fd
2574 1.1 mrg fd.overnext = fd2;
2575 1.1 mrg
2576 1.1 mrg /* If fd2 is covering a tag symbol, then fd has to cover the same one
2577 1.1 mrg */
2578 1.1 mrg auto ps = cast(void*)fd2 in sc._module.tagSymTab;
2579 1.1 mrg if (ps)
2580 1.1 mrg sc._module.tagSymTab[cast(void*)fd] = *ps;
2581 1.1 mrg
2582 1.1 mrg return fd;
2583 1.1 mrg }
2584 1.1 mrg
2585 1.1 mrg /* Just like with VarDeclaration, the types should match, which needs semantic() to be run on it.
2586 1.1 mrg * FuncDeclaration::semantic() detects this, but it relies on .overnext being set.
2587 1.1 mrg */
2588 1.1 mrg fd2.overloadInsert(fd);
2589 1.1 mrg
2590 1.1 mrg return fd2;
2591 1.1 mrg }
2592 1.1 mrg
2593 1.1 mrg auto td = s.isAliasDeclaration(); // new declaration
2594 1.1 mrg auto td2 = s2.isAliasDeclaration(); // existing declaration
2595 1.1 mrg if (td && td2)
2596 1.1 mrg {
2597 1.1 mrg /* BUG: just like with variables and functions, the types should match, which needs semantic() to be run on it.
2598 1.1 mrg * FuncDeclaration::semantic2() can detect this, but it relies overnext being set.
2599 1.1 mrg */
2600 1.1 mrg return td2;
2601 1.1 mrg }
2602 1.1 mrg
2603 1.1 mrg return collision();
2604 1.1 mrg }
2605