d: Merge upstream dmd, druntime 4ca4140e58, phobos 454dff14d.
[official-gcc.git] / gcc / d / dmd / declaration.d
blob7cd8df19bdcb0fab5dcd39c06a6efe611f4fa077
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.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.location;
39 import dmd.mtype;
40 import dmd.common.outbuffer;
41 import dmd.root.rootobject;
42 import dmd.target;
43 import dmd.tokens;
44 import dmd.typesem;
45 import dmd.visitor;
47 /************************************
48 * Check to see the aggregate type is nested and its context pointer is
49 * accessible from the current scope.
50 * Returns true if error occurs.
52 bool checkFrameAccess(Loc loc, Scope* sc, AggregateDeclaration ad, size_t iStart = 0)
54 Dsymbol sparent = ad.toParentLocal();
55 Dsymbol sparent2 = ad.toParent2();
56 Dsymbol s = sc.func;
57 if (ad.isNested() && s)
59 //printf("ad = %p %s [%s], parent:%p\n", ad, ad.toChars(), ad.loc.toChars(), ad.parent);
60 //printf("sparent = %p %s [%s], parent: %s\n", sparent, sparent.toChars(), sparent.loc.toChars(), sparent.parent,toChars());
61 //printf("sparent2 = %p %s [%s], parent: %s\n", sparent2, sparent2.toChars(), sparent2.loc.toChars(), sparent2.parent,toChars());
62 if (!ensureStaticLinkTo(s, sparent) || sparent != sparent2 && !ensureStaticLinkTo(s, sparent2))
64 error(loc, "cannot access frame pointer of `%s`", ad.toPrettyChars());
65 return true;
69 bool result = false;
70 for (size_t i = iStart; i < ad.fields.length; i++)
72 VarDeclaration vd = ad.fields[i];
73 Type tb = vd.type.baseElemOf();
74 if (tb.ty == Tstruct)
76 result |= checkFrameAccess(loc, sc, (cast(TypeStruct)tb).sym);
79 return result;
82 /***********************************************
83 * Mark variable v as modified if it is inside a constructor that var
84 * is a field in.
85 * Also used to allow immutable globals to be initialized inside a static constructor.
86 * Returns:
87 * true if it's an initialization of v
89 bool modifyFieldVar(Loc loc, Scope* sc, VarDeclaration var, Expression e1)
91 //printf("modifyFieldVar(var = %s)\n", var.toChars());
92 Dsymbol s = sc.func;
93 while (1)
95 FuncDeclaration fd = null;
96 if (s)
97 fd = s.isFuncDeclaration();
98 if (fd &&
99 ((fd.isCtorDeclaration() && var.isField()) ||
100 ((fd.isStaticCtorDeclaration() || fd.isCrtCtor) && !var.isField())) &&
101 fd.toParentDecl() == var.toParent2() &&
102 (!e1 || e1.op == EXP.this_))
104 bool result = true;
106 var.ctorinit = true;
107 //printf("setting ctorinit\n");
109 if (var.isField() && sc.ctorflow.fieldinit.length && !sc.intypeof)
111 assert(e1);
112 auto mustInit = ((var.storage_class & STC.nodefaultctor) != 0 ||
113 var.type.needsNested());
115 const dim = sc.ctorflow.fieldinit.length;
116 auto ad = fd.isMemberDecl();
117 assert(ad);
118 size_t i;
119 for (i = 0; i < dim; i++) // same as findFieldIndexByName in ctfeexp.c ?
121 if (ad.fields[i] == var)
122 break;
124 assert(i < dim);
125 auto fieldInit = &sc.ctorflow.fieldinit[i];
126 const fi = fieldInit.csx;
128 if (fi & CSX.this_ctor)
130 if (var.type.isMutable() && e1.type.isMutable())
131 result = false;
132 else
134 const(char)* modStr = !var.type.isMutable() ? MODtoChars(var.type.mod) : MODtoChars(e1.type.mod);
135 .error(loc, "%s field `%s` initialized multiple times", modStr, var.toChars());
136 .errorSupplemental(fieldInit.loc, "Previous initialization is here.");
139 else if (sc.inLoop || (fi & CSX.label))
141 if (!mustInit && var.type.isMutable() && e1.type.isMutable())
142 result = false;
143 else
145 const(char)* modStr = !var.type.isMutable() ? MODtoChars(var.type.mod) : MODtoChars(e1.type.mod);
146 .error(loc, "%s field `%s` initialization is not allowed in loops or after labels", modStr, var.toChars());
150 fieldInit.csx |= CSX.this_ctor;
151 fieldInit.loc = e1.loc;
152 if (var.overlapped) // https://issues.dlang.org/show_bug.cgi?id=15258
154 foreach (j, v; ad.fields)
156 if (v is var || !var.isOverlappedWith(v))
157 continue;
158 v.ctorinit = true;
159 sc.ctorflow.fieldinit[j].csx = CSX.this_ctor;
163 else if (fd != sc.func)
165 if (var.type.isMutable())
166 result = false;
167 else if (sc.func.fes)
169 const(char)* p = var.isField() ? "field" : var.kind();
170 .error(loc, "%s %s `%s` initialization is not allowed in foreach loop",
171 MODtoChars(var.type.mod), p, var.toChars());
173 else
175 const(char)* p = var.isField() ? "field" : var.kind();
176 .error(loc, "%s %s `%s` initialization is not allowed in nested function `%s`",
177 MODtoChars(var.type.mod), p, var.toChars(), sc.func.toChars());
180 else if (fd.isStaticCtorDeclaration() && !fd.isSharedStaticCtorDeclaration() &&
181 var.type.isImmutable())
183 .error(loc, "%s %s `%s` initialization is not allowed in `static this`",
184 MODtoChars(var.type.mod), var.kind(), var.toChars());
185 errorSupplemental(loc, "Use `shared static this` instead.");
187 return result;
189 else
191 if (s)
193 s = s.toParentP(var.toParent2());
194 continue;
197 break;
199 return false;
202 /******************************************
204 extern (C++) void ObjectNotFound(Identifier id)
206 error(Loc.initial, "`%s` not found. object.d may be incorrectly installed or corrupt.", id.toChars());
207 fatal();
210 /* Accumulator for successive matches.
212 struct MatchAccumulator
214 int count; // number of matches found so far
215 MATCH last = MATCH.nomatch; // match level of lastf
216 FuncDeclaration lastf; // last matching function we found
217 FuncDeclaration nextf; // if ambiguous match, this is the "other" function
220 /***********************************************************
222 extern (C++) abstract class Declaration : Dsymbol
224 Type type;
225 Type originalType; // before semantic analysis
226 StorageClass storage_class = STC.undefined_;
227 Visibility visibility;
228 LINK _linkage = LINK.default_; // may be `LINK.system`; use `resolvedLinkage()` to resolve it
229 short inuse; // used to detect cycles
231 ubyte adFlags; // control re-assignment of AliasDeclaration (put here for packing reasons)
232 enum wasRead = 1; // set if AliasDeclaration was read
233 enum ignoreRead = 2; // ignore any reads of AliasDeclaration
234 enum nounderscore = 4; // don't prepend _ to mangled name
236 Symbol* isym; // import version of csym
238 // overridden symbol with pragma(mangle, "...")
239 const(char)[] mangleOverride;
241 final extern (D) this(Identifier ident)
243 super(ident);
244 visibility = Visibility(Visibility.Kind.undefined);
247 final extern (D) this(const ref Loc loc, Identifier ident)
249 super(loc, ident);
250 visibility = Visibility(Visibility.Kind.undefined);
253 override const(char)* kind() const
255 return "declaration";
258 override final uinteger_t size(const ref Loc loc)
260 assert(type);
261 const sz = type.size();
262 if (sz == SIZE_INVALID)
263 errors = true;
264 return sz;
268 * Issue an error if an attempt to call a disabled method is made
270 * If the declaration is disabled but inside a disabled function,
271 * returns `true` but do not issue an error message.
273 * Params:
274 * loc = Location information of the call
275 * sc = Scope in which the call occurs
276 * isAliasedDeclaration = if `true` searches overload set
278 * Returns:
279 * `true` if this `Declaration` is `@disable`d, `false` otherwise.
281 extern (D) final bool checkDisabled(Loc loc, Scope* sc, bool isAliasedDeclaration = false)
283 if (!(storage_class & STC.disable))
284 return false;
286 if (sc.func && sc.func.storage_class & STC.disable)
287 return true;
289 if (auto p = toParent())
291 if (auto postblit = isPostBlitDeclaration())
293 /* https://issues.dlang.org/show_bug.cgi?id=21885
295 * If the generated postblit is disabled, it
296 * means that one of the fields has a disabled
297 * postblit. Print the first field that has
298 * a disabled postblit.
300 if (postblit.isGenerated())
302 auto sd = p.isStructDeclaration();
303 assert(sd);
304 for (size_t i = 0; i < sd.fields.length; i++)
306 auto structField = sd.fields[i];
307 if (structField.overlapped)
308 continue;
309 Type tv = structField.type.baseElemOf();
310 if (tv.ty != Tstruct)
311 continue;
312 auto sdv = (cast(TypeStruct)tv).sym;
313 if (!sdv.postblit)
314 continue;
315 if (sdv.postblit.isDisabled())
317 p.error(loc, "is not copyable because field `%s` is not copyable", structField.toChars());
318 return true;
322 p.error(loc, "is not copyable because it has a disabled postblit");
323 return true;
327 // if the function is @disabled, maybe there
328 // is an overload in the overload set that isn't
329 if (isAliasedDeclaration)
331 FuncDeclaration fd = isFuncDeclaration();
332 if (fd)
334 for (FuncDeclaration ovl = fd; ovl; ovl = cast(FuncDeclaration)ovl.overnext)
335 if (!(ovl.storage_class & STC.disable))
336 return false;
340 if (auto ctor = isCtorDeclaration())
342 if (ctor.isCpCtor && ctor.isGenerated())
344 .error(loc, "generating an `inout` copy constructor for `struct %s` failed, therefore instances of it are uncopyable", parent.toPrettyChars());
345 return true;
348 error(loc, "cannot be used because it is annotated with `@disable`");
349 return true;
352 /*************************************
353 * Check to see if declaration can be modified in this context (sc).
354 * Issue error if not.
355 * Params:
356 * loc = location for error messages
357 * e1 = `null` or `this` expression when this declaration is a field
358 * sc = context
359 * flag = if the first bit is set it means do not issue error message for
360 * invalid modification; if the second bit is set, it means that
361 this declaration is a field and a subfield of it is modified.
362 * Returns:
363 * Modifiable.yes or Modifiable.initialization
365 extern (D) final Modifiable checkModify(Loc loc, Scope* sc, Expression e1, ModifyFlags flag)
367 VarDeclaration v = isVarDeclaration();
368 if (v && v.canassign)
369 return Modifiable.initialization;
371 if (isParameter() || isResult())
373 for (Scope* scx = sc; scx; scx = scx.enclosing)
375 if (scx.func == parent && (scx.flags & SCOPE.contract))
377 const(char)* s = isParameter() && parent.ident != Id.ensure ? "parameter" : "result";
378 if (!(flag & ModifyFlags.noError))
379 error(loc, "cannot modify %s `%s` in contract", s, toChars());
380 return Modifiable.initialization; // do not report type related errors
385 if (e1 && e1.op == EXP.this_ && isField())
387 VarDeclaration vthis = e1.isThisExp().var;
388 for (Scope* scx = sc; scx; scx = scx.enclosing)
390 if (scx.func == vthis.parent && (scx.flags & SCOPE.contract))
392 if (!(flag & ModifyFlags.noError))
393 error(loc, "cannot modify parameter `this` in contract");
394 return Modifiable.initialization; // do not report type related errors
399 if (v && (v.isCtorinit() || isField()))
401 // It's only modifiable if inside the right constructor
402 if ((storage_class & (STC.foreach_ | STC.ref_)) == (STC.foreach_ | STC.ref_))
403 return Modifiable.initialization;
404 if (flag & ModifyFlags.fieldAssign)
405 return Modifiable.yes;
406 return modifyFieldVar(loc, sc, v, e1) ? Modifiable.initialization : Modifiable.yes;
408 return Modifiable.yes;
411 override final Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
413 Dsymbol s = Dsymbol.search(loc, ident, flags);
414 if (!s && type)
416 s = type.toDsymbol(_scope);
417 if (s)
418 s = s.search(loc, ident, flags);
420 return s;
423 final bool isStatic() const pure nothrow @nogc @safe
425 return (storage_class & STC.static_) != 0;
428 /// Returns the linkage, resolving the target-specific `System` one.
429 final LINK resolvedLinkage() const
431 return _linkage == LINK.system ? target.systemLinkage() : _linkage;
434 bool isDelete()
436 return false;
439 bool isDataseg()
441 return false;
444 bool isThreadlocal()
446 return false;
449 bool isCodeseg() const pure nothrow @nogc @safe
451 return false;
454 final bool isFinal() const pure nothrow @nogc @safe
456 return (storage_class & STC.final_) != 0;
459 bool isAbstract()
461 return (storage_class & STC.abstract_) != 0;
464 final bool isConst() const pure nothrow @nogc @safe
466 return (storage_class & STC.const_) != 0;
469 final bool isImmutable() const pure nothrow @nogc @safe
471 return (storage_class & STC.immutable_) != 0;
474 final bool isWild() const pure nothrow @nogc @safe
476 return (storage_class & STC.wild) != 0;
479 final bool isAuto() const pure nothrow @nogc @safe
481 return (storage_class & STC.auto_) != 0;
484 final bool isScope() const pure nothrow @nogc @safe
486 return (storage_class & STC.scope_) != 0;
489 final bool isReturn() const pure nothrow @nogc @safe
491 return (storage_class & STC.return_) != 0;
494 final bool isSynchronized() const pure nothrow @nogc @safe
496 return (storage_class & STC.synchronized_) != 0;
499 final bool isParameter() const pure nothrow @nogc @safe
501 return (storage_class & STC.parameter) != 0;
504 override final bool isDeprecated() const pure nothrow @nogc @safe
506 return (storage_class & STC.deprecated_) != 0;
509 final bool isDisabled() const pure nothrow @nogc @safe
511 return (storage_class & STC.disable) != 0;
514 final bool isOverride() const pure nothrow @nogc @safe
516 return (storage_class & STC.override_) != 0;
519 final bool isResult() const pure nothrow @nogc @safe
521 return (storage_class & STC.result) != 0;
524 final bool isField() const pure nothrow @nogc @safe
526 return (storage_class & STC.field) != 0;
529 final bool isIn() const pure nothrow @nogc @safe
531 return (storage_class & STC.in_) != 0;
534 final bool isOut() const pure nothrow @nogc @safe
536 return (storage_class & STC.out_) != 0;
539 final bool isRef() const pure nothrow @nogc @safe
541 return (storage_class & STC.ref_) != 0;
544 /// Returns: Whether the variable is a reference, annotated with `out` or `ref`
545 final bool isReference() const pure nothrow @nogc @safe
547 return (storage_class & (STC.ref_ | STC.out_)) != 0;
550 final bool isFuture() const pure nothrow @nogc @safe
552 return (storage_class & STC.future) != 0;
555 final extern(D) bool isSystem() const pure nothrow @nogc @safe
557 return (storage_class & STC.system) != 0;
560 override final Visibility visible() pure nothrow @nogc @safe
562 return visibility;
565 override final inout(Declaration) isDeclaration() inout pure nothrow @nogc @safe
567 return this;
570 override void accept(Visitor v)
572 v.visit(this);
576 /***********************************************************
578 extern (C++) final class TupleDeclaration : Declaration
580 Objects* objects;
581 TypeTuple tupletype; // !=null if this is a type tuple
582 bool isexp; // true: expression tuple
583 bool building; // it's growing in AliasAssign semantic
585 extern (D) this(const ref Loc loc, Identifier ident, Objects* objects)
587 super(loc, ident);
588 this.objects = objects;
591 override TupleDeclaration syntaxCopy(Dsymbol s)
593 assert(0);
596 override const(char)* kind() const
598 return "tuple";
601 override Type getType()
603 /* If this tuple represents a type, return that type
606 //printf("TupleDeclaration::getType() %s\n", toChars());
607 if (isexp || building)
608 return null;
609 if (!tupletype)
611 /* It's only a type tuple if all the Object's are types
613 for (size_t i = 0; i < objects.length; i++)
615 RootObject o = (*objects)[i];
616 if (o.dyncast() != DYNCAST.type)
618 //printf("\tnot[%d], %p, %d\n", i, o, o.dyncast());
619 return null;
623 /* We know it's a type tuple, so build the TypeTuple
625 Types* types = cast(Types*)objects;
626 auto args = new Parameters(objects.length);
627 OutBuffer buf;
628 int hasdeco = 1;
629 for (size_t i = 0; i < types.length; i++)
631 Type t = (*types)[i];
632 //printf("type = %s\n", t.toChars());
633 version (none)
635 buf.printf("_%s_%d", ident.toChars(), i);
636 const len = buf.offset;
637 const name = buf.extractSlice().ptr;
638 auto id = Identifier.idPool(name, len);
639 auto arg = new Parameter(STC.in_, t, id, null);
641 else
643 auto arg = new Parameter(0, t, null, null, null);
645 (*args)[i] = arg;
646 if (!t.deco)
647 hasdeco = 0;
650 tupletype = new TypeTuple(args);
651 if (hasdeco)
652 return tupletype.typeSemantic(Loc.initial, null);
654 return tupletype;
657 override Dsymbol toAlias2()
659 //printf("TupleDeclaration::toAlias2() '%s' objects = %s\n", toChars(), objects.toChars());
660 for (size_t i = 0; i < objects.length; i++)
662 RootObject o = (*objects)[i];
663 if (Dsymbol s = isDsymbol(o))
665 s = s.toAlias2();
666 (*objects)[i] = s;
669 return this;
672 override bool needThis()
674 //printf("TupleDeclaration::needThis(%s)\n", toChars());
675 return isexp ? foreachVar((s) { return s.needThis(); }) != 0 : false;
678 /***********************************************************
679 * Calls dg(Dsymbol) for each Dsymbol, which should be a VarDeclaration
680 * inside VarExp (isexp == true).
681 * Params:
682 * dg = delegate to call for each Dsymbol
684 extern (D) void foreachVar(scope void delegate(Dsymbol) dg)
686 assert(isexp);
687 foreach (o; *objects)
689 if (auto e = o.isExpression())
690 if (auto ve = e.isVarExp())
691 dg(ve.var);
695 /***********************************************************
696 * Calls dg(Dsymbol) for each Dsymbol, which should be a VarDeclaration
697 * inside VarExp (isexp == true).
698 * If dg returns !=0, stops and returns that value else returns 0.
699 * Params:
700 * dg = delegate to call for each Dsymbol
701 * Returns:
702 * last value returned by dg()
704 extern (D) int foreachVar(scope int delegate(Dsymbol) dg)
706 assert(isexp);
707 foreach (o; *objects)
709 if (auto e = o.isExpression())
710 if (auto ve = e.isVarExp())
711 if(auto ret = dg(ve.var))
712 return ret;
714 return 0;
717 override inout(TupleDeclaration) isTupleDeclaration() inout
719 return this;
722 override void accept(Visitor v)
724 v.visit(this);
728 /***********************************************************
729 * https://dlang.org/spec/declaration.html#AliasDeclaration
731 extern (C++) final class AliasDeclaration : Declaration
733 Dsymbol aliassym; // alias ident = aliassym;
735 Dsymbol overnext; // next in overload list
736 Dsymbol _import; // !=null if unresolved internal alias for selective import
738 extern (D) this(const ref Loc loc, Identifier ident, Type type)
740 super(loc, ident);
741 //printf("AliasDeclaration(id = '%s', type = %p)\n", id.toChars(), type);
742 //printf("type = '%s'\n", type.toChars());
743 this.type = type;
744 assert(type);
747 extern (D) this(const ref Loc loc, Identifier ident, Dsymbol s)
749 super(loc, ident);
750 //printf("AliasDeclaration(id = '%s', s = %p)\n", id.toChars(), s);
751 assert(s != this);
752 this.aliassym = s;
753 assert(s);
756 static AliasDeclaration create(const ref Loc loc, Identifier id, Type type)
758 return new AliasDeclaration(loc, id, type);
761 override AliasDeclaration syntaxCopy(Dsymbol s)
763 //printf("AliasDeclaration::syntaxCopy()\n");
764 assert(!s);
765 AliasDeclaration sa = type ? new AliasDeclaration(loc, ident, type.syntaxCopy()) : new AliasDeclaration(loc, ident, aliassym.syntaxCopy(null));
766 sa.comment = comment;
767 sa.storage_class = storage_class;
768 return sa;
771 override bool overloadInsert(Dsymbol s)
773 //printf("[%s] AliasDeclaration::overloadInsert('%s') s = %s %s @ [%s]\n",
774 // loc.toChars(), toChars(), s.kind(), s.toChars(), s.loc.toChars());
776 /** Aliases aren't overloadable themselves, but if their Aliasee is
777 * overloadable they are converted to an overloadable Alias (either
778 * FuncAliasDeclaration or OverDeclaration).
780 * This is done by moving the Aliasee into such an overloadable alias
781 * which is then used to replace the existing Aliasee. The original
782 * Alias (_this_) remains a useless shell.
784 * This is a horrible mess. It was probably done to avoid replacing
785 * existing AST nodes and references, but it needs a major
786 * simplification b/c it's too complex to maintain.
788 * A simpler approach might be to merge any colliding symbols into a
789 * simple Overload class (an array) and then later have that resolve
790 * all collisions.
792 if (semanticRun >= PASS.semanticdone)
794 /* Semantic analysis is already finished, and the aliased entity
795 * is not overloadable.
797 if (type)
800 If type has been resolved already we could
801 still be inserting an alias from an import.
803 If we are handling an alias then pretend
804 it was inserting and return true, if not then
805 false since we didn't even pretend to insert something.
807 return this._import && this.equals(s);
810 /* When s is added in member scope by static if, mixin("code") or others,
811 * aliassym is determined already. See the case in: test/compilable/test61.d
813 auto sa = aliassym.toAlias();
815 if (auto td = s.toAlias().isTemplateDeclaration())
816 s = td.funcroot ? td.funcroot : td;
818 if (auto fd = sa.isFuncDeclaration())
820 auto fa = new FuncAliasDeclaration(ident, fd);
821 fa.visibility = visibility;
822 fa.parent = parent;
823 aliassym = fa;
824 return aliassym.overloadInsert(s);
826 if (auto td = sa.isTemplateDeclaration())
828 auto od = new OverDeclaration(ident, td.funcroot ? td.funcroot : td);
829 od.visibility = visibility;
830 od.parent = parent;
831 aliassym = od;
832 return aliassym.overloadInsert(s);
834 if (auto od = sa.isOverDeclaration())
836 if (sa.ident != ident || sa.parent != parent)
838 od = new OverDeclaration(ident, od);
839 od.visibility = visibility;
840 od.parent = parent;
841 aliassym = od;
843 return od.overloadInsert(s);
845 if (auto os = sa.isOverloadSet())
847 if (sa.ident != ident || sa.parent != parent)
849 os = new OverloadSet(ident, os);
850 // TODO: visibility is lost here b/c OverloadSets have no visibility attribute
851 // Might no be a practical issue, b/c the code below fails to resolve the overload anyhow.
852 // ----
853 // module os1;
854 // import a, b;
855 // private alias merged = foo; // private alias to overload set of a.foo and b.foo
856 // ----
857 // module os2;
858 // import a, b;
859 // public alias merged = bar; // public alias to overload set of a.bar and b.bar
860 // ----
861 // module bug;
862 // import os1, os2;
863 // void test() { merged(123); } // should only look at os2.merged
865 // os.visibility = visibility;
866 os.parent = parent;
867 aliassym = os;
869 os.push(s);
870 return true;
872 return false;
875 /* Don't know yet what the aliased symbol is, so assume it can
876 * be overloaded and check later for correctness.
878 if (overnext)
879 return overnext.overloadInsert(s);
880 if (s is this)
881 return true;
882 overnext = s;
883 return true;
886 override const(char)* kind() const
888 return "alias";
891 override Type getType()
893 if (type)
894 return type;
895 return toAlias().getType();
898 override Dsymbol toAlias()
900 //printf("[%s] AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s', inuse = %d)\n",
901 // loc.toChars(), toChars(), this, aliassym, aliassym ? aliassym.kind() : "", inuse);
902 assert(this != aliassym);
903 //static int count; if (++count == 10) *(char*)0=0;
905 // Reading the AliasDeclaration
906 if (!(adFlags & ignoreRead))
907 adFlags |= wasRead; // can never assign to this AliasDeclaration again
909 if (inuse == 1 && type && _scope)
911 inuse = 2;
912 uint olderrors = global.errors;
913 Dsymbol s = type.toDsymbol(_scope);
914 //printf("[%s] type = %s, s = %p, this = %p\n", loc.toChars(), type.toChars(), s, this);
915 if (global.errors != olderrors)
916 goto Lerr;
917 if (s)
919 s = s.toAlias();
920 if (global.errors != olderrors)
921 goto Lerr;
922 aliassym = s;
923 inuse = 0;
925 else
927 Type t = type.typeSemantic(loc, _scope);
928 if (t.ty == Terror)
929 goto Lerr;
930 if (global.errors != olderrors)
931 goto Lerr;
932 //printf("t = %s\n", t.toChars());
933 inuse = 0;
936 if (inuse)
938 error("recursive alias declaration");
940 Lerr:
941 // Avoid breaking "recursive alias" state during errors gagged
942 if (global.gag)
943 return this;
944 aliassym = new AliasDeclaration(loc, ident, Type.terror);
945 type = Type.terror;
946 return aliassym;
949 if (semanticRun >= PASS.semanticdone)
951 // semantic is already done.
953 // Do not see aliassym !is null, because of lambda aliases.
955 // Do not see type.deco !is null, even so "alias T = const int;` needs
956 // semantic analysis to take the storage class `const` as type qualifier.
958 else
960 // stop AliasAssign tuple building
961 if (aliassym)
963 if (auto td = aliassym.isTupleDeclaration())
965 if (td.building)
967 td.building = false;
968 semanticRun = PASS.semanticdone;
969 return td;
973 if (_import && _import._scope)
975 /* If this is an internal alias for selective/renamed import,
976 * load the module first.
978 _import.dsymbolSemantic(null);
980 if (_scope)
982 aliasSemantic(this, _scope);
986 inuse = 1;
987 Dsymbol s = aliassym ? aliassym.toAlias() : this;
988 inuse = 0;
989 return s;
992 override Dsymbol toAlias2()
994 if (inuse)
996 error("recursive alias declaration");
997 return this;
999 inuse = 1;
1000 Dsymbol s = aliassym ? aliassym.toAlias2() : this;
1001 inuse = 0;
1002 return s;
1005 override bool isOverloadable() const
1007 // assume overloadable until alias is resolved
1008 return semanticRun < PASS.semanticdone ||
1009 aliassym && aliassym.isOverloadable();
1012 override inout(AliasDeclaration) isAliasDeclaration() inout
1014 return this;
1017 /** Returns: `true` if this instance was created to make a template parameter
1018 visible in the scope of a template body, `false` otherwise */
1019 extern (D) bool isAliasedTemplateParameter() const
1021 return !!(storage_class & STC.templateparameter);
1024 override void accept(Visitor v)
1026 v.visit(this);
1030 /***********************************************************
1032 extern (C++) final class OverDeclaration : Declaration
1034 Dsymbol overnext; // next in overload list
1035 Dsymbol aliassym;
1037 extern (D) this(Identifier ident, Dsymbol s)
1039 super(ident);
1040 this.aliassym = s;
1043 override const(char)* kind() const
1045 return "overload alias"; // todo
1048 override bool equals(const RootObject o) const
1050 if (this == o)
1051 return true;
1053 auto s = isDsymbol(o);
1054 if (!s)
1055 return false;
1057 if (auto od2 = s.isOverDeclaration())
1058 return this.aliassym.equals(od2.aliassym);
1059 return this.aliassym == s;
1062 override bool overloadInsert(Dsymbol s)
1064 //printf("OverDeclaration::overloadInsert('%s') aliassym = %p, overnext = %p\n", s.toChars(), aliassym, overnext);
1065 if (overnext)
1066 return overnext.overloadInsert(s);
1067 if (s == this)
1068 return true;
1069 overnext = s;
1070 return true;
1073 override bool isOverloadable() const
1075 return true;
1078 Dsymbol isUnique()
1080 Dsymbol result = null;
1081 overloadApply(aliassym, (Dsymbol s)
1083 if (result)
1085 result = null;
1086 return 1; // ambiguous, done
1088 else
1090 result = s;
1091 return 0;
1094 return result;
1097 override inout(OverDeclaration) isOverDeclaration() inout
1099 return this;
1102 override void accept(Visitor v)
1104 v.visit(this);
1108 /***********************************************************
1110 extern (C++) class VarDeclaration : Declaration
1112 Initializer _init;
1113 FuncDeclarations nestedrefs; // referenced by these lexically nested functions
1114 TupleDeclaration aliasTuple; // when `this` is really a tuple of declarations
1115 VarDeclaration lastVar; // Linked list of variables for goto-skips-init detection
1116 Expression edtor; // if !=null, does the destruction of the variable
1117 IntRange* range; // if !=null, the variable is known to be within the range
1118 VarDeclarations* maybes; // maybeScope variables that are assigned to this maybeScope variable
1120 uint endlinnum; // line number of end of scope that this var lives in
1121 uint offset;
1122 uint sequenceNumber; // order the variables are declared
1123 structalign_t alignment;
1125 // When interpreting, these point to the value (NULL if value not determinable)
1126 // The index of this variable on the CTFE stack, AdrOnStackNone if not allocated
1127 enum AdrOnStackNone = ~0u;
1128 uint ctfeAdrOnStack;
1130 // `bool` fields that are compacted into bit fields in a string mixin
1131 private extern (D) static struct BitFields
1133 bool isargptr; /// if parameter that _argptr points to
1134 bool ctorinit; /// it has been initialized in a ctor
1135 bool iscatchvar; /// this is the exception object variable in catch() clause
1136 bool isowner; /// this is an Owner, despite it being `scope`
1137 bool setInCtorOnly; /// field can only be set in a constructor, as it is const or immutable
1139 /// It is a class that was allocated on the stack
1141 /// This means the var is not rebindable once assigned,
1142 /// and the destructor gets run when it goes out of scope
1143 bool onstack;
1145 bool overlapped; /// if it is a field and has overlapping
1146 bool overlapUnsafe; /// if it is an overlapping field and the overlaps are unsafe
1147 bool maybeScope; /// allow inferring 'scope' for this variable
1148 bool doNotInferReturn; /// do not infer 'return' for this variable
1150 bool isArgDtorVar; /// temporary created to handle scope destruction of a function argument
1151 bool isCmacro; /// it is a C macro turned into a C declaration
1152 version (MARS)
1154 bool inClosure; /// is inserted into a GC allocated closure
1155 bool inAlignSection; /// is inserted into an aligned section on stack
1159 import dmd.common.bitfields : generateBitFields;
1160 mixin(generateBitFields!(BitFields, ushort));
1162 byte canassign; // it can be assigned to
1163 ubyte isdataseg; // private data for isDataseg 0 unset, 1 true, 2 false
1165 final extern (D) this(const ref Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.undefined_)
1168 assert(ident);
1172 //printf("VarDeclaration('%s')\n", ident.toChars());
1173 super(loc, ident);
1174 debug
1176 if (!type && !_init)
1178 //printf("VarDeclaration('%s')\n", ident.toChars());
1179 //*(char*)0=0;
1183 assert(type || _init);
1184 this.type = type;
1185 this._init = _init;
1186 ctfeAdrOnStack = AdrOnStackNone;
1187 this.storage_class = storage_class;
1190 static VarDeclaration create(const ref Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.undefined_)
1192 return new VarDeclaration(loc, type, ident, _init, storage_class);
1195 override VarDeclaration syntaxCopy(Dsymbol s)
1197 //printf("VarDeclaration::syntaxCopy(%s)\n", toChars());
1198 assert(!s);
1199 auto v = new VarDeclaration(loc, type ? type.syntaxCopy() : null, ident, _init ? _init.syntaxCopy() : null, storage_class);
1200 v.comment = comment;
1201 return v;
1204 override void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion)
1206 //printf("VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars());
1208 if (aliasTuple)
1210 // If this variable was really a tuple, set the offsets for the tuple fields
1211 aliasTuple.foreachVar((s) { s.setFieldOffset(ad, fieldState, isunion); });
1212 return;
1215 if (!isField())
1216 return;
1217 assert(!(storage_class & (STC.static_ | STC.extern_ | STC.parameter)));
1219 //printf("+VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars());
1221 /* Fields that are tuples appear both as part of TupleDeclarations and
1222 * as members. That means ignore them if they are already a field.
1224 if (offset)
1226 // already a field
1227 fieldState.offset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613
1228 return;
1230 for (size_t i = 0; i < ad.fields.length; i++)
1232 if (ad.fields[i] == this)
1234 // already a field
1235 fieldState.offset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613
1236 return;
1240 // Check for forward referenced types which will fail the size() call
1241 Type t = type.toBasetype();
1242 if (storage_class & STC.ref_)
1244 // References are the size of a pointer
1245 t = Type.tvoidptr;
1247 Type tv = t.baseElemOf();
1248 if (tv.ty == Tstruct)
1250 auto ts = cast(TypeStruct)tv;
1251 assert(ts.sym != ad); // already checked in ad.determineFields()
1252 if (!ts.sym.determineSize(loc))
1254 type = Type.terror;
1255 errors = true;
1256 return;
1260 // List in ad.fields. Even if the type is error, it's necessary to avoid
1261 // pointless error diagnostic "more initializers than fields" on struct literal.
1262 ad.fields.push(this);
1264 if (t.ty == Terror)
1265 return;
1267 /* If coming after a bit field in progress,
1268 * advance past the field
1270 fieldState.inFlight = false;
1272 const sz = t.size(loc);
1273 assert(sz != SIZE_INVALID && sz < uint.max);
1274 uint memsize = cast(uint)sz; // size of member
1275 uint memalignsize = target.fieldalign(t); // size of member for alignment purposes
1276 offset = AggregateDeclaration.placeField(
1277 &fieldState.offset,
1278 memsize, memalignsize, alignment,
1279 &ad.structsize, &ad.alignsize,
1280 isunion);
1282 //printf("\t%s: memalignsize = %d\n", toChars(), memalignsize);
1283 //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize);
1286 override const(char)* kind() const
1288 return "variable";
1291 override final inout(AggregateDeclaration) isThis() inout
1293 if (!(storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.templateparameter | STC.gshared | STC.ctfe)))
1295 /* The casting is necessary because `s = s.parent` is otherwise rejected
1297 for (auto s = cast(Dsymbol)this; s; s = s.parent)
1299 auto ad = (cast(inout)s).isMember();
1300 if (ad)
1301 return ad;
1302 if (!s.parent || !s.parent.isTemplateMixin())
1303 break;
1306 return null;
1309 override final bool needThis()
1311 //printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class);
1312 return isField();
1315 override final bool isExport() const
1317 return visibility.kind == Visibility.Kind.export_;
1320 override final bool isImportedSymbol() const
1322 /* If global variable has `export` and `extern` then it is imported
1323 * export int sym1; // definition: exported
1324 * export extern int sym2; // declaration: imported
1325 * export extern int sym3 = 0; // error, extern cannot have initializer
1327 bool result =
1328 visibility.kind == Visibility.Kind.export_ &&
1329 storage_class & STC.extern_ &&
1330 (storage_class & STC.static_ || parent.isModule());
1331 //printf("isImportedSymbol() %s %d\n", toChars(), result);
1332 return result;
1335 final bool isCtorinit() const pure nothrow @nogc @safe
1337 return setInCtorOnly;
1340 /*******************************
1341 * Does symbol go into data segment?
1342 * Includes extern variables.
1344 override final bool isDataseg()
1346 version (none)
1348 printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars());
1349 printf("%llx, isModule: %p, isTemplateInstance: %p, isNspace: %p\n",
1350 storage_class & (STC.static_ | STC.const_), parent.isModule(), parent.isTemplateInstance(), parent.isNspace());
1351 printf("parent = '%s'\n", parent.toChars());
1354 if (isdataseg == 0) // the value is not cached
1356 isdataseg = 2; // The Variables does not go into the datasegment
1358 if (!canTakeAddressOf())
1360 return false;
1363 Dsymbol parent = toParent();
1364 if (!parent && !(storage_class & STC.static_))
1366 error("forward referenced");
1367 type = Type.terror;
1369 else if (storage_class & (STC.static_ | STC.extern_ | STC.gshared) ||
1370 parent.isModule() || parent.isTemplateInstance() || parent.isNspace())
1372 assert(!isParameter() && !isResult());
1373 isdataseg = 1; // It is in the DataSegment
1377 return (isdataseg == 1);
1379 /************************************
1380 * Does symbol go into thread local storage?
1382 override final bool isThreadlocal()
1384 //printf("VarDeclaration::isThreadlocal(%p, '%s')\n", this, toChars());
1385 /* Data defaults to being thread-local. It is not thread-local
1386 * if it is immutable, const or shared.
1388 bool i = isDataseg() && !(storage_class & (STC.immutable_ | STC.const_ | STC.shared_ | STC.gshared));
1389 //printf("\treturn %d\n", i);
1390 return i;
1393 /********************************************
1394 * Can variable be read and written by CTFE?
1396 final bool isCTFE()
1398 return (storage_class & STC.ctfe) != 0; // || !isDataseg();
1401 final bool isOverlappedWith(VarDeclaration v)
1403 const vsz = v.type.size();
1404 const tsz = type.size();
1405 assert(vsz != SIZE_INVALID && tsz != SIZE_INVALID);
1407 // Overlap is checked by comparing bit offsets
1408 auto bitoffset = offset * 8;
1409 auto vbitoffset = v.offset * 8;
1411 // Bitsize of types are overridden by any bit-field widths.
1412 ulong tbitsize = void;
1413 if (auto bf = isBitFieldDeclaration())
1415 bitoffset += bf.bitOffset;
1416 tbitsize = bf.fieldWidth;
1418 else
1419 tbitsize = tsz * 8;
1421 ulong vbitsize = void;
1422 if (auto vbf = v.isBitFieldDeclaration())
1424 vbitoffset += vbf.bitOffset;
1425 vbitsize = vbf.fieldWidth;
1427 else
1428 vbitsize = vsz * 8;
1430 return bitoffset < vbitoffset + vbitsize &&
1431 vbitoffset < bitoffset + tbitsize;
1434 override final bool hasPointers()
1436 //printf("VarDeclaration::hasPointers() %s, ty = %d\n", toChars(), type.ty);
1437 return (!isDataseg() && type.hasPointers());
1440 /*************************************
1441 * Return true if we can take the address of this variable.
1443 final bool canTakeAddressOf()
1445 return !(storage_class & STC.manifest);
1448 /******************************************
1449 * Return true if variable needs to call the destructor.
1451 final bool needsScopeDtor()
1453 //printf("VarDeclaration::needsScopeDtor() %s\n", toChars());
1454 return edtor && !(storage_class & STC.nodtor);
1457 /******************************************
1458 * If a variable has a scope destructor call, return call for it.
1459 * Otherwise, return NULL.
1461 extern (D) final Expression callScopeDtor(Scope* sc)
1463 //printf("VarDeclaration::callScopeDtor() %s\n", toChars());
1465 // Destruction of STC.field's is handled by buildDtor()
1466 if (storage_class & (STC.nodtor | STC.ref_ | STC.out_ | STC.field))
1468 return null;
1471 if (iscatchvar)
1472 return null; // destructor is built by `void semantic(Catch c, Scope* sc)`, not here
1474 Expression e = null;
1475 // Destructors for structs and arrays of structs
1476 Type tv = type.baseElemOf();
1477 if (tv.ty == Tstruct)
1479 StructDeclaration sd = (cast(TypeStruct)tv).sym;
1480 if (!sd.dtor || sd.errors)
1481 return null;
1483 const sz = type.size();
1484 assert(sz != SIZE_INVALID);
1485 if (!sz)
1486 return null;
1488 if (type.toBasetype().ty == Tstruct)
1490 // v.__xdtor()
1491 e = new VarExp(loc, this);
1493 /* This is a hack so we can call destructors on const/immutable objects.
1494 * Need to add things like "const ~this()" and "immutable ~this()" to
1495 * fix properly.
1497 e.type = e.type.mutableOf();
1499 // Enable calling destructors on shared objects.
1500 // The destructor is always a single, non-overloaded function,
1501 // and must serve both shared and non-shared objects.
1502 e.type = e.type.unSharedOf;
1504 e = new DotVarExp(loc, e, sd.dtor, false);
1505 e = new CallExp(loc, e);
1507 else
1509 // __ArrayDtor(v[0 .. n])
1510 e = new VarExp(loc, this);
1512 const sdsz = sd.type.size();
1513 assert(sdsz != SIZE_INVALID && sdsz != 0);
1514 const n = sz / sdsz;
1515 SliceExp se = new SliceExp(loc, e, new IntegerExp(loc, 0, Type.tsize_t),
1516 new IntegerExp(loc, n, Type.tsize_t));
1518 // Prevent redundant bounds check
1519 se.upperIsInBounds = true;
1520 se.lowerIsLessThanUpper = true;
1522 // This is a hack so we can call destructors on const/immutable objects.
1523 se.type = sd.type.arrayOf();
1525 e = new CallExp(loc, new IdentifierExp(loc, Id.__ArrayDtor), se);
1527 return e;
1529 // Destructors for classes
1530 if (storage_class & (STC.auto_ | STC.scope_) && !(storage_class & STC.parameter))
1532 for (ClassDeclaration cd = type.isClassHandle(); cd; cd = cd.baseClass)
1534 /* We can do better if there's a way with onstack
1535 * classes to determine if there's no way the monitor
1536 * could be set.
1538 //if (cd.isInterfaceDeclaration())
1539 // error("interface `%s` cannot be scope", cd.toChars());
1541 if (onstack) // if any destructors
1543 // delete'ing C++ classes crashes (and delete is deprecated anyway)
1544 if (cd.classKind == ClassKind.cpp)
1546 // Don't call non-existant dtor
1547 if (!cd.dtor)
1548 break;
1550 e = new VarExp(loc, this);
1551 e.type = e.type.mutableOf().unSharedOf(); // Hack for mutable ctor on immutable instances
1552 e = new DotVarExp(loc, e, cd.dtor, false);
1553 e = new CallExp(loc, e);
1554 break;
1557 // delete this;
1558 Expression ec;
1559 ec = new VarExp(loc, this);
1560 e = new DeleteExp(loc, ec, true);
1561 e.type = Type.tvoid;
1562 break;
1566 return e;
1569 /*******************************************
1570 * If variable has a constant expression initializer, get it.
1571 * Otherwise, return null.
1573 extern (D) final Expression getConstInitializer(bool needFullType = true)
1575 assert(type && _init);
1577 // Ungag errors when not speculative
1578 uint oldgag = global.gag;
1579 if (global.gag)
1581 Dsymbol sym = isMember();
1582 if (sym && !sym.isSpeculative())
1583 global.gag = 0;
1586 if (_scope)
1588 inuse++;
1589 _init = _init.initializerSemantic(_scope, type, INITinterpret);
1590 _scope = null;
1591 inuse--;
1594 Expression e = _init.initializerToExpression(needFullType ? type : null);
1595 global.gag = oldgag;
1596 return e;
1599 /*******************************************
1600 * Helper function for the expansion of manifest constant.
1602 extern (D) final Expression expandInitializer(Loc loc)
1604 assert((storage_class & STC.manifest) && _init);
1606 auto e = getConstInitializer();
1607 if (!e)
1609 .error(loc, "cannot make expression out of initializer for `%s`", toChars());
1610 return ErrorExp.get();
1613 e = e.copy();
1614 e.loc = loc; // for better error message
1615 return e;
1618 override final void checkCtorConstInit()
1620 version (none)
1622 /* doesn't work if more than one static ctor */
1623 if (ctorinit == 0 && isCtorinit() && !isField())
1624 error("missing initializer in static constructor for const variable");
1628 /************************************
1629 * Check to see if this variable is actually in an enclosing function
1630 * rather than the current one.
1631 * Update nestedrefs[], closureVars[] and outerVars[].
1632 * Returns: true if error occurs.
1634 extern (D) final bool checkNestedReference(Scope* sc, Loc loc)
1636 //printf("VarDeclaration::checkNestedReference() %s\n", toChars());
1637 if (sc.intypeof == 1 || (sc.flags & SCOPE.ctfe))
1638 return false;
1639 if (!parent || parent == sc.parent)
1640 return false;
1641 if (isDataseg() || (storage_class & STC.manifest))
1642 return false;
1644 // The current function
1645 FuncDeclaration fdthis = sc.parent.isFuncDeclaration();
1646 if (!fdthis)
1647 return false; // out of function scope
1649 Dsymbol p = toParent2();
1651 // Function literals from fdthis to p must be delegates
1652 ensureStaticLinkTo(fdthis, p);
1654 // The function that this variable is in
1655 FuncDeclaration fdv = p.isFuncDeclaration();
1656 if (!fdv || fdv == fdthis)
1657 return false;
1659 // Add fdthis to nestedrefs[] if not already there
1660 if (!nestedrefs.contains(fdthis))
1661 nestedrefs.push(fdthis);
1663 //printf("\tfdv = %s\n", fdv.toChars());
1664 //printf("\tfdthis = %s\n", fdthis.toChars());
1665 if (loc.isValid())
1667 if (fdthis.getLevelAndCheck(loc, sc, fdv, this) == fdthis.LevelError)
1668 return true;
1671 // Add this VarDeclaration to fdv.closureVars[] if not already there
1672 if (!sc.intypeof && !(sc.flags & SCOPE.compile) &&
1673 // https://issues.dlang.org/show_bug.cgi?id=17605
1674 (fdv.skipCodegen || !fdthis.skipCodegen))
1676 if (!fdv.closureVars.contains(this))
1677 fdv.closureVars.push(this);
1680 if (!fdthis.outerVars.contains(this))
1681 fdthis.outerVars.push(this);
1683 //printf("fdthis is %s\n", fdthis.toChars());
1684 //printf("var %s in function %s is nested ref\n", toChars(), fdv.toChars());
1685 // __dollar creates problems because it isn't a real variable
1686 // https://issues.dlang.org/show_bug.cgi?id=3326
1687 if (ident == Id.dollar)
1689 .error(loc, "cannnot use `$` inside a function literal");
1690 return true;
1692 if (ident == Id.withSym) // https://issues.dlang.org/show_bug.cgi?id=1759
1694 ExpInitializer ez = _init.isExpInitializer();
1695 assert(ez);
1696 Expression e = ez.exp;
1697 if (e.op == EXP.construct || e.op == EXP.blit)
1698 e = (cast(AssignExp)e).e2;
1699 return lambdaCheckForNestedRef(e, sc);
1702 return false;
1705 override final Dsymbol toAlias()
1707 //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym);
1708 if ((!type || !type.deco) && _scope)
1709 dsymbolSemantic(this, _scope);
1711 assert(this != aliasTuple);
1712 Dsymbol s = aliasTuple ? aliasTuple.toAlias() : this;
1713 return s;
1716 // Eliminate need for dynamic_cast
1717 override final inout(VarDeclaration) isVarDeclaration() inout
1719 return this;
1722 override void accept(Visitor v)
1724 v.visit(this);
1728 /*******************************************************
1729 * C11 6.7.2.1-4 bit fields
1731 extern (C++) class BitFieldDeclaration : VarDeclaration
1733 Expression width;
1735 uint fieldWidth;
1736 uint bitOffset;
1738 final extern (D) this(const ref Loc loc, Type type, Identifier ident, Expression width)
1740 super(loc, type, ident, null);
1742 this.width = width;
1743 this.storage_class |= STC.field;
1746 override BitFieldDeclaration syntaxCopy(Dsymbol s)
1748 //printf("BitFieldDeclaration::syntaxCopy(%s)\n", toChars());
1749 assert(!s);
1750 auto bf = new BitFieldDeclaration(loc, type ? type.syntaxCopy() : null, ident, width.syntaxCopy());
1751 bf.comment = comment;
1752 return bf;
1755 override final inout(BitFieldDeclaration) isBitFieldDeclaration() inout
1757 return this;
1760 override void accept(Visitor v)
1762 v.visit(this);
1765 /***********************************
1766 * Retrieve the .min or .max values.
1767 * Only valid after semantic analysis.
1768 * Params:
1769 * id = Id.min or Id.max
1770 * Returns:
1771 * the min or max value
1773 final ulong getMinMax(Identifier id)
1775 const width = fieldWidth;
1776 const uns = type.isunsigned();
1777 const min = id == Id.min;
1778 ulong v;
1779 assert(width != 0); // should have been rejected in semantic pass
1780 if (width == ulong.sizeof * 8)
1781 v = uns ? (min ? ulong.min : ulong.max)
1782 : (min ? long.min : long.max);
1783 else
1784 v = uns ? (min ? 0
1785 : (1L << width) - 1)
1786 : (min ? -(1L << (width - 1))
1787 : (1L << (width - 1)) - 1);
1788 return v;
1791 override final void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion)
1793 enum log = false;
1794 static if (log)
1796 printf("BitFieldDeclaration::setFieldOffset(ad: %s, field: %s)\n", ad.toChars(), toChars());
1797 void print(const ref FieldState fieldState)
1799 printf("FieldState.offset = %d bytes\n", fieldState.offset);
1800 printf(" .fieldOffset = %d bytes\n", fieldState.fieldOffset);
1801 printf(" .bitOffset = %d bits\n", fieldState.bitOffset);
1802 printf(" .fieldSize = %d bytes\n", fieldState.fieldSize);
1803 printf(" .inFlight = %d\n", fieldState.inFlight);
1804 printf(" fieldWidth = %d bits\n", fieldWidth);
1806 print(fieldState);
1809 Type t = type.toBasetype();
1810 const bool anon = isAnonymous();
1812 // List in ad.fields. Even if the type is error, it's necessary to avoid
1813 // pointless error diagnostic "more initializers than fields" on struct literal.
1814 if (!anon)
1815 ad.fields.push(this);
1817 if (t.ty == Terror)
1818 return;
1820 const sz = t.size(loc);
1821 assert(sz != SIZE_INVALID && sz < uint.max);
1822 uint memsize = cast(uint)sz; // size of member
1823 uint memalignsize = target.fieldalign(t); // size of member for alignment purposes
1824 if (log) printf(" memsize: %u memalignsize: %u\n", memsize, memalignsize);
1826 if (fieldWidth == 0 && !anon)
1827 error(loc, "named bit fields cannot have 0 width");
1828 if (fieldWidth > memsize * 8)
1829 error(loc, "bit field width %d is larger than type", fieldWidth);
1831 const style = target.c.bitFieldStyle;
1833 void startNewField()
1835 if (log) printf("startNewField()\n");
1836 uint alignsize;
1837 if (style == TargetC.BitFieldStyle.Gcc_Clang)
1839 if (fieldWidth > 32)
1840 alignsize = memalignsize;
1841 else if (fieldWidth > 16)
1842 alignsize = 4;
1843 else if (fieldWidth > 8)
1844 alignsize = 2;
1845 else
1846 alignsize = 1;
1848 else
1849 alignsize = memsize; // not memalignsize
1851 uint dummy;
1852 offset = AggregateDeclaration.placeField(
1853 &fieldState.offset,
1854 memsize, alignsize, alignment,
1855 &ad.structsize,
1856 (anon && style == TargetC.BitFieldStyle.Gcc_Clang) ? &dummy : &ad.alignsize,
1857 isunion);
1859 fieldState.inFlight = true;
1860 fieldState.fieldOffset = offset;
1861 fieldState.bitOffset = 0;
1862 fieldState.fieldSize = memsize;
1865 if (style == TargetC.BitFieldStyle.Gcc_Clang)
1867 if (fieldWidth == 0)
1869 if (!isunion)
1871 // Use type of zero width field to align to next field
1872 fieldState.offset = (fieldState.offset + memalignsize - 1) & ~(memalignsize - 1);
1873 ad.structsize = fieldState.offset;
1876 fieldState.inFlight = false;
1877 return;
1880 if (ad.alignsize == 0)
1881 ad.alignsize = 1;
1882 if (!anon &&
1883 ad.alignsize < memalignsize)
1884 ad.alignsize = memalignsize;
1886 else if (style == TargetC.BitFieldStyle.MS)
1888 if (ad.alignsize == 0)
1889 ad.alignsize = 1;
1890 if (fieldWidth == 0)
1892 if (fieldState.inFlight && !isunion)
1894 // documentation says align to next int
1895 //const alsz = cast(uint)Type.tint32.size();
1896 const alsz = memsize; // but it really does this
1897 fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1);
1898 ad.structsize = fieldState.offset;
1901 fieldState.inFlight = false;
1902 return;
1905 else if (style == TargetC.BitFieldStyle.DM)
1907 if (anon && fieldWidth && (!fieldState.inFlight || fieldState.bitOffset == 0))
1908 return; // this probably should be a bug in DMC
1909 if (ad.alignsize == 0)
1910 ad.alignsize = 1;
1911 if (fieldWidth == 0)
1913 if (fieldState.inFlight && !isunion)
1915 const alsz = memsize;
1916 fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1);
1917 ad.structsize = fieldState.offset;
1920 fieldState.inFlight = false;
1921 return;
1925 if (!fieldState.inFlight)
1927 //printf("not in flight\n");
1928 startNewField();
1930 else if (style == TargetC.BitFieldStyle.Gcc_Clang)
1932 // If the bit-field spans more units of alignment than its type,
1933 // start a new field at the next alignment boundary.
1934 if (fieldState.bitOffset == fieldState.fieldSize * 8)
1935 startNewField(); // the bit field is full
1936 else
1938 // if alignment boundary is crossed
1939 uint start = fieldState.fieldOffset * 8 + fieldState.bitOffset;
1940 uint end = start + fieldWidth;
1941 //printf("%s start: %d end: %d memalignsize: %d\n", ad.toChars(), start, end, memalignsize);
1942 if (start / (memalignsize * 8) != (end - 1) / (memalignsize * 8))
1944 //printf("alignment is crossed\n");
1945 startNewField();
1949 else if (style == TargetC.BitFieldStyle.DM ||
1950 style == TargetC.BitFieldStyle.MS)
1952 if (memsize != fieldState.fieldSize ||
1953 fieldState.bitOffset + fieldWidth > fieldState.fieldSize * 8)
1955 //printf("new field\n");
1956 startNewField();
1959 else
1960 assert(0);
1962 offset = fieldState.fieldOffset;
1963 bitOffset = fieldState.bitOffset;
1965 const pastField = bitOffset + fieldWidth;
1966 if (style == TargetC.BitFieldStyle.Gcc_Clang)
1968 auto size = (pastField + 7) / 8;
1969 fieldState.fieldSize = size;
1970 //printf(" offset: %d, size: %d\n", offset, size);
1971 ad.structsize = offset + size;
1973 else
1974 fieldState.fieldSize = memsize;
1975 //printf("at end: ad.structsize = %d\n", cast(int)ad.structsize);
1976 //print(fieldState);
1978 if (!isunion)
1980 fieldState.offset = offset + fieldState.fieldSize;
1981 fieldState.bitOffset = pastField;
1984 //printf("\t%s: memalignsize = %d\n", toChars(), memalignsize);
1985 //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize);
1989 /***********************************************************
1990 * This is a shell around a back end symbol
1992 extern (C++) final class SymbolDeclaration : Declaration
1994 AggregateDeclaration dsym;
1996 extern (D) this(const ref Loc loc, AggregateDeclaration dsym)
1998 super(loc, dsym.ident);
1999 this.dsym = dsym;
2000 storage_class |= STC.const_;
2003 // Eliminate need for dynamic_cast
2004 override inout(SymbolDeclaration) isSymbolDeclaration() inout
2006 return this;
2009 override void accept(Visitor v)
2011 v.visit(this);
2015 /***********************************************************
2017 extern (C++) class TypeInfoDeclaration : VarDeclaration
2019 Type tinfo;
2021 final extern (D) this(Type tinfo)
2023 super(Loc.initial, Type.dtypeinfo.type, tinfo.getTypeInfoIdent(), null);
2024 this.tinfo = tinfo;
2025 storage_class = STC.static_ | STC.gshared;
2026 visibility = Visibility(Visibility.Kind.public_);
2027 _linkage = LINK.c;
2028 alignment.set(target.ptrsize);
2031 static TypeInfoDeclaration create(Type tinfo)
2033 return new TypeInfoDeclaration(tinfo);
2036 override final TypeInfoDeclaration syntaxCopy(Dsymbol s)
2038 assert(0); // should never be produced by syntax
2041 override final const(char)* toChars() const
2043 //printf("TypeInfoDeclaration::toChars() tinfo = %s\n", tinfo.toChars());
2044 OutBuffer buf;
2045 buf.writestring("typeid(");
2046 buf.writestring(tinfo.toChars());
2047 buf.writeByte(')');
2048 return buf.extractChars();
2051 override final inout(TypeInfoDeclaration) isTypeInfoDeclaration() inout @nogc nothrow pure @safe
2053 return this;
2056 override void accept(Visitor v)
2058 v.visit(this);
2062 /***********************************************************
2064 extern (C++) final class TypeInfoStructDeclaration : TypeInfoDeclaration
2066 extern (D) this(Type tinfo)
2068 super(tinfo);
2069 if (!Type.typeinfostruct)
2071 ObjectNotFound(Id.TypeInfo_Struct);
2073 type = Type.typeinfostruct.type;
2076 static TypeInfoStructDeclaration create(Type tinfo)
2078 return new TypeInfoStructDeclaration(tinfo);
2081 override void accept(Visitor v)
2083 v.visit(this);
2087 /***********************************************************
2089 extern (C++) final class TypeInfoClassDeclaration : TypeInfoDeclaration
2091 extern (D) this(Type tinfo)
2093 super(tinfo);
2094 if (!Type.typeinfoclass)
2096 ObjectNotFound(Id.TypeInfo_Class);
2098 type = Type.typeinfoclass.type;
2101 static TypeInfoClassDeclaration create(Type tinfo)
2103 return new TypeInfoClassDeclaration(tinfo);
2106 override void accept(Visitor v)
2108 v.visit(this);
2112 /***********************************************************
2114 extern (C++) final class TypeInfoInterfaceDeclaration : TypeInfoDeclaration
2116 extern (D) this(Type tinfo)
2118 super(tinfo);
2119 if (!Type.typeinfointerface)
2121 ObjectNotFound(Id.TypeInfo_Interface);
2123 type = Type.typeinfointerface.type;
2126 static TypeInfoInterfaceDeclaration create(Type tinfo)
2128 return new TypeInfoInterfaceDeclaration(tinfo);
2131 override void accept(Visitor v)
2133 v.visit(this);
2137 /***********************************************************
2139 extern (C++) final class TypeInfoPointerDeclaration : TypeInfoDeclaration
2141 extern (D) this(Type tinfo)
2143 super(tinfo);
2144 if (!Type.typeinfopointer)
2146 ObjectNotFound(Id.TypeInfo_Pointer);
2148 type = Type.typeinfopointer.type;
2151 static TypeInfoPointerDeclaration create(Type tinfo)
2153 return new TypeInfoPointerDeclaration(tinfo);
2156 override void accept(Visitor v)
2158 v.visit(this);
2162 /***********************************************************
2164 extern (C++) final class TypeInfoArrayDeclaration : TypeInfoDeclaration
2166 extern (D) this(Type tinfo)
2168 super(tinfo);
2169 if (!Type.typeinfoarray)
2171 ObjectNotFound(Id.TypeInfo_Array);
2173 type = Type.typeinfoarray.type;
2176 static TypeInfoArrayDeclaration create(Type tinfo)
2178 return new TypeInfoArrayDeclaration(tinfo);
2181 override void accept(Visitor v)
2183 v.visit(this);
2187 /***********************************************************
2189 extern (C++) final class TypeInfoStaticArrayDeclaration : TypeInfoDeclaration
2191 extern (D) this(Type tinfo)
2193 super(tinfo);
2194 if (!Type.typeinfostaticarray)
2196 ObjectNotFound(Id.TypeInfo_StaticArray);
2198 type = Type.typeinfostaticarray.type;
2201 static TypeInfoStaticArrayDeclaration create(Type tinfo)
2203 return new TypeInfoStaticArrayDeclaration(tinfo);
2206 override void accept(Visitor v)
2208 v.visit(this);
2212 /***********************************************************
2214 extern (C++) final class TypeInfoAssociativeArrayDeclaration : TypeInfoDeclaration
2216 extern (D) this(Type tinfo)
2218 super(tinfo);
2219 if (!Type.typeinfoassociativearray)
2221 ObjectNotFound(Id.TypeInfo_AssociativeArray);
2223 type = Type.typeinfoassociativearray.type;
2226 static TypeInfoAssociativeArrayDeclaration create(Type tinfo)
2228 return new TypeInfoAssociativeArrayDeclaration(tinfo);
2231 override void accept(Visitor v)
2233 v.visit(this);
2237 /***********************************************************
2239 extern (C++) final class TypeInfoEnumDeclaration : TypeInfoDeclaration
2241 extern (D) this(Type tinfo)
2243 super(tinfo);
2244 if (!Type.typeinfoenum)
2246 ObjectNotFound(Id.TypeInfo_Enum);
2248 type = Type.typeinfoenum.type;
2251 static TypeInfoEnumDeclaration create(Type tinfo)
2253 return new TypeInfoEnumDeclaration(tinfo);
2256 override void accept(Visitor v)
2258 v.visit(this);
2262 /***********************************************************
2264 extern (C++) final class TypeInfoFunctionDeclaration : TypeInfoDeclaration
2266 extern (D) this(Type tinfo)
2268 super(tinfo);
2269 if (!Type.typeinfofunction)
2271 ObjectNotFound(Id.TypeInfo_Function);
2273 type = Type.typeinfofunction.type;
2276 static TypeInfoFunctionDeclaration create(Type tinfo)
2278 return new TypeInfoFunctionDeclaration(tinfo);
2281 override void accept(Visitor v)
2283 v.visit(this);
2287 /***********************************************************
2289 extern (C++) final class TypeInfoDelegateDeclaration : TypeInfoDeclaration
2291 extern (D) this(Type tinfo)
2293 super(tinfo);
2294 if (!Type.typeinfodelegate)
2296 ObjectNotFound(Id.TypeInfo_Delegate);
2298 type = Type.typeinfodelegate.type;
2301 static TypeInfoDelegateDeclaration create(Type tinfo)
2303 return new TypeInfoDelegateDeclaration(tinfo);
2306 override void accept(Visitor v)
2308 v.visit(this);
2312 /***********************************************************
2314 extern (C++) final class TypeInfoTupleDeclaration : TypeInfoDeclaration
2316 extern (D) this(Type tinfo)
2318 super(tinfo);
2319 if (!Type.typeinfotypelist)
2321 ObjectNotFound(Id.TypeInfo_Tuple);
2323 type = Type.typeinfotypelist.type;
2326 static TypeInfoTupleDeclaration create(Type tinfo)
2328 return new TypeInfoTupleDeclaration(tinfo);
2331 override void accept(Visitor v)
2333 v.visit(this);
2337 /***********************************************************
2339 extern (C++) final class TypeInfoConstDeclaration : TypeInfoDeclaration
2341 extern (D) this(Type tinfo)
2343 super(tinfo);
2344 if (!Type.typeinfoconst)
2346 ObjectNotFound(Id.TypeInfo_Const);
2348 type = Type.typeinfoconst.type;
2351 static TypeInfoConstDeclaration create(Type tinfo)
2353 return new TypeInfoConstDeclaration(tinfo);
2356 override void accept(Visitor v)
2358 v.visit(this);
2362 /***********************************************************
2364 extern (C++) final class TypeInfoInvariantDeclaration : TypeInfoDeclaration
2366 extern (D) this(Type tinfo)
2368 super(tinfo);
2369 if (!Type.typeinfoinvariant)
2371 ObjectNotFound(Id.TypeInfo_Invariant);
2373 type = Type.typeinfoinvariant.type;
2376 static TypeInfoInvariantDeclaration create(Type tinfo)
2378 return new TypeInfoInvariantDeclaration(tinfo);
2381 override void accept(Visitor v)
2383 v.visit(this);
2387 /***********************************************************
2389 extern (C++) final class TypeInfoSharedDeclaration : TypeInfoDeclaration
2391 extern (D) this(Type tinfo)
2393 super(tinfo);
2394 if (!Type.typeinfoshared)
2396 ObjectNotFound(Id.TypeInfo_Shared);
2398 type = Type.typeinfoshared.type;
2401 static TypeInfoSharedDeclaration create(Type tinfo)
2403 return new TypeInfoSharedDeclaration(tinfo);
2406 override void accept(Visitor v)
2408 v.visit(this);
2412 /***********************************************************
2414 extern (C++) final class TypeInfoWildDeclaration : TypeInfoDeclaration
2416 extern (D) this(Type tinfo)
2418 super(tinfo);
2419 if (!Type.typeinfowild)
2421 ObjectNotFound(Id.TypeInfo_Wild);
2423 type = Type.typeinfowild.type;
2426 static TypeInfoWildDeclaration create(Type tinfo)
2428 return new TypeInfoWildDeclaration(tinfo);
2431 override void accept(Visitor v)
2433 v.visit(this);
2437 /***********************************************************
2439 extern (C++) final class TypeInfoVectorDeclaration : TypeInfoDeclaration
2441 extern (D) this(Type tinfo)
2443 super(tinfo);
2444 if (!Type.typeinfovector)
2446 ObjectNotFound(Id.TypeInfo_Vector);
2448 type = Type.typeinfovector.type;
2451 static TypeInfoVectorDeclaration create(Type tinfo)
2453 return new TypeInfoVectorDeclaration(tinfo);
2456 override void accept(Visitor v)
2458 v.visit(this);
2462 /***********************************************************
2463 * For the "this" parameter to member functions
2465 extern (C++) final class ThisDeclaration : VarDeclaration
2467 extern (D) this(const ref Loc loc, Type t)
2469 super(loc, t, Id.This, null);
2470 storage_class |= STC.nodtor;
2473 override ThisDeclaration syntaxCopy(Dsymbol s)
2475 assert(0); // should never be produced by syntax
2478 override inout(ThisDeclaration) isThisDeclaration() inout
2480 return this;
2483 override void accept(Visitor v)
2485 v.visit(this);