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;
34 import dmd.identifier;
39 import dmd.common.outbuffer;
40 import dmd.root.rootobject;
46 /************************************
47 * Check to see the aggregate type is nested and its context pointer is
48 * accessible from the current scope.
49 * Returns true if error occurs.
51 bool checkFrameAccess(Loc loc, Scope* sc, AggregateDeclaration ad, size_t iStart = 0)
53 Dsymbol sparent = ad.toParentLocal();
54 Dsymbol sparent2 = ad.toParent2();
56 if (ad.isNested() && s)
58 //printf("ad = %p %s [%s], parent:%p\n", ad, ad.toChars(), ad.loc.toChars(), ad.parent);
59 //printf("sparent = %p %s [%s], parent: %s\n", sparent, sparent.toChars(), sparent.loc.toChars(), sparent.parent,toChars());
60 //printf("sparent2 = %p %s [%s], parent: %s\n", sparent2, sparent2.toChars(), sparent2.loc.toChars(), sparent2.parent,toChars());
61 if (!ensureStaticLinkTo(s, sparent) || sparent != sparent2 && !ensureStaticLinkTo(s, sparent2))
63 error(loc, "cannot access frame pointer of `%s`", ad.toPrettyChars());
69 for (size_t i = iStart; i < ad.fields.length; i++)
71 VarDeclaration vd = ad.fields[i];
72 Type tb = vd.type.baseElemOf();
75 result |= checkFrameAccess(loc, sc, (cast(TypeStruct)tb).sym);
81 /***********************************************
82 * Mark variable v as modified if it is inside a constructor that var
85 bool modifyFieldVar(Loc loc, Scope* sc, VarDeclaration var, Expression e1)
87 //printf("modifyFieldVar(var = %s)\n", var.toChars());
91 FuncDeclaration fd = null;
93 fd = s.isFuncDeclaration();
95 ((fd.isCtorDeclaration() && var.isField()) ||
96 (fd.isStaticCtorDeclaration() && !var.isField())) &&
97 fd.toParentDecl() == var.toParent2() &&
98 (!e1 || e1.op == EXP.this_))
103 //printf("setting ctorinit\n");
105 if (var.isField() && sc.ctorflow.fieldinit.length && !sc.intypeof)
108 auto mustInit = ((var.storage_class & STC.nodefaultctor) != 0 ||
109 var.type.needsNested());
111 const dim = sc.ctorflow.fieldinit.length;
112 auto ad = fd.isMemberDecl();
115 for (i = 0; i < dim; i++) // same as findFieldIndexByName in ctfeexp.c ?
117 if (ad.fields[i] == var)
121 auto fieldInit = &sc.ctorflow.fieldinit[i];
122 const fi = fieldInit.csx;
124 if (fi & CSX.this_ctor)
126 if (var.type.isMutable() && e1.type.isMutable())
130 const(char)* modStr = !var.type.isMutable() ? MODtoChars(var.type.mod) : MODtoChars(e1.type.mod);
131 .error(loc, "%s field `%s` initialized multiple times", modStr, var.toChars());
132 .errorSupplemental(fieldInit.loc, "Previous initialization is here.");
135 else if (sc.inLoop || (fi & CSX.label))
137 if (!mustInit && var.type.isMutable() && e1.type.isMutable())
141 const(char)* modStr = !var.type.isMutable() ? MODtoChars(var.type.mod) : MODtoChars(e1.type.mod);
142 .error(loc, "%s field `%s` initialization is not allowed in loops or after labels", modStr, var.toChars());
146 fieldInit.csx |= CSX.this_ctor;
147 fieldInit.loc = e1.loc;
148 if (var.overlapped) // https://issues.dlang.org/show_bug.cgi?id=15258
150 foreach (j, v; ad.fields)
152 if (v is var || !var.isOverlappedWith(v))
155 sc.ctorflow.fieldinit[j].csx = CSX.this_ctor;
159 else if (fd != sc.func)
161 if (var.type.isMutable())
163 else if (sc.func.fes)
165 const(char)* p = var.isField() ? "field" : var.kind();
166 .error(loc, "%s %s `%s` initialization is not allowed in foreach loop",
167 MODtoChars(var.type.mod), p, var.toChars());
171 const(char)* p = var.isField() ? "field" : var.kind();
172 .error(loc, "%s %s `%s` initialization is not allowed in nested function `%s`",
173 MODtoChars(var.type.mod), p, var.toChars(), sc.func.toChars());
176 else if (fd.isStaticCtorDeclaration() && !fd.isSharedStaticCtorDeclaration() &&
177 var.type.isImmutable())
179 .error(loc, "%s %s `%s` initialization is not allowed in `static this`",
180 MODtoChars(var.type.mod), var.kind(), var.toChars());
181 errorSupplemental(loc, "Use `shared static this` instead.");
189 s = s.toParentP(var.toParent2());
198 /******************************************
200 extern (C++) void ObjectNotFound(Identifier id)
202 error(Loc.initial, "`%s` not found. object.d may be incorrectly installed or corrupt.", id.toChars());
206 /* Accumulator for successive matches.
208 struct MatchAccumulator
210 int count; // number of matches found so far
211 MATCH last = MATCH.nomatch; // match level of lastf
212 FuncDeclaration lastf; // last matching function we found
213 FuncDeclaration nextf; // if ambiguous match, this is the "other" function
216 /***********************************************************
218 extern (C++) abstract class Declaration : Dsymbol
221 Type originalType; // before semantic analysis
222 StorageClass storage_class = STC.undefined_;
223 Visibility visibility;
224 LINK _linkage = LINK.default_; // may be `LINK.system`; use `resolvedLinkage()` to resolve it
225 short inuse; // used to detect cycles
227 ubyte adFlags; // control re-assignment of AliasDeclaration (put here for packing reasons)
228 enum wasRead = 1; // set if AliasDeclaration was read
229 enum ignoreRead = 2; // ignore any reads of AliasDeclaration
230 enum nounderscore = 4; // don't prepend _ to mangled name
232 Symbol* isym; // import version of csym
234 // overridden symbol with pragma(mangle, "...")
235 const(char)[] mangleOverride;
237 final extern (D) this(Identifier ident)
240 visibility = Visibility(Visibility.Kind.undefined);
243 final extern (D) this(const ref Loc loc, Identifier ident)
246 visibility = Visibility(Visibility.Kind.undefined);
249 override const(char)* kind() const
251 return "declaration";
254 override final uinteger_t size(const ref Loc loc)
257 const sz = type.size();
258 if (sz == SIZE_INVALID)
264 * Issue an error if an attempt to call a disabled method is made
266 * If the declaration is disabled but inside a disabled function,
267 * returns `true` but do not issue an error message.
270 * loc = Location information of the call
271 * sc = Scope in which the call occurs
272 * isAliasedDeclaration = if `true` searches overload set
275 * `true` if this `Declaration` is `@disable`d, `false` otherwise.
277 extern (D) final bool checkDisabled(Loc loc, Scope* sc, bool isAliasedDeclaration = false)
279 if (!(storage_class & STC.disable))
282 if (sc.func && sc.func.storage_class & STC.disable)
285 if (auto p = toParent())
287 if (auto postblit = isPostBlitDeclaration())
289 /* https://issues.dlang.org/show_bug.cgi?id=21885
291 * If the generated postblit is disabled, it
292 * means that one of the fields has a disabled
293 * postblit. Print the first field that has
294 * a disabled postblit.
296 if (postblit.isGenerated())
298 auto sd = p.isStructDeclaration();
300 for (size_t i = 0; i < sd.fields.length; i++)
302 auto structField = sd.fields[i];
303 if (structField.overlapped)
305 Type tv = structField.type.baseElemOf();
306 if (tv.ty != Tstruct)
308 auto sdv = (cast(TypeStruct)tv).sym;
311 if (sdv.postblit.isDisabled())
313 p.error(loc, "is not copyable because field `%s` is not copyable", structField.toChars());
318 p.error(loc, "is not copyable because it has a disabled postblit");
323 // if the function is @disabled, maybe there
324 // is an overload in the overload set that isn't
325 if (isAliasedDeclaration)
327 FuncDeclaration fd = isFuncDeclaration();
330 for (FuncDeclaration ovl = fd; ovl; ovl = cast(FuncDeclaration)ovl.overnext)
331 if (!(ovl.storage_class & STC.disable))
336 if (auto ctor = isCtorDeclaration())
338 if (ctor.isCpCtor && ctor.isGenerated())
340 .error(loc, "generating an `inout` copy constructor for `struct %s` failed, therefore instances of it are uncopyable", parent.toPrettyChars());
344 error(loc, "cannot be used because it is annotated with `@disable`");
348 /*************************************
349 * Check to see if declaration can be modified in this context (sc).
350 * Issue error if not.
352 * loc = location for error messages
353 * e1 = `null` or `this` expression when this declaration is a field
355 * flag = if the first bit is set it means do not issue error message for
356 * invalid modification; if the second bit is set, it means that
357 this declaration is a field and a subfield of it is modified.
359 * Modifiable.yes or Modifiable.initialization
361 extern (D) final Modifiable checkModify(Loc loc, Scope* sc, Expression e1, ModifyFlags flag)
363 VarDeclaration v = isVarDeclaration();
364 if (v && v.canassign)
365 return Modifiable.initialization;
367 if (isParameter() || isResult())
369 for (Scope* scx = sc; scx; scx = scx.enclosing)
371 if (scx.func == parent && (scx.flags & SCOPE.contract))
373 const(char)* s = isParameter() && parent.ident != Id.ensure ? "parameter" : "result";
374 if (!(flag & ModifyFlags.noError))
375 error(loc, "cannot modify %s `%s` in contract", s, toChars());
376 return Modifiable.initialization; // do not report type related errors
381 if (e1 && e1.op == EXP.this_ && isField())
383 VarDeclaration vthis = e1.isThisExp().var;
384 for (Scope* scx = sc; scx; scx = scx.enclosing)
386 if (scx.func == vthis.parent && (scx.flags & SCOPE.contract))
388 if (!(flag & ModifyFlags.noError))
389 error(loc, "cannot modify parameter `this` in contract");
390 return Modifiable.initialization; // do not report type related errors
395 if (v && (v.isCtorinit() || isField()))
397 // It's only modifiable if inside the right constructor
398 if ((storage_class & (STC.foreach_ | STC.ref_)) == (STC.foreach_ | STC.ref_))
399 return Modifiable.initialization;
400 if (flag & ModifyFlags.fieldAssign)
401 return Modifiable.yes;
402 return modifyFieldVar(loc, sc, v, e1) ? Modifiable.initialization : Modifiable.yes;
404 return Modifiable.yes;
407 override final Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
409 Dsymbol s = Dsymbol.search(loc, ident, flags);
412 s = type.toDsymbol(_scope);
414 s = s.search(loc, ident, flags);
419 final bool isStatic() const pure nothrow @nogc @safe
421 return (storage_class & STC.static_) != 0;
424 /// Returns the linkage, resolving the target-specific `System` one.
425 final LINK resolvedLinkage() const
427 return _linkage == LINK.system ? target.systemLinkage() : _linkage;
445 bool isCodeseg() const pure nothrow @nogc @safe
450 final bool isFinal() const pure nothrow @nogc @safe
452 return (storage_class & STC.final_) != 0;
457 return (storage_class & STC.abstract_) != 0;
460 final bool isConst() const pure nothrow @nogc @safe
462 return (storage_class & STC.const_) != 0;
465 final bool isImmutable() const pure nothrow @nogc @safe
467 return (storage_class & STC.immutable_) != 0;
470 final bool isWild() const pure nothrow @nogc @safe
472 return (storage_class & STC.wild) != 0;
475 final bool isAuto() const pure nothrow @nogc @safe
477 return (storage_class & STC.auto_) != 0;
480 final bool isScope() const pure nothrow @nogc @safe
482 return (storage_class & STC.scope_) != 0;
485 final bool isReturn() const pure nothrow @nogc @safe
487 return (storage_class & STC.return_) != 0;
490 final bool isSynchronized() const pure nothrow @nogc @safe
492 return (storage_class & STC.synchronized_) != 0;
495 final bool isParameter() const pure nothrow @nogc @safe
497 return (storage_class & STC.parameter) != 0;
500 override final bool isDeprecated() const pure nothrow @nogc @safe
502 return (storage_class & STC.deprecated_) != 0;
505 final bool isDisabled() const pure nothrow @nogc @safe
507 return (storage_class & STC.disable) != 0;
510 final bool isOverride() const pure nothrow @nogc @safe
512 return (storage_class & STC.override_) != 0;
515 final bool isResult() const pure nothrow @nogc @safe
517 return (storage_class & STC.result) != 0;
520 final bool isField() const pure nothrow @nogc @safe
522 return (storage_class & STC.field) != 0;
525 final bool isIn() const pure nothrow @nogc @safe
527 return (storage_class & STC.in_) != 0;
530 final bool isOut() const pure nothrow @nogc @safe
532 return (storage_class & STC.out_) != 0;
535 final bool isRef() const pure nothrow @nogc @safe
537 return (storage_class & STC.ref_) != 0;
540 /// Returns: Whether the variable is a reference, annotated with `out` or `ref`
541 final bool isReference() const pure nothrow @nogc @safe
543 return (storage_class & (STC.ref_ | STC.out_)) != 0;
546 final bool isFuture() const pure nothrow @nogc @safe
548 return (storage_class & STC.future) != 0;
551 final extern(D) bool isSystem() const pure nothrow @nogc @safe
553 return (storage_class & STC.system) != 0;
556 override final Visibility visible() pure nothrow @nogc @safe
561 override final inout(Declaration) isDeclaration() inout pure nothrow @nogc @safe
566 override void accept(Visitor v)
572 /***********************************************************
574 extern (C++) final class TupleDeclaration : Declaration
577 TypeTuple tupletype; // !=null if this is a type tuple
578 bool isexp; // true: expression tuple
579 bool building; // it's growing in AliasAssign semantic
581 extern (D) this(const ref Loc loc, Identifier ident, Objects* objects)
584 this.objects = objects;
587 override TupleDeclaration syntaxCopy(Dsymbol s)
592 override const(char)* kind() const
597 override Type getType()
599 /* If this tuple represents a type, return that type
602 //printf("TupleDeclaration::getType() %s\n", toChars());
603 if (isexp || building)
607 /* It's only a type tuple if all the Object's are types
609 for (size_t i = 0; i < objects.length; i++)
611 RootObject o = (*objects)[i];
612 if (o.dyncast() != DYNCAST.type)
614 //printf("\tnot[%d], %p, %d\n", i, o, o.dyncast());
619 /* We know it's a type tuple, so build the TypeTuple
621 Types* types = cast(Types*)objects;
622 auto args = new Parameters(objects.length);
625 for (size_t i = 0; i < types.length; i++)
627 Type t = (*types)[i];
628 //printf("type = %s\n", t.toChars());
631 buf.printf("_%s_%d", ident.toChars(), i);
632 const len = buf.offset;
633 const name = buf.extractSlice().ptr;
634 auto id = Identifier.idPool(name, len);
635 auto arg = new Parameter(STC.in_, t, id, null);
639 auto arg = new Parameter(0, t, null, null, null);
646 tupletype = new TypeTuple(args);
648 return tupletype.typeSemantic(Loc.initial, null);
653 override Dsymbol toAlias2()
655 //printf("TupleDeclaration::toAlias2() '%s' objects = %s\n", toChars(), objects.toChars());
656 for (size_t i = 0; i < objects.length; i++)
658 RootObject o = (*objects)[i];
659 if (Dsymbol s = isDsymbol(o))
668 override bool needThis()
670 //printf("TupleDeclaration::needThis(%s)\n", toChars());
671 return isexp ? foreachVar((s) { return s.needThis(); }) != 0 : false;
674 /***********************************************************
675 * Calls dg(Dsymbol) for each Dsymbol, which should be a VarDeclaration
676 * inside VarExp (isexp == true).
678 * dg = delegate to call for each Dsymbol
680 extern (D) void foreachVar(scope void delegate(Dsymbol) dg)
683 foreach (o; *objects)
685 if (auto e = o.isExpression())
686 if (auto ve = e.isVarExp())
691 /***********************************************************
692 * Calls dg(Dsymbol) for each Dsymbol, which should be a VarDeclaration
693 * inside VarExp (isexp == true).
694 * If dg returns !=0, stops and returns that value else returns 0.
696 * dg = delegate to call for each Dsymbol
698 * last value returned by dg()
700 extern (D) int foreachVar(scope int delegate(Dsymbol) dg)
703 foreach (o; *objects)
705 if (auto e = o.isExpression())
706 if (auto ve = e.isVarExp())
707 if(auto ret = dg(ve.var))
713 override inout(TupleDeclaration) isTupleDeclaration() inout
718 override void accept(Visitor v)
724 /***********************************************************
725 * https://dlang.org/spec/declaration.html#AliasDeclaration
727 extern (C++) final class AliasDeclaration : Declaration
729 Dsymbol aliassym; // alias ident = aliassym;
731 Dsymbol overnext; // next in overload list
732 Dsymbol _import; // !=null if unresolved internal alias for selective import
734 extern (D) this(const ref Loc loc, Identifier ident, Type type)
737 //printf("AliasDeclaration(id = '%s', type = %p)\n", id.toChars(), type);
738 //printf("type = '%s'\n", type.toChars());
743 extern (D) this(const ref Loc loc, Identifier ident, Dsymbol s)
746 //printf("AliasDeclaration(id = '%s', s = %p)\n", id.toChars(), s);
752 static AliasDeclaration create(const ref Loc loc, Identifier id, Type type)
754 return new AliasDeclaration(loc, id, type);
757 override AliasDeclaration syntaxCopy(Dsymbol s)
759 //printf("AliasDeclaration::syntaxCopy()\n");
761 AliasDeclaration sa = type ? new AliasDeclaration(loc, ident, type.syntaxCopy()) : new AliasDeclaration(loc, ident, aliassym.syntaxCopy(null));
762 sa.comment = comment;
763 sa.storage_class = storage_class;
767 override bool overloadInsert(Dsymbol s)
769 //printf("[%s] AliasDeclaration::overloadInsert('%s') s = %s %s @ [%s]\n",
770 // loc.toChars(), toChars(), s.kind(), s.toChars(), s.loc.toChars());
772 /** Aliases aren't overloadable themselves, but if their Aliasee is
773 * overloadable they are converted to an overloadable Alias (either
774 * FuncAliasDeclaration or OverDeclaration).
776 * This is done by moving the Aliasee into such an overloadable alias
777 * which is then used to replace the existing Aliasee. The original
778 * Alias (_this_) remains a useless shell.
780 * This is a horrible mess. It was probably done to avoid replacing
781 * existing AST nodes and references, but it needs a major
782 * simplification b/c it's too complex to maintain.
784 * A simpler approach might be to merge any colliding symbols into a
785 * simple Overload class (an array) and then later have that resolve
788 if (semanticRun >= PASS.semanticdone)
790 /* Semantic analysis is already finished, and the aliased entity
791 * is not overloadable.
796 If type has been resolved already we could
797 still be inserting an alias from an import.
799 If we are handling an alias then pretend
800 it was inserting and return true, if not then
801 false since we didn't even pretend to insert something.
803 return this._import && this.equals(s);
806 /* When s is added in member scope by static if, mixin("code") or others,
807 * aliassym is determined already. See the case in: test/compilable/test61.d
809 auto sa = aliassym.toAlias();
811 if (auto td = s.toAlias().isTemplateDeclaration())
812 s = td.funcroot ? td.funcroot : td;
814 if (auto fd = sa.isFuncDeclaration())
816 auto fa = new FuncAliasDeclaration(ident, fd);
817 fa.visibility = visibility;
820 return aliassym.overloadInsert(s);
822 if (auto td = sa.isTemplateDeclaration())
824 auto od = new OverDeclaration(ident, td.funcroot ? td.funcroot : td);
825 od.visibility = visibility;
828 return aliassym.overloadInsert(s);
830 if (auto od = sa.isOverDeclaration())
832 if (sa.ident != ident || sa.parent != parent)
834 od = new OverDeclaration(ident, od);
835 od.visibility = visibility;
839 return od.overloadInsert(s);
841 if (auto os = sa.isOverloadSet())
843 if (sa.ident != ident || sa.parent != parent)
845 os = new OverloadSet(ident, os);
846 // TODO: visibility is lost here b/c OverloadSets have no visibility attribute
847 // Might no be a practical issue, b/c the code below fails to resolve the overload anyhow.
851 // private alias merged = foo; // private alias to overload set of a.foo and b.foo
855 // public alias merged = bar; // public alias to overload set of a.bar and b.bar
859 // void test() { merged(123); } // should only look at os2.merged
861 // os.visibility = visibility;
871 /* Don't know yet what the aliased symbol is, so assume it can
872 * be overloaded and check later for correctness.
875 return overnext.overloadInsert(s);
882 override const(char)* kind() const
887 override Type getType()
891 return toAlias().getType();
894 override Dsymbol toAlias()
896 //printf("[%s] AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s', inuse = %d)\n",
897 // loc.toChars(), toChars(), this, aliassym, aliassym ? aliassym.kind() : "", inuse);
898 assert(this != aliassym);
899 //static int count; if (++count == 10) *(char*)0=0;
901 // Reading the AliasDeclaration
902 if (!(adFlags & ignoreRead))
903 adFlags |= wasRead; // can never assign to this AliasDeclaration again
905 if (inuse == 1 && type && _scope)
908 uint olderrors = global.errors;
909 Dsymbol s = type.toDsymbol(_scope);
910 //printf("[%s] type = %s, s = %p, this = %p\n", loc.toChars(), type.toChars(), s, this);
911 if (global.errors != olderrors)
916 if (global.errors != olderrors)
923 Type t = type.typeSemantic(loc, _scope);
926 if (global.errors != olderrors)
928 //printf("t = %s\n", t.toChars());
934 error("recursive alias declaration");
937 // Avoid breaking "recursive alias" state during errors gagged
940 aliassym = new AliasDeclaration(loc, ident, Type.terror);
945 if (semanticRun >= PASS.semanticdone)
947 // semantic is already done.
949 // Do not see aliassym !is null, because of lambda aliases.
951 // Do not see type.deco !is null, even so "alias T = const int;` needs
952 // semantic analysis to take the storage class `const` as type qualifier.
956 // stop AliasAssign tuple building
959 if (auto td = aliassym.isTupleDeclaration())
964 semanticRun = PASS.semanticdone;
969 if (_import && _import._scope)
971 /* If this is an internal alias for selective/renamed import,
972 * load the module first.
974 _import.dsymbolSemantic(null);
978 aliasSemantic(this, _scope);
983 Dsymbol s = aliassym ? aliassym.toAlias() : this;
988 override Dsymbol toAlias2()
992 error("recursive alias declaration");
996 Dsymbol s = aliassym ? aliassym.toAlias2() : this;
1001 override bool isOverloadable() const
1003 // assume overloadable until alias is resolved
1004 return semanticRun < PASS.semanticdone ||
1005 aliassym && aliassym.isOverloadable();
1008 override inout(AliasDeclaration) isAliasDeclaration() inout
1013 /** Returns: `true` if this instance was created to make a template parameter
1014 visible in the scope of a template body, `false` otherwise */
1015 extern (D) bool isAliasedTemplateParameter() const
1017 return !!(storage_class & STC.templateparameter);
1020 override void accept(Visitor v)
1026 /***********************************************************
1028 extern (C++) final class OverDeclaration : Declaration
1030 Dsymbol overnext; // next in overload list
1033 extern (D) this(Identifier ident, Dsymbol s)
1039 override const(char)* kind() const
1041 return "overload alias"; // todo
1044 override bool equals(const RootObject o) const
1049 auto s = isDsymbol(o);
1053 if (auto od2 = s.isOverDeclaration())
1054 return this.aliassym.equals(od2.aliassym);
1055 return this.aliassym == s;
1058 override bool overloadInsert(Dsymbol s)
1060 //printf("OverDeclaration::overloadInsert('%s') aliassym = %p, overnext = %p\n", s.toChars(), aliassym, overnext);
1062 return overnext.overloadInsert(s);
1069 override bool isOverloadable() const
1076 Dsymbol result = null;
1077 overloadApply(aliassym, (Dsymbol s)
1082 return 1; // ambiguous, done
1093 override inout(OverDeclaration) isOverDeclaration() inout
1098 override void accept(Visitor v)
1104 /***********************************************************
1106 extern (C++) class VarDeclaration : Declaration
1109 FuncDeclarations nestedrefs; // referenced by these lexically nested functions
1110 Dsymbol aliassym; // if redone as alias to another symbol
1111 VarDeclaration lastVar; // Linked list of variables for goto-skips-init detection
1112 Expression edtor; // if !=null, does the destruction of the variable
1113 IntRange* range; // if !=null, the variable is known to be within the range
1114 VarDeclarations* maybes; // maybeScope variables that are assigned to this maybeScope variable
1116 uint endlinnum; // line number of end of scope that this var lives in
1118 uint sequenceNumber; // order the variables are declared
1119 structalign_t alignment;
1121 // When interpreting, these point to the value (NULL if value not determinable)
1122 // The index of this variable on the CTFE stack, AdrOnStackNone if not allocated
1123 enum AdrOnStackNone = ~0u;
1124 uint ctfeAdrOnStack;
1126 // `bool` fields that are compacted into bit fields in a string mixin
1127 private extern (D) static struct BitFields
1129 bool isargptr; /// if parameter that _argptr points to
1130 bool ctorinit; /// it has been initialized in a ctor
1131 bool iscatchvar; /// this is the exception object variable in catch() clause
1132 bool isowner; /// this is an Owner, despite it being `scope`
1133 bool setInCtorOnly; /// field can only be set in a constructor, as it is const or immutable
1135 /// It is a class that was allocated on the stack
1137 /// This means the var is not rebindable once assigned,
1138 /// and the destructor gets run when it goes out of scope
1141 bool overlapped; /// if it is a field and has overlapping
1142 bool overlapUnsafe; /// if it is an overlapping field and the overlaps are unsafe
1143 bool maybeScope; /// allow inferring 'scope' for this variable
1144 bool doNotInferReturn; /// do not infer 'return' for this variable
1146 bool isArgDtorVar; /// temporary created to handle scope destruction of a function argument
1149 import dmd.common.bitfields : generateBitFields;
1150 mixin(generateBitFields!(BitFields, ushort));
1152 byte canassign; // it can be assigned to
1153 ubyte isdataseg; // private data for isDataseg 0 unset, 1 true, 2 false
1155 final extern (D) this(const ref Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.undefined_)
1162 //printf("VarDeclaration('%s')\n", ident.toChars());
1166 if (!type && !_init)
1168 //printf("VarDeclaration('%s')\n", ident.toChars());
1173 assert(type || _init);
1176 ctfeAdrOnStack = AdrOnStackNone;
1177 this.storage_class = storage_class;
1180 static VarDeclaration create(const ref Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.undefined_)
1182 return new VarDeclaration(loc, type, ident, _init, storage_class);
1185 override VarDeclaration syntaxCopy(Dsymbol s)
1187 //printf("VarDeclaration::syntaxCopy(%s)\n", toChars());
1189 auto v = new VarDeclaration(loc, type ? type.syntaxCopy() : null, ident, _init ? _init.syntaxCopy() : null, storage_class);
1190 v.comment = comment;
1194 override void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion)
1196 //printf("VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars());
1200 // If this variable was really a tuple, set the offsets for the tuple fields
1201 TupleDeclaration v2 = aliassym.isTupleDeclaration();
1203 v2.foreachVar((s) { s.setFieldOffset(ad, fieldState, isunion); });
1209 assert(!(storage_class & (STC.static_ | STC.extern_ | STC.parameter)));
1211 //printf("+VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars());
1213 /* Fields that are tuples appear both as part of TupleDeclarations and
1214 * as members. That means ignore them if they are already a field.
1219 fieldState.offset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613
1222 for (size_t i = 0; i < ad.fields.length; i++)
1224 if (ad.fields[i] == this)
1227 fieldState.offset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613
1232 // Check for forward referenced types which will fail the size() call
1233 Type t = type.toBasetype();
1234 if (storage_class & STC.ref_)
1236 // References are the size of a pointer
1239 Type tv = t.baseElemOf();
1240 if (tv.ty == Tstruct)
1242 auto ts = cast(TypeStruct)tv;
1243 assert(ts.sym != ad); // already checked in ad.determineFields()
1244 if (!ts.sym.determineSize(loc))
1252 // List in ad.fields. Even if the type is error, it's necessary to avoid
1253 // pointless error diagnostic "more initializers than fields" on struct literal.
1254 ad.fields.push(this);
1259 /* If coming after a bit field in progress,
1260 * advance past the field
1262 fieldState.inFlight = false;
1264 const sz = t.size(loc);
1265 assert(sz != SIZE_INVALID && sz < uint.max);
1266 uint memsize = cast(uint)sz; // size of member
1267 uint memalignsize = target.fieldalign(t); // size of member for alignment purposes
1268 offset = AggregateDeclaration.placeField(
1270 memsize, memalignsize, alignment,
1271 &ad.structsize, &ad.alignsize,
1274 //printf("\t%s: memalignsize = %d\n", toChars(), memalignsize);
1275 //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize);
1278 override const(char)* kind() const
1283 override final inout(AggregateDeclaration) isThis() inout
1285 if (!(storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.templateparameter | STC.gshared | STC.ctfe)))
1287 /* The casting is necessary because `s = s.parent` is otherwise rejected
1289 for (auto s = cast(Dsymbol)this; s; s = s.parent)
1291 auto ad = (cast(inout)s).isMember();
1294 if (!s.parent || !s.parent.isTemplateMixin())
1301 override final bool needThis()
1303 //printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class);
1307 override final bool isExport() const
1309 return visibility.kind == Visibility.Kind.export_;
1312 override final bool isImportedSymbol() const
1314 if (visibility.kind == Visibility.Kind.export_ && !_init && (storage_class & STC.static_ || parent.isModule()))
1319 final bool isCtorinit() const pure nothrow @nogc @safe
1321 return setInCtorOnly;
1324 /*******************************
1325 * Does symbol go into data segment?
1326 * Includes extern variables.
1328 override final bool isDataseg()
1332 printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars());
1333 printf("%llx, isModule: %p, isTemplateInstance: %p, isNspace: %p\n",
1334 storage_class & (STC.static_ | STC.const_), parent.isModule(), parent.isTemplateInstance(), parent.isNspace());
1335 printf("parent = '%s'\n", parent.toChars());
1338 if (isdataseg == 0) // the value is not cached
1340 isdataseg = 2; // The Variables does not go into the datasegment
1342 if (!canTakeAddressOf())
1347 Dsymbol parent = toParent();
1348 if (!parent && !(storage_class & STC.static_))
1350 error("forward referenced");
1353 else if (storage_class & (STC.static_ | STC.extern_ | STC.gshared) ||
1354 parent.isModule() || parent.isTemplateInstance() || parent.isNspace())
1356 assert(!isParameter() && !isResult());
1357 isdataseg = 1; // It is in the DataSegment
1361 return (isdataseg == 1);
1363 /************************************
1364 * Does symbol go into thread local storage?
1366 override final bool isThreadlocal()
1368 //printf("VarDeclaration::isThreadlocal(%p, '%s')\n", this, toChars());
1369 /* Data defaults to being thread-local. It is not thread-local
1370 * if it is immutable, const or shared.
1372 bool i = isDataseg() && !(storage_class & (STC.immutable_ | STC.const_ | STC.shared_ | STC.gshared));
1373 //printf("\treturn %d\n", i);
1377 /********************************************
1378 * Can variable be read and written by CTFE?
1382 return (storage_class & STC.ctfe) != 0; // || !isDataseg();
1385 final bool isOverlappedWith(VarDeclaration v)
1387 const vsz = v.type.size();
1388 const tsz = type.size();
1389 assert(vsz != SIZE_INVALID && tsz != SIZE_INVALID);
1391 // Overlap is checked by comparing bit offsets
1392 auto bitoffset = offset * 8;
1393 auto vbitoffset = v.offset * 8;
1395 // Bitsize of types are overridden by any bit-field widths.
1396 ulong tbitsize = void;
1397 if (auto bf = isBitFieldDeclaration())
1399 bitoffset += bf.bitOffset;
1400 tbitsize = bf.fieldWidth;
1405 ulong vbitsize = void;
1406 if (auto vbf = v.isBitFieldDeclaration())
1408 vbitoffset += vbf.bitOffset;
1409 vbitsize = vbf.fieldWidth;
1414 return bitoffset < vbitoffset + vbitsize &&
1415 vbitoffset < bitoffset + tbitsize;
1418 override final bool hasPointers()
1420 //printf("VarDeclaration::hasPointers() %s, ty = %d\n", toChars(), type.ty);
1421 return (!isDataseg() && type.hasPointers());
1424 /*************************************
1425 * Return true if we can take the address of this variable.
1427 final bool canTakeAddressOf()
1429 return !(storage_class & STC.manifest);
1432 /******************************************
1433 * Return true if variable needs to call the destructor.
1435 final bool needsScopeDtor()
1437 //printf("VarDeclaration::needsScopeDtor() %s\n", toChars());
1438 return edtor && !(storage_class & STC.nodtor);
1441 /******************************************
1442 * If a variable has a scope destructor call, return call for it.
1443 * Otherwise, return NULL.
1445 extern (D) final Expression callScopeDtor(Scope* sc)
1447 //printf("VarDeclaration::callScopeDtor() %s\n", toChars());
1449 // Destruction of STC.field's is handled by buildDtor()
1450 if (storage_class & (STC.nodtor | STC.ref_ | STC.out_ | STC.field))
1456 return null; // destructor is built by `void semantic(Catch c, Scope* sc)`, not here
1458 Expression e = null;
1459 // Destructors for structs and arrays of structs
1460 Type tv = type.baseElemOf();
1461 if (tv.ty == Tstruct)
1463 StructDeclaration sd = (cast(TypeStruct)tv).sym;
1464 if (!sd.dtor || sd.errors)
1467 const sz = type.size();
1468 assert(sz != SIZE_INVALID);
1472 if (type.toBasetype().ty == Tstruct)
1475 e = new VarExp(loc, this);
1477 /* This is a hack so we can call destructors on const/immutable objects.
1478 * Need to add things like "const ~this()" and "immutable ~this()" to
1481 e.type = e.type.mutableOf();
1483 // Enable calling destructors on shared objects.
1484 // The destructor is always a single, non-overloaded function,
1485 // and must serve both shared and non-shared objects.
1486 e.type = e.type.unSharedOf;
1488 e = new DotVarExp(loc, e, sd.dtor, false);
1489 e = new CallExp(loc, e);
1493 // __ArrayDtor(v[0 .. n])
1494 e = new VarExp(loc, this);
1496 const sdsz = sd.type.size();
1497 assert(sdsz != SIZE_INVALID && sdsz != 0);
1498 const n = sz / sdsz;
1499 SliceExp se = new SliceExp(loc, e, new IntegerExp(loc, 0, Type.tsize_t),
1500 new IntegerExp(loc, n, Type.tsize_t));
1502 // Prevent redundant bounds check
1503 se.upperIsInBounds = true;
1504 se.lowerIsLessThanUpper = true;
1506 // This is a hack so we can call destructors on const/immutable objects.
1507 se.type = sd.type.arrayOf();
1509 e = new CallExp(loc, new IdentifierExp(loc, Id.__ArrayDtor), se);
1513 // Destructors for classes
1514 if (storage_class & (STC.auto_ | STC.scope_) && !(storage_class & STC.parameter))
1516 for (ClassDeclaration cd = type.isClassHandle(); cd; cd = cd.baseClass)
1518 /* We can do better if there's a way with onstack
1519 * classes to determine if there's no way the monitor
1522 //if (cd.isInterfaceDeclaration())
1523 // error("interface `%s` cannot be scope", cd.toChars());
1525 if (onstack) // if any destructors
1527 // delete'ing C++ classes crashes (and delete is deprecated anyway)
1528 if (cd.classKind == ClassKind.cpp)
1530 // Don't call non-existant dtor
1534 e = new VarExp(loc, this);
1535 e.type = e.type.mutableOf().unSharedOf(); // Hack for mutable ctor on immutable instances
1536 e = new DotVarExp(loc, e, cd.dtor, false);
1537 e = new CallExp(loc, e);
1543 ec = new VarExp(loc, this);
1544 e = new DeleteExp(loc, ec, true);
1545 e.type = Type.tvoid;
1553 /*******************************************
1554 * If variable has a constant expression initializer, get it.
1555 * Otherwise, return null.
1557 extern (D) final Expression getConstInitializer(bool needFullType = true)
1559 assert(type && _init);
1561 // Ungag errors when not speculative
1562 uint oldgag = global.gag;
1565 Dsymbol sym = isMember();
1566 if (sym && !sym.isSpeculative())
1573 _init = _init.initializerSemantic(_scope, type, INITinterpret);
1578 Expression e = _init.initializerToExpression(needFullType ? type : null);
1579 global.gag = oldgag;
1583 /*******************************************
1584 * Helper function for the expansion of manifest constant.
1586 extern (D) final Expression expandInitializer(Loc loc)
1588 assert((storage_class & STC.manifest) && _init);
1590 auto e = getConstInitializer();
1593 .error(loc, "cannot make expression out of initializer for `%s`", toChars());
1594 return ErrorExp.get();
1598 e.loc = loc; // for better error message
1602 override final void checkCtorConstInit()
1606 /* doesn't work if more than one static ctor */
1607 if (ctorinit == 0 && isCtorinit() && !isField())
1608 error("missing initializer in static constructor for const variable");
1612 /************************************
1613 * Check to see if this variable is actually in an enclosing function
1614 * rather than the current one.
1615 * Update nestedrefs[], closureVars[] and outerVars[].
1616 * Returns: true if error occurs.
1618 extern (D) final bool checkNestedReference(Scope* sc, Loc loc)
1620 //printf("VarDeclaration::checkNestedReference() %s\n", toChars());
1621 if (sc.intypeof == 1 || (sc.flags & SCOPE.ctfe))
1623 if (!parent || parent == sc.parent)
1625 if (isDataseg() || (storage_class & STC.manifest))
1628 // The current function
1629 FuncDeclaration fdthis = sc.parent.isFuncDeclaration();
1631 return false; // out of function scope
1633 Dsymbol p = toParent2();
1635 // Function literals from fdthis to p must be delegates
1636 ensureStaticLinkTo(fdthis, p);
1638 // The function that this variable is in
1639 FuncDeclaration fdv = p.isFuncDeclaration();
1640 if (!fdv || fdv == fdthis)
1643 // Add fdthis to nestedrefs[] if not already there
1644 if (!nestedrefs.contains(fdthis))
1645 nestedrefs.push(fdthis);
1647 //printf("\tfdv = %s\n", fdv.toChars());
1648 //printf("\tfdthis = %s\n", fdthis.toChars());
1651 if (fdthis.getLevelAndCheck(loc, sc, fdv, this) == fdthis.LevelError)
1655 // Add this VarDeclaration to fdv.closureVars[] if not already there
1656 if (!sc.intypeof && !(sc.flags & SCOPE.compile) &&
1657 // https://issues.dlang.org/show_bug.cgi?id=17605
1658 (fdv.isCompileTimeOnly || !fdthis.isCompileTimeOnly)
1661 if (!fdv.closureVars.contains(this))
1662 fdv.closureVars.push(this);
1665 if (!fdthis.outerVars.contains(this))
1666 fdthis.outerVars.push(this);
1668 //printf("fdthis is %s\n", fdthis.toChars());
1669 //printf("var %s in function %s is nested ref\n", toChars(), fdv.toChars());
1670 // __dollar creates problems because it isn't a real variable
1671 // https://issues.dlang.org/show_bug.cgi?id=3326
1672 if (ident == Id.dollar)
1674 .error(loc, "cannnot use `$` inside a function literal");
1677 if (ident == Id.withSym) // https://issues.dlang.org/show_bug.cgi?id=1759
1679 ExpInitializer ez = _init.isExpInitializer();
1681 Expression e = ez.exp;
1682 if (e.op == EXP.construct || e.op == EXP.blit)
1683 e = (cast(AssignExp)e).e2;
1684 return lambdaCheckForNestedRef(e, sc);
1690 override final Dsymbol toAlias()
1692 //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym);
1693 if ((!type || !type.deco) && _scope)
1694 dsymbolSemantic(this, _scope);
1696 assert(this != aliassym);
1697 Dsymbol s = aliassym ? aliassym.toAlias() : this;
1701 // Eliminate need for dynamic_cast
1702 override final inout(VarDeclaration) isVarDeclaration() inout
1707 override void accept(Visitor v)
1713 /*******************************************************
1714 * C11 6.7.2.1-4 bit fields
1716 extern (C++) class BitFieldDeclaration : VarDeclaration
1723 final extern (D) this(const ref Loc loc, Type type, Identifier ident, Expression width)
1725 super(loc, type, ident, null);
1728 this.storage_class |= STC.field;
1731 override BitFieldDeclaration syntaxCopy(Dsymbol s)
1733 //printf("BitFieldDeclaration::syntaxCopy(%s)\n", toChars());
1735 auto bf = new BitFieldDeclaration(loc, type ? type.syntaxCopy() : null, ident, width.syntaxCopy());
1736 bf.comment = comment;
1740 override final inout(BitFieldDeclaration) isBitFieldDeclaration() inout
1745 override void accept(Visitor v)
1750 /***********************************
1751 * Retrieve the .min or .max values.
1752 * Only valid after semantic analysis.
1754 * id = Id.min or Id.max
1756 * the min or max value
1758 final ulong getMinMax(Identifier id)
1760 const width = fieldWidth;
1761 const uns = type.isunsigned();
1762 const min = id == Id.min;
1764 assert(width != 0); // should have been rejected in semantic pass
1765 if (width == ulong.sizeof * 8)
1766 v = uns ? (min ? ulong.min : ulong.max)
1767 : (min ? long.min : long.max);
1770 : (1L << width) - 1)
1771 : (min ? -(1L << (width - 1))
1772 : (1L << (width - 1)) - 1);
1776 override final void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion)
1781 printf("BitFieldDeclaration::setFieldOffset(ad: %s, field: %s)\n", ad.toChars(), toChars());
1782 void print(const ref FieldState fieldState)
1784 printf("FieldState.offset = %d bytes\n", fieldState.offset);
1785 printf(" .fieldOffset = %d bytes\n", fieldState.fieldOffset);
1786 printf(" .bitOffset = %d bits\n", fieldState.bitOffset);
1787 printf(" .fieldSize = %d bytes\n", fieldState.fieldSize);
1788 printf(" .inFlight = %d\n", fieldState.inFlight);
1789 printf(" fieldWidth = %d bits\n", fieldWidth);
1794 Type t = type.toBasetype();
1795 const bool anon = isAnonymous();
1797 // List in ad.fields. Even if the type is error, it's necessary to avoid
1798 // pointless error diagnostic "more initializers than fields" on struct literal.
1800 ad.fields.push(this);
1805 const sz = t.size(loc);
1806 assert(sz != SIZE_INVALID && sz < uint.max);
1807 uint memsize = cast(uint)sz; // size of member
1808 uint memalignsize = target.fieldalign(t); // size of member for alignment purposes
1809 if (log) printf(" memsize: %u memalignsize: %u\n", memsize, memalignsize);
1811 if (fieldWidth == 0 && !anon)
1812 error(loc, "named bit fields cannot have 0 width");
1813 if (fieldWidth > memsize * 8)
1814 error(loc, "bit field width %d is larger than type", fieldWidth);
1816 const style = target.c.bitFieldStyle;
1818 void startNewField()
1820 if (log) printf("startNewField()\n");
1822 if (style == TargetC.BitFieldStyle.Gcc_Clang)
1824 if (fieldWidth > 32)
1825 alignsize = memalignsize;
1826 else if (fieldWidth > 16)
1828 else if (fieldWidth > 8)
1834 alignsize = memsize; // not memalignsize
1837 offset = AggregateDeclaration.placeField(
1839 memsize, alignsize, alignment,
1841 (anon && style == TargetC.BitFieldStyle.Gcc_Clang) ? &dummy : &ad.alignsize,
1844 fieldState.inFlight = true;
1845 fieldState.fieldOffset = offset;
1846 fieldState.bitOffset = 0;
1847 fieldState.fieldSize = memsize;
1850 if (style == TargetC.BitFieldStyle.Gcc_Clang)
1852 if (fieldWidth == 0)
1856 // Use type of zero width field to align to next field
1857 fieldState.offset = (fieldState.offset + memalignsize - 1) & ~(memalignsize - 1);
1858 ad.structsize = fieldState.offset;
1861 fieldState.inFlight = false;
1865 if (ad.alignsize == 0)
1868 ad.alignsize < memalignsize)
1869 ad.alignsize = memalignsize;
1871 else if (style == TargetC.BitFieldStyle.MS)
1873 if (ad.alignsize == 0)
1875 if (fieldWidth == 0)
1877 if (fieldState.inFlight && !isunion)
1879 // documentation says align to next int
1880 //const alsz = cast(uint)Type.tint32.size();
1881 const alsz = memsize; // but it really does this
1882 fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1);
1883 ad.structsize = fieldState.offset;
1886 fieldState.inFlight = false;
1890 else if (style == TargetC.BitFieldStyle.DM)
1892 if (anon && fieldWidth && (!fieldState.inFlight || fieldState.bitOffset == 0))
1893 return; // this probably should be a bug in DMC
1894 if (ad.alignsize == 0)
1896 if (fieldWidth == 0)
1898 if (fieldState.inFlight && !isunion)
1900 const alsz = memsize;
1901 fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1);
1902 ad.structsize = fieldState.offset;
1905 fieldState.inFlight = false;
1910 if (!fieldState.inFlight)
1912 //printf("not in flight\n");
1915 else if (style == TargetC.BitFieldStyle.Gcc_Clang)
1917 // If the bit-field spans more units of alignment than its type,
1918 // start a new field at the next alignment boundary.
1919 if (fieldState.bitOffset == fieldState.fieldSize * 8)
1920 startNewField(); // the bit field is full
1923 // if alignment boundary is crossed
1924 uint start = fieldState.fieldOffset * 8 + fieldState.bitOffset;
1925 uint end = start + fieldWidth;
1926 //printf("%s start: %d end: %d memalignsize: %d\n", ad.toChars(), start, end, memalignsize);
1927 if (start / (memalignsize * 8) != (end - 1) / (memalignsize * 8))
1929 //printf("alignment is crossed\n");
1934 else if (style == TargetC.BitFieldStyle.DM ||
1935 style == TargetC.BitFieldStyle.MS)
1937 if (memsize != fieldState.fieldSize ||
1938 fieldState.bitOffset + fieldWidth > fieldState.fieldSize * 8)
1940 //printf("new field\n");
1947 offset = fieldState.fieldOffset;
1948 bitOffset = fieldState.bitOffset;
1950 const pastField = bitOffset + fieldWidth;
1951 if (style == TargetC.BitFieldStyle.Gcc_Clang)
1953 auto size = (pastField + 7) / 8;
1954 fieldState.fieldSize = size;
1955 //printf(" offset: %d, size: %d\n", offset, size);
1956 ad.structsize = offset + size;
1959 fieldState.fieldSize = memsize;
1960 //printf("at end: ad.structsize = %d\n", cast(int)ad.structsize);
1961 //print(fieldState);
1965 fieldState.offset = offset + fieldState.fieldSize;
1966 fieldState.bitOffset = pastField;
1969 //printf("\t%s: memalignsize = %d\n", toChars(), memalignsize);
1970 //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize);
1974 /***********************************************************
1975 * This is a shell around a back end symbol
1977 extern (C++) final class SymbolDeclaration : Declaration
1979 AggregateDeclaration dsym;
1981 extern (D) this(const ref Loc loc, AggregateDeclaration dsym)
1983 super(loc, dsym.ident);
1985 storage_class |= STC.const_;
1988 // Eliminate need for dynamic_cast
1989 override inout(SymbolDeclaration) isSymbolDeclaration() inout
1994 override void accept(Visitor v)
2000 /***********************************************************
2002 extern (C++) class TypeInfoDeclaration : VarDeclaration
2006 final extern (D) this(Type tinfo)
2008 super(Loc.initial, Type.dtypeinfo.type, tinfo.getTypeInfoIdent(), null);
2010 storage_class = STC.static_ | STC.gshared;
2011 visibility = Visibility(Visibility.Kind.public_);
2013 alignment.set(target.ptrsize);
2016 static TypeInfoDeclaration create(Type tinfo)
2018 return new TypeInfoDeclaration(tinfo);
2021 override final TypeInfoDeclaration syntaxCopy(Dsymbol s)
2023 assert(0); // should never be produced by syntax
2026 override final const(char)* toChars() const
2028 //printf("TypeInfoDeclaration::toChars() tinfo = %s\n", tinfo.toChars());
2030 buf.writestring("typeid(");
2031 buf.writestring(tinfo.toChars());
2033 return buf.extractChars();
2036 override final inout(TypeInfoDeclaration) isTypeInfoDeclaration() inout @nogc nothrow pure @safe
2041 override void accept(Visitor v)
2047 /***********************************************************
2049 extern (C++) final class TypeInfoStructDeclaration : TypeInfoDeclaration
2051 extern (D) this(Type tinfo)
2054 if (!Type.typeinfostruct)
2056 ObjectNotFound(Id.TypeInfo_Struct);
2058 type = Type.typeinfostruct.type;
2061 static TypeInfoStructDeclaration create(Type tinfo)
2063 return new TypeInfoStructDeclaration(tinfo);
2066 override void accept(Visitor v)
2072 /***********************************************************
2074 extern (C++) final class TypeInfoClassDeclaration : TypeInfoDeclaration
2076 extern (D) this(Type tinfo)
2079 if (!Type.typeinfoclass)
2081 ObjectNotFound(Id.TypeInfo_Class);
2083 type = Type.typeinfoclass.type;
2086 static TypeInfoClassDeclaration create(Type tinfo)
2088 return new TypeInfoClassDeclaration(tinfo);
2091 override void accept(Visitor v)
2097 /***********************************************************
2099 extern (C++) final class TypeInfoInterfaceDeclaration : TypeInfoDeclaration
2101 extern (D) this(Type tinfo)
2104 if (!Type.typeinfointerface)
2106 ObjectNotFound(Id.TypeInfo_Interface);
2108 type = Type.typeinfointerface.type;
2111 static TypeInfoInterfaceDeclaration create(Type tinfo)
2113 return new TypeInfoInterfaceDeclaration(tinfo);
2116 override void accept(Visitor v)
2122 /***********************************************************
2124 extern (C++) final class TypeInfoPointerDeclaration : TypeInfoDeclaration
2126 extern (D) this(Type tinfo)
2129 if (!Type.typeinfopointer)
2131 ObjectNotFound(Id.TypeInfo_Pointer);
2133 type = Type.typeinfopointer.type;
2136 static TypeInfoPointerDeclaration create(Type tinfo)
2138 return new TypeInfoPointerDeclaration(tinfo);
2141 override void accept(Visitor v)
2147 /***********************************************************
2149 extern (C++) final class TypeInfoArrayDeclaration : TypeInfoDeclaration
2151 extern (D) this(Type tinfo)
2154 if (!Type.typeinfoarray)
2156 ObjectNotFound(Id.TypeInfo_Array);
2158 type = Type.typeinfoarray.type;
2161 static TypeInfoArrayDeclaration create(Type tinfo)
2163 return new TypeInfoArrayDeclaration(tinfo);
2166 override void accept(Visitor v)
2172 /***********************************************************
2174 extern (C++) final class TypeInfoStaticArrayDeclaration : TypeInfoDeclaration
2176 extern (D) this(Type tinfo)
2179 if (!Type.typeinfostaticarray)
2181 ObjectNotFound(Id.TypeInfo_StaticArray);
2183 type = Type.typeinfostaticarray.type;
2186 static TypeInfoStaticArrayDeclaration create(Type tinfo)
2188 return new TypeInfoStaticArrayDeclaration(tinfo);
2191 override void accept(Visitor v)
2197 /***********************************************************
2199 extern (C++) final class TypeInfoAssociativeArrayDeclaration : TypeInfoDeclaration
2201 extern (D) this(Type tinfo)
2204 if (!Type.typeinfoassociativearray)
2206 ObjectNotFound(Id.TypeInfo_AssociativeArray);
2208 type = Type.typeinfoassociativearray.type;
2211 static TypeInfoAssociativeArrayDeclaration create(Type tinfo)
2213 return new TypeInfoAssociativeArrayDeclaration(tinfo);
2216 override void accept(Visitor v)
2222 /***********************************************************
2224 extern (C++) final class TypeInfoEnumDeclaration : TypeInfoDeclaration
2226 extern (D) this(Type tinfo)
2229 if (!Type.typeinfoenum)
2231 ObjectNotFound(Id.TypeInfo_Enum);
2233 type = Type.typeinfoenum.type;
2236 static TypeInfoEnumDeclaration create(Type tinfo)
2238 return new TypeInfoEnumDeclaration(tinfo);
2241 override void accept(Visitor v)
2247 /***********************************************************
2249 extern (C++) final class TypeInfoFunctionDeclaration : TypeInfoDeclaration
2251 extern (D) this(Type tinfo)
2254 if (!Type.typeinfofunction)
2256 ObjectNotFound(Id.TypeInfo_Function);
2258 type = Type.typeinfofunction.type;
2261 static TypeInfoFunctionDeclaration create(Type tinfo)
2263 return new TypeInfoFunctionDeclaration(tinfo);
2266 override void accept(Visitor v)
2272 /***********************************************************
2274 extern (C++) final class TypeInfoDelegateDeclaration : TypeInfoDeclaration
2276 extern (D) this(Type tinfo)
2279 if (!Type.typeinfodelegate)
2281 ObjectNotFound(Id.TypeInfo_Delegate);
2283 type = Type.typeinfodelegate.type;
2286 static TypeInfoDelegateDeclaration create(Type tinfo)
2288 return new TypeInfoDelegateDeclaration(tinfo);
2291 override void accept(Visitor v)
2297 /***********************************************************
2299 extern (C++) final class TypeInfoTupleDeclaration : TypeInfoDeclaration
2301 extern (D) this(Type tinfo)
2304 if (!Type.typeinfotypelist)
2306 ObjectNotFound(Id.TypeInfo_Tuple);
2308 type = Type.typeinfotypelist.type;
2311 static TypeInfoTupleDeclaration create(Type tinfo)
2313 return new TypeInfoTupleDeclaration(tinfo);
2316 override void accept(Visitor v)
2322 /***********************************************************
2324 extern (C++) final class TypeInfoConstDeclaration : TypeInfoDeclaration
2326 extern (D) this(Type tinfo)
2329 if (!Type.typeinfoconst)
2331 ObjectNotFound(Id.TypeInfo_Const);
2333 type = Type.typeinfoconst.type;
2336 static TypeInfoConstDeclaration create(Type tinfo)
2338 return new TypeInfoConstDeclaration(tinfo);
2341 override void accept(Visitor v)
2347 /***********************************************************
2349 extern (C++) final class TypeInfoInvariantDeclaration : TypeInfoDeclaration
2351 extern (D) this(Type tinfo)
2354 if (!Type.typeinfoinvariant)
2356 ObjectNotFound(Id.TypeInfo_Invariant);
2358 type = Type.typeinfoinvariant.type;
2361 static TypeInfoInvariantDeclaration create(Type tinfo)
2363 return new TypeInfoInvariantDeclaration(tinfo);
2366 override void accept(Visitor v)
2372 /***********************************************************
2374 extern (C++) final class TypeInfoSharedDeclaration : TypeInfoDeclaration
2376 extern (D) this(Type tinfo)
2379 if (!Type.typeinfoshared)
2381 ObjectNotFound(Id.TypeInfo_Shared);
2383 type = Type.typeinfoshared.type;
2386 static TypeInfoSharedDeclaration create(Type tinfo)
2388 return new TypeInfoSharedDeclaration(tinfo);
2391 override void accept(Visitor v)
2397 /***********************************************************
2399 extern (C++) final class TypeInfoWildDeclaration : TypeInfoDeclaration
2401 extern (D) this(Type tinfo)
2404 if (!Type.typeinfowild)
2406 ObjectNotFound(Id.TypeInfo_Wild);
2408 type = Type.typeinfowild.type;
2411 static TypeInfoWildDeclaration create(Type tinfo)
2413 return new TypeInfoWildDeclaration(tinfo);
2416 override void accept(Visitor v)
2422 /***********************************************************
2424 extern (C++) final class TypeInfoVectorDeclaration : TypeInfoDeclaration
2426 extern (D) this(Type tinfo)
2429 if (!Type.typeinfovector)
2431 ObjectNotFound(Id.TypeInfo_Vector);
2433 type = Type.typeinfovector.type;
2436 static TypeInfoVectorDeclaration create(Type tinfo)
2438 return new TypeInfoVectorDeclaration(tinfo);
2441 override void accept(Visitor v)
2447 /***********************************************************
2448 * For the "this" parameter to member functions
2450 extern (C++) final class ThisDeclaration : VarDeclaration
2452 extern (D) this(const ref Loc loc, Type t)
2454 super(loc, t, Id.This, null);
2455 storage_class |= STC.nodtor;
2458 override ThisDeclaration syntaxCopy(Dsymbol s)
2460 assert(0); // should never be produced by syntax
2463 override inout(ThisDeclaration) isThisDeclaration() inout
2468 override void accept(Visitor v)