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 __gshared uint nextSequenceNumber; // the counter for sequenceNumber
1052 structalign_t alignment;
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;
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
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
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
1077 bool isArgDtorVar; // temporary created to handle scope destruction of a function argument
1079 final extern (D) this(const ref Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.undefined_)
1086 //printf("VarDeclaration('%s')\n", ident.toChars());
1090 if (!type && !_init)
1092 //printf("VarDeclaration('%s')\n", ident.toChars());
1097 assert(type || _init);
1100 ctfeAdrOnStack = AdrOnStackNone;
1101 this.storage_class = storage_class;
1102 sequenceNumber = ++nextSequenceNumber;
1105 static VarDeclaration create(const ref Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.undefined_)
1107 return new VarDeclaration(loc, type, ident, _init, storage_class);
1110 override VarDeclaration syntaxCopy(Dsymbol s)
1112 //printf("VarDeclaration::syntaxCopy(%s)\n", toChars());
1114 auto v = new VarDeclaration(loc, type ? type.syntaxCopy() : null, ident, _init ? _init.syntaxCopy() : null, storage_class);
1115 v.comment = comment;
1119 override void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion)
1121 //printf("VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars());
1125 // If this variable was really a tuple, set the offsets for the tuple fields
1126 TupleDeclaration v2 = aliassym.isTupleDeclaration();
1128 for (size_t i = 0; i < v2.objects.dim; i++)
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);
1142 assert(!(storage_class & (STC.static_ | STC.extern_ | STC.parameter | STC.tls)));
1144 //printf("+VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars());
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.
1152 fieldState.offset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613
1155 for (size_t i = 0; i < ad.fields.dim; i++)
1157 if (ad.fields[i] == this)
1160 fieldState.offset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613
1165 // Check for forward referenced types which will fail the size() call
1166 Type t = type.toBasetype();
1167 if (storage_class & STC.ref_)
1169 // References are the size of a pointer
1172 Type tv = t.baseElemOf();
1173 if (tv.ty == Tstruct)
1175 auto ts = cast(TypeStruct)tv;
1176 assert(ts.sym != ad); // already checked in ad.determineFields()
1177 if (!ts.sym.determineSize(loc))
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);
1192 /* If coming after a bit field in progress,
1193 * advance past the field
1195 fieldState.inFlight = false;
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(
1203 memsize, memalignsize, alignment,
1204 &ad.structsize, &ad.alignsize,
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);
1211 override const(char)* kind() const
1216 override final inout(AggregateDeclaration) isThis() inout
1218 if (!(storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.templateparameter | STC.tls | STC.gshared | STC.ctfe)))
1220 /* The casting is necessary because `s = s.parent` is otherwise rejected
1222 for (auto s = cast(Dsymbol)this; s; s = s.parent)
1224 auto ad = (cast(inout)s).isMember();
1227 if (!s.parent || !s.parent.isTemplateMixin())
1234 override final bool needThis()
1236 //printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class);
1240 override final bool isExport() const
1242 return visibility.kind == Visibility.Kind.export_;
1245 override final bool isImportedSymbol() const
1247 if (visibility.kind == Visibility.Kind.export_ && !_init && (storage_class & STC.static_ || parent.isModule()))
1252 final bool isCtorinit() const pure nothrow @nogc @safe
1254 return setInCtorOnly;
1257 /*******************************
1258 * Does symbol go into data segment?
1259 * Includes extern variables.
1261 override final bool isDataseg()
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());
1271 if (isdataseg == 0) // the value is not cached
1273 isdataseg = 2; // The Variables does not go into the datasegment
1275 if (!canTakeAddressOf())
1280 Dsymbol parent = toParent();
1281 if (!parent && !(storage_class & STC.static_))
1283 error("forward referenced");
1286 else if (storage_class & (STC.static_ | STC.extern_ | STC.tls | STC.gshared) ||
1287 parent.isModule() || parent.isTemplateInstance() || parent.isNspace())
1289 assert(!isParameter() && !isResult());
1290 isdataseg = 1; // It is in the DataSegment
1294 return (isdataseg == 1);
1296 /************************************
1297 * Does symbol go into thread local storage?
1299 override final bool isThreadlocal()
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.
1305 bool i = isDataseg() && !(storage_class & (STC.immutable_ | STC.const_ | STC.shared_ | STC.gshared));
1306 //printf("\treturn %d\n", i);
1310 /********************************************
1311 * Can variable be read and written by CTFE?
1315 return (storage_class & STC.ctfe) != 0; // || !isDataseg();
1318 final bool isOverlappedWith(VarDeclaration v)
1320 const vsz = v.type.size();
1321 const tsz = type.size();
1322 assert(vsz != SIZE_INVALID && tsz != SIZE_INVALID);
1324 // Overlap is checked by comparing bit offsets
1325 auto bitoffset = offset * 8;
1326 auto vbitoffset = v.offset * 8;
1328 // Bitsize of types are overridden by any bit-field widths.
1329 ulong tbitsize = void;
1330 if (auto bf = isBitFieldDeclaration())
1332 bitoffset += bf.bitOffset;
1333 tbitsize = bf.fieldWidth;
1338 ulong vbitsize = void;
1339 if (auto vbf = v.isBitFieldDeclaration())
1341 vbitoffset += vbf.bitOffset;
1342 vbitsize = vbf.fieldWidth;
1347 return bitoffset < vbitoffset + vbitsize &&
1348 vbitoffset < bitoffset + tbitsize;
1351 override final bool hasPointers()
1353 //printf("VarDeclaration::hasPointers() %s, ty = %d\n", toChars(), type.ty);
1354 return (!isDataseg() && type.hasPointers());
1357 /*************************************
1358 * Return true if we can take the address of this variable.
1360 final bool canTakeAddressOf()
1362 return !(storage_class & STC.manifest);
1365 /******************************************
1366 * Return true if variable needs to call the destructor.
1368 final bool needsScopeDtor()
1370 //printf("VarDeclaration::needsScopeDtor() %s\n", toChars());
1371 return edtor && !(storage_class & STC.nodtor);
1374 /******************************************
1375 * If a variable has a scope destructor call, return call for it.
1376 * Otherwise, return NULL.
1378 extern (D) final Expression callScopeDtor(Scope* sc)
1380 //printf("VarDeclaration::callScopeDtor() %s\n", toChars());
1382 // Destruction of STC.field's is handled by buildDtor()
1383 if (storage_class & (STC.nodtor | STC.ref_ | STC.out_ | STC.field))
1389 return null; // destructor is built by `void semantic(Catch c, Scope* sc)`, not here
1391 Expression e = null;
1392 // Destructors for structs and arrays of structs
1393 Type tv = type.baseElemOf();
1394 if (tv.ty == Tstruct)
1396 StructDeclaration sd = (cast(TypeStruct)tv).sym;
1397 if (!sd.dtor || sd.errors)
1400 const sz = type.size();
1401 assert(sz != SIZE_INVALID);
1405 if (type.toBasetype().ty == Tstruct)
1408 e = new VarExp(loc, this);
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
1414 e.type = e.type.mutableOf();
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;
1421 e = new DotVarExp(loc, e, sd.dtor, false);
1422 e = new CallExp(loc, e);
1426 // __ArrayDtor(v[0 .. n])
1427 e = new VarExp(loc, this);
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));
1434 // Prevent redundant bounds check
1435 (cast(SliceExp)e).upperIsInBounds = true;
1436 (cast(SliceExp)e).lowerIsLessThanUpper = true;
1438 // This is a hack so we can call destructors on const/immutable objects.
1439 e.type = sd.type.arrayOf();
1441 e = new CallExp(loc, new IdentifierExp(loc, Id.__ArrayDtor), e);
1445 // Destructors for classes
1446 if (storage_class & (STC.auto_ | STC.scope_) && !(storage_class & STC.parameter))
1448 for (ClassDeclaration cd = type.isClassHandle(); cd; cd = cd.baseClass)
1450 /* We can do better if there's a way with onstack
1451 * classes to determine if there's no way the monitor
1454 //if (cd.isInterfaceDeclaration())
1455 // error("interface `%s` cannot be scope", cd.toChars());
1457 if (mynew || onstack) // if any destructors
1459 // delete'ing C++ classes crashes (and delete is deprecated anyway)
1460 if (cd.classKind == ClassKind.cpp)
1462 // Don't call non-existant dtor
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);
1475 ec = new VarExp(loc, this);
1476 e = new DeleteExp(loc, ec, true);
1477 e.type = Type.tvoid;
1485 /*******************************************
1486 * If variable has a constant expression initializer, get it.
1487 * Otherwise, return null.
1489 extern (D) final Expression getConstInitializer(bool needFullType = true)
1491 assert(type && _init);
1493 // Ungag errors when not speculative
1494 uint oldgag = global.gag;
1497 Dsymbol sym = toParent().isAggregateDeclaration();
1498 if (sym && !sym.isSpeculative())
1505 _init = _init.initializerSemantic(_scope, type, INITinterpret);
1510 Expression e = _init.initializerToExpression(needFullType ? type : null);
1511 global.gag = oldgag;
1515 /*******************************************
1516 * Helper function for the expansion of manifest constant.
1518 extern (D) final Expression expandInitializer(Loc loc)
1520 assert((storage_class & STC.manifest) && _init);
1522 auto e = getConstInitializer();
1525 .error(loc, "cannot make expression out of initializer for `%s`", toChars());
1526 return ErrorExp.get();
1530 e.loc = loc; // for better error message
1534 override final void checkCtorConstInit()
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");
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.
1550 extern (D) final bool checkNestedReference(Scope* sc, Loc loc)
1552 //printf("VarDeclaration::checkNestedReference() %s\n", toChars());
1553 if (sc.intypeof == 1 || (sc.flags & SCOPE.ctfe))
1555 if (!parent || parent == sc.parent)
1557 if (isDataseg() || (storage_class & STC.manifest))
1560 // The current function
1561 FuncDeclaration fdthis = sc.parent.isFuncDeclaration();
1563 return false; // out of function scope
1565 Dsymbol p = toParent2();
1567 // Function literals from fdthis to p must be delegates
1568 ensureStaticLinkTo(fdthis, p);
1570 // The function that this variable is in
1571 FuncDeclaration fdv = p.isFuncDeclaration();
1572 if (!fdv || fdv == fdthis)
1575 // Add fdthis to nestedrefs[] if not already there
1576 if (!nestedrefs.contains(fdthis))
1577 nestedrefs.push(fdthis);
1579 //printf("\tfdv = %s\n", fdv.toChars());
1580 //printf("\tfdthis = %s\n", fdthis.toChars());
1583 if (fdthis.getLevelAndCheck(loc, sc, fdv, this) == fdthis.LevelError)
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))
1593 if (!fdv.closureVars.contains(this))
1594 fdv.closureVars.push(this);
1597 if (!fdthis.outerVars.contains(this))
1598 fdthis.outerVars.push(this);
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)
1606 .error(loc, "cannnot use `$` inside a function literal");
1609 if (ident == Id.withSym) // https://issues.dlang.org/show_bug.cgi?id=1759
1611 ExpInitializer ez = _init.isExpInitializer();
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);
1622 override final Dsymbol toAlias()
1624 //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym);
1625 if ((!type || !type.deco) && _scope)
1626 dsymbolSemantic(this, _scope);
1628 assert(this != aliassym);
1629 Dsymbol s = aliassym ? aliassym.toAlias() : this;
1633 // Eliminate need for dynamic_cast
1634 override final inout(VarDeclaration) isVarDeclaration() inout
1639 override void accept(Visitor v)
1644 /**********************************
1645 * Determine if `this` has a lifetime that lasts past
1646 * the destruction of `v`
1648 * v = variable to test against
1652 final bool enclosesLifetimeOf(VarDeclaration v) const pure
1654 // VarDeclaration's with these STC's need special treatment
1655 enum special = STC.temp | STC.foreach_;
1657 // Sequence numbers work when there are no special VarDeclaration's involved
1658 if (!((this.storage_class | v.storage_class) & special))
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();
1665 return (this.sequenceNumber < v.sequenceNumber) == exp;
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;
1673 // Fall back to lexical order
1674 assert(this.loc != Loc.initial);
1675 assert(v.loc != Loc.initial);
1677 if (this.loc.linnum != v.loc.linnum)
1678 return this.loc.linnum < v.loc.linnum;
1680 if (this.loc.charnum != v.loc.charnum)
1681 return this.loc.charnum < v.loc.charnum;
1684 return this.sequenceNumber < v.sequenceNumber;
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
1694 * v = an STC.maybescope variable that was assigned to `this`
1696 final void addMaybe(VarDeclaration v)
1698 //printf("add %s to %s's list of dependencies\n", v.toChars(), toChars());
1700 maybes = new VarDeclarations();
1705 /*******************************************************
1706 * C11 6.7.2.1-4 bit fields
1708 extern (C++) class BitFieldDeclaration : VarDeclaration
1715 final extern (D) this(const ref Loc loc, Type type, Identifier ident, Expression width)
1717 super(loc, type, ident, null);
1720 this.storage_class |= STC.field;
1723 override BitFieldDeclaration syntaxCopy(Dsymbol s)
1725 //printf("BitFieldDeclaration::syntaxCopy(%s)\n", toChars());
1727 auto bf = new BitFieldDeclaration(loc, type ? type.syntaxCopy() : null, ident, width.syntaxCopy());
1728 bf.comment = comment;
1732 override final inout(BitFieldDeclaration) isBitFieldDeclaration() inout
1737 override void accept(Visitor v)
1742 override final void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion)
1744 //printf("BitFieldDeclaration::setFieldOffset(ad: %s, field: %s)\n", ad.toChars(), toChars());
1745 static void print(const ref FieldState fieldState)
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);
1753 //print(fieldState);
1755 Type t = type.toBasetype();
1756 const bool anon = isAnonymous();
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.
1761 ad.fields.push(this);
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
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);
1776 const style = target.c.bitFieldStyle;
1778 void startNewField()
1781 if (style == TargetC.BitFieldStyle.Gcc_Clang)
1783 if (fieldWidth > 32)
1784 alignsize = memalignsize;
1785 else if (fieldWidth > 16)
1787 else if (fieldWidth > 8)
1793 alignsize = memsize; // not memalignsize
1796 offset = AggregateDeclaration.placeField(
1798 memsize, alignsize, alignment,
1800 (anon && style == TargetC.BitFieldStyle.Gcc_Clang) ? &dummy : &ad.alignsize,
1803 fieldState.inFlight = true;
1804 fieldState.fieldOffset = offset;
1805 fieldState.bitOffset = 0;
1806 fieldState.fieldSize = memsize;
1809 if (style == TargetC.BitFieldStyle.Gcc_Clang)
1811 if (fieldWidth == 0)
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;
1820 fieldState.inFlight = false;
1824 if (ad.alignsize == 0)
1827 ad.alignsize < memalignsize)
1828 ad.alignsize = memalignsize;
1830 else if (style == TargetC.BitFieldStyle.MS)
1832 if (ad.alignsize == 0)
1834 if (fieldWidth == 0)
1836 if (fieldState.inFlight && !isunion)
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;
1845 fieldState.inFlight = false;
1849 else if (style == TargetC.BitFieldStyle.DM)
1851 if (anon && fieldWidth && (!fieldState.inFlight || fieldState.bitOffset == 0))
1852 return; // this probably should be a bug in DMC
1853 if (ad.alignsize == 0)
1855 if (fieldWidth == 0)
1857 if (fieldState.inFlight && !isunion)
1859 const alsz = memsize;
1860 fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1);
1861 ad.structsize = fieldState.offset;
1864 fieldState.inFlight = false;
1869 if (!fieldState.inFlight)
1873 else if (style == TargetC.BitFieldStyle.Gcc_Clang)
1875 if (fieldState.bitOffset + fieldWidth > memsize * 8)
1877 //printf("start1 fieldState.bitOffset:%u fieldWidth:%u memsize:%u\n", fieldState.bitOffset, fieldWidth, memsize);
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))
1888 //printf("alignment is crossed\n");
1893 else if (style == TargetC.BitFieldStyle.DM ||
1894 style == TargetC.BitFieldStyle.MS)
1896 if (memsize != fieldState.fieldSize ||
1897 fieldState.bitOffset + fieldWidth > fieldState.fieldSize * 8)
1905 offset = fieldState.fieldOffset;
1906 bitOffset = fieldState.bitOffset;
1908 const pastField = bitOffset + fieldWidth;
1909 if (style == TargetC.BitFieldStyle.Gcc_Clang)
1911 auto size = (pastField + 7) / 8;
1912 fieldState.fieldSize = size;
1913 //printf(" offset: %d, size: %d\n", offset, size);
1914 ad.structsize = offset + size;
1917 fieldState.fieldSize = memsize;
1918 //printf("at end: ad.structsize = %d\n", cast(int)ad.structsize);
1919 //print(fieldState);
1923 fieldState.offset = offset + fieldState.fieldSize;
1924 fieldState.bitOffset = pastField;
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);
1932 /***********************************************************
1933 * This is a shell around a back end symbol
1935 extern (C++) final class SymbolDeclaration : Declaration
1937 AggregateDeclaration dsym;
1939 extern (D) this(const ref Loc loc, AggregateDeclaration dsym)
1941 super(loc, dsym.ident);
1943 storage_class |= STC.const_;
1946 // Eliminate need for dynamic_cast
1947 override inout(SymbolDeclaration) isSymbolDeclaration() inout
1952 override void accept(Visitor v)
1958 /***********************************************************
1960 extern (C++) class TypeInfoDeclaration : VarDeclaration
1964 final extern (D) this(Type tinfo)
1966 super(Loc.initial, Type.dtypeinfo.type, tinfo.getTypeInfoIdent(), null);
1968 storage_class = STC.static_ | STC.gshared;
1969 visibility = Visibility(Visibility.Kind.public_);
1971 alignment.set(target.ptrsize);
1974 static TypeInfoDeclaration create(Type tinfo)
1976 return new TypeInfoDeclaration(tinfo);
1979 override final TypeInfoDeclaration syntaxCopy(Dsymbol s)
1981 assert(0); // should never be produced by syntax
1984 override final const(char)* toChars() const
1986 //printf("TypeInfoDeclaration::toChars() tinfo = %s\n", tinfo.toChars());
1988 buf.writestring("typeid(");
1989 buf.writestring(tinfo.toChars());
1991 return buf.extractChars();
1994 override final inout(TypeInfoDeclaration) isTypeInfoDeclaration() inout @nogc nothrow pure @safe
1999 override void accept(Visitor v)
2005 /***********************************************************
2007 extern (C++) final class TypeInfoStructDeclaration : TypeInfoDeclaration
2009 extern (D) this(Type tinfo)
2012 if (!Type.typeinfostruct)
2014 ObjectNotFound(Id.TypeInfo_Struct);
2016 type = Type.typeinfostruct.type;
2019 static TypeInfoStructDeclaration create(Type tinfo)
2021 return new TypeInfoStructDeclaration(tinfo);
2024 override void accept(Visitor v)
2030 /***********************************************************
2032 extern (C++) final class TypeInfoClassDeclaration : TypeInfoDeclaration
2034 extern (D) this(Type tinfo)
2037 if (!Type.typeinfoclass)
2039 ObjectNotFound(Id.TypeInfo_Class);
2041 type = Type.typeinfoclass.type;
2044 static TypeInfoClassDeclaration create(Type tinfo)
2046 return new TypeInfoClassDeclaration(tinfo);
2049 override void accept(Visitor v)
2055 /***********************************************************
2057 extern (C++) final class TypeInfoInterfaceDeclaration : TypeInfoDeclaration
2059 extern (D) this(Type tinfo)
2062 if (!Type.typeinfointerface)
2064 ObjectNotFound(Id.TypeInfo_Interface);
2066 type = Type.typeinfointerface.type;
2069 static TypeInfoInterfaceDeclaration create(Type tinfo)
2071 return new TypeInfoInterfaceDeclaration(tinfo);
2074 override void accept(Visitor v)
2080 /***********************************************************
2082 extern (C++) final class TypeInfoPointerDeclaration : TypeInfoDeclaration
2084 extern (D) this(Type tinfo)
2087 if (!Type.typeinfopointer)
2089 ObjectNotFound(Id.TypeInfo_Pointer);
2091 type = Type.typeinfopointer.type;
2094 static TypeInfoPointerDeclaration create(Type tinfo)
2096 return new TypeInfoPointerDeclaration(tinfo);
2099 override void accept(Visitor v)
2105 /***********************************************************
2107 extern (C++) final class TypeInfoArrayDeclaration : TypeInfoDeclaration
2109 extern (D) this(Type tinfo)
2112 if (!Type.typeinfoarray)
2114 ObjectNotFound(Id.TypeInfo_Array);
2116 type = Type.typeinfoarray.type;
2119 static TypeInfoArrayDeclaration create(Type tinfo)
2121 return new TypeInfoArrayDeclaration(tinfo);
2124 override void accept(Visitor v)
2130 /***********************************************************
2132 extern (C++) final class TypeInfoStaticArrayDeclaration : TypeInfoDeclaration
2134 extern (D) this(Type tinfo)
2137 if (!Type.typeinfostaticarray)
2139 ObjectNotFound(Id.TypeInfo_StaticArray);
2141 type = Type.typeinfostaticarray.type;
2144 static TypeInfoStaticArrayDeclaration create(Type tinfo)
2146 return new TypeInfoStaticArrayDeclaration(tinfo);
2149 override void accept(Visitor v)
2155 /***********************************************************
2157 extern (C++) final class TypeInfoAssociativeArrayDeclaration : TypeInfoDeclaration
2159 extern (D) this(Type tinfo)
2162 if (!Type.typeinfoassociativearray)
2164 ObjectNotFound(Id.TypeInfo_AssociativeArray);
2166 type = Type.typeinfoassociativearray.type;
2169 static TypeInfoAssociativeArrayDeclaration create(Type tinfo)
2171 return new TypeInfoAssociativeArrayDeclaration(tinfo);
2174 override void accept(Visitor v)
2180 /***********************************************************
2182 extern (C++) final class TypeInfoEnumDeclaration : TypeInfoDeclaration
2184 extern (D) this(Type tinfo)
2187 if (!Type.typeinfoenum)
2189 ObjectNotFound(Id.TypeInfo_Enum);
2191 type = Type.typeinfoenum.type;
2194 static TypeInfoEnumDeclaration create(Type tinfo)
2196 return new TypeInfoEnumDeclaration(tinfo);
2199 override void accept(Visitor v)
2205 /***********************************************************
2207 extern (C++) final class TypeInfoFunctionDeclaration : TypeInfoDeclaration
2209 extern (D) this(Type tinfo)
2212 if (!Type.typeinfofunction)
2214 ObjectNotFound(Id.TypeInfo_Function);
2216 type = Type.typeinfofunction.type;
2219 static TypeInfoFunctionDeclaration create(Type tinfo)
2221 return new TypeInfoFunctionDeclaration(tinfo);
2224 override void accept(Visitor v)
2230 /***********************************************************
2232 extern (C++) final class TypeInfoDelegateDeclaration : TypeInfoDeclaration
2234 extern (D) this(Type tinfo)
2237 if (!Type.typeinfodelegate)
2239 ObjectNotFound(Id.TypeInfo_Delegate);
2241 type = Type.typeinfodelegate.type;
2244 static TypeInfoDelegateDeclaration create(Type tinfo)
2246 return new TypeInfoDelegateDeclaration(tinfo);
2249 override void accept(Visitor v)
2255 /***********************************************************
2257 extern (C++) final class TypeInfoTupleDeclaration : TypeInfoDeclaration
2259 extern (D) this(Type tinfo)
2262 if (!Type.typeinfotypelist)
2264 ObjectNotFound(Id.TypeInfo_Tuple);
2266 type = Type.typeinfotypelist.type;
2269 static TypeInfoTupleDeclaration create(Type tinfo)
2271 return new TypeInfoTupleDeclaration(tinfo);
2274 override void accept(Visitor v)
2280 /***********************************************************
2282 extern (C++) final class TypeInfoConstDeclaration : TypeInfoDeclaration
2284 extern (D) this(Type tinfo)
2287 if (!Type.typeinfoconst)
2289 ObjectNotFound(Id.TypeInfo_Const);
2291 type = Type.typeinfoconst.type;
2294 static TypeInfoConstDeclaration create(Type tinfo)
2296 return new TypeInfoConstDeclaration(tinfo);
2299 override void accept(Visitor v)
2305 /***********************************************************
2307 extern (C++) final class TypeInfoInvariantDeclaration : TypeInfoDeclaration
2309 extern (D) this(Type tinfo)
2312 if (!Type.typeinfoinvariant)
2314 ObjectNotFound(Id.TypeInfo_Invariant);
2316 type = Type.typeinfoinvariant.type;
2319 static TypeInfoInvariantDeclaration create(Type tinfo)
2321 return new TypeInfoInvariantDeclaration(tinfo);
2324 override void accept(Visitor v)
2330 /***********************************************************
2332 extern (C++) final class TypeInfoSharedDeclaration : TypeInfoDeclaration
2334 extern (D) this(Type tinfo)
2337 if (!Type.typeinfoshared)
2339 ObjectNotFound(Id.TypeInfo_Shared);
2341 type = Type.typeinfoshared.type;
2344 static TypeInfoSharedDeclaration create(Type tinfo)
2346 return new TypeInfoSharedDeclaration(tinfo);
2349 override void accept(Visitor v)
2355 /***********************************************************
2357 extern (C++) final class TypeInfoWildDeclaration : TypeInfoDeclaration
2359 extern (D) this(Type tinfo)
2362 if (!Type.typeinfowild)
2364 ObjectNotFound(Id.TypeInfo_Wild);
2366 type = Type.typeinfowild.type;
2369 static TypeInfoWildDeclaration create(Type tinfo)
2371 return new TypeInfoWildDeclaration(tinfo);
2374 override void accept(Visitor v)
2380 /***********************************************************
2382 extern (C++) final class TypeInfoVectorDeclaration : TypeInfoDeclaration
2384 extern (D) this(Type tinfo)
2387 if (!Type.typeinfovector)
2389 ObjectNotFound(Id.TypeInfo_Vector);
2391 type = Type.typeinfovector.type;
2394 static TypeInfoVectorDeclaration create(Type tinfo)
2396 return new TypeInfoVectorDeclaration(tinfo);
2399 override void accept(Visitor v)
2405 /***********************************************************
2406 * For the "this" parameter to member functions
2408 extern (C++) final class ThisDeclaration : VarDeclaration
2410 extern (D) this(const ref Loc loc, Type t)
2412 super(loc, t, Id.This, null);
2413 storage_class |= STC.nodtor;
2416 override ThisDeclaration syntaxCopy(Dsymbol s)
2418 assert(0); // should never be produced by syntax
2421 override inout(ThisDeclaration) isThisDeclaration() inout
2426 override void accept(Visitor v)