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-2023 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;
40 import dmd.common.outbuffer;
41 import dmd.root.rootobject;
47 /************************************
48 * Check to see the aggregate type is nested and its context pointer is
49 * accessible from the current scope.
50 * Returns true if error occurs.
52 bool checkFrameAccess(Loc loc, Scope* sc, AggregateDeclaration ad, size_t iStart = 0)
54 Dsymbol sparent = ad.toParentLocal();
55 Dsymbol sparent2 = ad.toParent2();
57 if (ad.isNested() && s)
59 //printf("ad = %p %s [%s], parent:%p\n", ad, ad.toChars(), ad.loc.toChars(), ad.parent);
60 //printf("sparent = %p %s [%s], parent: %s\n", sparent, sparent.toChars(), sparent.loc.toChars(), sparent.parent,toChars());
61 //printf("sparent2 = %p %s [%s], parent: %s\n", sparent2, sparent2.toChars(), sparent2.loc.toChars(), sparent2.parent,toChars());
62 if (!ensureStaticLinkTo(s, sparent) || sparent != sparent2 && !ensureStaticLinkTo(s, sparent2))
64 error(loc, "cannot access frame pointer of `%s`", ad.toPrettyChars());
70 for (size_t i = iStart; i < ad.fields.length; i++)
72 VarDeclaration vd = ad.fields[i];
73 Type tb = vd.type.baseElemOf();
76 result |= checkFrameAccess(loc, sc, (cast(TypeStruct)tb).sym);
82 /***********************************************
83 * Mark variable v as modified if it is inside a constructor that var
85 * Also used to allow immutable globals to be initialized inside a static constructor.
87 * true if it's an initialization of v
89 bool modifyFieldVar(Loc loc, Scope* sc, VarDeclaration var, Expression e1)
91 //printf("modifyFieldVar(var = %s)\n", var.toChars());
95 FuncDeclaration fd = null;
97 fd = s.isFuncDeclaration();
99 ((fd.isCtorDeclaration() && var.isField()) ||
100 ((fd.isStaticCtorDeclaration() || fd.isCrtCtor) && !var.isField())) &&
101 fd.toParentDecl() == var.toParent2() &&
102 (!e1 || e1.op == EXP.this_))
107 //printf("setting ctorinit\n");
109 if (var.isField() && sc.ctorflow.fieldinit.length && !sc.intypeof)
112 auto mustInit = ((var.storage_class & STC.nodefaultctor) != 0 ||
113 var.type.needsNested());
115 const dim = sc.ctorflow.fieldinit.length;
116 auto ad = fd.isMemberDecl();
119 for (i = 0; i < dim; i++) // same as findFieldIndexByName in ctfeexp.c ?
121 if (ad.fields[i] == var)
125 auto fieldInit = &sc.ctorflow.fieldinit[i];
126 const fi = fieldInit.csx;
128 if (fi & CSX.this_ctor)
130 if (var.type.isMutable() && e1.type.isMutable())
134 const(char)* modStr = !var.type.isMutable() ? MODtoChars(var.type.mod) : MODtoChars(e1.type.mod);
135 .error(loc, "%s field `%s` initialized multiple times", modStr, var.toChars());
136 .errorSupplemental(fieldInit.loc, "Previous initialization is here.");
139 else if (sc.inLoop || (fi & CSX.label))
141 if (!mustInit && var.type.isMutable() && e1.type.isMutable())
145 const(char)* modStr = !var.type.isMutable() ? MODtoChars(var.type.mod) : MODtoChars(e1.type.mod);
146 .error(loc, "%s field `%s` initialization is not allowed in loops or after labels", modStr, var.toChars());
150 fieldInit.csx |= CSX.this_ctor;
151 fieldInit.loc = e1.loc;
152 if (var.overlapped) // https://issues.dlang.org/show_bug.cgi?id=15258
154 foreach (j, v; ad.fields)
156 if (v is var || !var.isOverlappedWith(v))
159 sc.ctorflow.fieldinit[j].csx = CSX.this_ctor;
163 else if (fd != sc.func)
165 if (var.type.isMutable())
167 else if (sc.func.fes)
169 const(char)* p = var.isField() ? "field" : var.kind();
170 .error(loc, "%s %s `%s` initialization is not allowed in foreach loop",
171 MODtoChars(var.type.mod), p, var.toChars());
175 const(char)* p = var.isField() ? "field" : var.kind();
176 .error(loc, "%s %s `%s` initialization is not allowed in nested function `%s`",
177 MODtoChars(var.type.mod), p, var.toChars(), sc.func.toChars());
180 else if (fd.isStaticCtorDeclaration() && !fd.isSharedStaticCtorDeclaration() &&
181 var.type.isImmutable())
183 .error(loc, "%s %s `%s` initialization is not allowed in `static this`",
184 MODtoChars(var.type.mod), var.kind(), var.toChars());
185 errorSupplemental(loc, "Use `shared static this` instead.");
193 s = s.toParentP(var.toParent2());
202 /******************************************
204 extern (C++) void ObjectNotFound(Identifier id)
206 error(Loc.initial, "`%s` not found. object.d may be incorrectly installed or corrupt.", id.toChars());
210 /* Accumulator for successive matches.
212 struct MatchAccumulator
214 int count; // number of matches found so far
215 MATCH last = MATCH.nomatch; // match level of lastf
216 FuncDeclaration lastf; // last matching function we found
217 FuncDeclaration nextf; // if ambiguous match, this is the "other" function
220 /***********************************************************
222 extern (C++) abstract class Declaration : Dsymbol
225 Type originalType; // before semantic analysis
226 StorageClass storage_class = STC.undefined_;
227 Visibility visibility;
228 LINK _linkage = LINK.default_; // may be `LINK.system`; use `resolvedLinkage()` to resolve it
229 short inuse; // used to detect cycles
231 ubyte adFlags; // control re-assignment of AliasDeclaration (put here for packing reasons)
232 enum wasRead = 1; // set if AliasDeclaration was read
233 enum ignoreRead = 2; // ignore any reads of AliasDeclaration
234 enum nounderscore = 4; // don't prepend _ to mangled name
236 Symbol* isym; // import version of csym
238 // overridden symbol with pragma(mangle, "...")
239 const(char)[] mangleOverride;
241 final extern (D) this(Identifier ident)
244 visibility = Visibility(Visibility.Kind.undefined);
247 final extern (D) this(const ref Loc loc, Identifier ident)
250 visibility = Visibility(Visibility.Kind.undefined);
253 override const(char)* kind() const
255 return "declaration";
258 override final uinteger_t size(const ref Loc loc)
261 const sz = type.size();
262 if (sz == SIZE_INVALID)
268 * Issue an error if an attempt to call a disabled method is made
270 * If the declaration is disabled but inside a disabled function,
271 * returns `true` but do not issue an error message.
274 * loc = Location information of the call
275 * sc = Scope in which the call occurs
276 * isAliasedDeclaration = if `true` searches overload set
279 * `true` if this `Declaration` is `@disable`d, `false` otherwise.
281 extern (D) final bool checkDisabled(Loc loc, Scope* sc, bool isAliasedDeclaration = false)
283 if (!(storage_class & STC.disable))
286 if (sc.func && sc.func.storage_class & STC.disable)
289 if (auto p = toParent())
291 if (auto postblit = isPostBlitDeclaration())
293 /* https://issues.dlang.org/show_bug.cgi?id=21885
295 * If the generated postblit is disabled, it
296 * means that one of the fields has a disabled
297 * postblit. Print the first field that has
298 * a disabled postblit.
300 if (postblit.isGenerated())
302 auto sd = p.isStructDeclaration();
304 for (size_t i = 0; i < sd.fields.length; i++)
306 auto structField = sd.fields[i];
307 if (structField.overlapped)
309 Type tv = structField.type.baseElemOf();
310 if (tv.ty != Tstruct)
312 auto sdv = (cast(TypeStruct)tv).sym;
315 if (sdv.postblit.isDisabled())
317 p.error(loc, "is not copyable because field `%s` is not copyable", structField.toChars());
322 p.error(loc, "is not copyable because it has a disabled postblit");
327 // if the function is @disabled, maybe there
328 // is an overload in the overload set that isn't
329 if (isAliasedDeclaration)
331 FuncDeclaration fd = isFuncDeclaration();
334 for (FuncDeclaration ovl = fd; ovl; ovl = cast(FuncDeclaration)ovl.overnext)
335 if (!(ovl.storage_class & STC.disable))
340 if (auto ctor = isCtorDeclaration())
342 if (ctor.isCpCtor && ctor.isGenerated())
344 .error(loc, "generating an `inout` copy constructor for `struct %s` failed, therefore instances of it are uncopyable", parent.toPrettyChars());
348 error(loc, "cannot be used because it is annotated with `@disable`");
352 /*************************************
353 * Check to see if declaration can be modified in this context (sc).
354 * Issue error if not.
356 * loc = location for error messages
357 * e1 = `null` or `this` expression when this declaration is a field
359 * flag = if the first bit is set it means do not issue error message for
360 * invalid modification; if the second bit is set, it means that
361 this declaration is a field and a subfield of it is modified.
363 * Modifiable.yes or Modifiable.initialization
365 extern (D) final Modifiable checkModify(Loc loc, Scope* sc, Expression e1, ModifyFlags flag)
367 VarDeclaration v = isVarDeclaration();
368 if (v && v.canassign)
369 return Modifiable.initialization;
371 if (isParameter() || isResult())
373 for (Scope* scx = sc; scx; scx = scx.enclosing)
375 if (scx.func == parent && (scx.flags & SCOPE.contract))
377 const(char)* s = isParameter() && parent.ident != Id.ensure ? "parameter" : "result";
378 if (!(flag & ModifyFlags.noError))
379 error(loc, "cannot modify %s `%s` in contract", s, toChars());
380 return Modifiable.initialization; // do not report type related errors
385 if (e1 && e1.op == EXP.this_ && isField())
387 VarDeclaration vthis = e1.isThisExp().var;
388 for (Scope* scx = sc; scx; scx = scx.enclosing)
390 if (scx.func == vthis.parent && (scx.flags & SCOPE.contract))
392 if (!(flag & ModifyFlags.noError))
393 error(loc, "cannot modify parameter `this` in contract");
394 return Modifiable.initialization; // do not report type related errors
399 if (v && (v.isCtorinit() || isField()))
401 // It's only modifiable if inside the right constructor
402 if ((storage_class & (STC.foreach_ | STC.ref_)) == (STC.foreach_ | STC.ref_))
403 return Modifiable.initialization;
404 if (flag & ModifyFlags.fieldAssign)
405 return Modifiable.yes;
406 return modifyFieldVar(loc, sc, v, e1) ? Modifiable.initialization : Modifiable.yes;
408 return Modifiable.yes;
411 override final Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
413 Dsymbol s = Dsymbol.search(loc, ident, flags);
416 s = type.toDsymbol(_scope);
418 s = s.search(loc, ident, flags);
423 final bool isStatic() const pure nothrow @nogc @safe
425 return (storage_class & STC.static_) != 0;
428 /// Returns the linkage, resolving the target-specific `System` one.
429 final LINK resolvedLinkage() const
431 return _linkage == LINK.system ? target.systemLinkage() : _linkage;
449 bool isCodeseg() const pure nothrow @nogc @safe
454 final bool isFinal() const pure nothrow @nogc @safe
456 return (storage_class & STC.final_) != 0;
461 return (storage_class & STC.abstract_) != 0;
464 final bool isConst() const pure nothrow @nogc @safe
466 return (storage_class & STC.const_) != 0;
469 final bool isImmutable() const pure nothrow @nogc @safe
471 return (storage_class & STC.immutable_) != 0;
474 final bool isWild() const pure nothrow @nogc @safe
476 return (storage_class & STC.wild) != 0;
479 final bool isAuto() const pure nothrow @nogc @safe
481 return (storage_class & STC.auto_) != 0;
484 final bool isScope() const pure nothrow @nogc @safe
486 return (storage_class & STC.scope_) != 0;
489 final bool isReturn() const pure nothrow @nogc @safe
491 return (storage_class & STC.return_) != 0;
494 final bool isSynchronized() const pure nothrow @nogc @safe
496 return (storage_class & STC.synchronized_) != 0;
499 final bool isParameter() const pure nothrow @nogc @safe
501 return (storage_class & STC.parameter) != 0;
504 override final bool isDeprecated() const pure nothrow @nogc @safe
506 return (storage_class & STC.deprecated_) != 0;
509 final bool isDisabled() const pure nothrow @nogc @safe
511 return (storage_class & STC.disable) != 0;
514 final bool isOverride() const pure nothrow @nogc @safe
516 return (storage_class & STC.override_) != 0;
519 final bool isResult() const pure nothrow @nogc @safe
521 return (storage_class & STC.result) != 0;
524 final bool isField() const pure nothrow @nogc @safe
526 return (storage_class & STC.field) != 0;
529 final bool isIn() const pure nothrow @nogc @safe
531 return (storage_class & STC.in_) != 0;
534 final bool isOut() const pure nothrow @nogc @safe
536 return (storage_class & STC.out_) != 0;
539 final bool isRef() const pure nothrow @nogc @safe
541 return (storage_class & STC.ref_) != 0;
544 /// Returns: Whether the variable is a reference, annotated with `out` or `ref`
545 final bool isReference() const pure nothrow @nogc @safe
547 return (storage_class & (STC.ref_ | STC.out_)) != 0;
550 final bool isFuture() const pure nothrow @nogc @safe
552 return (storage_class & STC.future) != 0;
555 final extern(D) bool isSystem() const pure nothrow @nogc @safe
557 return (storage_class & STC.system) != 0;
560 override final Visibility visible() pure nothrow @nogc @safe
565 override final inout(Declaration) isDeclaration() inout pure nothrow @nogc @safe
570 override void accept(Visitor v)
576 /***********************************************************
578 extern (C++) final class TupleDeclaration : Declaration
581 TypeTuple tupletype; // !=null if this is a type tuple
582 bool isexp; // true: expression tuple
583 bool building; // it's growing in AliasAssign semantic
585 extern (D) this(const ref Loc loc, Identifier ident, Objects* objects)
588 this.objects = objects;
591 override TupleDeclaration syntaxCopy(Dsymbol s)
596 override const(char)* kind() const
601 override Type getType()
603 /* If this tuple represents a type, return that type
606 //printf("TupleDeclaration::getType() %s\n", toChars());
607 if (isexp || building)
611 /* It's only a type tuple if all the Object's are types
613 for (size_t i = 0; i < objects.length; i++)
615 RootObject o = (*objects)[i];
616 if (o.dyncast() != DYNCAST.type)
618 //printf("\tnot[%d], %p, %d\n", i, o, o.dyncast());
623 /* We know it's a type tuple, so build the TypeTuple
625 Types* types = cast(Types*)objects;
626 auto args = new Parameters(objects.length);
629 for (size_t i = 0; i < types.length; i++)
631 Type t = (*types)[i];
632 //printf("type = %s\n", t.toChars());
635 buf.printf("_%s_%d", ident.toChars(), i);
636 const len = buf.offset;
637 const name = buf.extractSlice().ptr;
638 auto id = Identifier.idPool(name, len);
639 auto arg = new Parameter(STC.in_, t, id, null);
643 auto arg = new Parameter(0, t, null, null, null);
650 tupletype = new TypeTuple(args);
652 return tupletype.typeSemantic(Loc.initial, null);
657 override Dsymbol toAlias2()
659 //printf("TupleDeclaration::toAlias2() '%s' objects = %s\n", toChars(), objects.toChars());
660 for (size_t i = 0; i < objects.length; i++)
662 RootObject o = (*objects)[i];
663 if (Dsymbol s = isDsymbol(o))
672 override bool needThis()
674 //printf("TupleDeclaration::needThis(%s)\n", toChars());
675 return isexp ? foreachVar((s) { return s.needThis(); }) != 0 : false;
678 /***********************************************************
679 * Calls dg(Dsymbol) for each Dsymbol, which should be a VarDeclaration
680 * inside VarExp (isexp == true).
682 * dg = delegate to call for each Dsymbol
684 extern (D) void foreachVar(scope void delegate(Dsymbol) dg)
687 foreach (o; *objects)
689 if (auto e = o.isExpression())
690 if (auto ve = e.isVarExp())
695 /***********************************************************
696 * Calls dg(Dsymbol) for each Dsymbol, which should be a VarDeclaration
697 * inside VarExp (isexp == true).
698 * If dg returns !=0, stops and returns that value else returns 0.
700 * dg = delegate to call for each Dsymbol
702 * last value returned by dg()
704 extern (D) int foreachVar(scope int delegate(Dsymbol) dg)
707 foreach (o; *objects)
709 if (auto e = o.isExpression())
710 if (auto ve = e.isVarExp())
711 if(auto ret = dg(ve.var))
717 override inout(TupleDeclaration) isTupleDeclaration() inout
722 override void accept(Visitor v)
728 /***********************************************************
729 * https://dlang.org/spec/declaration.html#AliasDeclaration
731 extern (C++) final class AliasDeclaration : Declaration
733 Dsymbol aliassym; // alias ident = aliassym;
735 Dsymbol overnext; // next in overload list
736 Dsymbol _import; // !=null if unresolved internal alias for selective import
738 extern (D) this(const ref Loc loc, Identifier ident, Type type)
741 //printf("AliasDeclaration(id = '%s', type = %p)\n", ident.toChars(), type);
742 //printf("type = '%s'\n", type.toChars());
747 extern (D) this(const ref Loc loc, Identifier ident, Dsymbol s)
750 //printf("AliasDeclaration(id = '%s', s = %p)\n", ident.toChars(), s);
756 static AliasDeclaration create(const ref Loc loc, Identifier id, Type type)
758 return new AliasDeclaration(loc, id, type);
761 override AliasDeclaration syntaxCopy(Dsymbol s)
763 //printf("AliasDeclaration::syntaxCopy()\n");
765 AliasDeclaration sa = type ? new AliasDeclaration(loc, ident, type.syntaxCopy()) : new AliasDeclaration(loc, ident, aliassym.syntaxCopy(null));
766 sa.comment = comment;
767 sa.storage_class = storage_class;
771 override bool overloadInsert(Dsymbol s)
773 //printf("[%s] AliasDeclaration::overloadInsert('%s') s = %s %s @ [%s]\n",
774 // loc.toChars(), toChars(), s.kind(), s.toChars(), s.loc.toChars());
776 /** Aliases aren't overloadable themselves, but if their Aliasee is
777 * overloadable they are converted to an overloadable Alias (either
778 * FuncAliasDeclaration or OverDeclaration).
780 * This is done by moving the Aliasee into such an overloadable alias
781 * which is then used to replace the existing Aliasee. The original
782 * Alias (_this_) remains a useless shell.
784 * This is a horrible mess. It was probably done to avoid replacing
785 * existing AST nodes and references, but it needs a major
786 * simplification b/c it's too complex to maintain.
788 * A simpler approach might be to merge any colliding symbols into a
789 * simple Overload class (an array) and then later have that resolve
792 if (semanticRun >= PASS.semanticdone)
794 /* Semantic analysis is already finished, and the aliased entity
795 * is not overloadable.
800 If type has been resolved already we could
801 still be inserting an alias from an import.
803 If we are handling an alias then pretend
804 it was inserting and return true, if not then
805 false since we didn't even pretend to insert something.
807 return this._import && this.equals(s);
810 /* When s is added in member scope by static if, mixin("code") or others,
811 * aliassym is determined already. See the case in: test/compilable/test61.d
813 auto sa = aliassym.toAlias();
815 if (auto td = s.toAlias().isTemplateDeclaration())
816 s = td.funcroot ? td.funcroot : td;
818 if (auto fd = sa.isFuncDeclaration())
820 auto fa = new FuncAliasDeclaration(ident, fd);
821 fa.visibility = visibility;
824 return aliassym.overloadInsert(s);
826 if (auto td = sa.isTemplateDeclaration())
828 auto od = new OverDeclaration(ident, td.funcroot ? td.funcroot : td);
829 od.visibility = visibility;
832 return aliassym.overloadInsert(s);
834 if (auto od = sa.isOverDeclaration())
836 if (sa.ident != ident || sa.parent != parent)
838 od = new OverDeclaration(ident, od);
839 od.visibility = visibility;
843 return od.overloadInsert(s);
845 if (auto os = sa.isOverloadSet())
847 if (sa.ident != ident || sa.parent != parent)
849 os = new OverloadSet(ident, os);
850 // TODO: visibility is lost here b/c OverloadSets have no visibility attribute
851 // Might no be a practical issue, b/c the code below fails to resolve the overload anyhow.
855 // private alias merged = foo; // private alias to overload set of a.foo and b.foo
859 // public alias merged = bar; // public alias to overload set of a.bar and b.bar
863 // void test() { merged(123); } // should only look at os2.merged
865 // os.visibility = visibility;
875 /* Don't know yet what the aliased symbol is, so assume it can
876 * be overloaded and check later for correctness.
879 return overnext.overloadInsert(s);
886 override const(char)* kind() const
891 override Type getType()
895 return toAlias().getType();
898 override Dsymbol toAlias()
900 //printf("[%s] AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s', inuse = %d)\n",
901 // loc.toChars(), toChars(), this, aliassym, aliassym ? aliassym.kind() : "", inuse);
902 assert(this != aliassym);
903 //static int count; if (++count == 10) *(char*)0=0;
905 // Reading the AliasDeclaration
906 if (!(adFlags & ignoreRead))
907 adFlags |= wasRead; // can never assign to this AliasDeclaration again
909 if (inuse == 1 && type && _scope)
912 uint olderrors = global.errors;
913 Dsymbol s = type.toDsymbol(_scope);
914 //printf("[%s] type = %s, s = %p, this = %p\n", loc.toChars(), type.toChars(), s, this);
915 if (global.errors != olderrors)
920 if (global.errors != olderrors)
927 Type t = type.typeSemantic(loc, _scope);
930 if (global.errors != olderrors)
932 //printf("t = %s\n", t.toChars());
938 error("recursive alias declaration");
941 // Avoid breaking "recursive alias" state during errors gagged
944 aliassym = new AliasDeclaration(loc, ident, Type.terror);
949 if (semanticRun >= PASS.semanticdone)
951 // semantic is already done.
953 // Do not see aliassym !is null, because of lambda aliases.
955 // Do not see type.deco !is null, even so "alias T = const int;` needs
956 // semantic analysis to take the storage class `const` as type qualifier.
960 // stop AliasAssign tuple building
963 if (auto td = aliassym.isTupleDeclaration())
968 semanticRun = PASS.semanticdone;
973 if (_import && _import._scope)
975 /* If this is an internal alias for selective/renamed import,
976 * load the module first.
978 _import.dsymbolSemantic(null);
982 aliasSemantic(this, _scope);
987 Dsymbol s = aliassym ? aliassym.toAlias() : this;
992 override Dsymbol toAlias2()
996 error("recursive alias declaration");
1000 Dsymbol s = aliassym ? aliassym.toAlias2() : this;
1005 override bool isOverloadable() const
1007 // assume overloadable until alias is resolved
1008 return semanticRun < PASS.semanticdone ||
1009 aliassym && aliassym.isOverloadable();
1012 override inout(AliasDeclaration) isAliasDeclaration() inout
1017 /** Returns: `true` if this instance was created to make a template parameter
1018 visible in the scope of a template body, `false` otherwise */
1019 extern (D) bool isAliasedTemplateParameter() const
1021 return !!(storage_class & STC.templateparameter);
1024 override void accept(Visitor v)
1030 /***********************************************************
1032 extern (C++) final class OverDeclaration : Declaration
1034 Dsymbol overnext; // next in overload list
1037 extern (D) this(Identifier ident, Dsymbol s)
1043 override const(char)* kind() const
1045 return "overload alias"; // todo
1048 override bool equals(const RootObject o) const
1053 auto s = isDsymbol(o);
1057 if (auto od2 = s.isOverDeclaration())
1058 return this.aliassym.equals(od2.aliassym);
1059 return this.aliassym == s;
1062 override bool overloadInsert(Dsymbol s)
1064 //printf("OverDeclaration::overloadInsert('%s') aliassym = %p, overnext = %p\n", s.toChars(), aliassym, overnext);
1066 return overnext.overloadInsert(s);
1073 override bool isOverloadable() const
1080 Dsymbol result = null;
1081 overloadApply(aliassym, (Dsymbol s)
1086 return 1; // ambiguous, done
1097 override inout(OverDeclaration) isOverDeclaration() inout
1102 override void accept(Visitor v)
1108 /***********************************************************
1110 extern (C++) class VarDeclaration : Declaration
1113 FuncDeclarations nestedrefs; // referenced by these lexically nested functions
1114 TupleDeclaration aliasTuple; // when `this` is really a tuple of declarations
1115 VarDeclaration lastVar; // Linked list of variables for goto-skips-init detection
1116 Expression edtor; // if !=null, does the destruction of the variable
1117 IntRange* range; // if !=null, the variable is known to be within the range
1118 VarDeclarations* maybes; // maybeScope variables that are assigned to this maybeScope variable
1120 uint endlinnum; // line number of end of scope that this var lives in
1122 uint sequenceNumber; // order the variables are declared
1123 structalign_t alignment;
1125 // When interpreting, these point to the value (NULL if value not determinable)
1126 // The index of this variable on the CTFE stack, AdrOnStackNone if not allocated
1127 enum AdrOnStackNone = ~0u;
1128 uint ctfeAdrOnStack;
1130 // `bool` fields that are compacted into bit fields in a string mixin
1131 private extern (D) static struct BitFields
1133 bool isargptr; /// if parameter that _argptr points to
1134 bool ctorinit; /// it has been initialized in a ctor
1135 bool iscatchvar; /// this is the exception object variable in catch() clause
1136 bool isowner; /// this is an Owner, despite it being `scope`
1137 bool setInCtorOnly; /// field can only be set in a constructor, as it is const or immutable
1139 /// It is a class that was allocated on the stack
1141 /// This means the var is not rebindable once assigned,
1142 /// and the destructor gets run when it goes out of scope
1145 bool overlapped; /// if it is a field and has overlapping
1146 bool overlapUnsafe; /// if it is an overlapping field and the overlaps are unsafe
1147 bool maybeScope; /// allow inferring 'scope' for this variable
1148 bool doNotInferReturn; /// do not infer 'return' for this variable
1150 bool isArgDtorVar; /// temporary created to handle scope destruction of a function argument
1151 bool isCmacro; /// it is a C macro turned into a C declaration
1152 bool dllImport; /// __declspec(dllimport)
1153 bool dllExport; /// __declspec(dllexport)
1156 bool inClosure; /// is inserted into a GC allocated closure
1157 bool inAlignSection; /// is inserted into an aligned section on stack
1161 import dmd.common.bitfields : generateBitFields;
1162 mixin(generateBitFields!(BitFields, ushort));
1164 byte canassign; // it can be assigned to
1165 ubyte isdataseg; // private data for isDataseg 0 unset, 1 true, 2 false
1167 final extern (D) this(const ref Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.undefined_)
1174 //printf("VarDeclaration('%s')\n", ident.toChars());
1178 if (!type && !_init)
1180 //printf("VarDeclaration('%s')\n", ident.toChars());
1185 assert(type || _init);
1188 ctfeAdrOnStack = AdrOnStackNone;
1189 this.storage_class = storage_class;
1192 static VarDeclaration create(const ref Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.undefined_)
1194 return new VarDeclaration(loc, type, ident, _init, storage_class);
1197 override VarDeclaration syntaxCopy(Dsymbol s)
1199 //printf("VarDeclaration::syntaxCopy(%s)\n", toChars());
1201 auto v = new VarDeclaration(loc, type ? type.syntaxCopy() : null, ident, _init ? _init.syntaxCopy() : null, storage_class);
1202 v.comment = comment;
1206 override void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion)
1208 //printf("VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars());
1212 // If this variable was really a tuple, set the offsets for the tuple fields
1213 aliasTuple.foreachVar((s) { s.setFieldOffset(ad, fieldState, isunion); });
1219 assert(!(storage_class & (STC.static_ | STC.extern_ | STC.parameter)));
1221 //printf("+VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars());
1223 /* Fields that are tuples appear both as part of TupleDeclarations and
1224 * as members. That means ignore them if they are already a field.
1229 fieldState.offset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613
1232 for (size_t i = 0; i < ad.fields.length; i++)
1234 if (ad.fields[i] == this)
1237 fieldState.offset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613
1242 // Check for forward referenced types which will fail the size() call
1243 Type t = type.toBasetype();
1244 if (storage_class & STC.ref_)
1246 // References are the size of a pointer
1249 Type tv = t.baseElemOf();
1250 if (tv.ty == Tstruct)
1252 auto ts = cast(TypeStruct)tv;
1253 assert(ts.sym != ad); // already checked in ad.determineFields()
1254 if (!ts.sym.determineSize(loc))
1262 // List in ad.fields. Even if the type is error, it's necessary to avoid
1263 // pointless error diagnostic "more initializers than fields" on struct literal.
1264 ad.fields.push(this);
1269 /* If coming after a bit field in progress,
1270 * advance past the field
1272 fieldState.inFlight = false;
1274 const sz = t.size(loc);
1275 assert(sz != SIZE_INVALID && sz < uint.max);
1276 uint memsize = cast(uint)sz; // size of member
1277 uint memalignsize = target.fieldalign(t); // size of member for alignment purposes
1278 offset = AggregateDeclaration.placeField(
1280 memsize, memalignsize, alignment,
1281 &ad.structsize, &ad.alignsize,
1284 //printf("\t%s: memalignsize = %d\n", toChars(), memalignsize);
1285 //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize);
1288 override const(char)* kind() const
1293 override final inout(AggregateDeclaration) isThis() inout
1295 if (!(storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.templateparameter | STC.gshared | STC.ctfe)))
1297 /* The casting is necessary because `s = s.parent` is otherwise rejected
1299 for (auto s = cast(Dsymbol)this; s; s = s.parent)
1301 auto ad = (cast(inout)s).isMember();
1304 if (!s.parent || !s.parent.isTemplateMixin())
1311 override final bool needThis()
1313 //printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class);
1317 override final bool isExport() const
1319 return visibility.kind == Visibility.Kind.export_ || dllExport;
1322 override final bool isImportedSymbol() const
1324 /* If global variable has `export` and `extern` then it is imported
1325 * export int sym1; // definition: exported
1326 * export extern int sym2; // declaration: imported
1327 * export extern int sym3 = 0; // error, extern cannot have initializer
1331 visibility.kind == Visibility.Kind.export_ &&
1332 storage_class & STC.extern_ &&
1333 (storage_class & STC.static_ || parent.isModule());
1334 //printf("isImportedSymbol() %s %d\n", toChars(), result);
1338 final bool isCtorinit() const pure nothrow @nogc @safe
1340 return setInCtorOnly;
1343 /*******************************
1344 * Does symbol go into data segment?
1345 * Includes extern variables.
1347 override final bool isDataseg()
1351 printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars());
1352 printf("%llx, isModule: %p, isTemplateInstance: %p, isNspace: %p\n",
1353 storage_class & (STC.static_ | STC.const_), parent.isModule(), parent.isTemplateInstance(), parent.isNspace());
1354 printf("parent = '%s'\n", parent.toChars());
1357 if (isdataseg == 0) // the value is not cached
1359 isdataseg = 2; // The Variables does not go into the datasegment
1361 if (!canTakeAddressOf())
1366 Dsymbol parent = toParent();
1367 if (!parent && !(storage_class & STC.static_))
1369 error("forward referenced");
1372 else if (storage_class & (STC.static_ | STC.extern_ | STC.gshared) ||
1373 parent.isModule() || parent.isTemplateInstance() || parent.isNspace())
1375 assert(!isParameter() && !isResult());
1376 isdataseg = 1; // It is in the DataSegment
1380 return (isdataseg == 1);
1382 /************************************
1383 * Does symbol go into thread local storage?
1385 override final bool isThreadlocal()
1387 //printf("VarDeclaration::isThreadlocal(%p, '%s')\n", this, toChars());
1388 /* Data defaults to being thread-local. It is not thread-local
1389 * if it is immutable, const or shared.
1391 bool i = isDataseg() && !(storage_class & (STC.immutable_ | STC.const_ | STC.shared_ | STC.gshared));
1392 //printf("\treturn %d\n", i);
1396 /********************************************
1397 * Can variable be read and written by CTFE?
1401 return (storage_class & STC.ctfe) != 0; // || !isDataseg();
1404 final bool isOverlappedWith(VarDeclaration v)
1406 const vsz = v.type.size();
1407 const tsz = type.size();
1408 assert(vsz != SIZE_INVALID && tsz != SIZE_INVALID);
1410 // Overlap is checked by comparing bit offsets
1411 auto bitoffset = offset * 8;
1412 auto vbitoffset = v.offset * 8;
1414 // Bitsize of types are overridden by any bit-field widths.
1415 ulong tbitsize = void;
1416 if (auto bf = isBitFieldDeclaration())
1418 bitoffset += bf.bitOffset;
1419 tbitsize = bf.fieldWidth;
1424 ulong vbitsize = void;
1425 if (auto vbf = v.isBitFieldDeclaration())
1427 vbitoffset += vbf.bitOffset;
1428 vbitsize = vbf.fieldWidth;
1433 return bitoffset < vbitoffset + vbitsize &&
1434 vbitoffset < bitoffset + tbitsize;
1437 override final bool hasPointers()
1439 //printf("VarDeclaration::hasPointers() %s, ty = %d\n", toChars(), type.ty);
1440 return (!isDataseg() && type.hasPointers());
1443 /*************************************
1444 * Return true if we can take the address of this variable.
1446 final bool canTakeAddressOf()
1448 return !(storage_class & STC.manifest);
1451 /******************************************
1452 * Return true if variable needs to call the destructor.
1454 final bool needsScopeDtor()
1456 //printf("VarDeclaration::needsScopeDtor() %s\n", toChars());
1457 return edtor && !(storage_class & STC.nodtor);
1460 /******************************************
1461 * If a variable has a scope destructor call, return call for it.
1462 * Otherwise, return NULL.
1464 extern (D) final Expression callScopeDtor(Scope* sc)
1466 //printf("VarDeclaration::callScopeDtor() %s\n", toChars());
1468 // Destruction of STC.field's is handled by buildDtor()
1469 if (storage_class & (STC.nodtor | STC.ref_ | STC.out_ | STC.field))
1475 return null; // destructor is built by `void semantic(Catch c, Scope* sc)`, not here
1477 Expression e = null;
1478 // Destructors for structs and arrays of structs
1479 Type tv = type.baseElemOf();
1480 if (tv.ty == Tstruct)
1482 StructDeclaration sd = (cast(TypeStruct)tv).sym;
1483 if (!sd.dtor || sd.errors)
1486 const sz = type.size();
1487 assert(sz != SIZE_INVALID);
1491 if (type.toBasetype().ty == Tstruct)
1494 e = new VarExp(loc, this);
1496 /* This is a hack so we can call destructors on const/immutable objects.
1497 * Need to add things like "const ~this()" and "immutable ~this()" to
1500 e.type = e.type.mutableOf();
1502 // Enable calling destructors on shared objects.
1503 // The destructor is always a single, non-overloaded function,
1504 // and must serve both shared and non-shared objects.
1505 e.type = e.type.unSharedOf;
1507 e = new DotVarExp(loc, e, sd.dtor, false);
1508 e = new CallExp(loc, e);
1512 // __ArrayDtor(v[0 .. n])
1513 e = new VarExp(loc, this);
1515 const sdsz = sd.type.size();
1516 assert(sdsz != SIZE_INVALID && sdsz != 0);
1517 const n = sz / sdsz;
1518 SliceExp se = new SliceExp(loc, e, new IntegerExp(loc, 0, Type.tsize_t),
1519 new IntegerExp(loc, n, Type.tsize_t));
1521 // Prevent redundant bounds check
1522 se.upperIsInBounds = true;
1523 se.lowerIsLessThanUpper = true;
1525 // This is a hack so we can call destructors on const/immutable objects.
1526 se.type = sd.type.arrayOf();
1528 e = new CallExp(loc, new IdentifierExp(loc, Id.__ArrayDtor), se);
1532 // Destructors for classes
1533 if (storage_class & (STC.auto_ | STC.scope_) && !(storage_class & STC.parameter))
1535 for (ClassDeclaration cd = type.isClassHandle(); cd; cd = cd.baseClass)
1537 /* We can do better if there's a way with onstack
1538 * classes to determine if there's no way the monitor
1541 //if (cd.isInterfaceDeclaration())
1542 // error("interface `%s` cannot be scope", cd.toChars());
1544 if (onstack) // if any destructors
1546 // delete'ing C++ classes crashes (and delete is deprecated anyway)
1547 if (cd.classKind == ClassKind.cpp)
1549 // Don't call non-existant dtor
1553 e = new VarExp(loc, this);
1554 e.type = e.type.mutableOf().unSharedOf(); // Hack for mutable ctor on immutable instances
1555 e = new DotVarExp(loc, e, cd.dtor, false);
1556 e = new CallExp(loc, e);
1562 ec = new VarExp(loc, this);
1563 e = new DeleteExp(loc, ec, true);
1564 e.type = Type.tvoid;
1572 /*******************************************
1573 * If variable has a constant expression initializer, get it.
1574 * Otherwise, return null.
1576 extern (D) final Expression getConstInitializer(bool needFullType = true)
1578 assert(type && _init);
1580 // Ungag errors when not speculative
1581 uint oldgag = global.gag;
1584 Dsymbol sym = isMember();
1585 if (sym && !sym.isSpeculative())
1592 _init = _init.initializerSemantic(_scope, type, INITinterpret);
1597 Expression e = _init.initializerToExpression(needFullType ? type : null);
1598 global.gag = oldgag;
1602 /*******************************************
1603 * Helper function for the expansion of manifest constant.
1605 extern (D) final Expression expandInitializer(Loc loc)
1607 assert((storage_class & STC.manifest) && _init);
1609 auto e = getConstInitializer();
1612 .error(loc, "cannot make expression out of initializer for `%s`", toChars());
1613 return ErrorExp.get();
1617 e.loc = loc; // for better error message
1621 override final void checkCtorConstInit()
1625 /* doesn't work if more than one static ctor */
1626 if (ctorinit == 0 && isCtorinit() && !isField())
1627 error("missing initializer in static constructor for const variable");
1631 /************************************
1632 * Check to see if this variable is actually in an enclosing function
1633 * rather than the current one.
1634 * Update nestedrefs[], closureVars[] and outerVars[].
1635 * Returns: true if error occurs.
1637 extern (D) final bool checkNestedReference(Scope* sc, Loc loc)
1639 //printf("VarDeclaration::checkNestedReference() %s\n", toChars());
1640 if (sc.intypeof == 1 || (sc.flags & SCOPE.ctfe))
1642 if (!parent || parent == sc.parent)
1644 if (isDataseg() || (storage_class & STC.manifest))
1647 // The current function
1648 FuncDeclaration fdthis = sc.parent.isFuncDeclaration();
1650 return false; // out of function scope
1652 Dsymbol p = toParent2();
1654 // Function literals from fdthis to p must be delegates
1655 ensureStaticLinkTo(fdthis, p);
1657 // The function that this variable is in
1658 FuncDeclaration fdv = p.isFuncDeclaration();
1659 if (!fdv || fdv == fdthis)
1662 // Add fdthis to nestedrefs[] if not already there
1663 if (!nestedrefs.contains(fdthis))
1664 nestedrefs.push(fdthis);
1666 //printf("\tfdv = %s\n", fdv.toChars());
1667 //printf("\tfdthis = %s\n", fdthis.toChars());
1670 if (fdthis.getLevelAndCheck(loc, sc, fdv, this) == fdthis.LevelError)
1674 // Add this VarDeclaration to fdv.closureVars[] if not already there
1675 if (!sc.intypeof && !(sc.flags & SCOPE.compile) &&
1676 // https://issues.dlang.org/show_bug.cgi?id=17605
1677 (fdv.skipCodegen || !fdthis.skipCodegen))
1679 if (!fdv.closureVars.contains(this))
1680 fdv.closureVars.push(this);
1683 if (!fdthis.outerVars.contains(this))
1684 fdthis.outerVars.push(this);
1686 //printf("fdthis is %s\n", fdthis.toChars());
1687 //printf("var %s in function %s is nested ref\n", toChars(), fdv.toChars());
1688 // __dollar creates problems because it isn't a real variable
1689 // https://issues.dlang.org/show_bug.cgi?id=3326
1690 if (ident == Id.dollar)
1692 .error(loc, "cannnot use `$` inside a function literal");
1695 if (ident == Id.withSym) // https://issues.dlang.org/show_bug.cgi?id=1759
1697 ExpInitializer ez = _init.isExpInitializer();
1699 Expression e = ez.exp;
1700 if (e.op == EXP.construct || e.op == EXP.blit)
1701 e = (cast(AssignExp)e).e2;
1702 return lambdaCheckForNestedRef(e, sc);
1708 override final Dsymbol toAlias()
1710 //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym);
1711 if ((!type || !type.deco) && _scope)
1712 dsymbolSemantic(this, _scope);
1714 assert(this != aliasTuple);
1715 Dsymbol s = aliasTuple ? aliasTuple.toAlias() : this;
1719 // Eliminate need for dynamic_cast
1720 override final inout(VarDeclaration) isVarDeclaration() inout
1725 override void accept(Visitor v)
1731 /*******************************************************
1732 * C11 6.7.2.1-4 bit fields
1734 extern (C++) class BitFieldDeclaration : VarDeclaration
1741 final extern (D) this(const ref Loc loc, Type type, Identifier ident, Expression width)
1743 super(loc, type, ident, null);
1746 this.storage_class |= STC.field;
1749 override BitFieldDeclaration syntaxCopy(Dsymbol s)
1751 //printf("BitFieldDeclaration::syntaxCopy(%s)\n", toChars());
1753 auto bf = new BitFieldDeclaration(loc, type ? type.syntaxCopy() : null, ident, width.syntaxCopy());
1754 bf.comment = comment;
1758 override final inout(BitFieldDeclaration) isBitFieldDeclaration() inout
1763 override void accept(Visitor v)
1768 /***********************************
1769 * Retrieve the .min or .max values.
1770 * Only valid after semantic analysis.
1772 * id = Id.min or Id.max
1774 * the min or max value
1776 final ulong getMinMax(Identifier id)
1778 const width = fieldWidth;
1779 const uns = type.isunsigned();
1780 const min = id == Id.min;
1782 assert(width != 0); // should have been rejected in semantic pass
1783 if (width == ulong.sizeof * 8)
1784 v = uns ? (min ? ulong.min : ulong.max)
1785 : (min ? long.min : long.max);
1788 : (1L << width) - 1)
1789 : (min ? -(1L << (width - 1))
1790 : (1L << (width - 1)) - 1);
1794 override final void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion)
1799 printf("BitFieldDeclaration::setFieldOffset(ad: %s, field: %s)\n", ad.toChars(), toChars());
1800 void print(const ref FieldState fieldState)
1802 printf("FieldState.offset = %d bytes\n", fieldState.offset);
1803 printf(" .fieldOffset = %d bytes\n", fieldState.fieldOffset);
1804 printf(" .bitOffset = %d bits\n", fieldState.bitOffset);
1805 printf(" .fieldSize = %d bytes\n", fieldState.fieldSize);
1806 printf(" .inFlight = %d\n", fieldState.inFlight);
1807 printf(" fieldWidth = %d bits\n", fieldWidth);
1812 Type t = type.toBasetype();
1813 const bool anon = isAnonymous();
1815 // List in ad.fields. Even if the type is error, it's necessary to avoid
1816 // pointless error diagnostic "more initializers than fields" on struct literal.
1818 ad.fields.push(this);
1823 const sz = t.size(loc);
1824 assert(sz != SIZE_INVALID && sz < uint.max);
1825 uint memsize = cast(uint)sz; // size of member
1826 uint memalignsize = target.fieldalign(t); // size of member for alignment purposes
1827 if (log) printf(" memsize: %u memalignsize: %u\n", memsize, memalignsize);
1829 if (fieldWidth == 0 && !anon)
1830 error(loc, "named bit fields cannot have 0 width");
1831 if (fieldWidth > memsize * 8)
1832 error(loc, "bit field width %d is larger than type", fieldWidth);
1834 const style = target.c.bitFieldStyle;
1836 void startNewField()
1838 if (log) printf("startNewField()\n");
1840 if (style == TargetC.BitFieldStyle.Gcc_Clang)
1842 if (fieldWidth > 32)
1843 alignsize = memalignsize;
1844 else if (fieldWidth > 16)
1846 else if (fieldWidth > 8)
1852 alignsize = memsize; // not memalignsize
1855 offset = AggregateDeclaration.placeField(
1857 memsize, alignsize, alignment,
1859 (anon && style == TargetC.BitFieldStyle.Gcc_Clang) ? &dummy : &ad.alignsize,
1862 fieldState.inFlight = true;
1863 fieldState.fieldOffset = offset;
1864 fieldState.bitOffset = 0;
1865 fieldState.fieldSize = memsize;
1868 if (style == TargetC.BitFieldStyle.Gcc_Clang)
1870 if (fieldWidth == 0)
1874 // Use type of zero width field to align to next field
1875 fieldState.offset = (fieldState.offset + memalignsize - 1) & ~(memalignsize - 1);
1876 ad.structsize = fieldState.offset;
1879 fieldState.inFlight = false;
1883 if (ad.alignsize == 0)
1886 ad.alignsize < memalignsize)
1887 ad.alignsize = memalignsize;
1889 else if (style == TargetC.BitFieldStyle.MS)
1891 if (ad.alignsize == 0)
1893 if (fieldWidth == 0)
1895 if (fieldState.inFlight && !isunion)
1897 // documentation says align to next int
1898 //const alsz = cast(uint)Type.tint32.size();
1899 const alsz = memsize; // but it really does this
1900 fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1);
1901 ad.structsize = fieldState.offset;
1904 fieldState.inFlight = false;
1908 else if (style == TargetC.BitFieldStyle.DM)
1910 if (anon && fieldWidth && (!fieldState.inFlight || fieldState.bitOffset == 0))
1911 return; // this probably should be a bug in DMC
1912 if (ad.alignsize == 0)
1914 if (fieldWidth == 0)
1916 if (fieldState.inFlight && !isunion)
1918 const alsz = memsize;
1919 fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1);
1920 ad.structsize = fieldState.offset;
1923 fieldState.inFlight = false;
1928 if (!fieldState.inFlight)
1930 //printf("not in flight\n");
1933 else if (style == TargetC.BitFieldStyle.Gcc_Clang)
1935 // If the bit-field spans more units of alignment than its type,
1936 // start a new field at the next alignment boundary.
1937 if (fieldState.bitOffset == fieldState.fieldSize * 8 &&
1938 fieldState.bitOffset + fieldWidth > memalignsize * 8)
1940 if (log) printf("more units of alignment than its type\n");
1941 startNewField(); // the bit field is full
1945 // if alignment boundary is crossed
1946 uint start = fieldState.fieldOffset * 8 + fieldState.bitOffset;
1947 uint end = start + fieldWidth;
1948 //printf("%s start: %d end: %d memalignsize: %d\n", ad.toChars(), start, end, memalignsize);
1949 if (start / (memalignsize * 8) != (end - 1) / (memalignsize * 8))
1951 if (log) printf("alignment is crossed\n");
1956 else if (style == TargetC.BitFieldStyle.DM ||
1957 style == TargetC.BitFieldStyle.MS)
1959 if (memsize != fieldState.fieldSize ||
1960 fieldState.bitOffset + fieldWidth > fieldState.fieldSize * 8)
1962 //printf("new field\n");
1969 offset = fieldState.fieldOffset;
1970 bitOffset = fieldState.bitOffset;
1972 const pastField = bitOffset + fieldWidth;
1973 if (style == TargetC.BitFieldStyle.Gcc_Clang)
1975 auto size = (pastField + 7) / 8;
1976 fieldState.fieldSize = size;
1977 //printf(" offset: %d, size: %d\n", offset, size);
1978 ad.structsize = offset + size;
1981 fieldState.fieldSize = memsize;
1982 //printf("at end: ad.structsize = %d\n", cast(int)ad.structsize);
1983 //print(fieldState);
1987 fieldState.offset = offset + fieldState.fieldSize;
1988 fieldState.bitOffset = pastField;
1991 //printf("\t%s: offset = %d bitOffset = %d fieldWidth = %d memsize = %d\n", toChars(), offset, bitOffset, fieldWidth, memsize);
1992 //printf("\t%s: memalignsize = %d\n", toChars(), memalignsize);
1993 //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize);
1997 /***********************************************************
1998 * This is a shell around a back end symbol
2000 extern (C++) final class SymbolDeclaration : Declaration
2002 AggregateDeclaration dsym;
2004 extern (D) this(const ref Loc loc, AggregateDeclaration dsym)
2006 super(loc, dsym.ident);
2008 storage_class |= STC.const_;
2011 // Eliminate need for dynamic_cast
2012 override inout(SymbolDeclaration) isSymbolDeclaration() inout
2017 override void accept(Visitor v)
2023 /***********************************************************
2025 extern (C++) class TypeInfoDeclaration : VarDeclaration
2029 final extern (D) this(Type tinfo)
2031 super(Loc.initial, Type.dtypeinfo.type, tinfo.getTypeInfoIdent(), null);
2033 storage_class = STC.static_ | STC.gshared;
2034 visibility = Visibility(Visibility.Kind.public_);
2036 alignment.set(target.ptrsize);
2039 static TypeInfoDeclaration create(Type tinfo)
2041 return new TypeInfoDeclaration(tinfo);
2044 override final TypeInfoDeclaration syntaxCopy(Dsymbol s)
2046 assert(0); // should never be produced by syntax
2049 override final const(char)* toChars() const
2051 //printf("TypeInfoDeclaration::toChars() tinfo = %s\n", tinfo.toChars());
2053 buf.writestring("typeid(");
2054 buf.writestring(tinfo.toChars());
2056 return buf.extractChars();
2059 override final inout(TypeInfoDeclaration) isTypeInfoDeclaration() inout @nogc nothrow pure @safe
2064 override void accept(Visitor v)
2070 /***********************************************************
2072 extern (C++) final class TypeInfoStructDeclaration : TypeInfoDeclaration
2074 extern (D) this(Type tinfo)
2077 if (!Type.typeinfostruct)
2079 ObjectNotFound(Id.TypeInfo_Struct);
2081 type = Type.typeinfostruct.type;
2084 static TypeInfoStructDeclaration create(Type tinfo)
2086 return new TypeInfoStructDeclaration(tinfo);
2089 override void accept(Visitor v)
2095 /***********************************************************
2097 extern (C++) final class TypeInfoClassDeclaration : TypeInfoDeclaration
2099 extern (D) this(Type tinfo)
2102 if (!Type.typeinfoclass)
2104 ObjectNotFound(Id.TypeInfo_Class);
2106 type = Type.typeinfoclass.type;
2109 static TypeInfoClassDeclaration create(Type tinfo)
2111 return new TypeInfoClassDeclaration(tinfo);
2114 override void accept(Visitor v)
2120 /***********************************************************
2122 extern (C++) final class TypeInfoInterfaceDeclaration : TypeInfoDeclaration
2124 extern (D) this(Type tinfo)
2127 if (!Type.typeinfointerface)
2129 ObjectNotFound(Id.TypeInfo_Interface);
2131 type = Type.typeinfointerface.type;
2134 static TypeInfoInterfaceDeclaration create(Type tinfo)
2136 return new TypeInfoInterfaceDeclaration(tinfo);
2139 override void accept(Visitor v)
2145 /***********************************************************
2147 extern (C++) final class TypeInfoPointerDeclaration : TypeInfoDeclaration
2149 extern (D) this(Type tinfo)
2152 if (!Type.typeinfopointer)
2154 ObjectNotFound(Id.TypeInfo_Pointer);
2156 type = Type.typeinfopointer.type;
2159 static TypeInfoPointerDeclaration create(Type tinfo)
2161 return new TypeInfoPointerDeclaration(tinfo);
2164 override void accept(Visitor v)
2170 /***********************************************************
2172 extern (C++) final class TypeInfoArrayDeclaration : TypeInfoDeclaration
2174 extern (D) this(Type tinfo)
2177 if (!Type.typeinfoarray)
2179 ObjectNotFound(Id.TypeInfo_Array);
2181 type = Type.typeinfoarray.type;
2184 static TypeInfoArrayDeclaration create(Type tinfo)
2186 return new TypeInfoArrayDeclaration(tinfo);
2189 override void accept(Visitor v)
2195 /***********************************************************
2197 extern (C++) final class TypeInfoStaticArrayDeclaration : TypeInfoDeclaration
2199 extern (D) this(Type tinfo)
2202 if (!Type.typeinfostaticarray)
2204 ObjectNotFound(Id.TypeInfo_StaticArray);
2206 type = Type.typeinfostaticarray.type;
2209 static TypeInfoStaticArrayDeclaration create(Type tinfo)
2211 return new TypeInfoStaticArrayDeclaration(tinfo);
2214 override void accept(Visitor v)
2220 /***********************************************************
2222 extern (C++) final class TypeInfoAssociativeArrayDeclaration : TypeInfoDeclaration
2224 extern (D) this(Type tinfo)
2227 if (!Type.typeinfoassociativearray)
2229 ObjectNotFound(Id.TypeInfo_AssociativeArray);
2231 type = Type.typeinfoassociativearray.type;
2234 static TypeInfoAssociativeArrayDeclaration create(Type tinfo)
2236 return new TypeInfoAssociativeArrayDeclaration(tinfo);
2239 override void accept(Visitor v)
2245 /***********************************************************
2247 extern (C++) final class TypeInfoEnumDeclaration : TypeInfoDeclaration
2249 extern (D) this(Type tinfo)
2252 if (!Type.typeinfoenum)
2254 ObjectNotFound(Id.TypeInfo_Enum);
2256 type = Type.typeinfoenum.type;
2259 static TypeInfoEnumDeclaration create(Type tinfo)
2261 return new TypeInfoEnumDeclaration(tinfo);
2264 override void accept(Visitor v)
2270 /***********************************************************
2272 extern (C++) final class TypeInfoFunctionDeclaration : TypeInfoDeclaration
2274 extern (D) this(Type tinfo)
2277 if (!Type.typeinfofunction)
2279 ObjectNotFound(Id.TypeInfo_Function);
2281 type = Type.typeinfofunction.type;
2284 static TypeInfoFunctionDeclaration create(Type tinfo)
2286 return new TypeInfoFunctionDeclaration(tinfo);
2289 override void accept(Visitor v)
2295 /***********************************************************
2297 extern (C++) final class TypeInfoDelegateDeclaration : TypeInfoDeclaration
2299 extern (D) this(Type tinfo)
2302 if (!Type.typeinfodelegate)
2304 ObjectNotFound(Id.TypeInfo_Delegate);
2306 type = Type.typeinfodelegate.type;
2309 static TypeInfoDelegateDeclaration create(Type tinfo)
2311 return new TypeInfoDelegateDeclaration(tinfo);
2314 override void accept(Visitor v)
2320 /***********************************************************
2322 extern (C++) final class TypeInfoTupleDeclaration : TypeInfoDeclaration
2324 extern (D) this(Type tinfo)
2327 if (!Type.typeinfotypelist)
2329 ObjectNotFound(Id.TypeInfo_Tuple);
2331 type = Type.typeinfotypelist.type;
2334 static TypeInfoTupleDeclaration create(Type tinfo)
2336 return new TypeInfoTupleDeclaration(tinfo);
2339 override void accept(Visitor v)
2345 /***********************************************************
2347 extern (C++) final class TypeInfoConstDeclaration : TypeInfoDeclaration
2349 extern (D) this(Type tinfo)
2352 if (!Type.typeinfoconst)
2354 ObjectNotFound(Id.TypeInfo_Const);
2356 type = Type.typeinfoconst.type;
2359 static TypeInfoConstDeclaration create(Type tinfo)
2361 return new TypeInfoConstDeclaration(tinfo);
2364 override void accept(Visitor v)
2370 /***********************************************************
2372 extern (C++) final class TypeInfoInvariantDeclaration : TypeInfoDeclaration
2374 extern (D) this(Type tinfo)
2377 if (!Type.typeinfoinvariant)
2379 ObjectNotFound(Id.TypeInfo_Invariant);
2381 type = Type.typeinfoinvariant.type;
2384 static TypeInfoInvariantDeclaration create(Type tinfo)
2386 return new TypeInfoInvariantDeclaration(tinfo);
2389 override void accept(Visitor v)
2395 /***********************************************************
2397 extern (C++) final class TypeInfoSharedDeclaration : TypeInfoDeclaration
2399 extern (D) this(Type tinfo)
2402 if (!Type.typeinfoshared)
2404 ObjectNotFound(Id.TypeInfo_Shared);
2406 type = Type.typeinfoshared.type;
2409 static TypeInfoSharedDeclaration create(Type tinfo)
2411 return new TypeInfoSharedDeclaration(tinfo);
2414 override void accept(Visitor v)
2420 /***********************************************************
2422 extern (C++) final class TypeInfoWildDeclaration : TypeInfoDeclaration
2424 extern (D) this(Type tinfo)
2427 if (!Type.typeinfowild)
2429 ObjectNotFound(Id.TypeInfo_Wild);
2431 type = Type.typeinfowild.type;
2434 static TypeInfoWildDeclaration create(Type tinfo)
2436 return new TypeInfoWildDeclaration(tinfo);
2439 override void accept(Visitor v)
2445 /***********************************************************
2447 extern (C++) final class TypeInfoVectorDeclaration : TypeInfoDeclaration
2449 extern (D) this(Type tinfo)
2452 if (!Type.typeinfovector)
2454 ObjectNotFound(Id.TypeInfo_Vector);
2456 type = Type.typeinfovector.type;
2459 static TypeInfoVectorDeclaration create(Type tinfo)
2461 return new TypeInfoVectorDeclaration(tinfo);
2464 override void accept(Visitor v)
2470 /***********************************************************
2471 * For the "this" parameter to member functions
2473 extern (C++) final class ThisDeclaration : VarDeclaration
2475 extern (D) this(const ref Loc loc, Type t)
2477 super(loc, t, Id.This, null);
2478 storage_class |= STC.nodtor;
2481 override ThisDeclaration syntaxCopy(Dsymbol s)
2483 assert(0); // should never be produced by syntax
2486 override inout(ThisDeclaration) isThisDeclaration() inout
2491 override void accept(Visitor v)