d: Merge upstream dmd, druntime 4c18eed967, phobos d945686a4.
[official-gcc.git] / gcc / d / dmd / declaration.d
blobb65e7e833d4d46a5dca0710a4185450b144193e9
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-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;
16 import dmd.aggregate;
17 import dmd.arraytypes;
18 import dmd.astenums;
19 import dmd.ctorflow;
20 import dmd.dclass;
21 import dmd.delegatize;
22 import dmd.dscope;
23 import dmd.dstruct;
24 import dmd.dsymbol;
25 import dmd.dsymbolsem;
26 import dmd.dtemplate;
27 import dmd.errors;
28 import dmd.expression;
29 import dmd.func;
30 import dmd.globals;
31 import dmd.gluelayer;
32 import dmd.id;
33 import dmd.identifier;
34 import dmd.init;
35 import dmd.initsem;
36 import dmd.intrange;
37 import dmd.location;
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 version (IN_GCC) {}
47 else version (IN_LLVM) {}
48 else version = MARS;
50 /************************************
51 * Check to see the aggregate type is nested and its context pointer is
52 * accessible from the current scope.
53 * Returns true if error occurs.
55 bool checkFrameAccess(Loc loc, Scope* sc, AggregateDeclaration ad, size_t iStart = 0)
57 Dsymbol sparent = ad.toParentLocal();
58 Dsymbol sparent2 = ad.toParent2();
59 Dsymbol s = sc.func;
60 if (ad.isNested() && s)
62 //printf("ad = %p %s [%s], parent:%p\n", ad, ad.toChars(), ad.loc.toChars(), ad.parent);
63 //printf("sparent = %p %s [%s], parent: %s\n", sparent, sparent.toChars(), sparent.loc.toChars(), sparent.parent,toChars());
64 //printf("sparent2 = %p %s [%s], parent: %s\n", sparent2, sparent2.toChars(), sparent2.loc.toChars(), sparent2.parent,toChars());
65 if (!ensureStaticLinkTo(s, sparent) || sparent != sparent2 && !ensureStaticLinkTo(s, sparent2))
67 error(loc, "cannot access frame pointer of `%s`", ad.toPrettyChars());
68 return true;
72 bool result = false;
73 for (size_t i = iStart; i < ad.fields.length; i++)
75 VarDeclaration vd = ad.fields[i];
76 Type tb = vd.type.baseElemOf();
77 if (tb.ty == Tstruct)
79 result |= checkFrameAccess(loc, sc, (cast(TypeStruct)tb).sym);
82 return result;
85 /***********************************************
86 * Mark variable v as modified if it is inside a constructor that var
87 * is a field in.
88 * Also used to allow immutable globals to be initialized inside a static constructor.
89 * Returns:
90 * true if it's an initialization of v
92 bool modifyFieldVar(Loc loc, Scope* sc, VarDeclaration var, Expression e1)
94 //printf("modifyFieldVar(var = %s)\n", var.toChars());
95 Dsymbol s = sc.func;
96 while (1)
98 FuncDeclaration fd = null;
99 if (s)
100 fd = s.isFuncDeclaration();
101 if (fd &&
102 ((fd.isCtorDeclaration() && var.isField()) ||
103 ((fd.isStaticCtorDeclaration() || fd.isCrtCtor) && !var.isField())) &&
104 fd.toParentDecl() == var.toParent2() &&
105 (!e1 || e1.op == EXP.this_))
107 bool result = true;
109 var.ctorinit = true;
110 //printf("setting ctorinit\n");
112 if (var.isField() && sc.ctorflow.fieldinit.length && !sc.intypeof)
114 assert(e1);
115 auto mustInit = ((var.storage_class & STC.nodefaultctor) != 0 ||
116 var.type.needsNested());
118 const dim = sc.ctorflow.fieldinit.length;
119 auto ad = fd.isMemberDecl();
120 assert(ad);
121 size_t i;
122 for (i = 0; i < dim; i++) // same as findFieldIndexByName in ctfeexp.c ?
124 if (ad.fields[i] == var)
125 break;
127 assert(i < dim);
128 auto fieldInit = &sc.ctorflow.fieldinit[i];
129 const fi = fieldInit.csx;
131 if (fi & CSX.this_ctor)
133 if (var.type.isMutable() && e1.type.isMutable())
134 result = false;
135 else
137 const(char)* modStr = !var.type.isMutable() ? MODtoChars(var.type.mod) : MODtoChars(e1.type.mod);
138 .error(loc, "%s field `%s` initialized multiple times", modStr, var.toChars());
139 .errorSupplemental(fieldInit.loc, "Previous initialization is here.");
142 else if (sc.inLoop || (fi & CSX.label))
144 if (!mustInit && var.type.isMutable() && e1.type.isMutable())
145 result = false;
146 else
148 const(char)* modStr = !var.type.isMutable() ? MODtoChars(var.type.mod) : MODtoChars(e1.type.mod);
149 .error(loc, "%s field `%s` initialization is not allowed in loops or after labels", modStr, var.toChars());
153 fieldInit.csx |= CSX.this_ctor;
154 fieldInit.loc = e1.loc;
155 if (var.overlapped) // https://issues.dlang.org/show_bug.cgi?id=15258
157 foreach (j, v; ad.fields)
159 if (v is var || !var.isOverlappedWith(v))
160 continue;
161 v.ctorinit = true;
162 sc.ctorflow.fieldinit[j].csx = CSX.this_ctor;
166 else if (fd != sc.func)
168 if (var.type.isMutable())
169 result = false;
170 else if (sc.func.fes)
172 const(char)* p = var.isField() ? "field" : var.kind();
173 .error(loc, "%s %s `%s` initialization is not allowed in foreach loop",
174 MODtoChars(var.type.mod), p, var.toChars());
176 else
178 const(char)* p = var.isField() ? "field" : var.kind();
179 .error(loc, "%s %s `%s` initialization is not allowed in nested function `%s`",
180 MODtoChars(var.type.mod), p, var.toChars(), sc.func.toChars());
183 else if (fd.isStaticCtorDeclaration() && !fd.isSharedStaticCtorDeclaration() &&
184 var.type.isImmutable())
186 .error(loc, "%s %s `%s` initialization is not allowed in `static this`",
187 MODtoChars(var.type.mod), var.kind(), var.toChars());
188 errorSupplemental(loc, "Use `shared static this` instead.");
190 else if (fd.isStaticCtorDeclaration() && !fd.isSharedStaticCtorDeclaration() &&
191 var.type.isConst())
193 // @@@DEPRECATED_2.116@@@
194 // Turn this into an error, merging with the branch above
195 .deprecation(loc, "%s %s `%s` initialization is not allowed in `static this`",
196 MODtoChars(var.type.mod), var.kind(), var.toChars());
197 deprecationSupplemental(loc, "Use `shared static this` instead.");
199 return result;
201 else
203 if (s)
205 s = s.toParentP(var.toParent2());
206 continue;
209 break;
211 return false;
214 /******************************************
216 extern (C++) void ObjectNotFound(Identifier id)
218 error(Loc.initial, "`%s` not found. object.d may be incorrectly installed or corrupt.", id.toChars());
219 fatal();
222 /* Accumulator for successive matches.
224 struct MatchAccumulator
226 int count; // number of matches found so far
227 MATCH last = MATCH.nomatch; // match level of lastf
228 FuncDeclaration lastf; // last matching function we found
229 FuncDeclaration nextf; // if ambiguous match, this is the "other" function
232 /***********************************************************
234 extern (C++) abstract class Declaration : Dsymbol
236 Type type;
237 Type originalType; // before semantic analysis
238 StorageClass storage_class = STC.undefined_;
239 Visibility visibility;
240 LINK _linkage = LINK.default_; // may be `LINK.system`; use `resolvedLinkage()` to resolve it
241 short inuse; // used to detect cycles
243 ubyte adFlags; // control re-assignment of AliasDeclaration (put here for packing reasons)
244 enum wasRead = 1; // set if AliasDeclaration was read
245 enum ignoreRead = 2; // ignore any reads of AliasDeclaration
246 enum nounderscore = 4; // don't prepend _ to mangled name
248 Symbol* isym; // import version of csym
250 // overridden symbol with pragma(mangle, "...")
251 const(char)[] mangleOverride;
253 final extern (D) this(Identifier ident) @safe
255 super(ident);
256 visibility = Visibility(Visibility.Kind.undefined);
259 final extern (D) this(const ref Loc loc, Identifier ident) @safe
261 super(loc, ident);
262 visibility = Visibility(Visibility.Kind.undefined);
265 override const(char)* kind() const
267 return "declaration";
270 override final uinteger_t size(const ref Loc loc)
272 assert(type);
273 const sz = type.size();
274 if (sz == SIZE_INVALID)
275 errors = true;
276 return sz;
280 * Issue an error if an attempt to call a disabled method is made
282 * If the declaration is disabled but inside a disabled function,
283 * returns `true` but do not issue an error message.
285 * Params:
286 * loc = Location information of the call
287 * sc = Scope in which the call occurs
288 * isAliasedDeclaration = if `true` searches overload set
290 * Returns:
291 * `true` if this `Declaration` is `@disable`d, `false` otherwise.
293 extern (D) final bool checkDisabled(Loc loc, Scope* sc, bool isAliasedDeclaration = false)
295 if (!(storage_class & STC.disable))
296 return false;
298 if (sc.func && sc.func.storage_class & STC.disable)
299 return true;
301 if (auto p = toParent())
303 if (auto postblit = isPostBlitDeclaration())
305 /* https://issues.dlang.org/show_bug.cgi?id=21885
307 * If the generated postblit is disabled, it
308 * means that one of the fields has a disabled
309 * postblit. Print the first field that has
310 * a disabled postblit.
312 if (postblit.isGenerated())
314 auto sd = p.isStructDeclaration();
315 assert(sd);
316 for (size_t i = 0; i < sd.fields.length; i++)
318 auto structField = sd.fields[i];
319 if (structField.overlapped)
320 continue;
321 Type tv = structField.type.baseElemOf();
322 if (tv.ty != Tstruct)
323 continue;
324 auto sdv = (cast(TypeStruct)tv).sym;
325 if (!sdv.postblit)
326 continue;
327 if (sdv.postblit.isDisabled())
329 .error(loc, "%s `%s` is not copyable because field `%s` is not copyable", p.kind, p.toPrettyChars, structField.toChars());
330 return true;
334 .error(loc, "%s `%s` is not copyable because it has a disabled postblit", p.kind, p.toPrettyChars);
335 return true;
339 // if the function is @disabled, maybe there
340 // is an overload in the overload set that isn't
341 if (isAliasedDeclaration)
343 FuncDeclaration fd = isFuncDeclaration();
344 if (fd)
346 for (FuncDeclaration ovl = fd; ovl; ovl = cast(FuncDeclaration)ovl.overnext)
347 if (!(ovl.storage_class & STC.disable))
348 return false;
352 if (auto ctor = isCtorDeclaration())
354 if (ctor.isCpCtor && ctor.isGenerated())
356 .error(loc, "generating an `inout` copy constructor for `struct %s` failed, therefore instances of it are uncopyable", parent.toPrettyChars());
357 return true;
360 .error(loc, "%s `%s` cannot be used because it is annotated with `@disable`", kind, toPrettyChars);
361 return true;
364 /*************************************
365 * Check to see if declaration can be modified in this context (sc).
366 * Issue error if not.
367 * Params:
368 * loc = location for error messages
369 * e1 = `null` or `this` expression when this declaration is a field
370 * sc = context
371 * flag = if the first bit is set it means do not issue error message for
372 * invalid modification; if the second bit is set, it means that
373 this declaration is a field and a subfield of it is modified.
374 * Returns:
375 * Modifiable.yes or Modifiable.initialization
377 extern (D) final Modifiable checkModify(Loc loc, Scope* sc, Expression e1, ModifyFlags flag)
379 VarDeclaration v = isVarDeclaration();
380 if (v && v.canassign)
381 return Modifiable.initialization;
383 if (isParameter() || isResult())
385 for (Scope* scx = sc; scx; scx = scx.enclosing)
387 if (scx.func == parent && (scx.flags & SCOPE.contract))
389 const(char)* s = isParameter() && parent.ident != Id.ensure ? "parameter" : "result";
390 if (!(flag & ModifyFlags.noError))
391 error(loc, "%s `%s` cannot modify %s `%s` in contract", kind, toPrettyChars, s, toChars());
392 return Modifiable.initialization; // do not report type related errors
397 if (e1 && e1.op == EXP.this_ && isField())
399 VarDeclaration vthis = e1.isThisExp().var;
400 for (Scope* scx = sc; scx; scx = scx.enclosing)
402 if (scx.func == vthis.parent && (scx.flags & SCOPE.contract))
404 if (!(flag & ModifyFlags.noError))
405 error(loc, "%s `%s` cannot modify parameter `this` in contract", kind, toPrettyChars);
406 return Modifiable.initialization; // do not report type related errors
411 if (v && (v.isCtorinit() || isField()))
413 // It's only modifiable if inside the right constructor
414 if ((storage_class & (STC.foreach_ | STC.ref_)) == (STC.foreach_ | STC.ref_))
415 return Modifiable.initialization;
416 if (flag & ModifyFlags.fieldAssign)
417 return Modifiable.yes;
418 return modifyFieldVar(loc, sc, v, e1) ? Modifiable.initialization : Modifiable.yes;
420 return Modifiable.yes;
423 override final Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
425 Dsymbol s = Dsymbol.search(loc, ident, flags);
426 if (!s && type)
428 s = type.toDsymbol(_scope);
429 if (s)
430 s = s.search(loc, ident, flags);
432 return s;
435 final bool isStatic() const pure nothrow @nogc @safe
437 return (storage_class & STC.static_) != 0;
440 /// Returns the linkage, resolving the target-specific `System` one.
441 final LINK resolvedLinkage() const
443 return _linkage == LINK.system ? target.systemLinkage() : _linkage;
446 bool isDelete()
448 return false;
451 bool isDataseg()
453 return false;
456 bool isThreadlocal()
458 return false;
461 bool isCodeseg() const pure nothrow @nogc @safe
463 return false;
466 final bool isFinal() const pure nothrow @nogc @safe
468 return (storage_class & STC.final_) != 0;
471 bool isAbstract()
473 return (storage_class & STC.abstract_) != 0;
476 final bool isConst() const pure nothrow @nogc @safe
478 return (storage_class & STC.const_) != 0;
481 final bool isImmutable() const pure nothrow @nogc @safe
483 return (storage_class & STC.immutable_) != 0;
486 final bool isWild() const pure nothrow @nogc @safe
488 return (storage_class & STC.wild) != 0;
491 final bool isAuto() const pure nothrow @nogc @safe
493 return (storage_class & STC.auto_) != 0;
496 final bool isScope() const pure nothrow @nogc @safe
498 return (storage_class & STC.scope_) != 0;
501 final bool isReturn() const pure nothrow @nogc @safe
503 return (storage_class & STC.return_) != 0;
506 final bool isSynchronized() const pure nothrow @nogc @safe
508 return (storage_class & STC.synchronized_) != 0;
511 final bool isParameter() const pure nothrow @nogc @safe
513 return (storage_class & STC.parameter) != 0;
516 override final bool isDeprecated() const pure nothrow @nogc @safe
518 return (storage_class & STC.deprecated_) != 0;
521 final bool isDisabled() const pure nothrow @nogc @safe
523 return (storage_class & STC.disable) != 0;
526 final bool isOverride() const pure nothrow @nogc @safe
528 return (storage_class & STC.override_) != 0;
531 final bool isResult() const pure nothrow @nogc @safe
533 return (storage_class & STC.result) != 0;
536 final bool isField() const pure nothrow @nogc @safe
538 return (storage_class & STC.field) != 0;
541 final bool isIn() const pure nothrow @nogc @safe
543 return (storage_class & STC.in_) != 0;
546 final bool isOut() const pure nothrow @nogc @safe
548 return (storage_class & STC.out_) != 0;
551 final bool isRef() const pure nothrow @nogc @safe
553 return (storage_class & STC.ref_) != 0;
556 /// Returns: Whether the variable is a reference, annotated with `out` or `ref`
557 final bool isReference() const pure nothrow @nogc @safe
559 return (storage_class & (STC.ref_ | STC.out_)) != 0;
562 final bool isFuture() const pure nothrow @nogc @safe
564 return (storage_class & STC.future) != 0;
567 final extern(D) bool isSystem() const pure nothrow @nogc @safe
569 return (storage_class & STC.system) != 0;
572 override final Visibility visible() pure nothrow @nogc @safe
574 return visibility;
577 override final inout(Declaration) isDeclaration() inout pure nothrow @nogc @safe
579 return this;
582 override void accept(Visitor v)
584 v.visit(this);
588 /***********************************************************
590 extern (C++) final class TupleDeclaration : Declaration
592 Objects* objects;
593 TypeTuple tupletype; // !=null if this is a type tuple
594 bool isexp; // true: expression tuple
595 bool building; // it's growing in AliasAssign semantic
597 extern (D) this(const ref Loc loc, Identifier ident, Objects* objects) @safe
599 super(loc, ident);
600 this.objects = objects;
603 override TupleDeclaration syntaxCopy(Dsymbol s)
605 assert(0);
608 override const(char)* kind() const
610 return "sequence";
613 override Type getType()
615 /* If this tuple represents a type, return that type
618 //printf("TupleDeclaration::getType() %s\n", toChars());
619 if (isexp || building)
620 return null;
621 if (!tupletype)
623 /* It's only a type tuple if all the Object's are types
625 for (size_t i = 0; i < objects.length; i++)
627 RootObject o = (*objects)[i];
628 if (!o.isType())
630 //printf("\tnot[%d], %p, %d\n", i, o, o.dyncast());
631 return null;
635 /* We know it's a type tuple, so build the TypeTuple
637 Types* types = cast(Types*)objects;
638 auto args = new Parameters(objects.length);
639 OutBuffer buf;
640 int hasdeco = 1;
641 for (size_t i = 0; i < types.length; i++)
643 Type t = (*types)[i];
644 //printf("type = %s\n", t.toChars());
645 version (none)
647 buf.printf("_%s_%d", ident.toChars(), i);
648 auto id = Identifier.idPool(buf.extractSlice());
649 auto arg = new Parameter(Loc.initial, STC.in_, t, id, null);
651 else
653 auto arg = new Parameter(Loc.initial, 0, t, null, null, null);
655 (*args)[i] = arg;
656 if (!t.deco)
657 hasdeco = 0;
660 tupletype = new TypeTuple(args);
661 if (hasdeco)
662 return tupletype.typeSemantic(Loc.initial, null);
664 return tupletype;
667 override Dsymbol toAlias2()
669 //printf("TupleDeclaration::toAlias2() '%s' objects = %s\n", toChars(), objects.toChars());
670 for (size_t i = 0; i < objects.length; i++)
672 RootObject o = (*objects)[i];
673 if (Dsymbol s = isDsymbol(o))
675 s = s.toAlias2();
676 (*objects)[i] = s;
679 return this;
682 override bool needThis()
684 //printf("TupleDeclaration::needThis(%s)\n", toChars());
685 return isexp ? foreachVar((s) { return s.needThis(); }) != 0 : false;
688 /***********************************************************
689 * Calls dg(Dsymbol) for each Dsymbol, which should be a VarDeclaration
690 * inside VarExp (isexp == true).
691 * Params:
692 * dg = delegate to call for each Dsymbol
694 extern (D) void foreachVar(scope void delegate(Dsymbol) dg)
696 assert(isexp);
697 foreach (o; *objects)
699 if (auto e = o.isExpression())
700 if (auto ve = e.isVarExp())
701 dg(ve.var);
705 /***********************************************************
706 * Calls dg(Dsymbol) for each Dsymbol, which should be a VarDeclaration
707 * inside VarExp (isexp == true).
708 * If dg returns !=0, stops and returns that value else returns 0.
709 * Params:
710 * dg = delegate to call for each Dsymbol
711 * Returns:
712 * last value returned by dg()
714 extern (D) int foreachVar(scope int delegate(Dsymbol) dg)
716 assert(isexp);
717 foreach (o; *objects)
719 if (auto e = o.isExpression())
720 if (auto ve = e.isVarExp())
721 if(auto ret = dg(ve.var))
722 return ret;
724 return 0;
727 override inout(TupleDeclaration) isTupleDeclaration() inout
729 return this;
732 override void accept(Visitor v)
734 v.visit(this);
738 /***********************************************************
739 * https://dlang.org/spec/declaration.html#AliasDeclaration
741 extern (C++) final class AliasDeclaration : Declaration
743 Dsymbol aliassym; // alias ident = aliassym;
745 Dsymbol overnext; // next in overload list
746 Dsymbol _import; // !=null if unresolved internal alias for selective import
748 extern (D) this(const ref Loc loc, Identifier ident, Type type) @safe
750 super(loc, ident);
751 //printf("AliasDeclaration(id = '%s', type = %p)\n", ident.toChars(), type);
752 //printf("type = '%s'\n", type.toChars());
753 this.type = type;
754 assert(type);
757 extern (D) this(const ref Loc loc, Identifier ident, Dsymbol s) @safe
759 super(loc, ident);
760 //printf("AliasDeclaration(id = '%s', s = %p)\n", ident.toChars(), s);
761 assert(s != this);
762 this.aliassym = s;
763 assert(s);
766 static AliasDeclaration create(const ref Loc loc, Identifier id, Type type) @safe
768 return new AliasDeclaration(loc, id, type);
771 override AliasDeclaration syntaxCopy(Dsymbol s)
773 //printf("AliasDeclaration::syntaxCopy()\n");
774 assert(!s);
775 AliasDeclaration sa = type ? new AliasDeclaration(loc, ident, type.syntaxCopy()) : new AliasDeclaration(loc, ident, aliassym.syntaxCopy(null));
776 sa.comment = comment;
777 sa.storage_class = storage_class;
778 return sa;
781 override bool overloadInsert(Dsymbol s)
783 //printf("[%s] AliasDeclaration::overloadInsert('%s') s = %s %s @ [%s]\n",
784 // loc.toChars(), toChars(), s.kind(), s.toChars(), s.loc.toChars());
786 /** Aliases aren't overloadable themselves, but if their Aliasee is
787 * overloadable they are converted to an overloadable Alias (either
788 * FuncAliasDeclaration or OverDeclaration).
790 * This is done by moving the Aliasee into such an overloadable alias
791 * which is then used to replace the existing Aliasee. The original
792 * Alias (_this_) remains a useless shell.
794 * This is a horrible mess. It was probably done to avoid replacing
795 * existing AST nodes and references, but it needs a major
796 * simplification b/c it's too complex to maintain.
798 * A simpler approach might be to merge any colliding symbols into a
799 * simple Overload class (an array) and then later have that resolve
800 * all collisions.
802 if (semanticRun >= PASS.semanticdone)
804 /* Semantic analysis is already finished, and the aliased entity
805 * is not overloadable.
807 if (type)
810 If type has been resolved already we could
811 still be inserting an alias from an import.
813 If we are handling an alias then pretend
814 it was inserting and return true, if not then
815 false since we didn't even pretend to insert something.
817 return this._import && this.equals(s);
820 /* When s is added in member scope by static if, mixin("code") or others,
821 * aliassym is determined already. See the case in: test/compilable/test61.d
823 auto sa = aliassym.toAlias();
825 if (auto td = s.toAlias().isTemplateDeclaration())
826 s = td.funcroot ? td.funcroot : td;
828 if (auto fd = sa.isFuncDeclaration())
830 auto fa = new FuncAliasDeclaration(ident, fd);
831 fa.visibility = visibility;
832 fa.parent = parent;
833 aliassym = fa;
834 return aliassym.overloadInsert(s);
836 if (auto td = sa.isTemplateDeclaration())
838 auto od = new OverDeclaration(ident, td.funcroot ? td.funcroot : td);
839 od.visibility = visibility;
840 od.parent = parent;
841 aliassym = od;
842 return aliassym.overloadInsert(s);
844 if (auto od = sa.isOverDeclaration())
846 if (sa.ident != ident || sa.parent != parent)
848 od = new OverDeclaration(ident, od);
849 od.visibility = visibility;
850 od.parent = parent;
851 aliassym = od;
853 return od.overloadInsert(s);
855 if (auto os = sa.isOverloadSet())
857 if (sa.ident != ident || sa.parent != parent)
859 os = new OverloadSet(ident, os);
860 // TODO: visibility is lost here b/c OverloadSets have no visibility attribute
861 // Might no be a practical issue, b/c the code below fails to resolve the overload anyhow.
862 // ----
863 // module os1;
864 // import a, b;
865 // private alias merged = foo; // private alias to overload set of a.foo and b.foo
866 // ----
867 // module os2;
868 // import a, b;
869 // public alias merged = bar; // public alias to overload set of a.bar and b.bar
870 // ----
871 // module bug;
872 // import os1, os2;
873 // void test() { merged(123); } // should only look at os2.merged
875 // os.visibility = visibility;
876 os.parent = parent;
877 aliassym = os;
879 os.push(s);
880 return true;
882 return false;
885 /* Don't know yet what the aliased symbol is, so assume it can
886 * be overloaded and check later for correctness.
888 if (overnext)
889 return overnext.overloadInsert(s);
890 if (s is this)
891 return true;
892 overnext = s;
893 return true;
896 override const(char)* kind() const
898 return "alias";
901 override Type getType()
903 if (type)
904 return type;
905 return toAlias().getType();
908 override Dsymbol toAlias()
910 //printf("[%s] AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s', inuse = %d)\n",
911 // loc.toChars(), toChars(), this, aliassym, aliassym ? aliassym.kind() : "", inuse);
912 assert(this != aliassym);
913 //static int count; if (++count == 10) *(char*)0=0;
915 // Reading the AliasDeclaration
916 if (!(adFlags & ignoreRead))
917 adFlags |= wasRead; // can never assign to this AliasDeclaration again
919 if (inuse == 1 && type && _scope)
921 inuse = 2;
922 uint olderrors = global.errors;
923 Dsymbol s = type.toDsymbol(_scope);
924 //printf("[%s] type = %s, s = %p, this = %p\n", loc.toChars(), type.toChars(), s, this);
925 if (global.errors != olderrors)
926 goto Lerr;
927 if (s)
929 s = s.toAlias();
930 if (global.errors != olderrors)
931 goto Lerr;
932 aliassym = s;
933 inuse = 0;
935 else
937 Type t = type.typeSemantic(loc, _scope);
938 if (t.ty == Terror)
939 goto Lerr;
940 if (global.errors != olderrors)
941 goto Lerr;
942 //printf("t = %s\n", t.toChars());
943 inuse = 0;
946 if (inuse)
948 .error(loc, "%s `%s` recursive alias declaration", kind, toPrettyChars);
950 Lerr:
951 // Avoid breaking "recursive alias" state during errors gagged
952 if (global.gag)
953 return this;
954 aliassym = new AliasDeclaration(loc, ident, Type.terror);
955 type = Type.terror;
956 return aliassym;
959 if (semanticRun >= PASS.semanticdone)
961 // semantic is already done.
963 // Do not see aliassym !is null, because of lambda aliases.
965 // Do not see type.deco !is null, even so "alias T = const int;` needs
966 // semantic analysis to take the storage class `const` as type qualifier.
968 else
970 // stop AliasAssign tuple building
971 if (aliassym)
973 if (auto td = aliassym.isTupleDeclaration())
975 if (td.building)
977 td.building = false;
978 semanticRun = PASS.semanticdone;
979 return td;
983 if (_import && _import._scope)
985 /* If this is an internal alias for selective/renamed import,
986 * load the module first.
988 _import.dsymbolSemantic(null);
990 if (_scope)
992 aliasSemantic(this, _scope);
996 inuse = 1;
997 Dsymbol s = aliassym ? aliassym.toAlias() : this;
998 inuse = 0;
999 return s;
1002 override Dsymbol toAlias2()
1004 if (inuse)
1006 .error(loc, "%s `%s` recursive alias declaration", kind, toPrettyChars);
1007 return this;
1009 inuse = 1;
1010 Dsymbol s = aliassym ? aliassym.toAlias2() : this;
1011 inuse = 0;
1012 return s;
1015 override bool isOverloadable() const
1017 // assume overloadable until alias is resolved
1018 return semanticRun < PASS.semanticdone ||
1019 aliassym && aliassym.isOverloadable();
1022 override inout(AliasDeclaration) isAliasDeclaration() inout
1024 return this;
1027 /** Returns: `true` if this instance was created to make a template parameter
1028 visible in the scope of a template body, `false` otherwise */
1029 extern (D) bool isAliasedTemplateParameter() const
1031 return !!(storage_class & STC.templateparameter);
1034 override void accept(Visitor v)
1036 v.visit(this);
1040 /***********************************************************
1042 extern (C++) final class OverDeclaration : Declaration
1044 Dsymbol overnext; // next in overload list
1045 Dsymbol aliassym;
1047 extern (D) this(Identifier ident, Dsymbol s) @safe
1049 super(ident);
1050 this.aliassym = s;
1053 override const(char)* kind() const
1055 return "overload alias"; // todo
1058 override bool equals(const RootObject o) const
1060 if (this == o)
1061 return true;
1063 auto s = isDsymbol(o);
1064 if (!s)
1065 return false;
1067 if (auto od2 = s.isOverDeclaration())
1068 return this.aliassym.equals(od2.aliassym);
1069 return this.aliassym == s;
1072 override bool overloadInsert(Dsymbol s)
1074 //printf("OverDeclaration::overloadInsert('%s') aliassym = %p, overnext = %p\n", s.toChars(), aliassym, overnext);
1075 if (overnext)
1076 return overnext.overloadInsert(s);
1077 if (s == this)
1078 return true;
1079 overnext = s;
1080 return true;
1083 override bool isOverloadable() const
1085 return true;
1088 Dsymbol isUnique()
1090 Dsymbol result = null;
1091 overloadApply(aliassym, (Dsymbol s)
1093 if (result)
1095 result = null;
1096 return 1; // ambiguous, done
1098 else
1100 result = s;
1101 return 0;
1104 return result;
1107 override inout(OverDeclaration) isOverDeclaration() inout
1109 return this;
1112 override void accept(Visitor v)
1114 v.visit(this);
1118 /***********************************************************
1120 extern (C++) class VarDeclaration : Declaration
1122 Initializer _init;
1123 FuncDeclarations nestedrefs; // referenced by these lexically nested functions
1124 TupleDeclaration aliasTuple; // when `this` is really a tuple of declarations
1125 VarDeclaration lastVar; // Linked list of variables for goto-skips-init detection
1126 Expression edtor; // if !=null, does the destruction of the variable
1127 IntRange* range; // if !=null, the variable is known to be within the range
1128 VarDeclarations* maybes; // maybeScope variables that are assigned to this maybeScope variable
1130 uint endlinnum; // line number of end of scope that this var lives in
1131 uint offset;
1132 uint sequenceNumber; // order the variables are declared
1133 structalign_t alignment;
1135 // When interpreting, these point to the value (NULL if value not determinable)
1136 // The index of this variable on the CTFE stack, AdrOnStackNone if not allocated
1137 enum AdrOnStackNone = ~0u;
1138 uint ctfeAdrOnStack;
1140 // `bool` fields that are compacted into bit fields in a string mixin
1141 private extern (D) static struct BitFields
1143 bool isargptr; /// if parameter that _argptr points to
1144 bool ctorinit; /// it has been initialized in a ctor
1145 bool iscatchvar; /// this is the exception object variable in catch() clause
1146 bool isowner; /// this is an Owner, despite it being `scope`
1147 bool setInCtorOnly; /// field can only be set in a constructor, as it is const or immutable
1149 /// It is a class that was allocated on the stack
1151 /// This means the var is not rebindable once assigned,
1152 /// and the destructor gets run when it goes out of scope
1153 bool onstack;
1155 bool overlapped; /// if it is a field and has overlapping
1156 bool overlapUnsafe; /// if it is an overlapping field and the overlaps are unsafe
1157 bool maybeScope; /// allow inferring 'scope' for this variable
1158 bool doNotInferReturn; /// do not infer 'return' for this variable
1160 bool isArgDtorVar; /// temporary created to handle scope destruction of a function argument
1161 bool isCmacro; /// it is a C macro turned into a C declaration
1162 bool dllImport; /// __declspec(dllimport)
1163 bool dllExport; /// __declspec(dllexport)
1164 version (MARS)
1166 bool inClosure; /// is inserted into a GC allocated closure
1167 bool inAlignSection; /// is inserted into an aligned section on stack
1169 bool systemInferred; /// @system was inferred from initializer
1172 import dmd.common.bitfields : generateBitFields;
1173 mixin(generateBitFields!(BitFields, uint));
1175 byte canassign; // it can be assigned to
1176 ubyte isdataseg; // private data for isDataseg 0 unset, 1 true, 2 false
1178 final extern (D) this(const ref Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.undefined_)
1181 assert(ident);
1185 //printf("VarDeclaration('%s')\n", ident.toChars());
1186 super(loc, ident);
1187 debug
1189 if (!type && !_init)
1191 //printf("VarDeclaration('%s')\n", ident.toChars());
1192 //*(char*)0=0;
1196 assert(type || _init);
1197 this.type = type;
1198 this._init = _init;
1199 ctfeAdrOnStack = AdrOnStackNone;
1200 this.storage_class = storage_class;
1203 static VarDeclaration create(const ref Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.undefined_)
1205 return new VarDeclaration(loc, type, ident, _init, storage_class);
1208 override VarDeclaration syntaxCopy(Dsymbol s)
1210 //printf("VarDeclaration::syntaxCopy(%s)\n", toChars());
1211 assert(!s);
1212 auto v = new VarDeclaration(loc, type ? type.syntaxCopy() : null, ident, _init ? _init.syntaxCopy() : null, storage_class);
1213 v.comment = comment;
1214 return v;
1217 override void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion)
1219 //printf("VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars());
1221 if (aliasTuple)
1223 // If this variable was really a tuple, set the offsets for the tuple fields
1224 aliasTuple.foreachVar((s) { s.setFieldOffset(ad, fieldState, isunion); });
1225 return;
1228 if (!isField())
1229 return;
1230 assert(!(storage_class & (STC.static_ | STC.extern_ | STC.parameter)));
1232 //printf("+VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars());
1234 /* Fields that are tuples appear both as part of TupleDeclarations and
1235 * as members. That means ignore them if they are already a field.
1237 if (offset)
1239 // already a field
1240 fieldState.offset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613
1241 return;
1243 for (size_t i = 0; i < ad.fields.length; i++)
1245 if (ad.fields[i] == this)
1247 // already a field
1248 fieldState.offset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613
1249 return;
1253 // Check for forward referenced types which will fail the size() call
1254 Type t = type.toBasetype();
1255 if (storage_class & STC.ref_)
1257 // References are the size of a pointer
1258 t = Type.tvoidptr;
1260 Type tv = t.baseElemOf();
1261 if (tv.ty == Tstruct)
1263 auto ts = cast(TypeStruct)tv;
1264 assert(ts.sym != ad); // already checked in ad.determineFields()
1265 if (!ts.sym.determineSize(loc))
1267 type = Type.terror;
1268 errors = true;
1269 return;
1273 // List in ad.fields. Even if the type is error, it's necessary to avoid
1274 // pointless error diagnostic "more initializers than fields" on struct literal.
1275 ad.fields.push(this);
1277 if (t.ty == Terror)
1278 return;
1280 /* If coming after a bit field in progress,
1281 * advance past the field
1283 fieldState.inFlight = false;
1285 const sz = t.size(loc);
1286 assert(sz != SIZE_INVALID && sz < uint.max);
1287 uint memsize = cast(uint)sz; // size of member
1288 uint memalignsize = target.fieldalign(t); // size of member for alignment purposes
1289 offset = AggregateDeclaration.placeField(
1290 &fieldState.offset,
1291 memsize, memalignsize, alignment,
1292 &ad.structsize, &ad.alignsize,
1293 isunion);
1295 //printf("\t%s: memalignsize = %d\n", toChars(), memalignsize);
1296 //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize);
1299 override const(char)* kind() const
1301 return "variable";
1304 override final inout(AggregateDeclaration) isThis() inout
1306 if (!(storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.templateparameter | STC.gshared | STC.ctfe)))
1308 /* The casting is necessary because `s = s.parent` is otherwise rejected
1310 for (auto s = cast(Dsymbol)this; s; s = s.parent)
1312 auto ad = (cast(inout)s).isMember();
1313 if (ad)
1314 return ad;
1315 if (!s.parent || !s.parent.isTemplateMixin())
1316 break;
1319 return null;
1322 override final bool needThis()
1324 //printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class);
1325 return isField();
1328 override final bool isExport() const
1330 return visibility.kind == Visibility.Kind.export_ || dllExport;
1333 override final bool isImportedSymbol() const
1335 /* If global variable has `export` and `extern` then it is imported
1336 * export int sym1; // definition: exported
1337 * export extern int sym2; // declaration: imported
1338 * export extern int sym3 = 0; // error, extern cannot have initializer
1340 bool result =
1341 dllImport ||
1342 visibility.kind == Visibility.Kind.export_ &&
1343 storage_class & STC.extern_ &&
1344 (storage_class & STC.static_ || parent.isModule());
1345 //printf("isImportedSymbol() %s %d\n", toChars(), result);
1346 return result;
1349 final bool isCtorinit() const pure nothrow @nogc @safe
1351 return setInCtorOnly;
1354 /*******************************
1355 * Does symbol go into data segment?
1356 * Includes extern variables.
1358 override final bool isDataseg()
1360 version (none)
1362 printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars());
1363 printf("%llx, isModule: %p, isTemplateInstance: %p, isNspace: %p\n",
1364 storage_class & (STC.static_ | STC.const_), parent.isModule(), parent.isTemplateInstance(), parent.isNspace());
1365 printf("parent = '%s'\n", parent.toChars());
1368 if (isdataseg == 0) // the value is not cached
1370 isdataseg = 2; // The Variables does not go into the datasegment
1372 if (!canTakeAddressOf())
1374 return false;
1377 Dsymbol parent = toParent();
1378 if (!parent && !(storage_class & STC.static_))
1380 .error(loc, "%s `%s` forward referenced", kind, toPrettyChars);
1381 type = Type.terror;
1383 else if (storage_class & (STC.static_ | STC.extern_ | STC.gshared) ||
1384 parent.isModule() || parent.isTemplateInstance() || parent.isNspace())
1386 assert(!isParameter() && !isResult());
1387 isdataseg = 1; // It is in the DataSegment
1391 return (isdataseg == 1);
1393 /************************************
1394 * Does symbol go into thread local storage?
1396 override final bool isThreadlocal()
1398 //printf("VarDeclaration::isThreadlocal(%p, '%s')\n", this, toChars());
1399 /* Data defaults to being thread-local. It is not thread-local
1400 * if it is immutable, const or shared.
1402 bool i = isDataseg() && !(storage_class & (STC.immutable_ | STC.const_ | STC.shared_ | STC.gshared));
1403 //printf("\treturn %d\n", i);
1404 return i;
1407 /********************************************
1408 * Can variable be read and written by CTFE?
1410 final bool isCTFE()
1412 return (storage_class & STC.ctfe) != 0; // || !isDataseg();
1415 final bool isOverlappedWith(VarDeclaration v)
1417 const vsz = v.type.size();
1418 const tsz = type.size();
1419 assert(vsz != SIZE_INVALID && tsz != SIZE_INVALID);
1421 // Overlap is checked by comparing bit offsets
1422 auto bitoffset = offset * 8;
1423 auto vbitoffset = v.offset * 8;
1425 // Bitsize of types are overridden by any bit-field widths.
1426 ulong tbitsize = void;
1427 if (auto bf = isBitFieldDeclaration())
1429 bitoffset += bf.bitOffset;
1430 tbitsize = bf.fieldWidth;
1432 else
1433 tbitsize = tsz * 8;
1435 ulong vbitsize = void;
1436 if (auto vbf = v.isBitFieldDeclaration())
1438 vbitoffset += vbf.bitOffset;
1439 vbitsize = vbf.fieldWidth;
1441 else
1442 vbitsize = vsz * 8;
1444 return bitoffset < vbitoffset + vbitsize &&
1445 vbitoffset < bitoffset + tbitsize;
1448 override final bool hasPointers()
1450 //printf("VarDeclaration::hasPointers() %s, ty = %d\n", toChars(), type.ty);
1451 return (!isDataseg() && type.hasPointers());
1454 /*************************************
1455 * Return true if we can take the address of this variable.
1457 final bool canTakeAddressOf()
1459 return !(storage_class & STC.manifest);
1462 /******************************************
1463 * Return true if variable needs to call the destructor.
1465 final bool needsScopeDtor()
1467 //printf("VarDeclaration::needsScopeDtor() %s\n", toChars());
1468 return edtor && !(storage_class & STC.nodtor);
1471 /******************************************
1472 * If a variable has a scope destructor call, return call for it.
1473 * Otherwise, return NULL.
1475 extern (D) final Expression callScopeDtor(Scope* sc)
1477 //printf("VarDeclaration::callScopeDtor() %s\n", toChars());
1479 // Destruction of STC.field's is handled by buildDtor()
1480 if (storage_class & (STC.nodtor | STC.ref_ | STC.out_ | STC.field))
1482 return null;
1485 if (iscatchvar)
1486 return null; // destructor is built by `void semantic(Catch c, Scope* sc)`, not here
1488 Expression e = null;
1489 // Destructors for structs and arrays of structs
1490 Type tv = type.baseElemOf();
1491 if (tv.ty == Tstruct)
1493 StructDeclaration sd = (cast(TypeStruct)tv).sym;
1494 if (!sd.dtor || sd.errors)
1495 return null;
1497 const sz = type.size();
1498 assert(sz != SIZE_INVALID);
1499 if (!sz)
1500 return null;
1502 if (type.toBasetype().ty == Tstruct)
1504 // v.__xdtor()
1505 e = new VarExp(loc, this);
1507 /* This is a hack so we can call destructors on const/immutable objects.
1508 * Need to add things like "const ~this()" and "immutable ~this()" to
1509 * fix properly.
1511 e.type = e.type.mutableOf();
1513 // Enable calling destructors on shared objects.
1514 // The destructor is always a single, non-overloaded function,
1515 // and must serve both shared and non-shared objects.
1516 e.type = e.type.unSharedOf;
1518 e = new DotVarExp(loc, e, sd.dtor, false);
1519 e = new CallExp(loc, e);
1521 else
1523 // __ArrayDtor(v[0 .. n])
1524 e = new VarExp(loc, this);
1526 const sdsz = sd.type.size();
1527 assert(sdsz != SIZE_INVALID && sdsz != 0);
1528 const n = sz / sdsz;
1529 SliceExp se = new SliceExp(loc, e, new IntegerExp(loc, 0, Type.tsize_t),
1530 new IntegerExp(loc, n, Type.tsize_t));
1532 // Prevent redundant bounds check
1533 se.upperIsInBounds = true;
1534 se.lowerIsLessThanUpper = true;
1536 // This is a hack so we can call destructors on const/immutable objects.
1537 se.type = sd.type.arrayOf();
1539 e = new CallExp(loc, new IdentifierExp(loc, Id.__ArrayDtor), se);
1541 return e;
1543 // Destructors for classes
1544 if (storage_class & (STC.auto_ | STC.scope_) && !(storage_class & STC.parameter))
1546 for (ClassDeclaration cd = type.isClassHandle(); cd; cd = cd.baseClass)
1548 /* We can do better if there's a way with onstack
1549 * classes to determine if there's no way the monitor
1550 * could be set.
1552 //if (cd.isInterfaceDeclaration())
1553 // error("interface `%s` cannot be scope", cd.toChars());
1555 if (onstack) // if any destructors
1557 // delete'ing C++ classes crashes (and delete is deprecated anyway)
1558 if (cd.classKind == ClassKind.cpp)
1560 // Don't call non-existant dtor
1561 if (!cd.dtor)
1562 break;
1564 e = new VarExp(loc, this);
1565 e.type = e.type.mutableOf().unSharedOf(); // Hack for mutable ctor on immutable instances
1566 e = new DotVarExp(loc, e, cd.dtor, false);
1567 e = new CallExp(loc, e);
1568 break;
1571 // delete this;
1572 Expression ec;
1573 ec = new VarExp(loc, this);
1574 e = new DeleteExp(loc, ec, true);
1575 e.type = Type.tvoid;
1576 break;
1580 return e;
1583 /*******************************************
1584 * If variable has a constant expression initializer, get it.
1585 * Otherwise, return null.
1587 extern (D) final Expression getConstInitializer(bool needFullType = true)
1589 assert(type && _init);
1591 // Ungag errors when not speculative
1592 uint oldgag = global.gag;
1593 if (global.gag)
1595 Dsymbol sym = isMember();
1596 if (sym && !sym.isSpeculative())
1597 global.gag = 0;
1600 if (_scope)
1602 inuse++;
1603 _init = _init.initializerSemantic(_scope, type, INITinterpret);
1604 import dmd.semantic2 : lowerStaticAAs;
1605 lowerStaticAAs(this, _scope);
1606 _scope = null;
1607 inuse--;
1610 Expression e = _init.initializerToExpression(needFullType ? type : null);
1611 global.gag = oldgag;
1612 return e;
1615 /*******************************************
1616 * Helper function for the expansion of manifest constant.
1618 extern (D) final Expression expandInitializer(Loc loc)
1620 assert((storage_class & STC.manifest) && _init);
1622 auto e = getConstInitializer();
1623 if (!e)
1625 .error(loc, "cannot make expression out of initializer for `%s`", toChars());
1626 return ErrorExp.get();
1629 e = e.copy();
1630 e.loc = loc; // for better error message
1631 return e;
1634 override final void checkCtorConstInit()
1636 version (none)
1638 /* doesn't work if more than one static ctor */
1639 if (ctorinit == 0 && isCtorinit() && !isField())
1640 error("missing initializer in static constructor for const variable");
1644 /************************************
1645 * Check to see if this variable is actually in an enclosing function
1646 * rather than the current one.
1647 * Update nestedrefs[], closureVars[] and outerVars[].
1648 * Returns: true if error occurs.
1650 extern (D) final bool checkNestedReference(Scope* sc, Loc loc)
1652 //printf("VarDeclaration::checkNestedReference() %s\n", toChars());
1653 if (sc.intypeof == 1 || (sc.flags & SCOPE.ctfe))
1654 return false;
1655 if (!parent || parent == sc.parent)
1656 return false;
1657 if (isDataseg() || (storage_class & STC.manifest))
1658 return false;
1660 // The current function
1661 FuncDeclaration fdthis = sc.parent.isFuncDeclaration();
1662 if (!fdthis)
1663 return false; // out of function scope
1665 Dsymbol p = toParent2();
1667 // Function literals from fdthis to p must be delegates
1668 ensureStaticLinkTo(fdthis, p);
1670 // The function that this variable is in
1671 FuncDeclaration fdv = p.isFuncDeclaration();
1672 if (!fdv || fdv == fdthis)
1673 return false;
1675 // Add fdthis to nestedrefs[] if not already there
1676 if (!nestedrefs.contains(fdthis))
1677 nestedrefs.push(fdthis);
1679 //printf("\tfdv = %s\n", fdv.toChars());
1680 //printf("\tfdthis = %s\n", fdthis.toChars());
1681 if (loc.isValid())
1683 if (fdthis.getLevelAndCheck(loc, sc, fdv, this) == fdthis.LevelError)
1684 return true;
1687 // Add this VarDeclaration to fdv.closureVars[] if not already there
1688 if (!sc.intypeof && !(sc.flags & SCOPE.compile) &&
1689 // https://issues.dlang.org/show_bug.cgi?id=17605
1690 (fdv.skipCodegen || !fdthis.skipCodegen))
1692 if (!fdv.closureVars.contains(this))
1693 fdv.closureVars.push(this);
1696 if (!fdthis.outerVars.contains(this))
1697 fdthis.outerVars.push(this);
1699 //printf("fdthis is %s\n", fdthis.toChars());
1700 //printf("var %s in function %s is nested ref\n", toChars(), fdv.toChars());
1701 // __dollar creates problems because it isn't a real variable
1702 // https://issues.dlang.org/show_bug.cgi?id=3326
1703 if (ident == Id.dollar)
1705 .error(loc, "cannnot use `$` inside a function literal");
1706 return true;
1708 if (ident == Id.withSym) // https://issues.dlang.org/show_bug.cgi?id=1759
1710 ExpInitializer ez = _init.isExpInitializer();
1711 assert(ez);
1712 Expression e = ez.exp;
1713 if (e.op == EXP.construct || e.op == EXP.blit)
1714 e = (cast(AssignExp)e).e2;
1715 return lambdaCheckForNestedRef(e, sc);
1718 return false;
1721 override final Dsymbol toAlias()
1723 //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym);
1724 if ((!type || !type.deco) && _scope)
1725 dsymbolSemantic(this, _scope);
1727 assert(this != aliasTuple);
1728 Dsymbol s = aliasTuple ? aliasTuple.toAlias() : this;
1729 return s;
1732 // Eliminate need for dynamic_cast
1733 override final inout(VarDeclaration) isVarDeclaration() inout
1735 return this;
1738 override void accept(Visitor v)
1740 v.visit(this);
1744 /*******************************************************
1745 * C11 6.7.2.1-4 bit fields
1747 extern (C++) class BitFieldDeclaration : VarDeclaration
1749 Expression width;
1751 uint fieldWidth;
1752 uint bitOffset;
1754 final extern (D) this(const ref Loc loc, Type type, Identifier ident, Expression width)
1756 super(loc, type, ident, null);
1758 this.width = width;
1759 this.storage_class |= STC.field;
1762 override BitFieldDeclaration syntaxCopy(Dsymbol s)
1764 //printf("BitFieldDeclaration::syntaxCopy(%s)\n", toChars());
1765 assert(!s);
1766 auto bf = new BitFieldDeclaration(loc, type ? type.syntaxCopy() : null, ident, width.syntaxCopy());
1767 bf.comment = comment;
1768 return bf;
1771 override final inout(BitFieldDeclaration) isBitFieldDeclaration() inout
1773 return this;
1776 override void accept(Visitor v)
1778 v.visit(this);
1781 /***********************************
1782 * Retrieve the .min or .max values.
1783 * Only valid after semantic analysis.
1784 * Params:
1785 * id = Id.min or Id.max
1786 * Returns:
1787 * the min or max value
1789 final ulong getMinMax(Identifier id)
1791 const width = fieldWidth;
1792 const uns = type.isunsigned();
1793 const min = id == Id.min;
1794 ulong v;
1795 assert(width != 0); // should have been rejected in semantic pass
1796 if (width == ulong.sizeof * 8)
1797 v = uns ? (min ? ulong.min : ulong.max)
1798 : (min ? long.min : long.max);
1799 else
1800 v = uns ? (min ? 0
1801 : (1L << width) - 1)
1802 : (min ? -(1L << (width - 1))
1803 : (1L << (width - 1)) - 1);
1804 return v;
1807 override final void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion)
1809 enum log = false;
1810 static if (log)
1812 printf("BitFieldDeclaration::setFieldOffset(ad: %s, field: %s)\n", ad.toChars(), toChars());
1813 void print(const ref FieldState fieldState)
1815 printf("FieldState.offset = %d bytes\n", fieldState.offset);
1816 printf(" .fieldOffset = %d bytes\n", fieldState.fieldOffset);
1817 printf(" .bitOffset = %d bits\n", fieldState.bitOffset);
1818 printf(" .fieldSize = %d bytes\n", fieldState.fieldSize);
1819 printf(" .inFlight = %d\n", fieldState.inFlight);
1820 printf(" fieldWidth = %d bits\n", fieldWidth);
1822 print(fieldState);
1825 Type t = type.toBasetype();
1826 const bool anon = isAnonymous();
1828 // List in ad.fields. Even if the type is error, it's necessary to avoid
1829 // pointless error diagnostic "more initializers than fields" on struct literal.
1830 if (!anon)
1831 ad.fields.push(this);
1833 if (t.ty == Terror)
1834 return;
1836 const sz = t.size(loc);
1837 assert(sz != SIZE_INVALID && sz < uint.max);
1838 uint memsize = cast(uint)sz; // size of member
1839 uint memalignsize = target.fieldalign(t); // size of member for alignment purposes
1840 if (log) printf(" memsize: %u memalignsize: %u\n", memsize, memalignsize);
1842 if (fieldWidth == 0 && !anon)
1843 error(loc, "named bit fields cannot have 0 width");
1844 if (fieldWidth > memsize * 8)
1845 error(loc, "bit field width %d is larger than type", fieldWidth);
1847 const style = target.c.bitFieldStyle;
1849 void startNewField()
1851 if (log) printf("startNewField()\n");
1852 uint alignsize;
1853 if (style == TargetC.BitFieldStyle.Gcc_Clang)
1855 if (fieldWidth > 32)
1856 alignsize = memalignsize;
1857 else if (fieldWidth > 16)
1858 alignsize = 4;
1859 else if (fieldWidth > 8)
1860 alignsize = 2;
1861 else
1862 alignsize = 1;
1864 else
1865 alignsize = memsize; // not memalignsize
1867 uint dummy;
1868 offset = AggregateDeclaration.placeField(
1869 &fieldState.offset,
1870 memsize, alignsize, alignment,
1871 &ad.structsize,
1872 (anon && style == TargetC.BitFieldStyle.Gcc_Clang) ? &dummy : &ad.alignsize,
1873 isunion);
1875 fieldState.inFlight = true;
1876 fieldState.fieldOffset = offset;
1877 fieldState.bitOffset = 0;
1878 fieldState.fieldSize = memsize;
1881 if (style == TargetC.BitFieldStyle.Gcc_Clang)
1883 if (fieldWidth == 0)
1885 if (!isunion)
1887 // Use type of zero width field to align to next field
1888 fieldState.offset = (fieldState.offset + memalignsize - 1) & ~(memalignsize - 1);
1889 ad.structsize = fieldState.offset;
1892 fieldState.inFlight = false;
1893 return;
1896 if (ad.alignsize == 0)
1897 ad.alignsize = 1;
1898 if (!anon &&
1899 ad.alignsize < memalignsize)
1900 ad.alignsize = memalignsize;
1902 else if (style == TargetC.BitFieldStyle.MS)
1904 if (ad.alignsize == 0)
1905 ad.alignsize = 1;
1906 if (fieldWidth == 0)
1908 if (fieldState.inFlight && !isunion)
1910 // documentation says align to next int
1911 //const alsz = cast(uint)Type.tint32.size();
1912 const alsz = memsize; // but it really does this
1913 fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1);
1914 ad.structsize = fieldState.offset;
1917 fieldState.inFlight = false;
1918 return;
1921 else if (style == TargetC.BitFieldStyle.DM)
1923 if (anon && fieldWidth && (!fieldState.inFlight || fieldState.bitOffset == 0))
1924 return; // this probably should be a bug in DMC
1925 if (ad.alignsize == 0)
1926 ad.alignsize = 1;
1927 if (fieldWidth == 0)
1929 if (fieldState.inFlight && !isunion)
1931 const alsz = memsize;
1932 fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1);
1933 ad.structsize = fieldState.offset;
1936 fieldState.inFlight = false;
1937 return;
1941 if (!fieldState.inFlight)
1943 //printf("not in flight\n");
1944 startNewField();
1946 else if (style == TargetC.BitFieldStyle.Gcc_Clang)
1948 // If the bit-field spans more units of alignment than its type,
1949 // start a new field at the next alignment boundary.
1950 if (fieldState.bitOffset == fieldState.fieldSize * 8 &&
1951 fieldState.bitOffset + fieldWidth > memalignsize * 8)
1953 if (log) printf("more units of alignment than its type\n");
1954 startNewField(); // the bit field is full
1956 else
1958 // if alignment boundary is crossed
1959 uint start = fieldState.fieldOffset * 8 + fieldState.bitOffset;
1960 uint end = start + fieldWidth;
1961 //printf("%s start: %d end: %d memalignsize: %d\n", ad.toChars(), start, end, memalignsize);
1962 if (start / (memalignsize * 8) != (end - 1) / (memalignsize * 8))
1964 if (log) printf("alignment is crossed\n");
1965 startNewField();
1969 else if (style == TargetC.BitFieldStyle.DM ||
1970 style == TargetC.BitFieldStyle.MS)
1972 if (memsize != fieldState.fieldSize ||
1973 fieldState.bitOffset + fieldWidth > fieldState.fieldSize * 8)
1975 //printf("new field\n");
1976 startNewField();
1979 else
1980 assert(0);
1982 offset = fieldState.fieldOffset;
1983 bitOffset = fieldState.bitOffset;
1985 const pastField = bitOffset + fieldWidth;
1986 if (style == TargetC.BitFieldStyle.Gcc_Clang)
1988 auto size = (pastField + 7) / 8;
1989 fieldState.fieldSize = size;
1990 //printf(" offset: %d, size: %d\n", offset, size);
1991 ad.structsize = offset + size;
1993 else
1994 fieldState.fieldSize = memsize;
1995 //printf("at end: ad.structsize = %d\n", cast(int)ad.structsize);
1996 //print(fieldState);
1998 if (!isunion)
2000 fieldState.offset = offset + fieldState.fieldSize;
2001 fieldState.bitOffset = pastField;
2004 //printf("\t%s: offset = %d bitOffset = %d fieldWidth = %d memsize = %d\n", toChars(), offset, bitOffset, fieldWidth, memsize);
2005 //printf("\t%s: memalignsize = %d\n", toChars(), memalignsize);
2006 //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize);
2010 /***********************************************************
2011 * This is a shell around a back end symbol
2013 extern (C++) final class SymbolDeclaration : Declaration
2015 AggregateDeclaration dsym;
2017 extern (D) this(const ref Loc loc, AggregateDeclaration dsym) @safe
2019 super(loc, dsym.ident);
2020 this.dsym = dsym;
2021 storage_class |= STC.const_;
2024 // Eliminate need for dynamic_cast
2025 override inout(SymbolDeclaration) isSymbolDeclaration() inout
2027 return this;
2030 override void accept(Visitor v)
2032 v.visit(this);
2036 /***********************************************************
2038 extern (C++) class TypeInfoDeclaration : VarDeclaration
2040 Type tinfo;
2042 final extern (D) this(Type tinfo)
2044 super(Loc.initial, Type.dtypeinfo.type, tinfo.getTypeInfoIdent(), null);
2045 this.tinfo = tinfo;
2046 storage_class = STC.static_ | STC.gshared;
2047 visibility = Visibility(Visibility.Kind.public_);
2048 _linkage = LINK.c;
2049 alignment.set(target.ptrsize);
2052 static TypeInfoDeclaration create(Type tinfo)
2054 return new TypeInfoDeclaration(tinfo);
2057 override final TypeInfoDeclaration syntaxCopy(Dsymbol s)
2059 assert(0); // should never be produced by syntax
2062 override final const(char)* toChars() const
2064 //printf("TypeInfoDeclaration::toChars() tinfo = %s\n", tinfo.toChars());
2065 OutBuffer buf;
2066 buf.writestring("typeid(");
2067 buf.writestring(tinfo.toChars());
2068 buf.writeByte(')');
2069 return buf.extractChars();
2072 override final inout(TypeInfoDeclaration) isTypeInfoDeclaration() inout @nogc nothrow pure @safe
2074 return this;
2077 override void accept(Visitor v)
2079 v.visit(this);
2083 /***********************************************************
2085 extern (C++) final class TypeInfoStructDeclaration : TypeInfoDeclaration
2087 extern (D) this(Type tinfo)
2089 super(tinfo);
2090 if (!Type.typeinfostruct)
2092 ObjectNotFound(Id.TypeInfo_Struct);
2094 type = Type.typeinfostruct.type;
2097 static TypeInfoStructDeclaration create(Type tinfo)
2099 return new TypeInfoStructDeclaration(tinfo);
2102 override void accept(Visitor v)
2104 v.visit(this);
2108 /***********************************************************
2110 extern (C++) final class TypeInfoClassDeclaration : TypeInfoDeclaration
2112 extern (D) this(Type tinfo)
2114 super(tinfo);
2115 if (!Type.typeinfoclass)
2117 ObjectNotFound(Id.TypeInfo_Class);
2119 type = Type.typeinfoclass.type;
2122 static TypeInfoClassDeclaration create(Type tinfo)
2124 return new TypeInfoClassDeclaration(tinfo);
2127 override void accept(Visitor v)
2129 v.visit(this);
2133 /***********************************************************
2135 extern (C++) final class TypeInfoInterfaceDeclaration : TypeInfoDeclaration
2137 extern (D) this(Type tinfo)
2139 super(tinfo);
2140 if (!Type.typeinfointerface)
2142 ObjectNotFound(Id.TypeInfo_Interface);
2144 type = Type.typeinfointerface.type;
2147 static TypeInfoInterfaceDeclaration create(Type tinfo)
2149 return new TypeInfoInterfaceDeclaration(tinfo);
2152 override void accept(Visitor v)
2154 v.visit(this);
2158 /***********************************************************
2160 extern (C++) final class TypeInfoPointerDeclaration : TypeInfoDeclaration
2162 extern (D) this(Type tinfo)
2164 super(tinfo);
2165 if (!Type.typeinfopointer)
2167 ObjectNotFound(Id.TypeInfo_Pointer);
2169 type = Type.typeinfopointer.type;
2172 static TypeInfoPointerDeclaration create(Type tinfo)
2174 return new TypeInfoPointerDeclaration(tinfo);
2177 override void accept(Visitor v)
2179 v.visit(this);
2183 /***********************************************************
2185 extern (C++) final class TypeInfoArrayDeclaration : TypeInfoDeclaration
2187 extern (D) this(Type tinfo)
2189 super(tinfo);
2190 if (!Type.typeinfoarray)
2192 ObjectNotFound(Id.TypeInfo_Array);
2194 type = Type.typeinfoarray.type;
2197 static TypeInfoArrayDeclaration create(Type tinfo)
2199 return new TypeInfoArrayDeclaration(tinfo);
2202 override void accept(Visitor v)
2204 v.visit(this);
2208 /***********************************************************
2210 extern (C++) final class TypeInfoStaticArrayDeclaration : TypeInfoDeclaration
2212 extern (D) this(Type tinfo)
2214 super(tinfo);
2215 if (!Type.typeinfostaticarray)
2217 ObjectNotFound(Id.TypeInfo_StaticArray);
2219 type = Type.typeinfostaticarray.type;
2222 static TypeInfoStaticArrayDeclaration create(Type tinfo)
2224 return new TypeInfoStaticArrayDeclaration(tinfo);
2227 override void accept(Visitor v)
2229 v.visit(this);
2233 /***********************************************************
2235 extern (C++) final class TypeInfoAssociativeArrayDeclaration : TypeInfoDeclaration
2237 extern (D) this(Type tinfo)
2239 super(tinfo);
2240 if (!Type.typeinfoassociativearray)
2242 ObjectNotFound(Id.TypeInfo_AssociativeArray);
2244 type = Type.typeinfoassociativearray.type;
2247 static TypeInfoAssociativeArrayDeclaration create(Type tinfo)
2249 return new TypeInfoAssociativeArrayDeclaration(tinfo);
2252 override void accept(Visitor v)
2254 v.visit(this);
2258 /***********************************************************
2260 extern (C++) final class TypeInfoEnumDeclaration : TypeInfoDeclaration
2262 extern (D) this(Type tinfo)
2264 super(tinfo);
2265 if (!Type.typeinfoenum)
2267 ObjectNotFound(Id.TypeInfo_Enum);
2269 type = Type.typeinfoenum.type;
2272 static TypeInfoEnumDeclaration create(Type tinfo)
2274 return new TypeInfoEnumDeclaration(tinfo);
2277 override void accept(Visitor v)
2279 v.visit(this);
2283 /***********************************************************
2285 extern (C++) final class TypeInfoFunctionDeclaration : TypeInfoDeclaration
2287 extern (D) this(Type tinfo)
2289 super(tinfo);
2290 if (!Type.typeinfofunction)
2292 ObjectNotFound(Id.TypeInfo_Function);
2294 type = Type.typeinfofunction.type;
2297 static TypeInfoFunctionDeclaration create(Type tinfo)
2299 return new TypeInfoFunctionDeclaration(tinfo);
2302 override void accept(Visitor v)
2304 v.visit(this);
2308 /***********************************************************
2310 extern (C++) final class TypeInfoDelegateDeclaration : TypeInfoDeclaration
2312 extern (D) this(Type tinfo)
2314 super(tinfo);
2315 if (!Type.typeinfodelegate)
2317 ObjectNotFound(Id.TypeInfo_Delegate);
2319 type = Type.typeinfodelegate.type;
2322 static TypeInfoDelegateDeclaration create(Type tinfo)
2324 return new TypeInfoDelegateDeclaration(tinfo);
2327 override void accept(Visitor v)
2329 v.visit(this);
2333 /***********************************************************
2335 extern (C++) final class TypeInfoTupleDeclaration : TypeInfoDeclaration
2337 extern (D) this(Type tinfo)
2339 super(tinfo);
2340 if (!Type.typeinfotypelist)
2342 ObjectNotFound(Id.TypeInfo_Tuple);
2344 type = Type.typeinfotypelist.type;
2347 static TypeInfoTupleDeclaration create(Type tinfo)
2349 return new TypeInfoTupleDeclaration(tinfo);
2352 override void accept(Visitor v)
2354 v.visit(this);
2358 /***********************************************************
2360 extern (C++) final class TypeInfoConstDeclaration : TypeInfoDeclaration
2362 extern (D) this(Type tinfo)
2364 super(tinfo);
2365 if (!Type.typeinfoconst)
2367 ObjectNotFound(Id.TypeInfo_Const);
2369 type = Type.typeinfoconst.type;
2372 static TypeInfoConstDeclaration create(Type tinfo)
2374 return new TypeInfoConstDeclaration(tinfo);
2377 override void accept(Visitor v)
2379 v.visit(this);
2383 /***********************************************************
2385 extern (C++) final class TypeInfoInvariantDeclaration : TypeInfoDeclaration
2387 extern (D) this(Type tinfo)
2389 super(tinfo);
2390 if (!Type.typeinfoinvariant)
2392 ObjectNotFound(Id.TypeInfo_Invariant);
2394 type = Type.typeinfoinvariant.type;
2397 static TypeInfoInvariantDeclaration create(Type tinfo)
2399 return new TypeInfoInvariantDeclaration(tinfo);
2402 override void accept(Visitor v)
2404 v.visit(this);
2408 /***********************************************************
2410 extern (C++) final class TypeInfoSharedDeclaration : TypeInfoDeclaration
2412 extern (D) this(Type tinfo)
2414 super(tinfo);
2415 if (!Type.typeinfoshared)
2417 ObjectNotFound(Id.TypeInfo_Shared);
2419 type = Type.typeinfoshared.type;
2422 static TypeInfoSharedDeclaration create(Type tinfo)
2424 return new TypeInfoSharedDeclaration(tinfo);
2427 override void accept(Visitor v)
2429 v.visit(this);
2433 /***********************************************************
2435 extern (C++) final class TypeInfoWildDeclaration : TypeInfoDeclaration
2437 extern (D) this(Type tinfo)
2439 super(tinfo);
2440 if (!Type.typeinfowild)
2442 ObjectNotFound(Id.TypeInfo_Wild);
2444 type = Type.typeinfowild.type;
2447 static TypeInfoWildDeclaration create(Type tinfo)
2449 return new TypeInfoWildDeclaration(tinfo);
2452 override void accept(Visitor v)
2454 v.visit(this);
2458 /***********************************************************
2460 extern (C++) final class TypeInfoVectorDeclaration : TypeInfoDeclaration
2462 extern (D) this(Type tinfo)
2464 super(tinfo);
2465 if (!Type.typeinfovector)
2467 ObjectNotFound(Id.TypeInfo_Vector);
2469 type = Type.typeinfovector.type;
2472 static TypeInfoVectorDeclaration create(Type tinfo)
2474 return new TypeInfoVectorDeclaration(tinfo);
2477 override void accept(Visitor v)
2479 v.visit(this);
2483 /***********************************************************
2484 * For the "this" parameter to member functions
2486 extern (C++) final class ThisDeclaration : VarDeclaration
2488 extern (D) this(const ref Loc loc, Type t)
2490 super(loc, t, Id.This, null);
2491 storage_class |= STC.nodtor;
2494 override ThisDeclaration syntaxCopy(Dsymbol s)
2496 assert(0); // should never be produced by syntax
2499 override inout(ThisDeclaration) isThisDeclaration() inout
2501 return this;
2504 override void accept(Visitor v)
2506 v.visit(this);