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