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