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