1 /**
2 * Miscellaneous declarations, including typedef, alias, variable declarations including the
3 * implicit this declaration, type tuples, ClassInfo, ModuleInfo and various TypeInfos.
4 *
5 * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
6 * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
7 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
8 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/declaration.d, _declaration.d)
9 * Documentation: https://dlang.org/phobos/dmd_declaration.html
10 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/declaration.d
11 */
12
13 module dmd.declaration;
14
15 import core.stdc.stdio;
16 import dmd.aggregate;
17 import dmd.arraytypes;
18 import dmd.ctorflow;
19 import dmd.dclass;
20 import dmd.delegatize;
21 import dmd.dscope;
22 import dmd.dstruct;
23 import dmd.dsymbol;
24 import dmd.dsymbolsem;
25 import dmd.dtemplate;
26 import dmd.errors;
27 import dmd.expression;
28 import dmd.func;
29 import dmd.globals;
30 import dmd.id;
31 import dmd.identifier;
32 import dmd.init;
33 import dmd.initsem;
34 import dmd.intrange;
35 import dmd.mtype;
36 import dmd.root.outbuffer;
37 import dmd.root.rootobject;
38 import dmd.target;
39 import dmd.tokens;
40 import dmd.typesem;
41 import dmd.visitor;
42
43 /************************************
44 * Check to see the aggregate type is nested and its context pointer is
45 * accessible from the current scope.
46 * Returns true if error occurs.
47 */
48 bool checkFrameAccess(Loc loc, Scope* sc, AggregateDeclaration ad, size_t iStart = 0)
49 {
50 Dsymbol sparent = ad.toParentLocal();
51 Dsymbol sparent2 = ad.toParent2();
52 Dsymbol s = sc.func;
53 if (ad.isNested() && s)
54 {
55 //printf("ad = %p %s [%s], parent:%p\n", ad, ad.toChars(), ad.loc.toChars(), ad.parent);
56 //printf("sparent = %p %s [%s], parent: %s\n", sparent, sparent.toChars(), sparent.loc.toChars(), sparent.parent,toChars());
57 //printf("sparent2 = %p %s [%s], parent: %s\n", sparent2, sparent2.toChars(), sparent2.loc.toChars(), sparent2.parent,toChars());
58 if (!ensureStaticLinkTo(s, sparent) || sparent != sparent2 && !ensureStaticLinkTo(s, sparent2))
59 {
60 error(loc, "cannot access frame pointer of `%s`", ad.toPrettyChars());
61 return true;
62 }
63 }
64
65 bool result = false;
66 for (size_t i = iStart; i < ad.fields.dim; i++)
67 {
68 VarDeclaration vd = ad.fields[i];
69 Type tb = vd.type.baseElemOf();
70 if (tb.ty == Tstruct)
71 {
72 result |= checkFrameAccess(loc, sc, (cast(TypeStruct)tb).sym);
73 }
74 }
75 return result;
76 }
77
78 /***********************************************
79 * Mark variable v as modified if it is inside a constructor that var
80 * is a field in.
81 */
82 bool modifyFieldVar(Loc loc, Scope* sc, VarDeclaration var, Expression e1)
83 {
84 //printf("modifyFieldVar(var = %s)\n", var.toChars());
85 Dsymbol s = sc.func;
86 while (1)
87 {
88 FuncDeclaration fd = null;
89 if (s)
90 fd = s.isFuncDeclaration();
91 if (fd &&
92 ((fd.isCtorDeclaration() && var.isField()) ||
93 (fd.isStaticCtorDeclaration() && !var.isField())) &&
94 fd.toParentDecl() == var.toParent2() &&
95 (!e1 || e1.op == TOK.this_))
96 {
97 bool result = true;
98
99 var.ctorinit = true;
100 //printf("setting ctorinit\n");
101
102 if (var.isField() && sc.ctorflow.fieldinit.length && !sc.intypeof)
103 {
104 assert(e1);
105 auto mustInit = ((var.storage_class & STC.nodefaultctor) != 0 ||
106 var.type.needsNested());
107
108 const dim = sc.ctorflow.fieldinit.length;
109 auto ad = fd.isMemberDecl();
110 assert(ad);
111 size_t i;
112 for (i = 0; i < dim; i++) // same as findFieldIndexByName in ctfeexp.c ?
113 {
114 if (ad.fields[i] == var)
115 break;
116 }
117 assert(i < dim);
118 auto fieldInit = &sc.ctorflow.fieldinit[i];
119 const fi = fieldInit.csx;
120
121 if (fi & CSX.this_ctor)
122 {
123 if (var.type.isMutable() && e1.type.isMutable())
124 result = false;
125 else
126 {
127 const(char)* modStr = !var.type.isMutable() ? MODtoChars(var.type.mod) : MODtoChars(e1.type.mod);
128 .error(loc, "%s field `%s` initialized multiple times", modStr, var.toChars());
129 .errorSupplemental(fieldInit.loc, "Previous initialization is here.");
130 }
131 }
132 else if (sc.inLoop || (fi & CSX.label))
133 {
134 if (!mustInit && var.type.isMutable() && e1.type.isMutable())
135 result = false;
136 else
137 {
138 const(char)* modStr = !var.type.isMutable() ? MODtoChars(var.type.mod) : MODtoChars(e1.type.mod);
139 .error(loc, "%s field `%s` initialization is not allowed in loops or after labels", modStr, var.toChars());
140 }
141 }
142
143 fieldInit.csx |= CSX.this_ctor;
144 fieldInit.loc = e1.loc;
145 if (var.overlapped) // https://issues.dlang.org/show_bug.cgi?id=15258
146 {
147 foreach (j, v; ad.fields)
148 {
149 if (v is var || !var.isOverlappedWith(v))
150 continue;
151 v.ctorinit = true;
152 sc.ctorflow.fieldinit[j].csx = CSX.this_ctor;
153 }
154 }
155 }
156 else if (fd != sc.func)
157 {
158 if (var.type.isMutable())
159 result = false;
160 else if (sc.func.fes)
161 {
162 const(char)* p = var.isField() ? "field" : var.kind();
163 .error(loc, "%s %s `%s` initialization is not allowed in foreach loop",
164 MODtoChars(var.type.mod), p, var.toChars());
165 }
166 else
167 {
168 const(char)* p = var.isField() ? "field" : var.kind();
169 .error(loc, "%s %s `%s` initialization is not allowed in nested function `%s`",
170 MODtoChars(var.type.mod), p, var.toChars(), sc.func.toChars());
171 }
172 }
173 return result;
174 }
175 else
176 {
177 if (s)
178 {
179 s = s.toParentP(var.toParent2());
180 continue;
181 }
182 }
183 break;
184 }
185 return false;
186 }
187
188 /******************************************
189 */
190 extern (C++) void ObjectNotFound(Identifier id)
191 {
192 error(Loc.initial, "`%s` not found. object.d may be incorrectly installed or corrupt.", id.toChars());
193 fatal();
194 }
195
196 enum STC : ulong
197 {
198 undefined_ = 0L,
199 static_ = (1L << 0),
200 extern_ = (1L << 1),
201 const_ = (1L << 2),
202 final_ = (1L << 3),
203 abstract_ = (1L << 4),
204 parameter = (1L << 5),
205 field = (1L << 6),
206 override_ = (1L << 7),
207 auto_ = (1L << 8),
208 synchronized_ = (1L << 9),
209 deprecated_ = (1L << 10),
210 in_ = (1L << 11), // in parameter
211 out_ = (1L << 12), // out parameter
212 lazy_ = (1L << 13), // lazy parameter
213 foreach_ = (1L << 14), // variable for foreach loop
214 //(1L << 15)
215 variadic = (1L << 16), // the 'variadic' parameter in: T foo(T a, U b, V variadic...)
216 ctorinit = (1L << 17), // can only be set inside constructor
217 templateparameter = (1L << 18), // template parameter
218 scope_ = (1L << 19),
219 immutable_ = (1L << 20),
220 ref_ = (1L << 21),
221 init = (1L << 22), // has explicit initializer
222 manifest = (1L << 23), // manifest constant
223 nodtor = (1L << 24), // don't run destructor
224 nothrow_ = (1L << 25), // never throws exceptions
225 pure_ = (1L << 26), // pure function
226 tls = (1L << 27), // thread local
227 alias_ = (1L << 28), // alias parameter
228 shared_ = (1L << 29), // accessible from multiple threads
229 gshared = (1L << 30), // accessible from multiple threads, but not typed as "shared"
230 wild = (1L << 31), // for "wild" type constructor
231 property = (1L << 32),
232 safe = (1L << 33),
233 trusted = (1L << 34),
234 system = (1L << 35),
235 ctfe = (1L << 36), // can be used in CTFE, even if it is static
236 disable = (1L << 37), // for functions that are not callable
237 result = (1L << 38), // for result variables passed to out contracts
238 nodefaultctor = (1L << 39), // must be set inside constructor
239 temp = (1L << 40), // temporary variable
240 rvalue = (1L << 41), // force rvalue for variables
241 nogc = (1L << 42), // @nogc
242 volatile_ = (1L << 43), // destined for volatile in the back end
243 return_ = (1L << 44), // 'return ref' or 'return scope' for function parameters
244 autoref = (1L << 45), // Mark for the already deduced 'auto ref' parameter
245 inference = (1L << 46), // do attribute inference
246 exptemp = (1L << 47), // temporary variable that has lifetime restricted to an expression
247 maybescope = (1L << 48), // parameter might be 'scope'
248 scopeinferred = (1L << 49), // 'scope' has been inferred and should not be part of mangling
249 future = (1L << 50), // introducing new base class function
250 local = (1L << 51), // do not forward (see dmd.dsymbol.ForwardingScopeDsymbol).
251 returninferred = (1L << 52), // 'return' has been inferred and should not be part of mangling
252 live = (1L << 53), // function @live attribute
253
254 // Group members are mutually exclusive (there can be only one)
255 safeGroup = STC.safe | STC.trusted | STC.system,
256
257 /// Group for `in` / `out` / `ref` storage classes on parameter
258 IOR = STC.in_ | STC.ref_ | STC.out_,
259
260 TYPECTOR = (STC.const_ | STC.immutable_ | STC.shared_ | STC.wild),
261 FUNCATTR = (STC.ref_ | STC.nothrow_ | STC.nogc | STC.pure_ | STC.property | STC.live |
262 STC.safeGroup),
263 }
264
265 enum STCStorageClass =
266 (STC.auto_ | STC.scope_ | STC.static_ | STC.extern_ | STC.const_ | STC.final_ | STC.abstract_ | STC.synchronized_ |
267 STC.deprecated_ | STC.future | STC.override_ | STC.lazy_ | STC.alias_ | STC.out_ | STC.in_ | STC.manifest |
268 STC.immutable_ | STC.shared_ | STC.wild | STC.nothrow_ | STC.nogc | STC.pure_ | STC.ref_ | STC.return_ | STC.tls | STC.gshared |
269 STC.property | STC.safeGroup | STC.disable | STC.local | STC.live);
270
271 /* These storage classes "flow through" to the inner scope of a Dsymbol
272 */
273 enum STCFlowThruAggregate = STC.safeGroup; /// for an AggregateDeclaration
274 enum STCFlowThruFunction = ~(STC.auto_ | STC.scope_ | STC.static_ | STC.extern_ | STC.abstract_ | STC.deprecated_ | STC.override_ |
275 STC.TYPECTOR | STC.final_ | STC.tls | STC.gshared | STC.ref_ | STC.return_ | STC.property |
276 STC.nothrow_ | STC.pure_ | STC.safe | STC.trusted | STC.system); /// for a FuncDeclaration
277
278 /* Accumulator for successive matches.
279 */
280 struct MatchAccumulator
281 {
282 int count; // number of matches found so far
283 MATCH last = MATCH.nomatch; // match level of lastf
284 FuncDeclaration lastf; // last matching function we found
285 FuncDeclaration nextf; // if ambiguous match, this is the "other" function
286 }
287
288 /***********************************************************
289 */
290 extern (C++) abstract class Declaration : Dsymbol
291 {
292 Type type;
293 Type originalType; // before semantic analysis
294 StorageClass storage_class = STC.undefined_;
295 Visibility visibility;
296 LINK linkage = LINK.default_;
297 short inuse; // used to detect cycles
298
299 ubyte adFlags; // control re-assignment of AliasDeclaration (put here for packing reasons)
300 enum wasRead = 1; // set if AliasDeclaration was read
301 enum ignoreRead = 2; // ignore any reads of AliasDeclaration
302
303 // overridden symbol with pragma(mangle, "...")
304 const(char)[] mangleOverride;
305
306 final extern (D) this(Identifier ident)
307 {
308 super(ident);
309 visibility = Visibility(Visibility.Kind.undefined);
310 }
311
312 final extern (D) this(const ref Loc loc, Identifier ident)
313 {
314 super(loc, ident);
315 visibility = Visibility(Visibility.Kind.undefined);
316 }
317
318 override const(char)* kind() const
319 {
320 return "declaration";
321 }
322
323 override final d_uns64 size(const ref Loc loc)
324 {
325 assert(type);
326 return type.size();
327 }
328
329 /**
330 * Issue an error if an attempt to call a disabled method is made
331 *
332 * If the declaration is disabled but inside a disabled function,
333 * returns `true` but do not issue an error message.
334 *
335 * Params:
336 * loc = Location information of the call
337 * sc = Scope in which the call occurs
338 * isAliasedDeclaration = if `true` searches overload set
339 *
340 * Returns:
341 * `true` if this `Declaration` is `@disable`d, `false` otherwise.
342 */
343 extern (D) final bool checkDisabled(Loc loc, Scope* sc, bool isAliasedDeclaration = false)
344 {
345 if (!(storage_class & STC.disable))
346 return false;
347
348 if (sc.func && sc.func.storage_class & STC.disable)
349 return true;
350
351 auto p = toParent();
352 if (p && isPostBlitDeclaration())
353 {
354 p.error(loc, "is not copyable because it is annotated with `@disable`");
355 return true;
356 }
357
358 // if the function is @disabled, maybe there
359 // is an overload in the overload set that isn't
360 if (isAliasedDeclaration)
361 {
362 FuncDeclaration fd = isFuncDeclaration();
363 if (fd)
364 {
365 for (FuncDeclaration ovl = fd; ovl; ovl = cast(FuncDeclaration)ovl.overnext)
366 if (!(ovl.storage_class & STC.disable))
367 return false;
368 }
369 }
370
371 if (auto ctor = isCtorDeclaration())
372 {
373 if (ctor.isCpCtor && ctor.generated)
374 {
375 .error(loc, "Generating an `inout` copy constructor for `struct %s` failed, therefore instances of it are uncopyable", parent.toPrettyChars());
376 return true;
377 }
378 }
379 error(loc, "cannot be used because it is annotated with `@disable`");
380 return true;
381 }
382
383 /*************************************
384 * Check to see if declaration can be modified in this context (sc).
385 * Issue error if not.
386 * Params:
387 * loc = location for error messages
388 * e1 = `null` or `this` expression when this declaration is a field
389 * sc = context
390 * flag = !=0 means do not issue error message for invalid modification
391 * Returns:
392 * Modifiable.yes or Modifiable.initialization
393 */
394 extern (D) final Modifiable checkModify(Loc loc, Scope* sc, Expression e1, int flag)
395 {
396 VarDeclaration v = isVarDeclaration();
397 if (v && v.canassign)
398 return Modifiable.initialization;
399
400 if (isParameter() || isResult())
401 {
402 for (Scope* scx = sc; scx; scx = scx.enclosing)
403 {
404 if (scx.func == parent && (scx.flags & SCOPE.contract))
405 {
406 const(char)* s = isParameter() && parent.ident != Id.ensure ? "parameter" : "result";
407 if (!flag)
408 error(loc, "cannot modify %s `%s` in contract", s, toChars());
409 return Modifiable.initialization; // do not report type related errors
410 }
411 }
412 }
413
414 if (e1 && e1.op == TOK.this_ && isField())
415 {
416 VarDeclaration vthis = (cast(ThisExp)e1).var;
417 for (Scope* scx = sc; scx; scx = scx.enclosing)
418 {
419 if (scx.func == vthis.parent && (scx.flags & SCOPE.contract))
420 {
421 if (!flag)
422 error(loc, "cannot modify parameter `this` in contract");
423 return Modifiable.initialization; // do not report type related errors
424 }
425 }
426 }
427
428 if (v && (isCtorinit() || isField()))
429 {
430 // It's only modifiable if inside the right constructor
431 if ((storage_class & (STC.foreach_ | STC.ref_)) == (STC.foreach_ | STC.ref_))
432 return Modifiable.initialization;
433 return modifyFieldVar(loc, sc, v, e1)
434 ? Modifiable.initialization : Modifiable.yes;
435 }
436 return Modifiable.yes;
437 }
438
439 override final Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
440 {
441 Dsymbol s = Dsymbol.search(loc, ident, flags);
442 if (!s && type)
443 {
444 s = type.toDsymbol(_scope);
445 if (s)
446 s = s.search(loc, ident, flags);
447 }
448 return s;
449 }
450
451 final bool isStatic() const pure nothrow @nogc @safe
452 {
453 return (storage_class & STC.static_) != 0;
454 }
455
456 bool isDelete()
457 {
458 return false;
459 }
460
461 bool isDataseg()
462 {
463 return false;
464 }
465
466 bool isThreadlocal()
467 {
468 return false;
469 }
470
471 bool isCodeseg() const pure nothrow @nogc @safe
472 {
473 return false;
474 }
475
476 final bool isCtorinit() const pure nothrow @nogc @safe
477 {
478 return (storage_class & STC.ctorinit) != 0;
479 }
480
481 final bool isFinal() const pure nothrow @nogc @safe
482 {
483 return (storage_class & STC.final_) != 0;
484 }
485
486 bool isAbstract()
487 {
488 return (storage_class & STC.abstract_) != 0;
489 }
490
491 final bool isConst() const pure nothrow @nogc @safe
492 {
493 return (storage_class & STC.const_) != 0;
494 }
495
496 final bool isImmutable() const pure nothrow @nogc @safe
497 {
498 return (storage_class & STC.immutable_) != 0;
499 }
500
501 final bool isWild() const pure nothrow @nogc @safe
502 {
503 return (storage_class & STC.wild) != 0;
504 }
505
506 final bool isAuto() const pure nothrow @nogc @safe
507 {
508 return (storage_class & STC.auto_) != 0;
509 }
510
511 final bool isScope() const pure nothrow @nogc @safe
512 {
513 return (storage_class & STC.scope_) != 0;
514 }
515
516 final bool isSynchronized() const pure nothrow @nogc @safe
517 {
518 return (storage_class & STC.synchronized_) != 0;
519 }
520
521 final bool isParameter() const pure nothrow @nogc @safe
522 {
523 return (storage_class & STC.parameter) != 0;
524 }
525
526 override final bool isDeprecated() const pure nothrow @nogc @safe
527 {
528 return (storage_class & STC.deprecated_) != 0;
529 }
530
531 final bool isDisabled() const pure nothrow @nogc @safe
532 {
533 return (storage_class & STC.disable) != 0;
534 }
535
536 final bool isOverride() const pure nothrow @nogc @safe
537 {
538 return (storage_class & STC.override_) != 0;
539 }
540
541 final bool isResult() const pure nothrow @nogc @safe
542 {
543 return (storage_class & STC.result) != 0;
544 }
545
546 final bool isField() const pure nothrow @nogc @safe
547 {
548 return (storage_class & STC.field) != 0;
549 }
550
551 final bool isIn() const pure nothrow @nogc @safe
552 {
553 return (storage_class & STC.in_) != 0;
554 }
555
556 final bool isOut() const pure nothrow @nogc @safe
557 {
558 return (storage_class & STC.out_) != 0;
559 }
560
561 final bool isRef() const pure nothrow @nogc @safe
562 {
563 return (storage_class & STC.ref_) != 0;
564 }
565
566 final bool isFuture() const pure nothrow @nogc @safe
567 {
568 return (storage_class & STC.future) != 0;
569 }
570
571 override final Visibility visible() pure nothrow @nogc @safe
572 {
573 return visibility;
574 }
575
576 override final inout(Declaration) isDeclaration() inout
577 {
578 return this;
579 }
580
581 override void accept(Visitor v)
582 {
583 v.visit(this);
584 }
585 }
586
587 /***********************************************************
588 */
589 extern (C++) final class TupleDeclaration : Declaration
590 {
591 Objects* objects;
592 bool isexp; // true: expression tuple
593 TypeTuple tupletype; // !=null if this is a type tuple
594
595 extern (D) this(const ref Loc loc, Identifier ident, Objects* objects)
596 {
597 super(loc, ident);
598 this.objects = objects;
599 }
600
601 override TupleDeclaration syntaxCopy(Dsymbol s)
602 {
603 assert(0);
604 }
605
606 override const(char)* kind() const
607 {
608 return "tuple";
609 }
610
611 override Type getType()
612 {
613 /* If this tuple represents a type, return that type
614 */
615
616 //printf("TupleDeclaration::getType() %s\n", toChars());
617 if (isexp)
618 return null;
619 if (!tupletype)
620 {
621 /* It's only a type tuple if all the Object's are types
622 */
623 for (size_t i = 0; i < objects.dim; i++)
624 {
625 RootObject o = (*objects)[i];
626 if (o.dyncast() != DYNCAST.type)
627 {
628 //printf("\tnot[%d], %p, %d\n", i, o, o.dyncast());
629 return null;
630 }
631 }
632
633 /* We know it's a type tuple, so build the TypeTuple
634 */
635 Types* types = cast(Types*)objects;
636 auto args = new Parameters(objects.dim);
637 OutBuffer buf;
638 int hasdeco = 1;
639 for (size_t i = 0; i < types.dim; i++)
640 {
641 Type t = (*types)[i];
642 //printf("type = %s\n", t.toChars());
643 version (none)
644 {
645 buf.printf("_%s_%d", ident.toChars(), i);
646 const len = buf.offset;
647 const name = buf.extractSlice().ptr;
648 auto id = Identifier.idPool(name, len);
649 auto arg = new Parameter(STC.in_, t, id, null);
650 }
651 else
652 {
653 auto arg = new Parameter(0, t, null, null, null);
654 }
655 (*args)[i] = arg;
656 if (!t.deco)
657 hasdeco = 0;
658 }
659
660 tupletype = new TypeTuple(args);
661 if (hasdeco)
662 return tupletype.typeSemantic(Loc.initial, null);
663 }
664 return tupletype;
665 }
666
667 override Dsymbol toAlias2()
668 {
669 //printf("TupleDeclaration::toAlias2() '%s' objects = %s\n", toChars(), objects.toChars());
670 for (size_t i = 0; i < objects.dim; i++)
671 {
672 RootObject o = (*objects)[i];
673 if (Dsymbol s = isDsymbol(o))
674 {
675 s = s.toAlias2();
676 (*objects)[i] = s;
677 }
678 }
679 return this;
680 }
681
682 override bool needThis()
683 {
684 //printf("TupleDeclaration::needThis(%s)\n", toChars());
685 for (size_t i = 0; i < objects.dim; i++)
686 {
687 RootObject o = (*objects)[i];
688 if (o.dyncast() == DYNCAST.expression)
689 {
690 Expression e = cast(Expression)o;
691 if (e.op == TOK.dSymbol)
692 {
693 DsymbolExp ve = cast(DsymbolExp)e;
694 Declaration d = ve.s.isDeclaration();
695 if (d && d.needThis())
696 {
697 return true;
698 }
699 }
700 }
701 }
702 return false;
703 }
704
705 override inout(TupleDeclaration) isTupleDeclaration() inout
706 {
707 return this;
708 }
709
710 override void accept(Visitor v)
711 {
712 v.visit(this);
713 }
714 }
715
716 /***********************************************************
717 */
718 extern (C++) final class AliasDeclaration : Declaration
719 {
720 Dsymbol aliassym;
721 Dsymbol overnext; // next in overload list
722 Dsymbol _import; // !=null if unresolved internal alias for selective import
723
724 extern (D) this(const ref Loc loc, Identifier ident, Type type)
725 {
726 super(loc, ident);
727 //printf("AliasDeclaration(id = '%s', type = %p)\n", id.toChars(), type);
728 //printf("type = '%s'\n", type.toChars());
729 this.type = type;
730 assert(type);
731 }
732
733 extern (D) this(const ref Loc loc, Identifier ident, Dsymbol s)
734 {
735 super(loc, ident);
736 //printf("AliasDeclaration(id = '%s', s = %p)\n", id.toChars(), s);
737 assert(s != this);
738 this.aliassym = s;
739 assert(s);
740 }
741
742 static AliasDeclaration create(Loc loc, Identifier id, Type type)
743 {
744 return new AliasDeclaration(loc, id, type);
745 }
746
747 override AliasDeclaration syntaxCopy(Dsymbol s)
748 {
749 //printf("AliasDeclaration::syntaxCopy()\n");
750 assert(!s);
751 AliasDeclaration sa = type ? new AliasDeclaration(loc, ident, type.syntaxCopy()) : new AliasDeclaration(loc, ident, aliassym.syntaxCopy(null));
752 sa.comment = comment;
753 sa.storage_class = storage_class;
754 return sa;
755 }
756
757 override bool overloadInsert(Dsymbol s)
758 {
759 //printf("[%s] AliasDeclaration::overloadInsert('%s') s = %s %s @ [%s]\n",
760 // loc.toChars(), toChars(), s.kind(), s.toChars(), s.loc.toChars());
761
762 /** Aliases aren't overloadable themselves, but if their Aliasee is
763 * overloadable they are converted to an overloadable Alias (either
764 * FuncAliasDeclaration or OverDeclaration).
765 *
766 * This is done by moving the Aliasee into such an overloadable alias
767 * which is then used to replace the existing Aliasee. The original
768 * Alias (_this_) remains a useless shell.
769 *
770 * This is a horrible mess. It was probably done to avoid replacing
771 * existing AST nodes and references, but it needs a major
772 * simplification b/c it's too complex to maintain.
773 *
774 * A simpler approach might be to merge any colliding symbols into a
775 * simple Overload class (an array) and then later have that resolve
776 * all collisions.
777 */
778 if (semanticRun >= PASS.semanticdone)
779 {
780 /* Semantic analysis is already finished, and the aliased entity
781 * is not overloadable.
782 */
783 if (type)
784 return false;
785
786 /* When s is added in member scope by static if, mixin("code") or others,
787 * aliassym is determined already. See the case in: test/compilable/test61.d
788 */
789 auto sa = aliassym.toAlias();
790
791 if (auto td = s.toAlias().isTemplateDeclaration())
792 s = td.funcroot ? td.funcroot : td;
793
794 if (auto fd = sa.isFuncDeclaration())
795 {
796 auto fa = new FuncAliasDeclaration(ident, fd);
797 fa.visibility = visibility;
798 fa.parent = parent;
799 aliassym = fa;
800 return aliassym.overloadInsert(s);
801 }
802 if (auto td = sa.isTemplateDeclaration())
803 {
804 auto od = new OverDeclaration(ident, td.funcroot ? td.funcroot : td);
805 od.visibility = visibility;
806 od.parent = parent;
807 aliassym = od;
808 return aliassym.overloadInsert(s);
809 }
810 if (auto od = sa.isOverDeclaration())
811 {
812 if (sa.ident != ident || sa.parent != parent)
813 {
814 od = new OverDeclaration(ident, od);
815 od.visibility = visibility;
816 od.parent = parent;
817 aliassym = od;
818 }
819 return od.overloadInsert(s);
820 }
821 if (auto os = sa.isOverloadSet())
822 {
823 if (sa.ident != ident || sa.parent != parent)
824 {
825 os = new OverloadSet(ident, os);
826 // TODO: visibility is lost here b/c OverloadSets have no visibility attribute
827 // Might no be a practical issue, b/c the code below fails to resolve the overload anyhow.
828 // ----
829 // module os1;
830 // import a, b;
831 // private alias merged = foo; // private alias to overload set of a.foo and b.foo
832 // ----
833 // module os2;
834 // import a, b;
835 // public alias merged = bar; // public alias to overload set of a.bar and b.bar
836 // ----
837 // module bug;
838 // import os1, os2;
839 // void test() { merged(123); } // should only look at os2.merged
840 //
841 // os.visibility = visibility;
842 os.parent = parent;
843 aliassym = os;
844 }
845 os.push(s);
846 return true;
847 }
848 return false;
849 }
850
851 /* Don't know yet what the aliased symbol is, so assume it can
852 * be overloaded and check later for correctness.
853 */
854 if (overnext)
855 return overnext.overloadInsert(s);
856 if (s is this)
857 return true;
858 overnext = s;
859 return true;
860 }
861
862 override const(char)* kind() const
863 {
864 return "alias";
865 }
866
867 override Type getType()
868 {
869 if (type)
870 return type;
871 return toAlias().getType();
872 }
873
874 override Dsymbol toAlias()
875 {
876 //printf("[%s] AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s', inuse = %d)\n",
877 // loc.toChars(), toChars(), this, aliassym, aliassym ? aliassym.kind() : "", inuse);
878 assert(this != aliassym);
879 //static int count; if (++count == 10) *(char*)0=0;
880
881 // Reading the AliasDeclaration
882 if (!(adFlags & ignoreRead))
883 adFlags |= wasRead; // can never assign to this AliasDeclaration again
884
885 if (inuse == 1 && type && _scope)
886 {
887 inuse = 2;
888 uint olderrors = global.errors;
889 Dsymbol s = type.toDsymbol(_scope);
890 //printf("[%s] type = %s, s = %p, this = %p\n", loc.toChars(), type.toChars(), s, this);
891 if (global.errors != olderrors)
892 goto Lerr;
893 if (s)
894 {
895 s = s.toAlias();
896 if (global.errors != olderrors)
897 goto Lerr;
898 aliassym = s;
899 inuse = 0;
900 }
901 else
902 {
903 Type t = type.typeSemantic(loc, _scope);
904 if (t.ty == Terror)
905 goto Lerr;
906 if (global.errors != olderrors)
907 goto Lerr;
908 //printf("t = %s\n", t.toChars());
909 inuse = 0;
910 }
911 }
912 if (inuse)
913 {
914 error("recursive alias declaration");
915
916 Lerr:
917 // Avoid breaking "recursive alias" state during errors gagged
918 if (global.gag)
919 return this;
920 aliassym = new AliasDeclaration(loc, ident, Type.terror);
921 type = Type.terror;
922 return aliassym;
923 }
924
925 if (semanticRun >= PASS.semanticdone)
926 {
927 // semantic is already done.
928
929 // Do not see aliassym !is null, because of lambda aliases.
930
931 // Do not see type.deco !is null, even so "alias T = const int;` needs
932 // semantic analysis to take the storage class `const` as type qualifier.
933 }
934 else
935 {
936 if (_import && _import._scope)
937 {
938 /* If this is an internal alias for selective/renamed import,
939 * load the module first.
940 */
941 _import.dsymbolSemantic(null);
942 }
943 if (_scope)
944 {
945 aliasSemantic(this, _scope);
946 }
947 }
948
949 inuse = 1;
950 Dsymbol s = aliassym ? aliassym.toAlias() : this;
951 inuse = 0;
952 return s;
953 }
954
955 override Dsymbol toAlias2()
956 {
957 if (inuse)
958 {
959 error("recursive alias declaration");
960 return this;
961 }
962 inuse = 1;
963 Dsymbol s = aliassym ? aliassym.toAlias2() : this;
964 inuse = 0;
965 return s;
966 }
967
968 override bool isOverloadable() const
969 {
970 // assume overloadable until alias is resolved
971 return semanticRun < PASS.semanticdone ||
972 aliassym && aliassym.isOverloadable();
973 }
974
975 override inout(AliasDeclaration) isAliasDeclaration() inout
976 {
977 return this;
978 }
979
980 /** Returns: `true` if this instance was created to make a template parameter
981 visible in the scope of a template body, `false` otherwise */
982 extern (D) bool isAliasedTemplateParameter() const
983 {
984 return !!(storage_class & STC.templateparameter);
985 }
986
987 override void accept(Visitor v)
988 {
989 v.visit(this);
990 }
991 }
992
993 /***********************************************************
994 */
995 extern (C++) final class OverDeclaration : Declaration
996 {
997 Dsymbol overnext; // next in overload list
998 Dsymbol aliassym;
999
1000 extern (D) this(Identifier ident, Dsymbol s)
1001 {
1002 super(ident);
1003 this.aliassym = s;
1004 }
1005
1006 override const(char)* kind() const
1007 {
1008 return "overload alias"; // todo
1009 }
1010
1011 override bool equals(const RootObject o) const
1012 {
1013 if (this == o)
1014 return true;
1015
1016 auto s = isDsymbol(o);
1017 if (!s)
1018 return false;
1019
1020 if (auto od2 = s.isOverDeclaration())
1021 return this.aliassym.equals(od2.aliassym);
1022 return this.aliassym == s;
1023 }
1024
1025 override bool overloadInsert(Dsymbol s)
1026 {
1027 //printf("OverDeclaration::overloadInsert('%s') aliassym = %p, overnext = %p\n", s.toChars(), aliassym, overnext);
1028 if (overnext)
1029 return overnext.overloadInsert(s);
1030 if (s == this)
1031 return true;
1032 overnext = s;
1033 return true;
1034 }
1035
1036 override bool isOverloadable() const
1037 {
1038 return true;
1039 }
1040
1041 Dsymbol isUnique()
1042 {
1043 Dsymbol result = null;
1044 overloadApply(aliassym, (Dsymbol s)
1045 {
1046 if (result)
1047 {
1048 result = null;
1049 return 1; // ambiguous, done
1050 }
1051 else
1052 {
1053 result = s;
1054 return 0;
1055 }
1056 });
1057 return result;
1058 }
1059
1060 override inout(OverDeclaration) isOverDeclaration() inout
1061 {
1062 return this;
1063 }
1064
1065 override void accept(Visitor v)
1066 {
1067 v.visit(this);
1068 }
1069 }
1070
1071 /***********************************************************
1072 */
1073 extern (C++) class VarDeclaration : Declaration
1074 {
1075 Initializer _init;
1076 FuncDeclarations nestedrefs; // referenced by these lexically nested functions
1077 Dsymbol aliassym; // if redone as alias to another symbol
1078 VarDeclaration lastVar; // Linked list of variables for goto-skips-init detection
1079 Expression edtor; // if !=null, does the destruction of the variable
1080 IntRange* range; // if !=null, the variable is known to be within the range
1081 VarDeclarations* maybes; // STC.maybescope variables that are assigned to this STC.maybescope variable
1082
1083 uint endlinnum; // line number of end of scope that this var lives in
1084 uint offset;
1085 uint sequenceNumber; // order the variables are declared
1086 __gshared uint nextSequenceNumber; // the counter for sequenceNumber
1087 structalign_t alignment;
1088
1089 // When interpreting, these point to the value (NULL if value not determinable)
1090 // The index of this variable on the CTFE stack, AdrOnStackNone if not allocated
1091 enum AdrOnStackNone = ~0u;
1092 uint ctfeAdrOnStack;
1093
1094 bool isargptr; // if parameter that _argptr points to
1095 bool ctorinit; // it has been initialized in a ctor
1096 bool iscatchvar; // this is the exception object variable in catch() clause
1097 bool isowner; // this is an Owner, despite it being `scope`
1098
1099 // Both these mean the var is not rebindable once assigned,
1100 // and the destructor gets run when it goes out of scope
1101 bool onstack; // it is a class that was allocated on the stack
1102 bool mynew; // it is a class new'd with custom operator new
1103
1104 byte canassign; // it can be assigned to
1105 bool overlapped; // if it is a field and has overlapping
1106 bool overlapUnsafe; // if it is an overlapping field and the overlaps are unsafe
1107 bool doNotInferScope; // do not infer 'scope' for this variable
1108 bool doNotInferReturn; // do not infer 'return' for this variable
1109 ubyte isdataseg; // private data for isDataseg 0 unset, 1 true, 2 false
1110
1111 bool isArgDtorVar; // temporary created to handle scope destruction of a function argument
1112
1113 final extern (D) this(const ref Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.undefined_)
1114 in
1115 {
1116 assert(ident);
1117 }
1118 do
1119 {
1120 //printf("VarDeclaration('%s')\n", ident.toChars());
1121 super(loc, ident);
1122 debug
1123 {
1124 if (!type && !_init)
1125 {
1126 //printf("VarDeclaration('%s')\n", ident.toChars());
1127 //*(char*)0=0;
1128 }
1129 }
1130
1131 assert(type || _init);
1132 this.type = type;
1133 this._init = _init;
1134 ctfeAdrOnStack = AdrOnStackNone;
1135 this.storage_class = storage_class;
1136 sequenceNumber = ++nextSequenceNumber;
1137 }
1138
1139 static VarDeclaration create(const ref Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.undefined_)
1140 {
1141 return new VarDeclaration(loc, type, ident, _init, storage_class);
1142 }
1143
1144 override VarDeclaration syntaxCopy(Dsymbol s)
1145 {
1146 //printf("VarDeclaration::syntaxCopy(%s)\n", toChars());
1147 assert(!s);
1148 auto v = new VarDeclaration(loc, type ? type.syntaxCopy() : null, ident, _init ? _init.syntaxCopy() : null, storage_class);
1149 v.comment = comment;
1150 return v;
1151 }
1152
1153 override final void setFieldOffset(AggregateDeclaration ad, uint* poffset, bool isunion)
1154 {
1155 //printf("VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars());
1156
1157 if (aliassym)
1158 {
1159 // If this variable was really a tuple, set the offsets for the tuple fields
1160 TupleDeclaration v2 = aliassym.isTupleDeclaration();
1161 assert(v2);
1162 for (size_t i = 0; i < v2.objects.dim; i++)
1163 {
1164 RootObject o = (*v2.objects)[i];
1165 assert(o.dyncast() == DYNCAST.expression);
1166 Expression e = cast(Expression)o;
1167 assert(e.op == TOK.dSymbol);
1168 DsymbolExp se = cast(DsymbolExp)e;
1169 se.s.setFieldOffset(ad, poffset, isunion);
1170 }
1171 return;
1172 }
1173
1174 if (!isField())
1175 return;
1176 assert(!(storage_class & (STC.static_ | STC.extern_ | STC.parameter | STC.tls)));
1177
1178 //printf("+VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars());
1179
1180 /* Fields that are tuples appear both as part of TupleDeclarations and
1181 * as members. That means ignore them if they are already a field.
1182 */
1183 if (offset)
1184 {
1185 // already a field
1186 *poffset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613
1187 return;
1188 }
1189 for (size_t i = 0; i < ad.fields.dim; i++)
1190 {
1191 if (ad.fields[i] == this)
1192 {
1193 // already a field
1194 *poffset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613
1195 return;
1196 }
1197 }
1198
1199 // Check for forward referenced types which will fail the size() call
1200 Type t = type.toBasetype();
1201 if (storage_class & STC.ref_)
1202 {
1203 // References are the size of a pointer
1204 t = Type.tvoidptr;
1205 }
1206 Type tv = t.baseElemOf();
1207 if (tv.ty == Tstruct)
1208 {
1209 auto ts = cast(TypeStruct)tv;
1210 assert(ts.sym != ad); // already checked in ad.determineFields()
1211 if (!ts.sym.determineSize(loc))
1212 {
1213 type = Type.terror;
1214 errors = true;
1215 return;
1216 }
1217 }
1218
1219 // List in ad.fields. Even if the type is error, it's necessary to avoid
1220 // pointless error diagnostic "more initializers than fields" on struct literal.
1221 ad.fields.push(this);
1222
1223 if (t.ty == Terror)
1224 return;
1225
1226 const sz = t.size(loc);
1227 assert(sz != SIZE_INVALID && sz < uint.max);
1228 uint memsize = cast(uint)sz; // size of member
1229 uint memalignsize = target.fieldalign(t); // size of member for alignment purposes
1230 offset = AggregateDeclaration.placeField(
1231 poffset,
1232 memsize, memalignsize, alignment,
1233 &ad.structsize, &ad.alignsize,
1234 isunion);
1235
1236 //printf("\t%s: memalignsize = %d\n", toChars(), memalignsize);
1237 //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize);
1238 }
1239
1240 override const(char)* kind() const
1241 {
1242 return "variable";
1243 }
1244
1245 override final inout(AggregateDeclaration) isThis() inout
1246 {
1247 if (!(storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.templateparameter | STC.tls | STC.gshared | STC.ctfe)))
1248 {
1249 /* The casting is necessary because `s = s.parent` is otherwise rejected
1250 */
1251 for (auto s = cast(Dsymbol)this; s; s = s.parent)
1252 {
1253 auto ad = (cast(inout)s).isMember();
1254 if (ad)
1255 return ad;
1256 if (!s.parent || !s.parent.isTemplateMixin())
1257 break;
1258 }
1259 }
1260 return null;
1261 }
1262
1263 override final bool needThis()
1264 {
1265 //printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class);
1266 return isField();
1267 }
1268
1269 override final bool isExport() const
1270 {
1271 return visibility.kind == Visibility.Kind.export_;
1272 }
1273
1274 override final bool isImportedSymbol() const
1275 {
1276 if (visibility.kind == Visibility.Kind.export_ && !_init && (storage_class & STC.static_ || parent.isModule()))
1277 return true;
1278 return false;
1279 }
1280
1281 /*******************************
1282 * Does symbol go into data segment?
1283 * Includes extern variables.
1284 */
1285 override final bool isDataseg()
1286 {
1287 version (none)
1288 {
1289 printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars());
1290 printf("%llx, isModule: %p, isTemplateInstance: %p, isNspace: %p\n",
1291 storage_class & (STC.static_ | STC.const_), parent.isModule(), parent.isTemplateInstance(), parent.isNspace());
1292 printf("parent = '%s'\n", parent.toChars());
1293 }
1294
1295 if (isdataseg == 0) // the value is not cached
1296 {
1297 isdataseg = 2; // The Variables does not go into the datasegment
1298
1299 if (!canTakeAddressOf())
1300 {
1301 return false;
1302 }
1303
1304 Dsymbol parent = toParent();
1305 if (!parent && !(storage_class & STC.static_))
1306 {
1307 error("forward referenced");
1308 type = Type.terror;
1309 }
1310 else if (storage_class & (STC.static_ | STC.extern_ | STC.tls | STC.gshared) ||
1311 parent.isModule() || parent.isTemplateInstance() || parent.isNspace())
1312 {
1313 assert(!isParameter() && !isResult());
1314 isdataseg = 1; // It is in the DataSegment
1315 }
1316 }
1317
1318 return (isdataseg == 1);
1319 }
1320 /************************************
1321 * Does symbol go into thread local storage?
1322 */
1323 override final bool isThreadlocal()
1324 {
1325 //printf("VarDeclaration::isThreadlocal(%p, '%s')\n", this, toChars());
1326 /* Data defaults to being thread-local. It is not thread-local
1327 * if it is immutable, const or shared.
1328 */
1329 bool i = isDataseg() && !(storage_class & (STC.immutable_ | STC.const_ | STC.shared_ | STC.gshared));
1330 //printf("\treturn %d\n", i);
1331 return i;
1332 }
1333
1334 /********************************************
1335 * Can variable be read and written by CTFE?
1336 */
1337 final bool isCTFE()
1338 {
1339 return (storage_class & STC.ctfe) != 0; // || !isDataseg();
1340 }
1341
1342 final bool isOverlappedWith(VarDeclaration v)
1343 {
1344 const vsz = v.type.size();
1345 const tsz = type.size();
1346 assert(vsz != SIZE_INVALID && tsz != SIZE_INVALID);
1347 return offset < v.offset + vsz &&
1348 v.offset < offset + tsz;
1349 }
1350
1351 override final bool hasPointers()
1352 {
1353 //printf("VarDeclaration::hasPointers() %s, ty = %d\n", toChars(), type.ty);
1354 return (!isDataseg() && type.hasPointers());
1355 }
1356
1357 /*************************************
1358 * Return true if we can take the address of this variable.
1359 */
1360 final bool canTakeAddressOf()
1361 {
1362 return !(storage_class & STC.manifest);
1363 }
1364
1365 /******************************************
1366 * Return true if variable needs to call the destructor.
1367 */
1368 final bool needsScopeDtor()
1369 {
1370 //printf("VarDeclaration::needsScopeDtor() %s\n", toChars());
1371 return edtor && !(storage_class & STC.nodtor);
1372 }
1373
1374 /******************************************
1375 * If a variable has a scope destructor call, return call for it.
1376 * Otherwise, return NULL.
1377 */
1378 extern (D) final Expression callScopeDtor(Scope* sc)
1379 {
1380 //printf("VarDeclaration::callScopeDtor() %s\n", toChars());
1381
1382 // Destruction of STC.field's is handled by buildDtor()
1383 if (storage_class & (STC.nodtor | STC.ref_ | STC.out_ | STC.field))
1384 {
1385 return null;
1386 }
1387
1388 if (iscatchvar)
1389 return null; // destructor is built by `void semantic(Catch c, Scope* sc)`, not here
1390
1391 Expression e = null;
1392 // Destructors for structs and arrays of structs
1393 Type tv = type.baseElemOf();
1394 if (tv.ty == Tstruct)
1395 {
1396 StructDeclaration sd = (cast(TypeStruct)tv).sym;
1397 if (!sd.dtor || sd.errors)
1398 return null;
1399
1400 const sz = type.size();
1401 assert(sz != SIZE_INVALID);
1402 if (!sz)
1403 return null;
1404
1405 if (type.toBasetype().ty == Tstruct)
1406 {
1407 // v.__xdtor()
1408 e = new VarExp(loc, this);
1409
1410 /* This is a hack so we can call destructors on const/immutable objects.
1411 * Need to add things like "const ~this()" and "immutable ~this()" to
1412 * fix properly.
1413 */
1414 e.type = e.type.mutableOf();
1415
1416 // Enable calling destructors on shared objects.
1417 // The destructor is always a single, non-overloaded function,
1418 // and must serve both shared and non-shared objects.
1419 e.type = e.type.unSharedOf;
1420
1421 e = new DotVarExp(loc, e, sd.dtor, false);
1422 e = new CallExp(loc, e);
1423 }
1424 else
1425 {
1426 // __ArrayDtor(v[0 .. n])
1427 e = new VarExp(loc, this);
1428
1429 const sdsz = sd.type.size();
1430 assert(sdsz != SIZE_INVALID && sdsz != 0);
1431 const n = sz / sdsz;
1432 e = new SliceExp(loc, e, new IntegerExp(loc, 0, Type.tsize_t), new IntegerExp(loc, n, Type.tsize_t));
1433
1434 // Prevent redundant bounds check
1435 (cast(SliceExp)e).upperIsInBounds = true;
1436 (cast(SliceExp)e).lowerIsLessThanUpper = true;
1437
1438 // This is a hack so we can call destructors on const/immutable objects.
1439 e.type = sd.type.arrayOf();
1440
1441 e = new CallExp(loc, new IdentifierExp(loc, Id.__ArrayDtor), e);
1442 }
1443 return e;
1444 }
1445 // Destructors for classes
1446 if (storage_class & (STC.auto_ | STC.scope_) && !(storage_class & STC.parameter))
1447 {
1448 for (ClassDeclaration cd = type.isClassHandle(); cd; cd = cd.baseClass)
1449 {
1450 /* We can do better if there's a way with onstack
1451 * classes to determine if there's no way the monitor
1452 * could be set.
1453 */
1454 //if (cd.isInterfaceDeclaration())
1455 // error("interface `%s` cannot be scope", cd.toChars());
1456
1457 // Destroying C++ scope classes crashes currently. Since C++ class dtors are not currently supported, simply do not run dtors for them.
1458 // See https://issues.dlang.org/show_bug.cgi?id=13182
1459 if (cd.classKind == ClassKind.cpp)
1460 {
1461 break;
1462 }
1463 if (mynew || onstack) // if any destructors
1464 {
1465 // delete this;
1466 Expression ec;
1467 ec = new VarExp(loc, this);
1468 e = new DeleteExp(loc, ec, true);
1469 e.type = Type.tvoid;
1470 break;
1471 }
1472 }
1473 }
1474 return e;
1475 }
1476
1477 /*******************************************
1478 * If variable has a constant expression initializer, get it.
1479 * Otherwise, return null.
1480 */
1481 extern (D) final Expression getConstInitializer(bool needFullType = true)
1482 {
1483 assert(type && _init);
1484
1485 // Ungag errors when not speculative
1486 uint oldgag = global.gag;
1487 if (global.gag)
1488 {
1489 Dsymbol sym = toParent().isAggregateDeclaration();
1490 if (sym && !sym.isSpeculative())
1491 global.gag = 0;
1492 }
1493
1494 if (_scope)
1495 {
1496 inuse++;
1497 _init = _init.initializerSemantic(_scope, type, INITinterpret);
1498 _scope = null;
1499 inuse--;
1500 }
1501
1502 Expression e = _init.initializerToExpression(needFullType ? type : null);
1503 global.gag = oldgag;
1504 return e;
1505 }
1506
1507 /*******************************************
1508 * Helper function for the expansion of manifest constant.
1509 */
1510 extern (D) final Expression expandInitializer(Loc loc)
1511 {
1512 assert((storage_class & STC.manifest) && _init);
1513
1514 auto e = getConstInitializer();
1515 if (!e)
1516 {
1517 .error(loc, "cannot make expression out of initializer for `%s`", toChars());
1518 return ErrorExp.get();
1519 }
1520
1521 e = e.copy();
1522 e.loc = loc; // for better error message
1523 return e;
1524 }
1525
1526 override final void checkCtorConstInit()
1527 {
1528 version (none)
1529 {
1530 /* doesn't work if more than one static ctor */
1531 if (ctorinit == 0 && isCtorinit() && !isField())
1532 error("missing initializer in static constructor for const variable");
1533 }
1534 }
1535
1536 /************************************
1537 * Check to see if this variable is actually in an enclosing function
1538 * rather than the current one.
1539 * Update nestedrefs[], closureVars[] and outerVars[].
1540 * Returns: true if error occurs.
1541 */
1542 extern (D) final bool checkNestedReference(Scope* sc, Loc loc)
1543 {
1544 //printf("VarDeclaration::checkNestedReference() %s\n", toChars());
1545 if (sc.intypeof == 1 || (sc.flags & SCOPE.ctfe))
1546 return false;
1547 if (!parent || parent == sc.parent)
1548 return false;
1549 if (isDataseg() || (storage_class & STC.manifest))
1550 return false;
1551
1552 // The current function
1553 FuncDeclaration fdthis = sc.parent.isFuncDeclaration();
1554 if (!fdthis)
1555 return false; // out of function scope
1556
1557 Dsymbol p = toParent2();
1558
1559 // Function literals from fdthis to p must be delegates
1560 ensureStaticLinkTo(fdthis, p);
1561
1562 // The function that this variable is in
1563 FuncDeclaration fdv = p.isFuncDeclaration();
1564 if (!fdv || fdv == fdthis)
1565 return false;
1566
1567 // Add fdthis to nestedrefs[] if not already there
1568 if (!nestedrefs.contains(fdthis))
1569 nestedrefs.push(fdthis);
1570
1571 //printf("\tfdv = %s\n", fdv.toChars());
1572 //printf("\tfdthis = %s\n", fdthis.toChars());
1573 if (loc.isValid())
1574 {
1575 if (fdthis.getLevelAndCheck(loc, sc, fdv, this) == fdthis.LevelError)
1576 return true;
1577 }
1578
1579 // Add this VarDeclaration to fdv.closureVars[] if not already there
1580 if (!sc.intypeof && !(sc.flags & SCOPE.compile) &&
1581 // https://issues.dlang.org/show_bug.cgi?id=17605
1582 (fdv.flags & FUNCFLAG.compileTimeOnly || !(fdthis.flags & FUNCFLAG.compileTimeOnly))
1583 )
1584 {
1585 if (!fdv.closureVars.contains(this))
1586 fdv.closureVars.push(this);
1587 }
1588
1589 if (!fdthis.outerVars.contains(this))
1590 fdthis.outerVars.push(this);
1591
1592 //printf("fdthis is %s\n", fdthis.toChars());
1593 //printf("var %s in function %s is nested ref\n", toChars(), fdv.toChars());
1594 // __dollar creates problems because it isn't a real variable
1595 // https://issues.dlang.org/show_bug.cgi?id=3326
1596 if (ident == Id.dollar)
1597 {
1598 .error(loc, "cannnot use `$` inside a function literal");
1599 return true;
1600 }
1601 if (ident == Id.withSym) // https://issues.dlang.org/show_bug.cgi?id=1759
1602 {
1603 ExpInitializer ez = _init.isExpInitializer();
1604 assert(ez);
1605 Expression e = ez.exp;
1606 if (e.op == TOK.construct || e.op == TOK.blit)
1607 e = (cast(AssignExp)e).e2;
1608 return lambdaCheckForNestedRef(e, sc);
1609 }
1610
1611 return false;
1612 }
1613
1614 override final Dsymbol toAlias()
1615 {
1616 //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym);
1617 if ((!type || !type.deco) && _scope)
1618 dsymbolSemantic(this, _scope);
1619
1620 assert(this != aliassym);
1621 Dsymbol s = aliassym ? aliassym.toAlias() : this;
1622 return s;
1623 }
1624
1625 // Eliminate need for dynamic_cast
1626 override final inout(VarDeclaration) isVarDeclaration() inout
1627 {
1628 return this;
1629 }
1630
1631 override void accept(Visitor v)
1632 {
1633 v.visit(this);
1634 }
1635
1636 /**********************************
1637 * Determine if `this` has a lifetime that lasts past
1638 * the destruction of `v`
1639 * Params:
1640 * v = variable to test against
1641 * Returns:
1642 * true if it does
1643 */
1644 final bool enclosesLifetimeOf(VarDeclaration v) const pure
1645 {
1646 return sequenceNumber < v.sequenceNumber;
1647 }
1648
1649 /***************************************
1650 * Add variable to maybes[].
1651 * When a maybescope variable `v` is assigned to a maybescope variable `this`,
1652 * we cannot determine if `this` is actually scope until the semantic
1653 * analysis for the function is completed. Thus, we save the data
1654 * until then.
1655 * Params:
1656 * v = an STC.maybescope variable that was assigned to `this`
1657 */
1658 final void addMaybe(VarDeclaration v)
1659 {
1660 //printf("add %s to %s's list of dependencies\n", v.toChars(), toChars());
1661 if (!maybes)
1662 maybes = new VarDeclarations();
1663 maybes.push(v);
1664 }
1665 }
1666
1667 /***********************************************************
1668 * This is a shell around a back end symbol
1669 */
1670 extern (C++) final class SymbolDeclaration : Declaration
1671 {
1672 StructDeclaration dsym;
1673
1674 extern (D) this(const ref Loc loc, StructDeclaration dsym)
1675 {
1676 super(loc, dsym.ident);
1677 this.dsym = dsym;
1678 storage_class |= STC.const_;
1679 }
1680
1681 // Eliminate need for dynamic_cast
1682 override inout(SymbolDeclaration) isSymbolDeclaration() inout
1683 {
1684 return this;
1685 }
1686
1687 override void accept(Visitor v)
1688 {
1689 v.visit(this);
1690 }
1691 }
1692
1693 /***********************************************************
1694 */
1695 extern (C++) class TypeInfoDeclaration : VarDeclaration
1696 {
1697 Type tinfo;
1698
1699 final extern (D) this(Type tinfo)
1700 {
1701 super(Loc.initial, Type.dtypeinfo.type, tinfo.getTypeInfoIdent(), null);
1702 this.tinfo = tinfo;
1703 storage_class = STC.static_ | STC.gshared;
1704 visibility = Visibility(Visibility.Kind.public_);
1705 linkage = LINK.c;
1706 alignment = target.ptrsize;
1707 }
1708
1709 static TypeInfoDeclaration create(Type tinfo)
1710 {
1711 return new TypeInfoDeclaration(tinfo);
1712 }
1713
1714 override final TypeInfoDeclaration syntaxCopy(Dsymbol s)
1715 {
1716 assert(0); // should never be produced by syntax
1717 }
1718
1719 override final const(char)* toChars() const
1720 {
1721 //printf("TypeInfoDeclaration::toChars() tinfo = %s\n", tinfo.toChars());
1722 OutBuffer buf;
1723 buf.writestring("typeid(");
1724 buf.writestring(tinfo.toChars());
1725 buf.writeByte(')');
1726 return buf.extractChars();
1727 }
1728
1729 override final inout(TypeInfoDeclaration) isTypeInfoDeclaration() inout
1730 {
1731 return this;
1732 }
1733
1734 override void accept(Visitor v)
1735 {
1736 v.visit(this);
1737 }
1738 }
1739
1740 /***********************************************************
1741 */
1742 extern (C++) final class TypeInfoStructDeclaration : TypeInfoDeclaration
1743 {
1744 extern (D) this(Type tinfo)
1745 {
1746 super(tinfo);
1747 if (!Type.typeinfostruct)
1748 {
1749 ObjectNotFound(Id.TypeInfo_Struct);
1750 }
1751 type = Type.typeinfostruct.type;
1752 }
1753
1754 static TypeInfoStructDeclaration create(Type tinfo)
1755 {
1756 return new TypeInfoStructDeclaration(tinfo);
1757 }
1758
1759 override void accept(Visitor v)
1760 {
1761 v.visit(this);
1762 }
1763 }
1764
1765 /***********************************************************
1766 */
1767 extern (C++) final class TypeInfoClassDeclaration : TypeInfoDeclaration
1768 {
1769 extern (D) this(Type tinfo)
1770 {
1771 super(tinfo);
1772 if (!Type.typeinfoclass)
1773 {
1774 ObjectNotFound(Id.TypeInfo_Class);
1775 }
1776 type = Type.typeinfoclass.type;
1777 }
1778
1779 static TypeInfoClassDeclaration create(Type tinfo)
1780 {
1781 return new TypeInfoClassDeclaration(tinfo);
1782 }
1783
1784 override void accept(Visitor v)
1785 {
1786 v.visit(this);
1787 }
1788 }
1789
1790 /***********************************************************
1791 */
1792 extern (C++) final class TypeInfoInterfaceDeclaration : TypeInfoDeclaration
1793 {
1794 extern (D) this(Type tinfo)
1795 {
1796 super(tinfo);
1797 if (!Type.typeinfointerface)
1798 {
1799 ObjectNotFound(Id.TypeInfo_Interface);
1800 }
1801 type = Type.typeinfointerface.type;
1802 }
1803
1804 static TypeInfoInterfaceDeclaration create(Type tinfo)
1805 {
1806 return new TypeInfoInterfaceDeclaration(tinfo);
1807 }
1808
1809 override void accept(Visitor v)
1810 {
1811 v.visit(this);
1812 }
1813 }
1814
1815 /***********************************************************
1816 */
1817 extern (C++) final class TypeInfoPointerDeclaration : TypeInfoDeclaration
1818 {
1819 extern (D) this(Type tinfo)
1820 {
1821 super(tinfo);
1822 if (!Type.typeinfopointer)
1823 {
1824 ObjectNotFound(Id.TypeInfo_Pointer);
1825 }
1826 type = Type.typeinfopointer.type;
1827 }
1828
1829 static TypeInfoPointerDeclaration create(Type tinfo)
1830 {
1831 return new TypeInfoPointerDeclaration(tinfo);
1832 }
1833
1834 override void accept(Visitor v)
1835 {
1836 v.visit(this);
1837 }
1838 }
1839
1840 /***********************************************************
1841 */
1842 extern (C++) final class TypeInfoArrayDeclaration : TypeInfoDeclaration
1843 {
1844 extern (D) this(Type tinfo)
1845 {
1846 super(tinfo);
1847 if (!Type.typeinfoarray)
1848 {
1849 ObjectNotFound(Id.TypeInfo_Array);
1850 }
1851 type = Type.typeinfoarray.type;
1852 }
1853
1854 static TypeInfoArrayDeclaration create(Type tinfo)
1855 {
1856 return new TypeInfoArrayDeclaration(tinfo);
1857 }
1858
1859 override void accept(Visitor v)
1860 {
1861 v.visit(this);
1862 }
1863 }
1864
1865 /***********************************************************
1866 */
1867 extern (C++) final class TypeInfoStaticArrayDeclaration : TypeInfoDeclaration
1868 {
1869 extern (D) this(Type tinfo)
1870 {
1871 super(tinfo);
1872 if (!Type.typeinfostaticarray)
1873 {
1874 ObjectNotFound(Id.TypeInfo_StaticArray);
1875 }
1876 type = Type.typeinfostaticarray.type;
1877 }
1878
1879 static TypeInfoStaticArrayDeclaration create(Type tinfo)
1880 {
1881 return new TypeInfoStaticArrayDeclaration(tinfo);
1882 }
1883
1884 override void accept(Visitor v)
1885 {
1886 v.visit(this);
1887 }
1888 }
1889
1890 /***********************************************************
1891 */
1892 extern (C++) final class TypeInfoAssociativeArrayDeclaration : TypeInfoDeclaration
1893 {
1894 extern (D) this(Type tinfo)
1895 {
1896 super(tinfo);
1897 if (!Type.typeinfoassociativearray)
1898 {
1899 ObjectNotFound(Id.TypeInfo_AssociativeArray);
1900 }
1901 type = Type.typeinfoassociativearray.type;
1902 }
1903
1904 static TypeInfoAssociativeArrayDeclaration create(Type tinfo)
1905 {
1906 return new TypeInfoAssociativeArrayDeclaration(tinfo);
1907 }
1908
1909 override void accept(Visitor v)
1910 {
1911 v.visit(this);
1912 }
1913 }
1914
1915 /***********************************************************
1916 */
1917 extern (C++) final class TypeInfoEnumDeclaration : TypeInfoDeclaration
1918 {
1919 extern (D) this(Type tinfo)
1920 {
1921 super(tinfo);
1922 if (!Type.typeinfoenum)
1923 {
1924 ObjectNotFound(Id.TypeInfo_Enum);
1925 }
1926 type = Type.typeinfoenum.type;
1927 }
1928
1929 static TypeInfoEnumDeclaration create(Type tinfo)
1930 {
1931 return new TypeInfoEnumDeclaration(tinfo);
1932 }
1933
1934 override void accept(Visitor v)
1935 {
1936 v.visit(this);
1937 }
1938 }
1939
1940 /***********************************************************
1941 */
1942 extern (C++) final class TypeInfoFunctionDeclaration : TypeInfoDeclaration
1943 {
1944 extern (D) this(Type tinfo)
1945 {
1946 super(tinfo);
1947 if (!Type.typeinfofunction)
1948 {
1949 ObjectNotFound(Id.TypeInfo_Function);
1950 }
1951 type = Type.typeinfofunction.type;
1952 }
1953
1954 static TypeInfoFunctionDeclaration create(Type tinfo)
1955 {
1956 return new TypeInfoFunctionDeclaration(tinfo);
1957 }
1958
1959 override void accept(Visitor v)
1960 {
1961 v.visit(this);
1962 }
1963 }
1964
1965 /***********************************************************
1966 */
1967 extern (C++) final class TypeInfoDelegateDeclaration : TypeInfoDeclaration
1968 {
1969 extern (D) this(Type tinfo)
1970 {
1971 super(tinfo);
1972 if (!Type.typeinfodelegate)
1973 {
1974 ObjectNotFound(Id.TypeInfo_Delegate);
1975 }
1976 type = Type.typeinfodelegate.type;
1977 }
1978
1979 static TypeInfoDelegateDeclaration create(Type tinfo)
1980 {
1981 return new TypeInfoDelegateDeclaration(tinfo);
1982 }
1983
1984 override void accept(Visitor v)
1985 {
1986 v.visit(this);
1987 }
1988 }
1989
1990 /***********************************************************
1991 */
1992 extern (C++) final class TypeInfoTupleDeclaration : TypeInfoDeclaration
1993 {
1994 extern (D) this(Type tinfo)
1995 {
1996 super(tinfo);
1997 if (!Type.typeinfotypelist)
1998 {
1999 ObjectNotFound(Id.TypeInfo_Tuple);
2000 }
2001 type = Type.typeinfotypelist.type;
2002 }
2003
2004 static TypeInfoTupleDeclaration create(Type tinfo)
2005 {
2006 return new TypeInfoTupleDeclaration(tinfo);
2007 }
2008
2009 override void accept(Visitor v)
2010 {
2011 v.visit(this);
2012 }
2013 }
2014
2015 /***********************************************************
2016 */
2017 extern (C++) final class TypeInfoConstDeclaration : TypeInfoDeclaration
2018 {
2019 extern (D) this(Type tinfo)
2020 {
2021 super(tinfo);
2022 if (!Type.typeinfoconst)
2023 {
2024 ObjectNotFound(Id.TypeInfo_Const);
2025 }
2026 type = Type.typeinfoconst.type;
2027 }
2028
2029 static TypeInfoConstDeclaration create(Type tinfo)
2030 {
2031 return new TypeInfoConstDeclaration(tinfo);
2032 }
2033
2034 override void accept(Visitor v)
2035 {
2036 v.visit(this);
2037 }
2038 }
2039
2040 /***********************************************************
2041 */
2042 extern (C++) final class TypeInfoInvariantDeclaration : TypeInfoDeclaration
2043 {
2044 extern (D) this(Type tinfo)
2045 {
2046 super(tinfo);
2047 if (!Type.typeinfoinvariant)
2048 {
2049 ObjectNotFound(Id.TypeInfo_Invariant);
2050 }
2051 type = Type.typeinfoinvariant.type;
2052 }
2053
2054 static TypeInfoInvariantDeclaration create(Type tinfo)
2055 {
2056 return new TypeInfoInvariantDeclaration(tinfo);
2057 }
2058
2059 override void accept(Visitor v)
2060 {
2061 v.visit(this);
2062 }
2063 }
2064
2065 /***********************************************************
2066 */
2067 extern (C++) final class TypeInfoSharedDeclaration : TypeInfoDeclaration
2068 {
2069 extern (D) this(Type tinfo)
2070 {
2071 super(tinfo);
2072 if (!Type.typeinfoshared)
2073 {
2074 ObjectNotFound(Id.TypeInfo_Shared);
2075 }
2076 type = Type.typeinfoshared.type;
2077 }
2078
2079 static TypeInfoSharedDeclaration create(Type tinfo)
2080 {
2081 return new TypeInfoSharedDeclaration(tinfo);
2082 }
2083
2084 override void accept(Visitor v)
2085 {
2086 v.visit(this);
2087 }
2088 }
2089
2090 /***********************************************************
2091 */
2092 extern (C++) final class TypeInfoWildDeclaration : TypeInfoDeclaration
2093 {
2094 extern (D) this(Type tinfo)
2095 {
2096 super(tinfo);
2097 if (!Type.typeinfowild)
2098 {
2099 ObjectNotFound(Id.TypeInfo_Wild);
2100 }
2101 type = Type.typeinfowild.type;
2102 }
2103
2104 static TypeInfoWildDeclaration create(Type tinfo)
2105 {
2106 return new TypeInfoWildDeclaration(tinfo);
2107 }
2108
2109 override void accept(Visitor v)
2110 {
2111 v.visit(this);
2112 }
2113 }
2114
2115 /***********************************************************
2116 */
2117 extern (C++) final class TypeInfoVectorDeclaration : TypeInfoDeclaration
2118 {
2119 extern (D) this(Type tinfo)
2120 {
2121 super(tinfo);
2122 if (!Type.typeinfovector)
2123 {
2124 ObjectNotFound(Id.TypeInfo_Vector);
2125 }
2126 type = Type.typeinfovector.type;
2127 }
2128
2129 static TypeInfoVectorDeclaration create(Type tinfo)
2130 {
2131 return new TypeInfoVectorDeclaration(tinfo);
2132 }
2133
2134 override void accept(Visitor v)
2135 {
2136 v.visit(this);
2137 }
2138 }
2139
2140 /***********************************************************
2141 * For the "this" parameter to member functions
2142 */
2143 extern (C++) final class ThisDeclaration : VarDeclaration
2144 {
2145 extern (D) this(const ref Loc loc, Type t)
2146 {
2147 super(loc, t, Id.This, null);
2148 storage_class |= STC.nodtor;
2149 }
2150
2151 override ThisDeclaration syntaxCopy(Dsymbol s)
2152 {
2153 assert(0); // should never be produced by syntax
2154 }
2155
2156 override inout(ThisDeclaration) isThisDeclaration() inout
2157 {
2158 return this;
2159 }
2160
2161 override void accept(Visitor v)
2162 {
2163 v.visit(this);
2164 }
2165 }