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