d: Merge upstream dmd 4d1bfcf14, druntime 9ba9a6ae, phobos c0cc5e917.
[official-gcc.git] / gcc / d / dmd / declaration.d
blob45eb582745a21ac34f6d5af9e3a46ec900a88e11
1 /**
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;
16 import dmd.aggregate;
17 import dmd.arraytypes;
18 import dmd.astenums;
19 import dmd.attrib;
20 import dmd.ctorflow;
21 import dmd.dclass;
22 import dmd.delegatize;
23 import dmd.dscope;
24 import dmd.dstruct;
25 import dmd.dsymbol;
26 import dmd.dsymbolsem;
27 import dmd.dtemplate;
28 import dmd.errors;
29 import dmd.expression;
30 import dmd.func;
31 import dmd.globals;
32 import dmd.gluelayer;
33 import dmd.id;
34 import dmd.identifier;
35 import dmd.init;
36 import dmd.initsem;
37 import dmd.intrange;
38 import dmd.mtype;
39 import dmd.common.outbuffer;
40 import dmd.root.rootobject;
41 import dmd.target;
42 import dmd.tokens;
43 import dmd.typesem;
44 import dmd.visitor;
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();
55 Dsymbol s = sc.func;
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());
64 return true;
68 bool result = false;
69 for (size_t i = iStart; i < ad.fields.dim; i++)
71 VarDeclaration vd = ad.fields[i];
72 Type tb = vd.type.baseElemOf();
73 if (tb.ty == Tstruct)
75 result |= checkFrameAccess(loc, sc, (cast(TypeStruct)tb).sym);
78 return result;
81 /***********************************************
82 * Mark variable v as modified if it is inside a constructor that var
83 * is a field in.
85 bool modifyFieldVar(Loc loc, Scope* sc, VarDeclaration var, Expression e1)
87 //printf("modifyFieldVar(var = %s)\n", var.toChars());
88 Dsymbol s = sc.func;
89 while (1)
91 FuncDeclaration fd = null;
92 if (s)
93 fd = s.isFuncDeclaration();
94 if (fd &&
95 ((fd.isCtorDeclaration() && var.isField()) ||
96 (fd.isStaticCtorDeclaration() && !var.isField())) &&
97 fd.toParentDecl() == var.toParent2() &&
98 (!e1 || e1.op == EXP.this_))
100 bool result = true;
102 var.ctorinit = true;
103 //printf("setting ctorinit\n");
105 if (var.isField() && sc.ctorflow.fieldinit.length && !sc.intypeof)
107 assert(e1);
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();
113 assert(ad);
114 size_t i;
115 for (i = 0; i < dim; i++) // same as findFieldIndexByName in ctfeexp.c ?
117 if (ad.fields[i] == var)
118 break;
120 assert(i < dim);
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())
127 result = false;
128 else
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())
138 result = false;
139 else
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))
153 continue;
154 v.ctorinit = true;
155 sc.ctorflow.fieldinit[j].csx = CSX.this_ctor;
159 else if (fd != sc.func)
161 if (var.type.isMutable())
162 result = false;
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());
169 else
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.");
183 return result;
185 else
187 if (s)
189 s = s.toParentP(var.toParent2());
190 continue;
193 break;
195 return false;
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());
203 fatal();
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
220 Type type;
221 Type originalType; // before semantic analysis
222 StorageClass storage_class = STC.undefined_;
223 Visibility visibility;
224 LINK linkage = LINK.default_;
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
231 Symbol* isym; // import version of csym
233 // overridden symbol with pragma(mangle, "...")
234 const(char)[] mangleOverride;
236 final extern (D) this(Identifier ident)
238 super(ident);
239 visibility = Visibility(Visibility.Kind.undefined);
242 final extern (D) this(const ref Loc loc, Identifier ident)
244 super(loc, ident);
245 visibility = Visibility(Visibility.Kind.undefined);
248 override const(char)* kind() const
250 return "declaration";
253 override final uinteger_t size(const ref Loc loc)
255 assert(type);
256 const sz = type.size();
257 if (sz == SIZE_INVALID)
258 errors = true;
259 return sz;
263 * Issue an error if an attempt to call a disabled method is made
265 * If the declaration is disabled but inside a disabled function,
266 * returns `true` but do not issue an error message.
268 * Params:
269 * loc = Location information of the call
270 * sc = Scope in which the call occurs
271 * isAliasedDeclaration = if `true` searches overload set
273 * Returns:
274 * `true` if this `Declaration` is `@disable`d, `false` otherwise.
276 extern (D) final bool checkDisabled(Loc loc, Scope* sc, bool isAliasedDeclaration = false)
278 if (!(storage_class & STC.disable))
279 return false;
281 if (sc.func && sc.func.storage_class & STC.disable)
282 return true;
284 if (auto p = toParent())
286 if (auto postblit = isPostBlitDeclaration())
288 /* https://issues.dlang.org/show_bug.cgi?id=21885
290 * If the generated postblit is disabled, it
291 * means that one of the fields has a disabled
292 * postblit. Print the first field that has
293 * a disabled postblit.
295 if (postblit.isGenerated())
297 auto sd = p.isStructDeclaration();
298 assert(sd);
299 for (size_t i = 0; i < sd.fields.dim; i++)
301 auto structField = sd.fields[i];
302 if (structField.overlapped)
303 continue;
304 Type tv = structField.type.baseElemOf();
305 if (tv.ty != Tstruct)
306 continue;
307 auto sdv = (cast(TypeStruct)tv).sym;
308 if (!sdv.postblit)
309 continue;
310 if (sdv.postblit.isDisabled())
312 p.error(loc, "is not copyable because field `%s` is not copyable", structField.toChars());
313 return true;
317 p.error(loc, "is not copyable because it has a disabled postblit");
318 return true;
322 // if the function is @disabled, maybe there
323 // is an overload in the overload set that isn't
324 if (isAliasedDeclaration)
326 FuncDeclaration fd = isFuncDeclaration();
327 if (fd)
329 for (FuncDeclaration ovl = fd; ovl; ovl = cast(FuncDeclaration)ovl.overnext)
330 if (!(ovl.storage_class & STC.disable))
331 return false;
335 if (auto ctor = isCtorDeclaration())
337 if (ctor.isCpCtor && ctor.isGenerated())
339 .error(loc, "Generating an `inout` copy constructor for `struct %s` failed, therefore instances of it are uncopyable", parent.toPrettyChars());
340 return true;
343 error(loc, "cannot be used because it is annotated with `@disable`");
344 return true;
347 /*************************************
348 * Check to see if declaration can be modified in this context (sc).
349 * Issue error if not.
350 * Params:
351 * loc = location for error messages
352 * e1 = `null` or `this` expression when this declaration is a field
353 * sc = context
354 * flag = if the first bit is set it means do not issue error message for
355 * invalid modification; if the second bit is set, it means that
356 this declaration is a field and a subfield of it is modified.
357 * Returns:
358 * Modifiable.yes or Modifiable.initialization
360 extern (D) final Modifiable checkModify(Loc loc, Scope* sc, Expression e1, ModifyFlags flag)
362 VarDeclaration v = isVarDeclaration();
363 if (v && v.canassign)
364 return Modifiable.initialization;
366 if (isParameter() || isResult())
368 for (Scope* scx = sc; scx; scx = scx.enclosing)
370 if (scx.func == parent && (scx.flags & SCOPE.contract))
372 const(char)* s = isParameter() && parent.ident != Id.ensure ? "parameter" : "result";
373 if (!(flag & ModifyFlags.noError))
374 error(loc, "cannot modify %s `%s` in contract", s, toChars());
375 return Modifiable.initialization; // do not report type related errors
380 if (e1 && e1.op == EXP.this_ && isField())
382 VarDeclaration vthis = (cast(ThisExp)e1).var;
383 for (Scope* scx = sc; scx; scx = scx.enclosing)
385 if (scx.func == vthis.parent && (scx.flags & SCOPE.contract))
387 if (!(flag & ModifyFlags.noError))
388 error(loc, "cannot modify parameter `this` in contract");
389 return Modifiable.initialization; // do not report type related errors
394 if (v && (v.isCtorinit() || isField()))
396 // It's only modifiable if inside the right constructor
397 if ((storage_class & (STC.foreach_ | STC.ref_)) == (STC.foreach_ | STC.ref_))
398 return Modifiable.initialization;
399 if (flag & ModifyFlags.fieldAssign)
400 return Modifiable.yes;
401 return modifyFieldVar(loc, sc, v, e1) ? Modifiable.initialization : Modifiable.yes;
403 return Modifiable.yes;
406 override final Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
408 Dsymbol s = Dsymbol.search(loc, ident, flags);
409 if (!s && type)
411 s = type.toDsymbol(_scope);
412 if (s)
413 s = s.search(loc, ident, flags);
415 return s;
418 final bool isStatic() const pure nothrow @nogc @safe
420 return (storage_class & STC.static_) != 0;
423 bool isDelete()
425 return false;
428 bool isDataseg()
430 return false;
433 bool isThreadlocal()
435 return false;
438 bool isCodeseg() const pure nothrow @nogc @safe
440 return false;
443 final bool isFinal() const pure nothrow @nogc @safe
445 return (storage_class & STC.final_) != 0;
448 bool isAbstract()
450 return (storage_class & STC.abstract_) != 0;
453 final bool isConst() const pure nothrow @nogc @safe
455 return (storage_class & STC.const_) != 0;
458 final bool isImmutable() const pure nothrow @nogc @safe
460 return (storage_class & STC.immutable_) != 0;
463 final bool isWild() const pure nothrow @nogc @safe
465 return (storage_class & STC.wild) != 0;
468 final bool isAuto() const pure nothrow @nogc @safe
470 return (storage_class & STC.auto_) != 0;
473 final bool isScope() const pure nothrow @nogc @safe
475 return (storage_class & STC.scope_) != 0;
478 final bool isSynchronized() const pure nothrow @nogc @safe
480 return (storage_class & STC.synchronized_) != 0;
483 final bool isParameter() const pure nothrow @nogc @safe
485 return (storage_class & STC.parameter) != 0;
488 override final bool isDeprecated() const pure nothrow @nogc @safe
490 return (storage_class & STC.deprecated_) != 0;
493 final bool isDisabled() const pure nothrow @nogc @safe
495 return (storage_class & STC.disable) != 0;
498 final bool isOverride() const pure nothrow @nogc @safe
500 return (storage_class & STC.override_) != 0;
503 final bool isResult() const pure nothrow @nogc @safe
505 return (storage_class & STC.result) != 0;
508 final bool isField() const pure nothrow @nogc @safe
510 return (storage_class & STC.field) != 0;
513 final bool isIn() const pure nothrow @nogc @safe
515 return (storage_class & STC.in_) != 0;
518 final bool isOut() const pure nothrow @nogc @safe
520 return (storage_class & STC.out_) != 0;
523 final bool isRef() const pure nothrow @nogc @safe
525 return (storage_class & STC.ref_) != 0;
528 /// Returns: Whether the variable is a reference, annotated with `out` or `ref`
529 final bool isReference() const pure nothrow @nogc @safe
531 return (storage_class & (STC.ref_ | STC.out_)) != 0;
534 final bool isFuture() const pure nothrow @nogc @safe
536 return (storage_class & STC.future) != 0;
539 override final Visibility visible() pure nothrow @nogc @safe
541 return visibility;
544 override final inout(Declaration) isDeclaration() inout pure nothrow @nogc @safe
546 return this;
549 override void accept(Visitor v)
551 v.visit(this);
555 /***********************************************************
557 extern (C++) final class TupleDeclaration : Declaration
559 Objects* objects;
560 bool isexp; // true: expression tuple
561 TypeTuple tupletype; // !=null if this is a type tuple
563 extern (D) this(const ref Loc loc, Identifier ident, Objects* objects)
565 super(loc, ident);
566 this.objects = objects;
569 override TupleDeclaration syntaxCopy(Dsymbol s)
571 assert(0);
574 override const(char)* kind() const
576 return "tuple";
579 override Type getType()
581 /* If this tuple represents a type, return that type
584 //printf("TupleDeclaration::getType() %s\n", toChars());
585 if (isexp)
586 return null;
587 if (!tupletype)
589 /* It's only a type tuple if all the Object's are types
591 for (size_t i = 0; i < objects.dim; i++)
593 RootObject o = (*objects)[i];
594 if (o.dyncast() != DYNCAST.type)
596 //printf("\tnot[%d], %p, %d\n", i, o, o.dyncast());
597 return null;
601 /* We know it's a type tuple, so build the TypeTuple
603 Types* types = cast(Types*)objects;
604 auto args = new Parameters(objects.dim);
605 OutBuffer buf;
606 int hasdeco = 1;
607 for (size_t i = 0; i < types.dim; i++)
609 Type t = (*types)[i];
610 //printf("type = %s\n", t.toChars());
611 version (none)
613 buf.printf("_%s_%d", ident.toChars(), i);
614 const len = buf.offset;
615 const name = buf.extractSlice().ptr;
616 auto id = Identifier.idPool(name, len);
617 auto arg = new Parameter(STC.in_, t, id, null);
619 else
621 auto arg = new Parameter(0, t, null, null, null);
623 (*args)[i] = arg;
624 if (!t.deco)
625 hasdeco = 0;
628 tupletype = new TypeTuple(args);
629 if (hasdeco)
630 return tupletype.typeSemantic(Loc.initial, null);
632 return tupletype;
635 override Dsymbol toAlias2()
637 //printf("TupleDeclaration::toAlias2() '%s' objects = %s\n", toChars(), objects.toChars());
638 for (size_t i = 0; i < objects.dim; i++)
640 RootObject o = (*objects)[i];
641 if (Dsymbol s = isDsymbol(o))
643 s = s.toAlias2();
644 (*objects)[i] = s;
647 return this;
650 override bool needThis()
652 //printf("TupleDeclaration::needThis(%s)\n", toChars());
653 for (size_t i = 0; i < objects.dim; i++)
655 RootObject o = (*objects)[i];
656 if (o.dyncast() == DYNCAST.expression)
658 Expression e = cast(Expression)o;
659 if (e.op == EXP.dSymbol)
661 DsymbolExp ve = cast(DsymbolExp)e;
662 Declaration d = ve.s.isDeclaration();
663 if (d && d.needThis())
665 return true;
670 return false;
673 override inout(TupleDeclaration) isTupleDeclaration() inout
675 return this;
678 override void accept(Visitor v)
680 v.visit(this);
684 /***********************************************************
685 * https://dlang.org/spec/declaration.html#AliasDeclaration
687 extern (C++) final class AliasDeclaration : Declaration
689 Dsymbol aliassym; // alias ident = aliassym;
691 Dsymbol overnext; // next in overload list
692 Dsymbol _import; // !=null if unresolved internal alias for selective import
694 extern (D) this(const ref Loc loc, Identifier ident, Type type)
696 super(loc, ident);
697 //printf("AliasDeclaration(id = '%s', type = %p)\n", id.toChars(), type);
698 //printf("type = '%s'\n", type.toChars());
699 this.type = type;
700 assert(type);
703 extern (D) this(const ref Loc loc, Identifier ident, Dsymbol s)
705 super(loc, ident);
706 //printf("AliasDeclaration(id = '%s', s = %p)\n", id.toChars(), s);
707 assert(s != this);
708 this.aliassym = s;
709 assert(s);
712 static AliasDeclaration create(const ref Loc loc, Identifier id, Type type)
714 return new AliasDeclaration(loc, id, type);
717 override AliasDeclaration syntaxCopy(Dsymbol s)
719 //printf("AliasDeclaration::syntaxCopy()\n");
720 assert(!s);
721 AliasDeclaration sa = type ? new AliasDeclaration(loc, ident, type.syntaxCopy()) : new AliasDeclaration(loc, ident, aliassym.syntaxCopy(null));
722 sa.comment = comment;
723 sa.storage_class = storage_class;
724 return sa;
727 override bool overloadInsert(Dsymbol s)
729 //printf("[%s] AliasDeclaration::overloadInsert('%s') s = %s %s @ [%s]\n",
730 // loc.toChars(), toChars(), s.kind(), s.toChars(), s.loc.toChars());
732 /** Aliases aren't overloadable themselves, but if their Aliasee is
733 * overloadable they are converted to an overloadable Alias (either
734 * FuncAliasDeclaration or OverDeclaration).
736 * This is done by moving the Aliasee into such an overloadable alias
737 * which is then used to replace the existing Aliasee. The original
738 * Alias (_this_) remains a useless shell.
740 * This is a horrible mess. It was probably done to avoid replacing
741 * existing AST nodes and references, but it needs a major
742 * simplification b/c it's too complex to maintain.
744 * A simpler approach might be to merge any colliding symbols into a
745 * simple Overload class (an array) and then later have that resolve
746 * all collisions.
748 if (semanticRun >= PASS.semanticdone)
750 /* Semantic analysis is already finished, and the aliased entity
751 * is not overloadable.
753 if (type)
754 return false;
756 /* When s is added in member scope by static if, mixin("code") or others,
757 * aliassym is determined already. See the case in: test/compilable/test61.d
759 auto sa = aliassym.toAlias();
761 if (auto td = s.toAlias().isTemplateDeclaration())
762 s = td.funcroot ? td.funcroot : td;
764 if (auto fd = sa.isFuncDeclaration())
766 auto fa = new FuncAliasDeclaration(ident, fd);
767 fa.visibility = visibility;
768 fa.parent = parent;
769 aliassym = fa;
770 return aliassym.overloadInsert(s);
772 if (auto td = sa.isTemplateDeclaration())
774 auto od = new OverDeclaration(ident, td.funcroot ? td.funcroot : td);
775 od.visibility = visibility;
776 od.parent = parent;
777 aliassym = od;
778 return aliassym.overloadInsert(s);
780 if (auto od = sa.isOverDeclaration())
782 if (sa.ident != ident || sa.parent != parent)
784 od = new OverDeclaration(ident, od);
785 od.visibility = visibility;
786 od.parent = parent;
787 aliassym = od;
789 return od.overloadInsert(s);
791 if (auto os = sa.isOverloadSet())
793 if (sa.ident != ident || sa.parent != parent)
795 os = new OverloadSet(ident, os);
796 // TODO: visibility is lost here b/c OverloadSets have no visibility attribute
797 // Might no be a practical issue, b/c the code below fails to resolve the overload anyhow.
798 // ----
799 // module os1;
800 // import a, b;
801 // private alias merged = foo; // private alias to overload set of a.foo and b.foo
802 // ----
803 // module os2;
804 // import a, b;
805 // public alias merged = bar; // public alias to overload set of a.bar and b.bar
806 // ----
807 // module bug;
808 // import os1, os2;
809 // void test() { merged(123); } // should only look at os2.merged
811 // os.visibility = visibility;
812 os.parent = parent;
813 aliassym = os;
815 os.push(s);
816 return true;
818 return false;
821 /* Don't know yet what the aliased symbol is, so assume it can
822 * be overloaded and check later for correctness.
824 if (overnext)
825 return overnext.overloadInsert(s);
826 if (s is this)
827 return true;
828 overnext = s;
829 return true;
832 override const(char)* kind() const
834 return "alias";
837 override Type getType()
839 if (type)
840 return type;
841 return toAlias().getType();
844 override Dsymbol toAlias()
846 //printf("[%s] AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s', inuse = %d)\n",
847 // loc.toChars(), toChars(), this, aliassym, aliassym ? aliassym.kind() : "", inuse);
848 assert(this != aliassym);
849 //static int count; if (++count == 10) *(char*)0=0;
851 // Reading the AliasDeclaration
852 if (!(adFlags & ignoreRead))
853 adFlags |= wasRead; // can never assign to this AliasDeclaration again
855 if (inuse == 1 && type && _scope)
857 inuse = 2;
858 uint olderrors = global.errors;
859 Dsymbol s = type.toDsymbol(_scope);
860 //printf("[%s] type = %s, s = %p, this = %p\n", loc.toChars(), type.toChars(), s, this);
861 if (global.errors != olderrors)
862 goto Lerr;
863 if (s)
865 s = s.toAlias();
866 if (global.errors != olderrors)
867 goto Lerr;
868 aliassym = s;
869 inuse = 0;
871 else
873 Type t = type.typeSemantic(loc, _scope);
874 if (t.ty == Terror)
875 goto Lerr;
876 if (global.errors != olderrors)
877 goto Lerr;
878 //printf("t = %s\n", t.toChars());
879 inuse = 0;
882 if (inuse)
884 error("recursive alias declaration");
886 Lerr:
887 // Avoid breaking "recursive alias" state during errors gagged
888 if (global.gag)
889 return this;
890 aliassym = new AliasDeclaration(loc, ident, Type.terror);
891 type = Type.terror;
892 return aliassym;
895 if (semanticRun >= PASS.semanticdone)
897 // semantic is already done.
899 // Do not see aliassym !is null, because of lambda aliases.
901 // Do not see type.deco !is null, even so "alias T = const int;` needs
902 // semantic analysis to take the storage class `const` as type qualifier.
904 else
906 if (_import && _import._scope)
908 /* If this is an internal alias for selective/renamed import,
909 * load the module first.
911 _import.dsymbolSemantic(null);
913 if (_scope)
915 aliasSemantic(this, _scope);
919 inuse = 1;
920 Dsymbol s = aliassym ? aliassym.toAlias() : this;
921 inuse = 0;
922 return s;
925 override Dsymbol toAlias2()
927 if (inuse)
929 error("recursive alias declaration");
930 return this;
932 inuse = 1;
933 Dsymbol s = aliassym ? aliassym.toAlias2() : this;
934 inuse = 0;
935 return s;
938 override bool isOverloadable() const
940 // assume overloadable until alias is resolved
941 return semanticRun < PASS.semanticdone ||
942 aliassym && aliassym.isOverloadable();
945 override inout(AliasDeclaration) isAliasDeclaration() inout
947 return this;
950 /** Returns: `true` if this instance was created to make a template parameter
951 visible in the scope of a template body, `false` otherwise */
952 extern (D) bool isAliasedTemplateParameter() const
954 return !!(storage_class & STC.templateparameter);
957 override void accept(Visitor v)
959 v.visit(this);
963 /***********************************************************
965 extern (C++) final class OverDeclaration : Declaration
967 Dsymbol overnext; // next in overload list
968 Dsymbol aliassym;
970 extern (D) this(Identifier ident, Dsymbol s)
972 super(ident);
973 this.aliassym = s;
976 override const(char)* kind() const
978 return "overload alias"; // todo
981 override bool equals(const RootObject o) const
983 if (this == o)
984 return true;
986 auto s = isDsymbol(o);
987 if (!s)
988 return false;
990 if (auto od2 = s.isOverDeclaration())
991 return this.aliassym.equals(od2.aliassym);
992 return this.aliassym == s;
995 override bool overloadInsert(Dsymbol s)
997 //printf("OverDeclaration::overloadInsert('%s') aliassym = %p, overnext = %p\n", s.toChars(), aliassym, overnext);
998 if (overnext)
999 return overnext.overloadInsert(s);
1000 if (s == this)
1001 return true;
1002 overnext = s;
1003 return true;
1006 override bool isOverloadable() const
1008 return true;
1011 Dsymbol isUnique()
1013 Dsymbol result = null;
1014 overloadApply(aliassym, (Dsymbol s)
1016 if (result)
1018 result = null;
1019 return 1; // ambiguous, done
1021 else
1023 result = s;
1024 return 0;
1027 return result;
1030 override inout(OverDeclaration) isOverDeclaration() inout
1032 return this;
1035 override void accept(Visitor v)
1037 v.visit(this);
1041 /***********************************************************
1043 extern (C++) class VarDeclaration : Declaration
1045 Initializer _init;
1046 FuncDeclarations nestedrefs; // referenced by these lexically nested functions
1047 Dsymbol aliassym; // if redone as alias to another symbol
1048 VarDeclaration lastVar; // Linked list of variables for goto-skips-init detection
1049 Expression edtor; // if !=null, does the destruction of the variable
1050 IntRange* range; // if !=null, the variable is known to be within the range
1051 VarDeclarations* maybes; // STC.maybescope variables that are assigned to this STC.maybescope variable
1053 uint endlinnum; // line number of end of scope that this var lives in
1054 uint offset;
1055 uint sequenceNumber; // order the variables are declared
1056 structalign_t alignment;
1058 // When interpreting, these point to the value (NULL if value not determinable)
1059 // The index of this variable on the CTFE stack, AdrOnStackNone if not allocated
1060 enum AdrOnStackNone = ~0u;
1061 uint ctfeAdrOnStack;
1063 // `bool` fields that are compacted into bit fields in a string mixin
1064 private extern (D) static struct BitFields
1066 bool isargptr; /// if parameter that _argptr points to
1067 bool ctorinit; /// it has been initialized in a ctor
1068 bool iscatchvar; /// this is the exception object variable in catch() clause
1069 bool isowner; /// this is an Owner, despite it being `scope`
1070 bool setInCtorOnly; /// field can only be set in a constructor, as it is const or immutable
1072 /// It is a class that was allocated on the stack
1074 /// This means the var is not rebindable once assigned,
1075 /// and the destructor gets run when it goes out of scope
1076 bool onstack;
1078 bool overlapped; /// if it is a field and has overlapping
1079 bool overlapUnsafe; /// if it is an overlapping field and the overlaps are unsafe
1080 bool doNotInferScope; /// do not infer 'scope' for this variable
1081 bool doNotInferReturn; /// do not infer 'return' for this variable
1083 bool isArgDtorVar; /// temporary created to handle scope destruction of a function argument
1086 import dmd.common.bitfields : generateBitFields;
1087 mixin(generateBitFields!(BitFields, ushort));
1089 byte canassign; // it can be assigned to
1090 ubyte isdataseg; // private data for isDataseg 0 unset, 1 true, 2 false
1092 final extern (D) this(const ref Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.undefined_)
1095 assert(ident);
1099 //printf("VarDeclaration('%s')\n", ident.toChars());
1100 super(loc, ident);
1101 debug
1103 if (!type && !_init)
1105 //printf("VarDeclaration('%s')\n", ident.toChars());
1106 //*(char*)0=0;
1110 assert(type || _init);
1111 this.type = type;
1112 this._init = _init;
1113 ctfeAdrOnStack = AdrOnStackNone;
1114 this.storage_class = storage_class;
1117 static VarDeclaration create(const ref Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.undefined_)
1119 return new VarDeclaration(loc, type, ident, _init, storage_class);
1122 override VarDeclaration syntaxCopy(Dsymbol s)
1124 //printf("VarDeclaration::syntaxCopy(%s)\n", toChars());
1125 assert(!s);
1126 auto v = new VarDeclaration(loc, type ? type.syntaxCopy() : null, ident, _init ? _init.syntaxCopy() : null, storage_class);
1127 v.comment = comment;
1128 return v;
1131 override void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion)
1133 //printf("VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars());
1135 if (aliassym)
1137 // If this variable was really a tuple, set the offsets for the tuple fields
1138 TupleDeclaration v2 = aliassym.isTupleDeclaration();
1139 assert(v2);
1140 for (size_t i = 0; i < v2.objects.dim; i++)
1142 RootObject o = (*v2.objects)[i];
1143 assert(o.dyncast() == DYNCAST.expression);
1144 Expression e = cast(Expression)o;
1145 assert(e.op == EXP.dSymbol);
1146 DsymbolExp se = cast(DsymbolExp)e;
1147 se.s.setFieldOffset(ad, fieldState, isunion);
1149 return;
1152 if (!isField())
1153 return;
1154 assert(!(storage_class & (STC.static_ | STC.extern_ | STC.parameter)));
1156 //printf("+VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars());
1158 /* Fields that are tuples appear both as part of TupleDeclarations and
1159 * as members. That means ignore them if they are already a field.
1161 if (offset)
1163 // already a field
1164 fieldState.offset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613
1165 return;
1167 for (size_t i = 0; i < ad.fields.dim; i++)
1169 if (ad.fields[i] == this)
1171 // already a field
1172 fieldState.offset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613
1173 return;
1177 // Check for forward referenced types which will fail the size() call
1178 Type t = type.toBasetype();
1179 if (storage_class & STC.ref_)
1181 // References are the size of a pointer
1182 t = Type.tvoidptr;
1184 Type tv = t.baseElemOf();
1185 if (tv.ty == Tstruct)
1187 auto ts = cast(TypeStruct)tv;
1188 assert(ts.sym != ad); // already checked in ad.determineFields()
1189 if (!ts.sym.determineSize(loc))
1191 type = Type.terror;
1192 errors = true;
1193 return;
1197 // List in ad.fields. Even if the type is error, it's necessary to avoid
1198 // pointless error diagnostic "more initializers than fields" on struct literal.
1199 ad.fields.push(this);
1201 if (t.ty == Terror)
1202 return;
1204 /* If coming after a bit field in progress,
1205 * advance past the field
1207 fieldState.inFlight = false;
1209 const sz = t.size(loc);
1210 assert(sz != SIZE_INVALID && sz < uint.max);
1211 uint memsize = cast(uint)sz; // size of member
1212 uint memalignsize = target.fieldalign(t); // size of member for alignment purposes
1213 offset = AggregateDeclaration.placeField(
1214 &fieldState.offset,
1215 memsize, memalignsize, alignment,
1216 &ad.structsize, &ad.alignsize,
1217 isunion);
1219 //printf("\t%s: memalignsize = %d\n", toChars(), memalignsize);
1220 //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize);
1223 override const(char)* kind() const
1225 return "variable";
1228 override final inout(AggregateDeclaration) isThis() inout
1230 if (!(storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.templateparameter | STC.gshared | STC.ctfe)))
1232 /* The casting is necessary because `s = s.parent` is otherwise rejected
1234 for (auto s = cast(Dsymbol)this; s; s = s.parent)
1236 auto ad = (cast(inout)s).isMember();
1237 if (ad)
1238 return ad;
1239 if (!s.parent || !s.parent.isTemplateMixin())
1240 break;
1243 return null;
1246 override final bool needThis()
1248 //printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class);
1249 return isField();
1252 override final bool isExport() const
1254 return visibility.kind == Visibility.Kind.export_;
1257 override final bool isImportedSymbol() const
1259 if (visibility.kind == Visibility.Kind.export_ && !_init && (storage_class & STC.static_ || parent.isModule()))
1260 return true;
1261 return false;
1264 final bool isCtorinit() const pure nothrow @nogc @safe
1266 return setInCtorOnly;
1269 /*******************************
1270 * Does symbol go into data segment?
1271 * Includes extern variables.
1273 override final bool isDataseg()
1275 version (none)
1277 printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars());
1278 printf("%llx, isModule: %p, isTemplateInstance: %p, isNspace: %p\n",
1279 storage_class & (STC.static_ | STC.const_), parent.isModule(), parent.isTemplateInstance(), parent.isNspace());
1280 printf("parent = '%s'\n", parent.toChars());
1283 if (isdataseg == 0) // the value is not cached
1285 isdataseg = 2; // The Variables does not go into the datasegment
1287 if (!canTakeAddressOf())
1289 return false;
1292 Dsymbol parent = toParent();
1293 if (!parent && !(storage_class & STC.static_))
1295 error("forward referenced");
1296 type = Type.terror;
1298 else if (storage_class & (STC.static_ | STC.extern_ | STC.gshared) ||
1299 parent.isModule() || parent.isTemplateInstance() || parent.isNspace())
1301 assert(!isParameter() && !isResult());
1302 isdataseg = 1; // It is in the DataSegment
1306 return (isdataseg == 1);
1308 /************************************
1309 * Does symbol go into thread local storage?
1311 override final bool isThreadlocal()
1313 //printf("VarDeclaration::isThreadlocal(%p, '%s')\n", this, toChars());
1314 /* Data defaults to being thread-local. It is not thread-local
1315 * if it is immutable, const or shared.
1317 bool i = isDataseg() && !(storage_class & (STC.immutable_ | STC.const_ | STC.shared_ | STC.gshared));
1318 //printf("\treturn %d\n", i);
1319 return i;
1322 /********************************************
1323 * Can variable be read and written by CTFE?
1325 final bool isCTFE()
1327 return (storage_class & STC.ctfe) != 0; // || !isDataseg();
1330 final bool isOverlappedWith(VarDeclaration v)
1332 const vsz = v.type.size();
1333 const tsz = type.size();
1334 assert(vsz != SIZE_INVALID && tsz != SIZE_INVALID);
1336 // Overlap is checked by comparing bit offsets
1337 auto bitoffset = offset * 8;
1338 auto vbitoffset = v.offset * 8;
1340 // Bitsize of types are overridden by any bit-field widths.
1341 ulong tbitsize = void;
1342 if (auto bf = isBitFieldDeclaration())
1344 bitoffset += bf.bitOffset;
1345 tbitsize = bf.fieldWidth;
1347 else
1348 tbitsize = tsz * 8;
1350 ulong vbitsize = void;
1351 if (auto vbf = v.isBitFieldDeclaration())
1353 vbitoffset += vbf.bitOffset;
1354 vbitsize = vbf.fieldWidth;
1356 else
1357 vbitsize = vsz * 8;
1359 return bitoffset < vbitoffset + vbitsize &&
1360 vbitoffset < bitoffset + tbitsize;
1363 override final bool hasPointers()
1365 //printf("VarDeclaration::hasPointers() %s, ty = %d\n", toChars(), type.ty);
1366 return (!isDataseg() && type.hasPointers());
1369 /*************************************
1370 * Return true if we can take the address of this variable.
1372 final bool canTakeAddressOf()
1374 return !(storage_class & STC.manifest);
1377 /******************************************
1378 * Return true if variable needs to call the destructor.
1380 final bool needsScopeDtor()
1382 //printf("VarDeclaration::needsScopeDtor() %s\n", toChars());
1383 return edtor && !(storage_class & STC.nodtor);
1386 /******************************************
1387 * If a variable has a scope destructor call, return call for it.
1388 * Otherwise, return NULL.
1390 extern (D) final Expression callScopeDtor(Scope* sc)
1392 //printf("VarDeclaration::callScopeDtor() %s\n", toChars());
1394 // Destruction of STC.field's is handled by buildDtor()
1395 if (storage_class & (STC.nodtor | STC.ref_ | STC.out_ | STC.field))
1397 return null;
1400 if (iscatchvar)
1401 return null; // destructor is built by `void semantic(Catch c, Scope* sc)`, not here
1403 Expression e = null;
1404 // Destructors for structs and arrays of structs
1405 Type tv = type.baseElemOf();
1406 if (tv.ty == Tstruct)
1408 StructDeclaration sd = (cast(TypeStruct)tv).sym;
1409 if (!sd.dtor || sd.errors)
1410 return null;
1412 const sz = type.size();
1413 assert(sz != SIZE_INVALID);
1414 if (!sz)
1415 return null;
1417 if (type.toBasetype().ty == Tstruct)
1419 // v.__xdtor()
1420 e = new VarExp(loc, this);
1422 /* This is a hack so we can call destructors on const/immutable objects.
1423 * Need to add things like "const ~this()" and "immutable ~this()" to
1424 * fix properly.
1426 e.type = e.type.mutableOf();
1428 // Enable calling destructors on shared objects.
1429 // The destructor is always a single, non-overloaded function,
1430 // and must serve both shared and non-shared objects.
1431 e.type = e.type.unSharedOf;
1433 e = new DotVarExp(loc, e, sd.dtor, false);
1434 e = new CallExp(loc, e);
1436 else
1438 // __ArrayDtor(v[0 .. n])
1439 e = new VarExp(loc, this);
1441 const sdsz = sd.type.size();
1442 assert(sdsz != SIZE_INVALID && sdsz != 0);
1443 const n = sz / sdsz;
1444 e = new SliceExp(loc, e, new IntegerExp(loc, 0, Type.tsize_t), new IntegerExp(loc, n, Type.tsize_t));
1446 // Prevent redundant bounds check
1447 (cast(SliceExp)e).upperIsInBounds = true;
1448 (cast(SliceExp)e).lowerIsLessThanUpper = true;
1450 // This is a hack so we can call destructors on const/immutable objects.
1451 e.type = sd.type.arrayOf();
1453 e = new CallExp(loc, new IdentifierExp(loc, Id.__ArrayDtor), e);
1455 return e;
1457 // Destructors for classes
1458 if (storage_class & (STC.auto_ | STC.scope_) && !(storage_class & STC.parameter))
1460 for (ClassDeclaration cd = type.isClassHandle(); cd; cd = cd.baseClass)
1462 /* We can do better if there's a way with onstack
1463 * classes to determine if there's no way the monitor
1464 * could be set.
1466 //if (cd.isInterfaceDeclaration())
1467 // error("interface `%s` cannot be scope", cd.toChars());
1469 if (onstack) // if any destructors
1471 // delete'ing C++ classes crashes (and delete is deprecated anyway)
1472 if (cd.classKind == ClassKind.cpp)
1474 // Don't call non-existant dtor
1475 if (!cd.dtor)
1476 break;
1478 e = new VarExp(loc, this);
1479 e.type = e.type.mutableOf().unSharedOf(); // Hack for mutable ctor on immutable instances
1480 e = new DotVarExp(loc, e, cd.dtor, false);
1481 e = new CallExp(loc, e);
1482 break;
1485 // delete this;
1486 Expression ec;
1487 ec = new VarExp(loc, this);
1488 e = new DeleteExp(loc, ec, true);
1489 e.type = Type.tvoid;
1490 break;
1494 return e;
1497 /*******************************************
1498 * If variable has a constant expression initializer, get it.
1499 * Otherwise, return null.
1501 extern (D) final Expression getConstInitializer(bool needFullType = true)
1503 assert(type && _init);
1505 // Ungag errors when not speculative
1506 uint oldgag = global.gag;
1507 if (global.gag)
1509 Dsymbol sym = toParent().isAggregateDeclaration();
1510 if (sym && !sym.isSpeculative())
1511 global.gag = 0;
1514 if (_scope)
1516 inuse++;
1517 _init = _init.initializerSemantic(_scope, type, INITinterpret);
1518 _scope = null;
1519 inuse--;
1522 Expression e = _init.initializerToExpression(needFullType ? type : null);
1523 global.gag = oldgag;
1524 return e;
1527 /*******************************************
1528 * Helper function for the expansion of manifest constant.
1530 extern (D) final Expression expandInitializer(Loc loc)
1532 assert((storage_class & STC.manifest) && _init);
1534 auto e = getConstInitializer();
1535 if (!e)
1537 .error(loc, "cannot make expression out of initializer for `%s`", toChars());
1538 return ErrorExp.get();
1541 e = e.copy();
1542 e.loc = loc; // for better error message
1543 return e;
1546 override final void checkCtorConstInit()
1548 version (none)
1550 /* doesn't work if more than one static ctor */
1551 if (ctorinit == 0 && isCtorinit() && !isField())
1552 error("missing initializer in static constructor for const variable");
1556 /************************************
1557 * Check to see if this variable is actually in an enclosing function
1558 * rather than the current one.
1559 * Update nestedrefs[], closureVars[] and outerVars[].
1560 * Returns: true if error occurs.
1562 extern (D) final bool checkNestedReference(Scope* sc, Loc loc)
1564 //printf("VarDeclaration::checkNestedReference() %s\n", toChars());
1565 if (sc.intypeof == 1 || (sc.flags & SCOPE.ctfe))
1566 return false;
1567 if (!parent || parent == sc.parent)
1568 return false;
1569 if (isDataseg() || (storage_class & STC.manifest))
1570 return false;
1572 // The current function
1573 FuncDeclaration fdthis = sc.parent.isFuncDeclaration();
1574 if (!fdthis)
1575 return false; // out of function scope
1577 Dsymbol p = toParent2();
1579 // Function literals from fdthis to p must be delegates
1580 ensureStaticLinkTo(fdthis, p);
1582 // The function that this variable is in
1583 FuncDeclaration fdv = p.isFuncDeclaration();
1584 if (!fdv || fdv == fdthis)
1585 return false;
1587 // Add fdthis to nestedrefs[] if not already there
1588 if (!nestedrefs.contains(fdthis))
1589 nestedrefs.push(fdthis);
1591 //printf("\tfdv = %s\n", fdv.toChars());
1592 //printf("\tfdthis = %s\n", fdthis.toChars());
1593 if (loc.isValid())
1595 if (fdthis.getLevelAndCheck(loc, sc, fdv, this) == fdthis.LevelError)
1596 return true;
1599 // Add this VarDeclaration to fdv.closureVars[] if not already there
1600 if (!sc.intypeof && !(sc.flags & SCOPE.compile) &&
1601 // https://issues.dlang.org/show_bug.cgi?id=17605
1602 (fdv.flags & FUNCFLAG.compileTimeOnly || !(fdthis.flags & FUNCFLAG.compileTimeOnly))
1605 if (!fdv.closureVars.contains(this))
1606 fdv.closureVars.push(this);
1609 if (!fdthis.outerVars.contains(this))
1610 fdthis.outerVars.push(this);
1612 //printf("fdthis is %s\n", fdthis.toChars());
1613 //printf("var %s in function %s is nested ref\n", toChars(), fdv.toChars());
1614 // __dollar creates problems because it isn't a real variable
1615 // https://issues.dlang.org/show_bug.cgi?id=3326
1616 if (ident == Id.dollar)
1618 .error(loc, "cannnot use `$` inside a function literal");
1619 return true;
1621 if (ident == Id.withSym) // https://issues.dlang.org/show_bug.cgi?id=1759
1623 ExpInitializer ez = _init.isExpInitializer();
1624 assert(ez);
1625 Expression e = ez.exp;
1626 if (e.op == EXP.construct || e.op == EXP.blit)
1627 e = (cast(AssignExp)e).e2;
1628 return lambdaCheckForNestedRef(e, sc);
1631 return false;
1634 override final Dsymbol toAlias()
1636 //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym);
1637 if ((!type || !type.deco) && _scope)
1638 dsymbolSemantic(this, _scope);
1640 assert(this != aliassym);
1641 Dsymbol s = aliassym ? aliassym.toAlias() : this;
1642 return s;
1645 // Eliminate need for dynamic_cast
1646 override final inout(VarDeclaration) isVarDeclaration() inout
1648 return this;
1651 override void accept(Visitor v)
1653 v.visit(this);
1657 /*******************************************************
1658 * C11 6.7.2.1-4 bit fields
1660 extern (C++) class BitFieldDeclaration : VarDeclaration
1662 Expression width;
1664 uint fieldWidth;
1665 uint bitOffset;
1667 final extern (D) this(const ref Loc loc, Type type, Identifier ident, Expression width)
1669 super(loc, type, ident, null);
1671 this.width = width;
1672 this.storage_class |= STC.field;
1675 override BitFieldDeclaration syntaxCopy(Dsymbol s)
1677 //printf("BitFieldDeclaration::syntaxCopy(%s)\n", toChars());
1678 assert(!s);
1679 auto bf = new BitFieldDeclaration(loc, type ? type.syntaxCopy() : null, ident, width.syntaxCopy());
1680 bf.comment = comment;
1681 return bf;
1684 override final inout(BitFieldDeclaration) isBitFieldDeclaration() inout
1686 return this;
1689 override void accept(Visitor v)
1691 v.visit(this);
1694 override final void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion)
1696 //printf("BitFieldDeclaration::setFieldOffset(ad: %s, field: %s)\n", ad.toChars(), toChars());
1697 static void print(const ref FieldState fieldState)
1699 printf("FieldState.offset = %d bytes\n", fieldState.offset);
1700 printf(" .fieldOffset = %d bytes\n", fieldState.fieldOffset);
1701 printf(" .bitOffset = %d bits\n", fieldState.bitOffset);
1702 printf(" .fieldSize = %d bytes\n", fieldState.fieldSize);
1703 printf(" .inFlight = %d\n\n", fieldState.inFlight);
1705 //print(fieldState);
1707 Type t = type.toBasetype();
1708 const bool anon = isAnonymous();
1710 // List in ad.fields. Even if the type is error, it's necessary to avoid
1711 // pointless error diagnostic "more initializers than fields" on struct literal.
1712 if (!anon)
1713 ad.fields.push(this);
1715 if (t.ty == Terror)
1716 return;
1718 const sz = t.size(loc);
1719 assert(sz != SIZE_INVALID && sz < uint.max);
1720 uint memsize = cast(uint)sz; // size of member
1721 uint memalignsize = target.fieldalign(t); // size of member for alignment purposes
1723 if (fieldWidth == 0 && !anon)
1724 error(loc, "named bit fields cannot have 0 width");
1725 if (fieldWidth > memsize * 8)
1726 error(loc, "bit field width %d is larger than type", fieldWidth);
1728 const style = target.c.bitFieldStyle;
1730 void startNewField()
1732 uint alignsize;
1733 if (style == TargetC.BitFieldStyle.Gcc_Clang)
1735 if (fieldWidth > 32)
1736 alignsize = memalignsize;
1737 else if (fieldWidth > 16)
1738 alignsize = 4;
1739 else if (fieldWidth > 8)
1740 alignsize = 2;
1741 else
1742 alignsize = 1;
1744 else
1745 alignsize = memsize; // not memalignsize
1747 uint dummy;
1748 offset = AggregateDeclaration.placeField(
1749 &fieldState.offset,
1750 memsize, alignsize, alignment,
1751 &ad.structsize,
1752 (anon && style == TargetC.BitFieldStyle.Gcc_Clang) ? &dummy : &ad.alignsize,
1753 isunion);
1755 fieldState.inFlight = true;
1756 fieldState.fieldOffset = offset;
1757 fieldState.bitOffset = 0;
1758 fieldState.fieldSize = memsize;
1761 if (style == TargetC.BitFieldStyle.Gcc_Clang)
1763 if (fieldWidth == 0)
1765 if (!isunion)
1767 // Use type of zero width field to align to next field
1768 fieldState.offset = (fieldState.offset + memalignsize - 1) & ~(memalignsize - 1);
1769 ad.structsize = fieldState.offset;
1772 fieldState.inFlight = false;
1773 return;
1776 if (ad.alignsize == 0)
1777 ad.alignsize = 1;
1778 if (!anon &&
1779 ad.alignsize < memalignsize)
1780 ad.alignsize = memalignsize;
1782 else if (style == TargetC.BitFieldStyle.MS)
1784 if (ad.alignsize == 0)
1785 ad.alignsize = 1;
1786 if (fieldWidth == 0)
1788 if (fieldState.inFlight && !isunion)
1790 // documentation says align to next int
1791 //const alsz = cast(uint)Type.tint32.size();
1792 const alsz = memsize; // but it really does this
1793 fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1);
1794 ad.structsize = fieldState.offset;
1797 fieldState.inFlight = false;
1798 return;
1801 else if (style == TargetC.BitFieldStyle.DM)
1803 if (anon && fieldWidth && (!fieldState.inFlight || fieldState.bitOffset == 0))
1804 return; // this probably should be a bug in DMC
1805 if (ad.alignsize == 0)
1806 ad.alignsize = 1;
1807 if (fieldWidth == 0)
1809 if (fieldState.inFlight && !isunion)
1811 const alsz = memsize;
1812 fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1);
1813 ad.structsize = fieldState.offset;
1816 fieldState.inFlight = false;
1817 return;
1821 if (!fieldState.inFlight)
1823 startNewField();
1825 else if (style == TargetC.BitFieldStyle.Gcc_Clang)
1827 if (fieldState.bitOffset + fieldWidth > memsize * 8)
1829 //printf("start1 fieldState.bitOffset:%u fieldWidth:%u memsize:%u\n", fieldState.bitOffset, fieldWidth, memsize);
1830 startNewField();
1832 else
1834 // if alignment boundary is crossed
1835 uint start = fieldState.fieldOffset * 8 + fieldState.bitOffset;
1836 uint end = start + fieldWidth;
1837 //printf("%s start: %d end: %d memalignsize: %d\n", ad.toChars(), start, end, memalignsize);
1838 if (start / (memalignsize * 8) != (end - 1) / (memalignsize * 8))
1840 //printf("alignment is crossed\n");
1841 startNewField();
1845 else if (style == TargetC.BitFieldStyle.DM ||
1846 style == TargetC.BitFieldStyle.MS)
1848 if (memsize != fieldState.fieldSize ||
1849 fieldState.bitOffset + fieldWidth > fieldState.fieldSize * 8)
1851 startNewField();
1854 else
1855 assert(0);
1857 offset = fieldState.fieldOffset;
1858 bitOffset = fieldState.bitOffset;
1860 const pastField = bitOffset + fieldWidth;
1861 if (style == TargetC.BitFieldStyle.Gcc_Clang)
1863 auto size = (pastField + 7) / 8;
1864 fieldState.fieldSize = size;
1865 //printf(" offset: %d, size: %d\n", offset, size);
1866 ad.structsize = offset + size;
1868 else
1869 fieldState.fieldSize = memsize;
1870 //printf("at end: ad.structsize = %d\n", cast(int)ad.structsize);
1871 //print(fieldState);
1873 if (!isunion)
1875 fieldState.offset = offset + fieldState.fieldSize;
1876 fieldState.bitOffset = pastField;
1879 //printf("\t%s: memalignsize = %d\n", toChars(), memalignsize);
1880 //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize);
1884 /***********************************************************
1885 * This is a shell around a back end symbol
1887 extern (C++) final class SymbolDeclaration : Declaration
1889 AggregateDeclaration dsym;
1891 extern (D) this(const ref Loc loc, AggregateDeclaration dsym)
1893 super(loc, dsym.ident);
1894 this.dsym = dsym;
1895 storage_class |= STC.const_;
1898 // Eliminate need for dynamic_cast
1899 override inout(SymbolDeclaration) isSymbolDeclaration() inout
1901 return this;
1904 override void accept(Visitor v)
1906 v.visit(this);
1910 /***********************************************************
1912 extern (C++) class TypeInfoDeclaration : VarDeclaration
1914 Type tinfo;
1916 final extern (D) this(Type tinfo)
1918 super(Loc.initial, Type.dtypeinfo.type, tinfo.getTypeInfoIdent(), null);
1919 this.tinfo = tinfo;
1920 storage_class = STC.static_ | STC.gshared;
1921 visibility = Visibility(Visibility.Kind.public_);
1922 linkage = LINK.c;
1923 alignment.set(target.ptrsize);
1926 static TypeInfoDeclaration create(Type tinfo)
1928 return new TypeInfoDeclaration(tinfo);
1931 override final TypeInfoDeclaration syntaxCopy(Dsymbol s)
1933 assert(0); // should never be produced by syntax
1936 override final const(char)* toChars() const
1938 //printf("TypeInfoDeclaration::toChars() tinfo = %s\n", tinfo.toChars());
1939 OutBuffer buf;
1940 buf.writestring("typeid(");
1941 buf.writestring(tinfo.toChars());
1942 buf.writeByte(')');
1943 return buf.extractChars();
1946 override final inout(TypeInfoDeclaration) isTypeInfoDeclaration() inout @nogc nothrow pure @safe
1948 return this;
1951 override void accept(Visitor v)
1953 v.visit(this);
1957 /***********************************************************
1959 extern (C++) final class TypeInfoStructDeclaration : TypeInfoDeclaration
1961 extern (D) this(Type tinfo)
1963 super(tinfo);
1964 if (!Type.typeinfostruct)
1966 ObjectNotFound(Id.TypeInfo_Struct);
1968 type = Type.typeinfostruct.type;
1971 static TypeInfoStructDeclaration create(Type tinfo)
1973 return new TypeInfoStructDeclaration(tinfo);
1976 override void accept(Visitor v)
1978 v.visit(this);
1982 /***********************************************************
1984 extern (C++) final class TypeInfoClassDeclaration : TypeInfoDeclaration
1986 extern (D) this(Type tinfo)
1988 super(tinfo);
1989 if (!Type.typeinfoclass)
1991 ObjectNotFound(Id.TypeInfo_Class);
1993 type = Type.typeinfoclass.type;
1996 static TypeInfoClassDeclaration create(Type tinfo)
1998 return new TypeInfoClassDeclaration(tinfo);
2001 override void accept(Visitor v)
2003 v.visit(this);
2007 /***********************************************************
2009 extern (C++) final class TypeInfoInterfaceDeclaration : TypeInfoDeclaration
2011 extern (D) this(Type tinfo)
2013 super(tinfo);
2014 if (!Type.typeinfointerface)
2016 ObjectNotFound(Id.TypeInfo_Interface);
2018 type = Type.typeinfointerface.type;
2021 static TypeInfoInterfaceDeclaration create(Type tinfo)
2023 return new TypeInfoInterfaceDeclaration(tinfo);
2026 override void accept(Visitor v)
2028 v.visit(this);
2032 /***********************************************************
2034 extern (C++) final class TypeInfoPointerDeclaration : TypeInfoDeclaration
2036 extern (D) this(Type tinfo)
2038 super(tinfo);
2039 if (!Type.typeinfopointer)
2041 ObjectNotFound(Id.TypeInfo_Pointer);
2043 type = Type.typeinfopointer.type;
2046 static TypeInfoPointerDeclaration create(Type tinfo)
2048 return new TypeInfoPointerDeclaration(tinfo);
2051 override void accept(Visitor v)
2053 v.visit(this);
2057 /***********************************************************
2059 extern (C++) final class TypeInfoArrayDeclaration : TypeInfoDeclaration
2061 extern (D) this(Type tinfo)
2063 super(tinfo);
2064 if (!Type.typeinfoarray)
2066 ObjectNotFound(Id.TypeInfo_Array);
2068 type = Type.typeinfoarray.type;
2071 static TypeInfoArrayDeclaration create(Type tinfo)
2073 return new TypeInfoArrayDeclaration(tinfo);
2076 override void accept(Visitor v)
2078 v.visit(this);
2082 /***********************************************************
2084 extern (C++) final class TypeInfoStaticArrayDeclaration : TypeInfoDeclaration
2086 extern (D) this(Type tinfo)
2088 super(tinfo);
2089 if (!Type.typeinfostaticarray)
2091 ObjectNotFound(Id.TypeInfo_StaticArray);
2093 type = Type.typeinfostaticarray.type;
2096 static TypeInfoStaticArrayDeclaration create(Type tinfo)
2098 return new TypeInfoStaticArrayDeclaration(tinfo);
2101 override void accept(Visitor v)
2103 v.visit(this);
2107 /***********************************************************
2109 extern (C++) final class TypeInfoAssociativeArrayDeclaration : TypeInfoDeclaration
2111 extern (D) this(Type tinfo)
2113 super(tinfo);
2114 if (!Type.typeinfoassociativearray)
2116 ObjectNotFound(Id.TypeInfo_AssociativeArray);
2118 type = Type.typeinfoassociativearray.type;
2121 static TypeInfoAssociativeArrayDeclaration create(Type tinfo)
2123 return new TypeInfoAssociativeArrayDeclaration(tinfo);
2126 override void accept(Visitor v)
2128 v.visit(this);
2132 /***********************************************************
2134 extern (C++) final class TypeInfoEnumDeclaration : TypeInfoDeclaration
2136 extern (D) this(Type tinfo)
2138 super(tinfo);
2139 if (!Type.typeinfoenum)
2141 ObjectNotFound(Id.TypeInfo_Enum);
2143 type = Type.typeinfoenum.type;
2146 static TypeInfoEnumDeclaration create(Type tinfo)
2148 return new TypeInfoEnumDeclaration(tinfo);
2151 override void accept(Visitor v)
2153 v.visit(this);
2157 /***********************************************************
2159 extern (C++) final class TypeInfoFunctionDeclaration : TypeInfoDeclaration
2161 extern (D) this(Type tinfo)
2163 super(tinfo);
2164 if (!Type.typeinfofunction)
2166 ObjectNotFound(Id.TypeInfo_Function);
2168 type = Type.typeinfofunction.type;
2171 static TypeInfoFunctionDeclaration create(Type tinfo)
2173 return new TypeInfoFunctionDeclaration(tinfo);
2176 override void accept(Visitor v)
2178 v.visit(this);
2182 /***********************************************************
2184 extern (C++) final class TypeInfoDelegateDeclaration : TypeInfoDeclaration
2186 extern (D) this(Type tinfo)
2188 super(tinfo);
2189 if (!Type.typeinfodelegate)
2191 ObjectNotFound(Id.TypeInfo_Delegate);
2193 type = Type.typeinfodelegate.type;
2196 static TypeInfoDelegateDeclaration create(Type tinfo)
2198 return new TypeInfoDelegateDeclaration(tinfo);
2201 override void accept(Visitor v)
2203 v.visit(this);
2207 /***********************************************************
2209 extern (C++) final class TypeInfoTupleDeclaration : TypeInfoDeclaration
2211 extern (D) this(Type tinfo)
2213 super(tinfo);
2214 if (!Type.typeinfotypelist)
2216 ObjectNotFound(Id.TypeInfo_Tuple);
2218 type = Type.typeinfotypelist.type;
2221 static TypeInfoTupleDeclaration create(Type tinfo)
2223 return new TypeInfoTupleDeclaration(tinfo);
2226 override void accept(Visitor v)
2228 v.visit(this);
2232 /***********************************************************
2234 extern (C++) final class TypeInfoConstDeclaration : TypeInfoDeclaration
2236 extern (D) this(Type tinfo)
2238 super(tinfo);
2239 if (!Type.typeinfoconst)
2241 ObjectNotFound(Id.TypeInfo_Const);
2243 type = Type.typeinfoconst.type;
2246 static TypeInfoConstDeclaration create(Type tinfo)
2248 return new TypeInfoConstDeclaration(tinfo);
2251 override void accept(Visitor v)
2253 v.visit(this);
2257 /***********************************************************
2259 extern (C++) final class TypeInfoInvariantDeclaration : TypeInfoDeclaration
2261 extern (D) this(Type tinfo)
2263 super(tinfo);
2264 if (!Type.typeinfoinvariant)
2266 ObjectNotFound(Id.TypeInfo_Invariant);
2268 type = Type.typeinfoinvariant.type;
2271 static TypeInfoInvariantDeclaration create(Type tinfo)
2273 return new TypeInfoInvariantDeclaration(tinfo);
2276 override void accept(Visitor v)
2278 v.visit(this);
2282 /***********************************************************
2284 extern (C++) final class TypeInfoSharedDeclaration : TypeInfoDeclaration
2286 extern (D) this(Type tinfo)
2288 super(tinfo);
2289 if (!Type.typeinfoshared)
2291 ObjectNotFound(Id.TypeInfo_Shared);
2293 type = Type.typeinfoshared.type;
2296 static TypeInfoSharedDeclaration create(Type tinfo)
2298 return new TypeInfoSharedDeclaration(tinfo);
2301 override void accept(Visitor v)
2303 v.visit(this);
2307 /***********************************************************
2309 extern (C++) final class TypeInfoWildDeclaration : TypeInfoDeclaration
2311 extern (D) this(Type tinfo)
2313 super(tinfo);
2314 if (!Type.typeinfowild)
2316 ObjectNotFound(Id.TypeInfo_Wild);
2318 type = Type.typeinfowild.type;
2321 static TypeInfoWildDeclaration create(Type tinfo)
2323 return new TypeInfoWildDeclaration(tinfo);
2326 override void accept(Visitor v)
2328 v.visit(this);
2332 /***********************************************************
2334 extern (C++) final class TypeInfoVectorDeclaration : TypeInfoDeclaration
2336 extern (D) this(Type tinfo)
2338 super(tinfo);
2339 if (!Type.typeinfovector)
2341 ObjectNotFound(Id.TypeInfo_Vector);
2343 type = Type.typeinfovector.type;
2346 static TypeInfoVectorDeclaration create(Type tinfo)
2348 return new TypeInfoVectorDeclaration(tinfo);
2351 override void accept(Visitor v)
2353 v.visit(this);
2357 /***********************************************************
2358 * For the "this" parameter to member functions
2360 extern (C++) final class ThisDeclaration : VarDeclaration
2362 extern (D) this(const ref Loc loc, Type t)
2364 super(loc, t, Id.This, null);
2365 storage_class |= STC.nodtor;
2368 override ThisDeclaration syntaxCopy(Dsymbol s)
2370 assert(0); // should never be produced by syntax
2373 override inout(ThisDeclaration) isThisDeclaration() inout
2375 return this;
2378 override void accept(Visitor v)
2380 v.visit(this);