2 * Miscellaneous declarations, including typedef, alias, variable declarations including the
3 * implicit this declaration, type tuples, ClassInfo, ModuleInfo and various TypeInfos.
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
13 module dmd.declaration;
15 import core.stdc.stdio;
17 import dmd.arraytypes;
22 import dmd.delegatize;
26 import dmd.dsymbolsem;
29 import dmd.expression;
33 import dmd.identifier;
38 import dmd.common.outbuffer;
39 import dmd.root.rootobject;
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.
50 bool checkFrameAccess(Loc loc, Scope* sc, AggregateDeclaration ad, size_t iStart = 0)
52 Dsymbol sparent = ad.toParentLocal();
53 Dsymbol sparent2 = ad.toParent2();
55 if (ad.isNested() && s)
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))
62 error(loc, "cannot access frame pointer of `%s`", ad.toPrettyChars());
68 for (size_t i = iStart; i < ad.fields.dim; i++)
70 VarDeclaration vd = ad.fields[i];
71 Type tb = vd.type.baseElemOf();
74 result |= checkFrameAccess(loc, sc, (cast(TypeStruct)tb).sym);
80 /***********************************************
81 * Mark variable v as modified if it is inside a constructor that var
84 bool modifyFieldVar(Loc loc, Scope* sc, VarDeclaration var, Expression e1)
86 //printf("modifyFieldVar(var = %s)\n", var.toChars());
90 FuncDeclaration fd = null;
92 fd = s.isFuncDeclaration();
94 ((fd.isCtorDeclaration() && var.isField()) ||
95 (fd.isStaticCtorDeclaration() && !var.isField())) &&
96 fd.toParentDecl() == var.toParent2() &&
97 (!e1 || e1.op == EXP.this_))
102 //printf("setting ctorinit\n");
104 if (var.isField() && sc.ctorflow.fieldinit.length && !sc.intypeof)
107 auto mustInit = ((var.storage_class & STC.nodefaultctor) != 0 ||
108 var.type.needsNested());
110 const dim = sc.ctorflow.fieldinit.length;
111 auto ad = fd.isMemberDecl();
114 for (i = 0; i < dim; i++) // same as findFieldIndexByName in ctfeexp.c ?
116 if (ad.fields[i] == var)
120 auto fieldInit = &sc.ctorflow.fieldinit[i];
121 const fi = fieldInit.csx;
123 if (fi & CSX.this_ctor)
125 if (var.type.isMutable() && e1.type.isMutable())
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.");
134 else if (sc.inLoop || (fi & CSX.label))
136 if (!mustInit && var.type.isMutable() && e1.type.isMutable())
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());
145 fieldInit.csx |= CSX.this_ctor;
146 fieldInit.loc = e1.loc;
147 if (var.overlapped) // https://issues.dlang.org/show_bug.cgi?id=15258
149 foreach (j, v; ad.fields)
151 if (v is var || !var.isOverlappedWith(v))
154 sc.ctorflow.fieldinit[j].csx = CSX.this_ctor;
158 else if (fd != sc.func)
160 if (var.type.isMutable())
162 else if (sc.func.fes)
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());
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());
175 else if (fd.isStaticCtorDeclaration() && !fd.isSharedStaticCtorDeclaration() &&
176 var.type.isImmutable())
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.");
188 s = s.toParentP(var.toParent2());
197 /******************************************
199 extern (C++) void ObjectNotFound(Identifier id)
201 error(Loc.initial, "`%s` not found. object.d may be incorrectly installed or corrupt.", id.toChars());
205 /* Accumulator for successive matches.
207 struct MatchAccumulator
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
215 /***********************************************************
217 extern (C++) abstract class Declaration : Dsymbol
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
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
230 // overridden symbol with pragma(mangle, "...")
231 const(char)[] mangleOverride;
233 final extern (D) this(Identifier ident)
236 visibility = Visibility(Visibility.Kind.undefined);
239 final extern (D) this(const ref Loc loc, Identifier ident)
242 visibility = Visibility(Visibility.Kind.undefined);
245 override const(char)* kind() const
247 return "declaration";
250 override final d_uns64 size(const ref Loc loc)
253 const sz = type.size();
254 if (sz == SIZE_INVALID)
260 * Issue an error if an attempt to call a disabled method is made
262 * If the declaration is disabled but inside a disabled function,
263 * returns `true` but do not issue an error message.
266 * loc = Location information of the call
267 * sc = Scope in which the call occurs
268 * isAliasedDeclaration = if `true` searches overload set
271 * `true` if this `Declaration` is `@disable`d, `false` otherwise.
273 extern (D) final bool checkDisabled(Loc loc, Scope* sc, bool isAliasedDeclaration = false)
275 if (!(storage_class & STC.disable))
278 if (sc.func && sc.func.storage_class & STC.disable)
281 if (auto p = toParent())
283 if (auto postblit = isPostBlitDeclaration())
285 /* https://issues.dlang.org/show_bug.cgi?id=21885
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.
292 if (postblit.generated)
294 auto sd = p.isStructDeclaration();
296 for (size_t i = 0; i < sd.fields.dim; i++)
298 auto structField = sd.fields[i];
299 if (structField.overlapped)
301 Type tv = structField.type.baseElemOf();
302 if (tv.ty != Tstruct)
304 auto sdv = (cast(TypeStruct)tv).sym;
307 if (sdv.postblit.isDisabled())
309 p.error(loc, "is not copyable because field `%s` is not copyable", structField.toChars());
314 p.error(loc, "is not copyable because it has a disabled postblit");
319 // if the function is @disabled, maybe there
320 // is an overload in the overload set that isn't
321 if (isAliasedDeclaration)
323 FuncDeclaration fd = isFuncDeclaration();
326 for (FuncDeclaration ovl = fd; ovl; ovl = cast(FuncDeclaration)ovl.overnext)
327 if (!(ovl.storage_class & STC.disable))
332 if (auto ctor = isCtorDeclaration())
334 if (ctor.isCpCtor && ctor.generated)
336 .error(loc, "Generating an `inout` copy constructor for `struct %s` failed, therefore instances of it are uncopyable", parent.toPrettyChars());
340 error(loc, "cannot be used because it is annotated with `@disable`");
344 /*************************************
345 * Check to see if declaration can be modified in this context (sc).
346 * Issue error if not.
348 * loc = location for error messages
349 * e1 = `null` or `this` expression when this declaration is a field
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.
355 * Modifiable.yes or Modifiable.initialization
357 extern (D) final Modifiable checkModify(Loc loc, Scope* sc, Expression e1, ModifyFlags flag)
359 VarDeclaration v = isVarDeclaration();
360 if (v && v.canassign)
361 return Modifiable.initialization;
363 if (isParameter() || isResult())
365 for (Scope* scx = sc; scx; scx = scx.enclosing)
367 if (scx.func == parent && (scx.flags & SCOPE.contract))
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
377 if (e1 && e1.op == EXP.this_ && isField())
379 VarDeclaration vthis = (cast(ThisExp)e1).var;
380 for (Scope* scx = sc; scx; scx = scx.enclosing)
382 if (scx.func == vthis.parent && (scx.flags & SCOPE.contract))
384 if (!(flag & ModifyFlags.noError))
385 error(loc, "cannot modify parameter `this` in contract");
386 return Modifiable.initialization; // do not report type related errors
391 if (v && (v.isCtorinit() || isField()))
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;
400 return Modifiable.yes;
403 override final Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
405 Dsymbol s = Dsymbol.search(loc, ident, flags);
408 s = type.toDsymbol(_scope);
410 s = s.search(loc, ident, flags);
415 final bool isStatic() const pure nothrow @nogc @safe
417 return (storage_class & STC.static_) != 0;
435 bool isCodeseg() const pure nothrow @nogc @safe
440 final bool isFinal() const pure nothrow @nogc @safe
442 return (storage_class & STC.final_) != 0;
447 return (storage_class & STC.abstract_) != 0;
450 final bool isConst() const pure nothrow @nogc @safe
452 return (storage_class & STC.const_) != 0;
455 final bool isImmutable() const pure nothrow @nogc @safe
457 return (storage_class & STC.immutable_) != 0;
460 final bool isWild() const pure nothrow @nogc @safe
462 return (storage_class & STC.wild) != 0;
465 final bool isAuto() const pure nothrow @nogc @safe
467 return (storage_class & STC.auto_) != 0;
470 final bool isScope() const pure nothrow @nogc @safe
472 return (storage_class & STC.scope_) != 0;
475 final bool isSynchronized() const pure nothrow @nogc @safe
477 return (storage_class & STC.synchronized_) != 0;
480 final bool isParameter() const pure nothrow @nogc @safe
482 return (storage_class & STC.parameter) != 0;
485 override final bool isDeprecated() const pure nothrow @nogc @safe
487 return (storage_class & STC.deprecated_) != 0;
490 final bool isDisabled() const pure nothrow @nogc @safe
492 return (storage_class & STC.disable) != 0;
495 final bool isOverride() const pure nothrow @nogc @safe
497 return (storage_class & STC.override_) != 0;
500 final bool isResult() const pure nothrow @nogc @safe
502 return (storage_class & STC.result) != 0;
505 final bool isField() const pure nothrow @nogc @safe
507 return (storage_class & STC.field) != 0;
510 final bool isIn() const pure nothrow @nogc @safe
512 return (storage_class & STC.in_) != 0;
515 final bool isOut() const pure nothrow @nogc @safe
517 return (storage_class & STC.out_) != 0;
520 final bool isRef() const pure nothrow @nogc @safe
522 return (storage_class & STC.ref_) != 0;
525 /// Returns: Whether the variable is a reference, annotated with `out` or `ref`
526 final bool isReference() const pure nothrow @nogc @safe
528 return (storage_class & (STC.ref_ | STC.out_)) != 0;
531 final bool isFuture() const pure nothrow @nogc @safe
533 return (storage_class & STC.future) != 0;
536 override final Visibility visible() pure nothrow @nogc @safe
541 override final inout(Declaration) isDeclaration() inout pure nothrow @nogc @safe
546 override void accept(Visitor v)
552 /***********************************************************
554 extern (C++) final class TupleDeclaration : Declaration
557 bool isexp; // true: expression tuple
558 TypeTuple tupletype; // !=null if this is a type tuple
560 extern (D) this(const ref Loc loc, Identifier ident, Objects* objects)
563 this.objects = objects;
566 override TupleDeclaration syntaxCopy(Dsymbol s)
571 override const(char)* kind() const
576 override Type getType()
578 /* If this tuple represents a type, return that type
581 //printf("TupleDeclaration::getType() %s\n", toChars());
586 /* It's only a type tuple if all the Object's are types
588 for (size_t i = 0; i < objects.dim; i++)
590 RootObject o = (*objects)[i];
591 if (o.dyncast() != DYNCAST.type)
593 //printf("\tnot[%d], %p, %d\n", i, o, o.dyncast());
598 /* We know it's a type tuple, so build the TypeTuple
600 Types* types = cast(Types*)objects;
601 auto args = new Parameters(objects.dim);
604 for (size_t i = 0; i < types.dim; i++)
606 Type t = (*types)[i];
607 //printf("type = %s\n", t.toChars());
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);
618 auto arg = new Parameter(0, t, null, null, null);
625 tupletype = new TypeTuple(args);
627 return tupletype.typeSemantic(Loc.initial, null);
632 override Dsymbol toAlias2()
634 //printf("TupleDeclaration::toAlias2() '%s' objects = %s\n", toChars(), objects.toChars());
635 for (size_t i = 0; i < objects.dim; i++)
637 RootObject o = (*objects)[i];
638 if (Dsymbol s = isDsymbol(o))
647 override bool needThis()
649 //printf("TupleDeclaration::needThis(%s)\n", toChars());
650 for (size_t i = 0; i < objects.dim; i++)
652 RootObject o = (*objects)[i];
653 if (o.dyncast() == DYNCAST.expression)
655 Expression e = cast(Expression)o;
656 if (e.op == EXP.dSymbol)
658 DsymbolExp ve = cast(DsymbolExp)e;
659 Declaration d = ve.s.isDeclaration();
660 if (d && d.needThis())
670 override inout(TupleDeclaration) isTupleDeclaration() inout
675 override void accept(Visitor v)
681 /***********************************************************
683 extern (C++) final class AliasDeclaration : Declaration
686 Dsymbol overnext; // next in overload list
687 Dsymbol _import; // !=null if unresolved internal alias for selective import
689 extern (D) this(const ref Loc loc, Identifier ident, Type type)
692 //printf("AliasDeclaration(id = '%s', type = %p)\n", id.toChars(), type);
693 //printf("type = '%s'\n", type.toChars());
698 extern (D) this(const ref Loc loc, Identifier ident, Dsymbol s)
701 //printf("AliasDeclaration(id = '%s', s = %p)\n", id.toChars(), s);
707 static AliasDeclaration create(const ref Loc loc, Identifier id, Type type)
709 return new AliasDeclaration(loc, id, type);
712 override AliasDeclaration syntaxCopy(Dsymbol s)
714 //printf("AliasDeclaration::syntaxCopy()\n");
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;
722 override bool overloadInsert(Dsymbol s)
724 //printf("[%s] AliasDeclaration::overloadInsert('%s') s = %s %s @ [%s]\n",
725 // loc.toChars(), toChars(), s.kind(), s.toChars(), s.loc.toChars());
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).
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.
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.
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
743 if (semanticRun >= PASS.semanticdone)
745 /* Semantic analysis is already finished, and the aliased entity
746 * is not overloadable.
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
754 auto sa = aliassym.toAlias();
756 if (auto td = s.toAlias().isTemplateDeclaration())
757 s = td.funcroot ? td.funcroot : td;
759 if (auto fd = sa.isFuncDeclaration())
761 auto fa = new FuncAliasDeclaration(ident, fd);
762 fa.visibility = visibility;
765 return aliassym.overloadInsert(s);
767 if (auto td = sa.isTemplateDeclaration())
769 auto od = new OverDeclaration(ident, td.funcroot ? td.funcroot : td);
770 od.visibility = visibility;
773 return aliassym.overloadInsert(s);
775 if (auto od = sa.isOverDeclaration())
777 if (sa.ident != ident || sa.parent != parent)
779 od = new OverDeclaration(ident, od);
780 od.visibility = visibility;
784 return od.overloadInsert(s);
786 if (auto os = sa.isOverloadSet())
788 if (sa.ident != ident || sa.parent != parent)
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.
796 // private alias merged = foo; // private alias to overload set of a.foo and b.foo
800 // public alias merged = bar; // public alias to overload set of a.bar and b.bar
804 // void test() { merged(123); } // should only look at os2.merged
806 // os.visibility = visibility;
816 /* Don't know yet what the aliased symbol is, so assume it can
817 * be overloaded and check later for correctness.
820 return overnext.overloadInsert(s);
827 override const(char)* kind() const
832 override Type getType()
836 return toAlias().getType();
839 override Dsymbol toAlias()
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;
846 // Reading the AliasDeclaration
847 if (!(adFlags & ignoreRead))
848 adFlags |= wasRead; // can never assign to this AliasDeclaration again
850 if (inuse == 1 && type && _scope)
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)
861 if (global.errors != olderrors)
868 Type t = type.typeSemantic(loc, _scope);
871 if (global.errors != olderrors)
873 //printf("t = %s\n", t.toChars());
879 error("recursive alias declaration");
882 // Avoid breaking "recursive alias" state during errors gagged
885 aliassym = new AliasDeclaration(loc, ident, Type.terror);
890 if (semanticRun >= PASS.semanticdone)
892 // semantic is already done.
894 // Do not see aliassym !is null, because of lambda aliases.
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.
901 if (_import && _import._scope)
903 /* If this is an internal alias for selective/renamed import,
904 * load the module first.
906 _import.dsymbolSemantic(null);
910 aliasSemantic(this, _scope);
915 Dsymbol s = aliassym ? aliassym.toAlias() : this;
920 override Dsymbol toAlias2()
924 error("recursive alias declaration");
928 Dsymbol s = aliassym ? aliassym.toAlias2() : this;
933 override bool isOverloadable() const
935 // assume overloadable until alias is resolved
936 return semanticRun < PASS.semanticdone ||
937 aliassym && aliassym.isOverloadable();
940 override inout(AliasDeclaration) isAliasDeclaration() inout
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
949 return !!(storage_class & STC.templateparameter);
952 override void accept(Visitor v)
958 /***********************************************************
960 extern (C++) final class OverDeclaration : Declaration
962 Dsymbol overnext; // next in overload list
965 extern (D) this(Identifier ident, Dsymbol s)
971 override const(char)* kind() const
973 return "overload alias"; // todo
976 override bool equals(const RootObject o) const
981 auto s = isDsymbol(o);
985 if (auto od2 = s.isOverDeclaration())
986 return this.aliassym.equals(od2.aliassym);
987 return this.aliassym == s;
990 override bool overloadInsert(Dsymbol s)
992 //printf("OverDeclaration::overloadInsert('%s') aliassym = %p, overnext = %p\n", s.toChars(), aliassym, overnext);
994 return overnext.overloadInsert(s);
1001 override bool isOverloadable() const
1008 Dsymbol result = null;
1009 overloadApply(aliassym, (Dsymbol s)
1014 return 1; // ambiguous, done
1025 override inout(OverDeclaration) isOverDeclaration() inout
1030 override void accept(Visitor v)
1036 /***********************************************************
1038 extern (C++) class VarDeclaration : Declaration
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
1048 uint endlinnum; // line number of end of scope that this var lives in
1050 uint sequenceNumber; // order the variables are declared
1051 structalign_t alignment;
1053 // When interpreting, these point to the value (NULL if value not determinable)
1054 // The index of this variable on the CTFE stack, AdrOnStackNone if not allocated
1055 enum AdrOnStackNone = ~0u;
1056 uint ctfeAdrOnStack;
1058 bool isargptr; // if parameter that _argptr points to
1059 bool ctorinit; // it has been initialized in a ctor
1060 bool iscatchvar; // this is the exception object variable in catch() clause
1061 bool isowner; // this is an Owner, despite it being `scope`
1062 bool setInCtorOnly; // field can only be set in a constructor, as it is const or immutable
1064 // Both these mean the var is not rebindable once assigned,
1065 // and the destructor gets run when it goes out of scope
1066 bool onstack; // it is a class that was allocated on the stack
1067 bool mynew; // it is a class new'd with custom operator new
1069 byte canassign; // it can be assigned to
1070 bool overlapped; // if it is a field and has overlapping
1071 bool overlapUnsafe; // if it is an overlapping field and the overlaps are unsafe
1072 bool doNotInferScope; // do not infer 'scope' for this variable
1073 bool doNotInferReturn; // do not infer 'return' for this variable
1074 ubyte isdataseg; // private data for isDataseg 0 unset, 1 true, 2 false
1076 bool isArgDtorVar; // temporary created to handle scope destruction of a function argument
1078 final extern (D) this(const ref Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.undefined_)
1085 //printf("VarDeclaration('%s')\n", ident.toChars());
1089 if (!type && !_init)
1091 //printf("VarDeclaration('%s')\n", ident.toChars());
1096 assert(type || _init);
1099 ctfeAdrOnStack = AdrOnStackNone;
1100 this.storage_class = storage_class;
1103 static VarDeclaration create(const ref Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.undefined_)
1105 return new VarDeclaration(loc, type, ident, _init, storage_class);
1108 override VarDeclaration syntaxCopy(Dsymbol s)
1110 //printf("VarDeclaration::syntaxCopy(%s)\n", toChars());
1112 auto v = new VarDeclaration(loc, type ? type.syntaxCopy() : null, ident, _init ? _init.syntaxCopy() : null, storage_class);
1113 v.comment = comment;
1117 override void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion)
1119 //printf("VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars());
1123 // If this variable was really a tuple, set the offsets for the tuple fields
1124 TupleDeclaration v2 = aliassym.isTupleDeclaration();
1126 for (size_t i = 0; i < v2.objects.dim; i++)
1128 RootObject o = (*v2.objects)[i];
1129 assert(o.dyncast() == DYNCAST.expression);
1130 Expression e = cast(Expression)o;
1131 assert(e.op == EXP.dSymbol);
1132 DsymbolExp se = cast(DsymbolExp)e;
1133 se.s.setFieldOffset(ad, fieldState, isunion);
1140 assert(!(storage_class & (STC.static_ | STC.extern_ | STC.parameter | STC.tls)));
1142 //printf("+VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars());
1144 /* Fields that are tuples appear both as part of TupleDeclarations and
1145 * as members. That means ignore them if they are already a field.
1150 fieldState.offset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613
1153 for (size_t i = 0; i < ad.fields.dim; i++)
1155 if (ad.fields[i] == this)
1158 fieldState.offset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613
1163 // Check for forward referenced types which will fail the size() call
1164 Type t = type.toBasetype();
1165 if (storage_class & STC.ref_)
1167 // References are the size of a pointer
1170 Type tv = t.baseElemOf();
1171 if (tv.ty == Tstruct)
1173 auto ts = cast(TypeStruct)tv;
1174 assert(ts.sym != ad); // already checked in ad.determineFields()
1175 if (!ts.sym.determineSize(loc))
1183 // List in ad.fields. Even if the type is error, it's necessary to avoid
1184 // pointless error diagnostic "more initializers than fields" on struct literal.
1185 ad.fields.push(this);
1190 /* If coming after a bit field in progress,
1191 * advance past the field
1193 fieldState.inFlight = false;
1195 const sz = t.size(loc);
1196 assert(sz != SIZE_INVALID && sz < uint.max);
1197 uint memsize = cast(uint)sz; // size of member
1198 uint memalignsize = target.fieldalign(t); // size of member for alignment purposes
1199 offset = AggregateDeclaration.placeField(
1201 memsize, memalignsize, alignment,
1202 &ad.structsize, &ad.alignsize,
1205 //printf("\t%s: memalignsize = %d\n", toChars(), memalignsize);
1206 //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize);
1209 override const(char)* kind() const
1214 override final inout(AggregateDeclaration) isThis() inout
1216 if (!(storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.templateparameter | STC.tls | STC.gshared | STC.ctfe)))
1218 /* The casting is necessary because `s = s.parent` is otherwise rejected
1220 for (auto s = cast(Dsymbol)this; s; s = s.parent)
1222 auto ad = (cast(inout)s).isMember();
1225 if (!s.parent || !s.parent.isTemplateMixin())
1232 override final bool needThis()
1234 //printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class);
1238 override final bool isExport() const
1240 return visibility.kind == Visibility.Kind.export_;
1243 override final bool isImportedSymbol() const
1245 if (visibility.kind == Visibility.Kind.export_ && !_init && (storage_class & STC.static_ || parent.isModule()))
1250 final bool isCtorinit() const pure nothrow @nogc @safe
1252 return setInCtorOnly;
1255 /*******************************
1256 * Does symbol go into data segment?
1257 * Includes extern variables.
1259 override final bool isDataseg()
1263 printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars());
1264 printf("%llx, isModule: %p, isTemplateInstance: %p, isNspace: %p\n",
1265 storage_class & (STC.static_ | STC.const_), parent.isModule(), parent.isTemplateInstance(), parent.isNspace());
1266 printf("parent = '%s'\n", parent.toChars());
1269 if (isdataseg == 0) // the value is not cached
1271 isdataseg = 2; // The Variables does not go into the datasegment
1273 if (!canTakeAddressOf())
1278 Dsymbol parent = toParent();
1279 if (!parent && !(storage_class & STC.static_))
1281 error("forward referenced");
1284 else if (storage_class & (STC.static_ | STC.extern_ | STC.tls | STC.gshared) ||
1285 parent.isModule() || parent.isTemplateInstance() || parent.isNspace())
1287 assert(!isParameter() && !isResult());
1288 isdataseg = 1; // It is in the DataSegment
1292 return (isdataseg == 1);
1294 /************************************
1295 * Does symbol go into thread local storage?
1297 override final bool isThreadlocal()
1299 //printf("VarDeclaration::isThreadlocal(%p, '%s')\n", this, toChars());
1300 /* Data defaults to being thread-local. It is not thread-local
1301 * if it is immutable, const or shared.
1303 bool i = isDataseg() && !(storage_class & (STC.immutable_ | STC.const_ | STC.shared_ | STC.gshared));
1304 //printf("\treturn %d\n", i);
1308 /********************************************
1309 * Can variable be read and written by CTFE?
1313 return (storage_class & STC.ctfe) != 0; // || !isDataseg();
1316 final bool isOverlappedWith(VarDeclaration v)
1318 const vsz = v.type.size();
1319 const tsz = type.size();
1320 assert(vsz != SIZE_INVALID && tsz != SIZE_INVALID);
1322 // Overlap is checked by comparing bit offsets
1323 auto bitoffset = offset * 8;
1324 auto vbitoffset = v.offset * 8;
1326 // Bitsize of types are overridden by any bit-field widths.
1327 ulong tbitsize = void;
1328 if (auto bf = isBitFieldDeclaration())
1330 bitoffset += bf.bitOffset;
1331 tbitsize = bf.fieldWidth;
1336 ulong vbitsize = void;
1337 if (auto vbf = v.isBitFieldDeclaration())
1339 vbitoffset += vbf.bitOffset;
1340 vbitsize = vbf.fieldWidth;
1345 return bitoffset < vbitoffset + vbitsize &&
1346 vbitoffset < bitoffset + tbitsize;
1349 override final bool hasPointers()
1351 //printf("VarDeclaration::hasPointers() %s, ty = %d\n", toChars(), type.ty);
1352 return (!isDataseg() && type.hasPointers());
1355 /*************************************
1356 * Return true if we can take the address of this variable.
1358 final bool canTakeAddressOf()
1360 return !(storage_class & STC.manifest);
1363 /******************************************
1364 * Return true if variable needs to call the destructor.
1366 final bool needsScopeDtor()
1368 //printf("VarDeclaration::needsScopeDtor() %s\n", toChars());
1369 return edtor && !(storage_class & STC.nodtor);
1372 /******************************************
1373 * If a variable has a scope destructor call, return call for it.
1374 * Otherwise, return NULL.
1376 extern (D) final Expression callScopeDtor(Scope* sc)
1378 //printf("VarDeclaration::callScopeDtor() %s\n", toChars());
1380 // Destruction of STC.field's is handled by buildDtor()
1381 if (storage_class & (STC.nodtor | STC.ref_ | STC.out_ | STC.field))
1387 return null; // destructor is built by `void semantic(Catch c, Scope* sc)`, not here
1389 Expression e = null;
1390 // Destructors for structs and arrays of structs
1391 Type tv = type.baseElemOf();
1392 if (tv.ty == Tstruct)
1394 StructDeclaration sd = (cast(TypeStruct)tv).sym;
1395 if (!sd.dtor || sd.errors)
1398 const sz = type.size();
1399 assert(sz != SIZE_INVALID);
1403 if (type.toBasetype().ty == Tstruct)
1406 e = new VarExp(loc, this);
1408 /* This is a hack so we can call destructors on const/immutable objects.
1409 * Need to add things like "const ~this()" and "immutable ~this()" to
1412 e.type = e.type.mutableOf();
1414 // Enable calling destructors on shared objects.
1415 // The destructor is always a single, non-overloaded function,
1416 // and must serve both shared and non-shared objects.
1417 e.type = e.type.unSharedOf;
1419 e = new DotVarExp(loc, e, sd.dtor, false);
1420 e = new CallExp(loc, e);
1424 // __ArrayDtor(v[0 .. n])
1425 e = new VarExp(loc, this);
1427 const sdsz = sd.type.size();
1428 assert(sdsz != SIZE_INVALID && sdsz != 0);
1429 const n = sz / sdsz;
1430 e = new SliceExp(loc, e, new IntegerExp(loc, 0, Type.tsize_t), new IntegerExp(loc, n, Type.tsize_t));
1432 // Prevent redundant bounds check
1433 (cast(SliceExp)e).upperIsInBounds = true;
1434 (cast(SliceExp)e).lowerIsLessThanUpper = true;
1436 // This is a hack so we can call destructors on const/immutable objects.
1437 e.type = sd.type.arrayOf();
1439 e = new CallExp(loc, new IdentifierExp(loc, Id.__ArrayDtor), e);
1443 // Destructors for classes
1444 if (storage_class & (STC.auto_ | STC.scope_) && !(storage_class & STC.parameter))
1446 for (ClassDeclaration cd = type.isClassHandle(); cd; cd = cd.baseClass)
1448 /* We can do better if there's a way with onstack
1449 * classes to determine if there's no way the monitor
1452 //if (cd.isInterfaceDeclaration())
1453 // error("interface `%s` cannot be scope", cd.toChars());
1455 if (mynew || onstack) // if any destructors
1457 // delete'ing C++ classes crashes (and delete is deprecated anyway)
1458 if (cd.classKind == ClassKind.cpp)
1460 // Don't call non-existant dtor
1464 e = new VarExp(loc, this);
1465 e.type = e.type.mutableOf().unSharedOf(); // Hack for mutable ctor on immutable instances
1466 e = new DotVarExp(loc, e, cd.dtor, false);
1467 e = new CallExp(loc, e);
1473 ec = new VarExp(loc, this);
1474 e = new DeleteExp(loc, ec, true);
1475 e.type = Type.tvoid;
1483 /*******************************************
1484 * If variable has a constant expression initializer, get it.
1485 * Otherwise, return null.
1487 extern (D) final Expression getConstInitializer(bool needFullType = true)
1489 assert(type && _init);
1491 // Ungag errors when not speculative
1492 uint oldgag = global.gag;
1495 Dsymbol sym = toParent().isAggregateDeclaration();
1496 if (sym && !sym.isSpeculative())
1503 _init = _init.initializerSemantic(_scope, type, INITinterpret);
1508 Expression e = _init.initializerToExpression(needFullType ? type : null);
1509 global.gag = oldgag;
1513 /*******************************************
1514 * Helper function for the expansion of manifest constant.
1516 extern (D) final Expression expandInitializer(Loc loc)
1518 assert((storage_class & STC.manifest) && _init);
1520 auto e = getConstInitializer();
1523 .error(loc, "cannot make expression out of initializer for `%s`", toChars());
1524 return ErrorExp.get();
1528 e.loc = loc; // for better error message
1532 override final void checkCtorConstInit()
1536 /* doesn't work if more than one static ctor */
1537 if (ctorinit == 0 && isCtorinit() && !isField())
1538 error("missing initializer in static constructor for const variable");
1542 /************************************
1543 * Check to see if this variable is actually in an enclosing function
1544 * rather than the current one.
1545 * Update nestedrefs[], closureVars[] and outerVars[].
1546 * Returns: true if error occurs.
1548 extern (D) final bool checkNestedReference(Scope* sc, Loc loc)
1550 //printf("VarDeclaration::checkNestedReference() %s\n", toChars());
1551 if (sc.intypeof == 1 || (sc.flags & SCOPE.ctfe))
1553 if (!parent || parent == sc.parent)
1555 if (isDataseg() || (storage_class & STC.manifest))
1558 // The current function
1559 FuncDeclaration fdthis = sc.parent.isFuncDeclaration();
1561 return false; // out of function scope
1563 Dsymbol p = toParent2();
1565 // Function literals from fdthis to p must be delegates
1566 ensureStaticLinkTo(fdthis, p);
1568 // The function that this variable is in
1569 FuncDeclaration fdv = p.isFuncDeclaration();
1570 if (!fdv || fdv == fdthis)
1573 // Add fdthis to nestedrefs[] if not already there
1574 if (!nestedrefs.contains(fdthis))
1575 nestedrefs.push(fdthis);
1577 //printf("\tfdv = %s\n", fdv.toChars());
1578 //printf("\tfdthis = %s\n", fdthis.toChars());
1581 if (fdthis.getLevelAndCheck(loc, sc, fdv, this) == fdthis.LevelError)
1585 // Add this VarDeclaration to fdv.closureVars[] if not already there
1586 if (!sc.intypeof && !(sc.flags & SCOPE.compile) &&
1587 // https://issues.dlang.org/show_bug.cgi?id=17605
1588 (fdv.flags & FUNCFLAG.compileTimeOnly || !(fdthis.flags & FUNCFLAG.compileTimeOnly))
1591 if (!fdv.closureVars.contains(this))
1592 fdv.closureVars.push(this);
1595 if (!fdthis.outerVars.contains(this))
1596 fdthis.outerVars.push(this);
1598 //printf("fdthis is %s\n", fdthis.toChars());
1599 //printf("var %s in function %s is nested ref\n", toChars(), fdv.toChars());
1600 // __dollar creates problems because it isn't a real variable
1601 // https://issues.dlang.org/show_bug.cgi?id=3326
1602 if (ident == Id.dollar)
1604 .error(loc, "cannnot use `$` inside a function literal");
1607 if (ident == Id.withSym) // https://issues.dlang.org/show_bug.cgi?id=1759
1609 ExpInitializer ez = _init.isExpInitializer();
1611 Expression e = ez.exp;
1612 if (e.op == EXP.construct || e.op == EXP.blit)
1613 e = (cast(AssignExp)e).e2;
1614 return lambdaCheckForNestedRef(e, sc);
1620 override final Dsymbol toAlias()
1622 //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym);
1623 if ((!type || !type.deco) && _scope)
1624 dsymbolSemantic(this, _scope);
1626 assert(this != aliassym);
1627 Dsymbol s = aliassym ? aliassym.toAlias() : this;
1631 // Eliminate need for dynamic_cast
1632 override final inout(VarDeclaration) isVarDeclaration() inout
1637 override void accept(Visitor v)
1642 /**********************************
1643 * Determine if `this` has a lifetime that lasts past
1644 * the destruction of `v`
1646 * v = variable to test against
1650 final bool enclosesLifetimeOf(VarDeclaration v) const pure
1652 // VarDeclaration's with these STC's need special treatment
1653 enum special = STC.temp | STC.foreach_;
1655 // Sequence numbers work when there are no special VarDeclaration's involved
1656 if (!((this.storage_class | v.storage_class) & special))
1658 assert(this.sequenceNumber != this.sequenceNumber.init);
1659 assert(v.sequenceNumber != v.sequenceNumber.init);
1661 return (this.sequenceNumber < v.sequenceNumber);
1664 // Assume that semantic produces temporaries according to their lifetime
1665 // (It won't create a temporary before the actual content)
1666 if ((this.storage_class & special) && (v.storage_class & special))
1667 return this.sequenceNumber < v.sequenceNumber;
1669 // Fall back to lexical order
1670 assert(this.loc != Loc.initial);
1671 assert(v.loc != Loc.initial);
1673 if (this.loc.linnum != v.loc.linnum)
1674 return this.loc.linnum < v.loc.linnum;
1676 if (this.loc.charnum != v.loc.charnum)
1677 return this.loc.charnum < v.loc.charnum;
1680 return this.sequenceNumber < v.sequenceNumber;
1683 /***************************************
1684 * Add variable to maybes[].
1685 * When a maybescope variable `v` is assigned to a maybescope variable `this`,
1686 * we cannot determine if `this` is actually scope until the semantic
1687 * analysis for the function is completed. Thus, we save the data
1690 * v = an STC.maybescope variable that was assigned to `this`
1692 final void addMaybe(VarDeclaration v)
1694 //printf("add %s to %s's list of dependencies\n", v.toChars(), toChars());
1696 maybes = new VarDeclarations();
1701 /*******************************************************
1702 * C11 6.7.2.1-4 bit fields
1704 extern (C++) class BitFieldDeclaration : VarDeclaration
1711 final extern (D) this(const ref Loc loc, Type type, Identifier ident, Expression width)
1713 super(loc, type, ident, null);
1716 this.storage_class |= STC.field;
1719 override BitFieldDeclaration syntaxCopy(Dsymbol s)
1721 //printf("BitFieldDeclaration::syntaxCopy(%s)\n", toChars());
1723 auto bf = new BitFieldDeclaration(loc, type ? type.syntaxCopy() : null, ident, width.syntaxCopy());
1724 bf.comment = comment;
1728 override final inout(BitFieldDeclaration) isBitFieldDeclaration() inout
1733 override void accept(Visitor v)
1738 override final void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion)
1740 //printf("BitFieldDeclaration::setFieldOffset(ad: %s, field: %s)\n", ad.toChars(), toChars());
1741 static void print(const ref FieldState fieldState)
1743 printf("FieldState.offset = %d bytes\n", fieldState.offset);
1744 printf(" .fieldOffset = %d bytes\n", fieldState.fieldOffset);
1745 printf(" .bitOffset = %d bits\n", fieldState.bitOffset);
1746 printf(" .fieldSize = %d bytes\n", fieldState.fieldSize);
1747 printf(" .inFlight = %d\n\n", fieldState.inFlight);
1749 //print(fieldState);
1751 Type t = type.toBasetype();
1752 const bool anon = isAnonymous();
1754 // List in ad.fields. Even if the type is error, it's necessary to avoid
1755 // pointless error diagnostic "more initializers than fields" on struct literal.
1757 ad.fields.push(this);
1762 const sz = t.size(loc);
1763 assert(sz != SIZE_INVALID && sz < uint.max);
1764 uint memsize = cast(uint)sz; // size of member
1765 uint memalignsize = target.fieldalign(t); // size of member for alignment purposes
1767 if (fieldWidth == 0 && !anon)
1768 error(loc, "named bit fields cannot have 0 width");
1769 if (fieldWidth > memsize * 8)
1770 error(loc, "bit field width %d is larger than type", fieldWidth);
1772 const style = target.c.bitFieldStyle;
1774 void startNewField()
1777 if (style == TargetC.BitFieldStyle.Gcc_Clang)
1779 if (fieldWidth > 32)
1780 alignsize = memalignsize;
1781 else if (fieldWidth > 16)
1783 else if (fieldWidth > 8)
1789 alignsize = memsize; // not memalignsize
1792 offset = AggregateDeclaration.placeField(
1794 memsize, alignsize, alignment,
1796 (anon && style == TargetC.BitFieldStyle.Gcc_Clang) ? &dummy : &ad.alignsize,
1799 fieldState.inFlight = true;
1800 fieldState.fieldOffset = offset;
1801 fieldState.bitOffset = 0;
1802 fieldState.fieldSize = memsize;
1805 if (style == TargetC.BitFieldStyle.Gcc_Clang)
1807 if (fieldWidth == 0)
1811 // Use type of zero width field to align to next field
1812 fieldState.offset = (fieldState.offset + memalignsize - 1) & ~(memalignsize - 1);
1813 ad.structsize = fieldState.offset;
1816 fieldState.inFlight = false;
1820 if (ad.alignsize == 0)
1823 ad.alignsize < memalignsize)
1824 ad.alignsize = memalignsize;
1826 else if (style == TargetC.BitFieldStyle.MS)
1828 if (ad.alignsize == 0)
1830 if (fieldWidth == 0)
1832 if (fieldState.inFlight && !isunion)
1834 // documentation says align to next int
1835 //const alsz = cast(uint)Type.tint32.size();
1836 const alsz = memsize; // but it really does this
1837 fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1);
1838 ad.structsize = fieldState.offset;
1841 fieldState.inFlight = false;
1845 else if (style == TargetC.BitFieldStyle.DM)
1847 if (anon && fieldWidth && (!fieldState.inFlight || fieldState.bitOffset == 0))
1848 return; // this probably should be a bug in DMC
1849 if (ad.alignsize == 0)
1851 if (fieldWidth == 0)
1853 if (fieldState.inFlight && !isunion)
1855 const alsz = memsize;
1856 fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1);
1857 ad.structsize = fieldState.offset;
1860 fieldState.inFlight = false;
1865 if (!fieldState.inFlight)
1869 else if (style == TargetC.BitFieldStyle.Gcc_Clang)
1871 if (fieldState.bitOffset + fieldWidth > memsize * 8)
1873 //printf("start1 fieldState.bitOffset:%u fieldWidth:%u memsize:%u\n", fieldState.bitOffset, fieldWidth, memsize);
1878 // if alignment boundary is crossed
1879 uint start = fieldState.fieldOffset * 8 + fieldState.bitOffset;
1880 uint end = start + fieldWidth;
1881 //printf("%s start: %d end: %d memalignsize: %d\n", ad.toChars(), start, end, memalignsize);
1882 if (start / (memalignsize * 8) != (end - 1) / (memalignsize * 8))
1884 //printf("alignment is crossed\n");
1889 else if (style == TargetC.BitFieldStyle.DM ||
1890 style == TargetC.BitFieldStyle.MS)
1892 if (memsize != fieldState.fieldSize ||
1893 fieldState.bitOffset + fieldWidth > fieldState.fieldSize * 8)
1901 offset = fieldState.fieldOffset;
1902 bitOffset = fieldState.bitOffset;
1904 const pastField = bitOffset + fieldWidth;
1905 if (style == TargetC.BitFieldStyle.Gcc_Clang)
1907 auto size = (pastField + 7) / 8;
1908 fieldState.fieldSize = size;
1909 //printf(" offset: %d, size: %d\n", offset, size);
1910 ad.structsize = offset + size;
1913 fieldState.fieldSize = memsize;
1914 //printf("at end: ad.structsize = %d\n", cast(int)ad.structsize);
1915 //print(fieldState);
1919 fieldState.offset = offset + fieldState.fieldSize;
1920 fieldState.bitOffset = pastField;
1923 //printf("\t%s: memalignsize = %d\n", toChars(), memalignsize);
1924 //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize);
1928 /***********************************************************
1929 * This is a shell around a back end symbol
1931 extern (C++) final class SymbolDeclaration : Declaration
1933 AggregateDeclaration dsym;
1935 extern (D) this(const ref Loc loc, AggregateDeclaration dsym)
1937 super(loc, dsym.ident);
1939 storage_class |= STC.const_;
1942 // Eliminate need for dynamic_cast
1943 override inout(SymbolDeclaration) isSymbolDeclaration() inout
1948 override void accept(Visitor v)
1954 /***********************************************************
1956 extern (C++) class TypeInfoDeclaration : VarDeclaration
1960 final extern (D) this(Type tinfo)
1962 super(Loc.initial, Type.dtypeinfo.type, tinfo.getTypeInfoIdent(), null);
1964 storage_class = STC.static_ | STC.gshared;
1965 visibility = Visibility(Visibility.Kind.public_);
1967 alignment.set(target.ptrsize);
1970 static TypeInfoDeclaration create(Type tinfo)
1972 return new TypeInfoDeclaration(tinfo);
1975 override final TypeInfoDeclaration syntaxCopy(Dsymbol s)
1977 assert(0); // should never be produced by syntax
1980 override final const(char)* toChars() const
1982 //printf("TypeInfoDeclaration::toChars() tinfo = %s\n", tinfo.toChars());
1984 buf.writestring("typeid(");
1985 buf.writestring(tinfo.toChars());
1987 return buf.extractChars();
1990 override final inout(TypeInfoDeclaration) isTypeInfoDeclaration() inout @nogc nothrow pure @safe
1995 override void accept(Visitor v)
2001 /***********************************************************
2003 extern (C++) final class TypeInfoStructDeclaration : TypeInfoDeclaration
2005 extern (D) this(Type tinfo)
2008 if (!Type.typeinfostruct)
2010 ObjectNotFound(Id.TypeInfo_Struct);
2012 type = Type.typeinfostruct.type;
2015 static TypeInfoStructDeclaration create(Type tinfo)
2017 return new TypeInfoStructDeclaration(tinfo);
2020 override void accept(Visitor v)
2026 /***********************************************************
2028 extern (C++) final class TypeInfoClassDeclaration : TypeInfoDeclaration
2030 extern (D) this(Type tinfo)
2033 if (!Type.typeinfoclass)
2035 ObjectNotFound(Id.TypeInfo_Class);
2037 type = Type.typeinfoclass.type;
2040 static TypeInfoClassDeclaration create(Type tinfo)
2042 return new TypeInfoClassDeclaration(tinfo);
2045 override void accept(Visitor v)
2051 /***********************************************************
2053 extern (C++) final class TypeInfoInterfaceDeclaration : TypeInfoDeclaration
2055 extern (D) this(Type tinfo)
2058 if (!Type.typeinfointerface)
2060 ObjectNotFound(Id.TypeInfo_Interface);
2062 type = Type.typeinfointerface.type;
2065 static TypeInfoInterfaceDeclaration create(Type tinfo)
2067 return new TypeInfoInterfaceDeclaration(tinfo);
2070 override void accept(Visitor v)
2076 /***********************************************************
2078 extern (C++) final class TypeInfoPointerDeclaration : TypeInfoDeclaration
2080 extern (D) this(Type tinfo)
2083 if (!Type.typeinfopointer)
2085 ObjectNotFound(Id.TypeInfo_Pointer);
2087 type = Type.typeinfopointer.type;
2090 static TypeInfoPointerDeclaration create(Type tinfo)
2092 return new TypeInfoPointerDeclaration(tinfo);
2095 override void accept(Visitor v)
2101 /***********************************************************
2103 extern (C++) final class TypeInfoArrayDeclaration : TypeInfoDeclaration
2105 extern (D) this(Type tinfo)
2108 if (!Type.typeinfoarray)
2110 ObjectNotFound(Id.TypeInfo_Array);
2112 type = Type.typeinfoarray.type;
2115 static TypeInfoArrayDeclaration create(Type tinfo)
2117 return new TypeInfoArrayDeclaration(tinfo);
2120 override void accept(Visitor v)
2126 /***********************************************************
2128 extern (C++) final class TypeInfoStaticArrayDeclaration : TypeInfoDeclaration
2130 extern (D) this(Type tinfo)
2133 if (!Type.typeinfostaticarray)
2135 ObjectNotFound(Id.TypeInfo_StaticArray);
2137 type = Type.typeinfostaticarray.type;
2140 static TypeInfoStaticArrayDeclaration create(Type tinfo)
2142 return new TypeInfoStaticArrayDeclaration(tinfo);
2145 override void accept(Visitor v)
2151 /***********************************************************
2153 extern (C++) final class TypeInfoAssociativeArrayDeclaration : TypeInfoDeclaration
2155 extern (D) this(Type tinfo)
2158 if (!Type.typeinfoassociativearray)
2160 ObjectNotFound(Id.TypeInfo_AssociativeArray);
2162 type = Type.typeinfoassociativearray.type;
2165 static TypeInfoAssociativeArrayDeclaration create(Type tinfo)
2167 return new TypeInfoAssociativeArrayDeclaration(tinfo);
2170 override void accept(Visitor v)
2176 /***********************************************************
2178 extern (C++) final class TypeInfoEnumDeclaration : TypeInfoDeclaration
2180 extern (D) this(Type tinfo)
2183 if (!Type.typeinfoenum)
2185 ObjectNotFound(Id.TypeInfo_Enum);
2187 type = Type.typeinfoenum.type;
2190 static TypeInfoEnumDeclaration create(Type tinfo)
2192 return new TypeInfoEnumDeclaration(tinfo);
2195 override void accept(Visitor v)
2201 /***********************************************************
2203 extern (C++) final class TypeInfoFunctionDeclaration : TypeInfoDeclaration
2205 extern (D) this(Type tinfo)
2208 if (!Type.typeinfofunction)
2210 ObjectNotFound(Id.TypeInfo_Function);
2212 type = Type.typeinfofunction.type;
2215 static TypeInfoFunctionDeclaration create(Type tinfo)
2217 return new TypeInfoFunctionDeclaration(tinfo);
2220 override void accept(Visitor v)
2226 /***********************************************************
2228 extern (C++) final class TypeInfoDelegateDeclaration : TypeInfoDeclaration
2230 extern (D) this(Type tinfo)
2233 if (!Type.typeinfodelegate)
2235 ObjectNotFound(Id.TypeInfo_Delegate);
2237 type = Type.typeinfodelegate.type;
2240 static TypeInfoDelegateDeclaration create(Type tinfo)
2242 return new TypeInfoDelegateDeclaration(tinfo);
2245 override void accept(Visitor v)
2251 /***********************************************************
2253 extern (C++) final class TypeInfoTupleDeclaration : TypeInfoDeclaration
2255 extern (D) this(Type tinfo)
2258 if (!Type.typeinfotypelist)
2260 ObjectNotFound(Id.TypeInfo_Tuple);
2262 type = Type.typeinfotypelist.type;
2265 static TypeInfoTupleDeclaration create(Type tinfo)
2267 return new TypeInfoTupleDeclaration(tinfo);
2270 override void accept(Visitor v)
2276 /***********************************************************
2278 extern (C++) final class TypeInfoConstDeclaration : TypeInfoDeclaration
2280 extern (D) this(Type tinfo)
2283 if (!Type.typeinfoconst)
2285 ObjectNotFound(Id.TypeInfo_Const);
2287 type = Type.typeinfoconst.type;
2290 static TypeInfoConstDeclaration create(Type tinfo)
2292 return new TypeInfoConstDeclaration(tinfo);
2295 override void accept(Visitor v)
2301 /***********************************************************
2303 extern (C++) final class TypeInfoInvariantDeclaration : TypeInfoDeclaration
2305 extern (D) this(Type tinfo)
2308 if (!Type.typeinfoinvariant)
2310 ObjectNotFound(Id.TypeInfo_Invariant);
2312 type = Type.typeinfoinvariant.type;
2315 static TypeInfoInvariantDeclaration create(Type tinfo)
2317 return new TypeInfoInvariantDeclaration(tinfo);
2320 override void accept(Visitor v)
2326 /***********************************************************
2328 extern (C++) final class TypeInfoSharedDeclaration : TypeInfoDeclaration
2330 extern (D) this(Type tinfo)
2333 if (!Type.typeinfoshared)
2335 ObjectNotFound(Id.TypeInfo_Shared);
2337 type = Type.typeinfoshared.type;
2340 static TypeInfoSharedDeclaration create(Type tinfo)
2342 return new TypeInfoSharedDeclaration(tinfo);
2345 override void accept(Visitor v)
2351 /***********************************************************
2353 extern (C++) final class TypeInfoWildDeclaration : TypeInfoDeclaration
2355 extern (D) this(Type tinfo)
2358 if (!Type.typeinfowild)
2360 ObjectNotFound(Id.TypeInfo_Wild);
2362 type = Type.typeinfowild.type;
2365 static TypeInfoWildDeclaration create(Type tinfo)
2367 return new TypeInfoWildDeclaration(tinfo);
2370 override void accept(Visitor v)
2376 /***********************************************************
2378 extern (C++) final class TypeInfoVectorDeclaration : TypeInfoDeclaration
2380 extern (D) this(Type tinfo)
2383 if (!Type.typeinfovector)
2385 ObjectNotFound(Id.TypeInfo_Vector);
2387 type = Type.typeinfovector.type;
2390 static TypeInfoVectorDeclaration create(Type tinfo)
2392 return new TypeInfoVectorDeclaration(tinfo);
2395 override void accept(Visitor v)
2401 /***********************************************************
2402 * For the "this" parameter to member functions
2404 extern (C++) final class ThisDeclaration : VarDeclaration
2406 extern (D) this(const ref Loc loc, Type t)
2408 super(loc, t, Id.This, null);
2409 storage_class |= STC.nodtor;
2412 override ThisDeclaration syntaxCopy(Dsymbol s)
2414 assert(0); // should never be produced by syntax
2417 override inout(ThisDeclaration) isThisDeclaration() inout
2422 override void accept(Visitor v)