rs6000: Correct the function code for _AMO_LD_DEC_BOUNDED
[official-gcc.git] / gcc / d / dmd / declaration.d
blob3f9769d71550e3717eb18861b1e2eb04fbb2e346
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-2024 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.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 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
247 enum hidden = 8; // don't print this in .di files
249 // overridden symbol with pragma(mangle, "...")
250 const(char)[] mangleOverride;
252 final extern (D) this(Identifier ident) @safe
254 super(ident);
255 visibility = Visibility(Visibility.Kind.undefined);
258 final extern (D) this(const ref Loc loc, Identifier ident) @safe
260 super(loc, ident);
261 visibility = Visibility(Visibility.Kind.undefined);
264 override const(char)* kind() const
266 return "declaration";
269 override final uinteger_t size(const ref Loc loc)
271 assert(type);
272 const sz = type.size();
273 if (sz == SIZE_INVALID)
274 errors = true;
275 return sz;
279 * Issue an error if an attempt to call a disabled method is made
281 * If the declaration is disabled but inside a disabled function,
282 * returns `true` but do not issue an error message.
284 * Params:
285 * loc = Location information of the call
286 * sc = Scope in which the call occurs
287 * isAliasedDeclaration = if `true` searches overload set
289 * Returns:
290 * `true` if this `Declaration` is `@disable`d, `false` otherwise.
292 extern (D) final bool checkDisabled(Loc loc, Scope* sc, bool isAliasedDeclaration = false)
294 if (!(storage_class & STC.disable))
295 return false;
297 if (sc.func && sc.func.storage_class & STC.disable)
298 return true;
300 if (auto p = toParent())
302 if (auto postblit = isPostBlitDeclaration())
304 /* https://issues.dlang.org/show_bug.cgi?id=21885
306 * If the generated postblit is disabled, it
307 * means that one of the fields has a disabled
308 * postblit. Print the first field that has
309 * a disabled postblit.
311 if (postblit.isGenerated())
313 auto sd = p.isStructDeclaration();
314 assert(sd);
315 for (size_t i = 0; i < sd.fields.length; i++)
317 auto structField = sd.fields[i];
318 if (structField.overlapped)
319 continue;
320 Type tv = structField.type.baseElemOf();
321 if (tv.ty != Tstruct)
322 continue;
323 auto sdv = (cast(TypeStruct)tv).sym;
324 if (!sdv.postblit)
325 continue;
326 if (sdv.postblit.isDisabled())
328 .error(loc, "%s `%s` is not copyable because field `%s` is not copyable", p.kind, p.toPrettyChars, structField.toChars());
329 return true;
333 .error(loc, "%s `%s` is not copyable because it has a disabled postblit", p.kind, p.toPrettyChars);
334 return true;
338 // if the function is @disabled, maybe there
339 // is an overload in the overload set that isn't
340 if (isAliasedDeclaration)
342 FuncDeclaration fd = isFuncDeclaration();
343 if (fd)
345 for (FuncDeclaration ovl = fd; ovl; ovl = cast(FuncDeclaration)ovl.overnext)
346 if (!(ovl.storage_class & STC.disable))
347 return false;
351 if (auto ctor = isCtorDeclaration())
353 if (ctor.isCpCtor && ctor.isGenerated())
355 .error(loc, "generating an `inout` copy constructor for `struct %s` failed, therefore instances of it are uncopyable", parent.toPrettyChars());
356 return true;
359 .error(loc, "%s `%s` cannot be used because it is annotated with `@disable`", kind, toPrettyChars);
360 return true;
363 /*************************************
364 * Check to see if declaration can be modified in this context (sc).
365 * Issue error if not.
366 * Params:
367 * loc = location for error messages
368 * e1 = `null` or `this` expression when this declaration is a field
369 * sc = context
370 * flag = if the first bit is set it means do not issue error message for
371 * invalid modification; if the second bit is set, it means that
372 this declaration is a field and a subfield of it is modified.
373 * Returns:
374 * Modifiable.yes or Modifiable.initialization
376 extern (D) final Modifiable checkModify(Loc loc, Scope* sc, Expression e1, ModifyFlags flag)
378 VarDeclaration v = isVarDeclaration();
379 if (v && v.canassign)
380 return Modifiable.initialization;
382 if (isParameter() || isResult())
384 for (Scope* scx = sc; scx; scx = scx.enclosing)
386 if (scx.func == parent && (scx.flags & SCOPE.contract))
388 const(char)* s = isParameter() && parent.ident != Id.ensure ? "parameter" : "result";
389 if (!(flag & ModifyFlags.noError))
390 error(loc, "%s `%s` cannot modify %s `%s` in contract", kind, toPrettyChars, s, toChars());
391 return Modifiable.initialization; // do not report type related errors
396 if (e1 && e1.op == EXP.this_ && isField())
398 VarDeclaration vthis = e1.isThisExp().var;
399 for (Scope* scx = sc; scx; scx = scx.enclosing)
401 if (scx.func == vthis.parent && (scx.flags & SCOPE.contract))
403 if (!(flag & ModifyFlags.noError))
404 error(loc, "%s `%s` cannot modify parameter `this` in contract", kind, toPrettyChars);
405 return Modifiable.initialization; // do not report type related errors
410 if (v && (v.isCtorinit() || isField()))
412 // It's only modifiable if inside the right constructor
413 if ((storage_class & (STC.foreach_ | STC.ref_)) == (STC.foreach_ | STC.ref_))
414 return Modifiable.initialization;
415 if (flag & ModifyFlags.fieldAssign)
416 return Modifiable.yes;
417 return modifyFieldVar(loc, sc, v, e1) ? Modifiable.initialization : Modifiable.yes;
419 return Modifiable.yes;
422 final bool isStatic() const pure nothrow @nogc @safe
424 return (storage_class & STC.static_) != 0;
427 /// Returns the linkage, resolving the target-specific `System` one.
428 final LINK resolvedLinkage() const
430 return _linkage == LINK.system ? target.systemLinkage() : _linkage;
433 bool isDelete()
435 return false;
438 bool isDataseg()
440 return false;
443 bool isThreadlocal()
445 return false;
448 bool isCodeseg() const pure nothrow @nogc @safe
450 return false;
453 final bool isFinal() const pure nothrow @nogc @safe
455 return (storage_class & STC.final_) != 0;
458 bool isAbstract()
460 return (storage_class & STC.abstract_) != 0;
463 final bool isConst() const pure nothrow @nogc @safe
465 return (storage_class & STC.const_) != 0;
468 final bool isImmutable() const pure nothrow @nogc @safe
470 return (storage_class & STC.immutable_) != 0;
473 final bool isWild() const pure nothrow @nogc @safe
475 return (storage_class & STC.wild) != 0;
478 final bool isAuto() const pure nothrow @nogc @safe
480 return (storage_class & STC.auto_) != 0;
483 final bool isScope() const pure nothrow @nogc @safe
485 return (storage_class & STC.scope_) != 0;
488 final bool isReturn() const pure nothrow @nogc @safe
490 return (storage_class & STC.return_) != 0;
493 final bool isSynchronized() const pure nothrow @nogc @safe
495 return (storage_class & STC.synchronized_) != 0;
498 final bool isParameter() const pure nothrow @nogc @safe
500 return (storage_class & STC.parameter) != 0;
503 override final bool isDeprecated() const pure nothrow @nogc @safe
505 return (storage_class & STC.deprecated_) != 0;
508 final bool isDisabled() const pure nothrow @nogc @safe
510 return (storage_class & STC.disable) != 0;
513 final bool isOverride() const pure nothrow @nogc @safe
515 return (storage_class & STC.override_) != 0;
518 final bool isResult() const pure nothrow @nogc @safe
520 return (storage_class & STC.result) != 0;
523 final bool isField() const pure nothrow @nogc @safe
525 return (storage_class & STC.field) != 0;
528 final bool isIn() const pure nothrow @nogc @safe
530 return (storage_class & STC.in_) != 0;
533 final bool isOut() const pure nothrow @nogc @safe
535 return (storage_class & STC.out_) != 0;
538 final bool isRef() const pure nothrow @nogc @safe
540 return (storage_class & STC.ref_) != 0;
543 /// Returns: Whether the variable is a reference, annotated with `out` or `ref`
544 final bool isReference() const pure nothrow @nogc @safe
546 return (storage_class & (STC.ref_ | STC.out_)) != 0;
549 final bool isFuture() const pure nothrow @nogc @safe
551 return (storage_class & STC.future) != 0;
554 final extern(D) bool isSystem() const pure nothrow @nogc @safe
556 return (storage_class & STC.system) != 0;
559 override final Visibility visible() pure nothrow @nogc @safe
561 return visibility;
564 override final inout(Declaration) isDeclaration() inout pure nothrow @nogc @safe
566 return this;
569 override void accept(Visitor v)
571 v.visit(this);
575 /***********************************************************
577 extern (C++) final class TupleDeclaration : Declaration
579 Objects* objects;
580 TypeTuple tupletype; // !=null if this is a type tuple
581 bool isexp; // true: expression tuple
582 bool building; // it's growing in AliasAssign semantic
584 extern (D) this(const ref Loc loc, Identifier ident, Objects* objects) @safe
586 super(loc, ident);
587 this.objects = objects;
590 override TupleDeclaration syntaxCopy(Dsymbol s)
592 assert(0);
595 override const(char)* kind() const
597 return "sequence";
600 override Type getType()
602 /* If this tuple represents a type, return that type
605 //printf("TupleDeclaration::getType() %s\n", toChars());
606 if (isexp || building)
607 return null;
608 if (!tupletype)
610 /* It's only a type tuple if all the Object's are types
612 for (size_t i = 0; i < objects.length; i++)
614 RootObject o = (*objects)[i];
615 if (!o.isType())
617 //printf("\tnot[%d], %p, %d\n", i, o, o.dyncast());
618 return null;
622 /* We know it's a type tuple, so build the TypeTuple
624 Types* types = cast(Types*)objects;
625 auto args = new Parameters(objects.length);
626 OutBuffer buf;
627 int hasdeco = 1;
628 for (size_t i = 0; i < types.length; i++)
630 Type t = (*types)[i];
631 //printf("type = %s\n", t.toChars());
632 version (none)
634 buf.printf("_%s_%d", ident.toChars(), i);
635 auto id = Identifier.idPool(buf.extractSlice());
636 auto arg = new Parameter(Loc.initial, STC.in_, t, id, null);
638 else
640 auto arg = new Parameter(Loc.initial, 0, t, null, null, null);
642 (*args)[i] = arg;
643 if (!t.deco)
644 hasdeco = 0;
647 tupletype = new TypeTuple(args);
648 if (hasdeco)
649 return tupletype.typeSemantic(Loc.initial, null);
651 return tupletype;
654 override Dsymbol toAlias2()
656 //printf("TupleDeclaration::toAlias2() '%s' objects = %s\n", toChars(), objects.toChars());
657 for (size_t i = 0; i < objects.length; i++)
659 RootObject o = (*objects)[i];
660 if (Dsymbol s = isDsymbol(o))
662 s = s.toAlias2();
663 (*objects)[i] = s;
666 return this;
669 override bool needThis()
671 //printf("TupleDeclaration::needThis(%s)\n", toChars());
672 return isexp ? foreachVar((s) { return s.needThis(); }) != 0 : false;
675 /***********************************************************
676 * Calls dg(Dsymbol) for each Dsymbol, which should be a VarDeclaration
677 * inside VarExp (isexp == true).
678 * Params:
679 * dg = delegate to call for each Dsymbol
681 extern (D) void foreachVar(scope void delegate(Dsymbol) dg)
683 assert(isexp);
684 foreach (o; *objects)
686 if (auto e = o.isExpression())
687 if (auto ve = e.isVarExp())
688 dg(ve.var);
692 /***********************************************************
693 * Calls dg(Dsymbol) for each Dsymbol, which should be a VarDeclaration
694 * inside VarExp (isexp == true).
695 * If dg returns !=0, stops and returns that value else returns 0.
696 * Params:
697 * dg = delegate to call for each Dsymbol
698 * Returns:
699 * last value returned by dg()
701 extern (D) int foreachVar(scope int delegate(Dsymbol) dg)
703 assert(isexp);
704 foreach (o; *objects)
706 if (auto e = o.isExpression())
707 if (auto ve = e.isVarExp())
708 if(auto ret = dg(ve.var))
709 return ret;
711 return 0;
714 override inout(TupleDeclaration) isTupleDeclaration() inout
716 return this;
719 override void accept(Visitor v)
721 v.visit(this);
725 /***********************************************************
726 * https://dlang.org/spec/declaration.html#AliasDeclaration
728 extern (C++) final class AliasDeclaration : Declaration
730 Dsymbol aliassym; // alias ident = aliassym;
732 Dsymbol overnext; // next in overload list
733 Dsymbol _import; // !=null if unresolved internal alias for selective import
735 extern (D) this(const ref Loc loc, Identifier ident, Type type) @safe
737 super(loc, ident);
738 //printf("AliasDeclaration(id = '%s', type = %p)\n", ident.toChars(), type);
739 //printf("type = '%s'\n", type.toChars());
740 this.type = type;
741 assert(type);
744 extern (D) this(const ref Loc loc, Identifier ident, Dsymbol s) @safe
746 super(loc, ident);
747 //printf("AliasDeclaration(id = '%s', s = %p)\n", ident.toChars(), s);
748 assert(s != this);
749 this.aliassym = s;
750 assert(s);
753 static AliasDeclaration create(const ref Loc loc, Identifier id, Type type) @safe
755 return new AliasDeclaration(loc, id, type);
758 override AliasDeclaration syntaxCopy(Dsymbol s)
760 //printf("AliasDeclaration::syntaxCopy()\n");
761 assert(!s);
762 AliasDeclaration sa = type ? new AliasDeclaration(loc, ident, type.syntaxCopy()) : new AliasDeclaration(loc, ident, aliassym.syntaxCopy(null));
763 sa.comment = comment;
764 sa.storage_class = storage_class;
765 return sa;
768 override bool overloadInsert(Dsymbol s)
770 //printf("[%s] AliasDeclaration::overloadInsert('%s') s = %s %s @ [%s]\n",
771 // loc.toChars(), toChars(), s.kind(), s.toChars(), s.loc.toChars());
773 /** Aliases aren't overloadable themselves, but if their Aliasee is
774 * overloadable they are converted to an overloadable Alias (either
775 * FuncAliasDeclaration or OverDeclaration).
777 * This is done by moving the Aliasee into such an overloadable alias
778 * which is then used to replace the existing Aliasee. The original
779 * Alias (_this_) remains a useless shell.
781 * This is a horrible mess. It was probably done to avoid replacing
782 * existing AST nodes and references, but it needs a major
783 * simplification b/c it's too complex to maintain.
785 * A simpler approach might be to merge any colliding symbols into a
786 * simple Overload class (an array) and then later have that resolve
787 * all collisions.
789 if (semanticRun >= PASS.semanticdone)
791 /* Semantic analysis is already finished, and the aliased entity
792 * is not overloadable.
794 if (type)
797 If type has been resolved already we could
798 still be inserting an alias from an import.
800 If we are handling an alias then pretend
801 it was inserting and return true, if not then
802 false since we didn't even pretend to insert something.
804 return this._import && this.equals(s);
807 // https://issues.dlang.org/show_bug.cgi?id=23865
808 // only insert if the symbol can be part of a set
809 const s1 = s.toAlias();
810 const isInsertCandidate = s1.isFuncDeclaration() || s1.isOverDeclaration() || s1.isTemplateDeclaration();
812 /* When s is added in member scope by static if, mixin("code") or others,
813 * aliassym is determined already. See the case in: test/compilable/test61.d
815 auto sa = aliassym.toAlias();
817 if (auto td = s.toAlias().isTemplateDeclaration())
818 s = td.funcroot ? td.funcroot : td;
820 if (auto fd = sa.isFuncDeclaration())
822 auto fa = new FuncAliasDeclaration(ident, fd);
823 fa.visibility = visibility;
824 fa.parent = parent;
825 aliassym = fa;
826 if (isInsertCandidate)
827 return aliassym.overloadInsert(s);
829 if (auto td = sa.isTemplateDeclaration())
831 auto od = new OverDeclaration(ident, td.funcroot ? td.funcroot : td);
832 od.visibility = visibility;
833 od.parent = parent;
834 aliassym = od;
835 if (isInsertCandidate)
836 return aliassym.overloadInsert(s);
838 if (auto od = sa.isOverDeclaration())
840 if (sa.ident != ident || sa.parent != parent)
842 od = new OverDeclaration(ident, od);
843 od.visibility = visibility;
844 od.parent = parent;
845 aliassym = od;
847 if (isInsertCandidate)
848 return od.overloadInsert(s);
850 if (auto os = sa.isOverloadSet())
852 if (sa.ident != ident || sa.parent != parent)
854 os = new OverloadSet(ident, os);
855 // TODO: visibility is lost here b/c OverloadSets have no visibility attribute
856 // Might no be a practical issue, b/c the code below fails to resolve the overload anyhow.
857 // ----
858 // module os1;
859 // import a, b;
860 // private alias merged = foo; // private alias to overload set of a.foo and b.foo
861 // ----
862 // module os2;
863 // import a, b;
864 // public alias merged = bar; // public alias to overload set of a.bar and b.bar
865 // ----
866 // module bug;
867 // import os1, os2;
868 // void test() { merged(123); } // should only look at os2.merged
870 // os.visibility = visibility;
871 os.parent = parent;
872 aliassym = os;
874 if (isInsertCandidate)
876 os.push(s);
877 return true;
880 return false;
883 /* Don't know yet what the aliased symbol is, so assume it can
884 * be overloaded and check later for correctness.
886 if (overnext)
887 return overnext.overloadInsert(s);
888 if (s is this)
889 return true;
890 overnext = s;
891 return true;
894 override const(char)* kind() const
896 return "alias";
899 override Type getType()
901 if (type)
902 return type;
903 return toAlias().getType();
906 override Dsymbol toAlias()
908 //printf("[%s] AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s', inuse = %d)\n",
909 // loc.toChars(), toChars(), this, aliassym, aliassym ? aliassym.kind() : "", inuse);
910 assert(this != aliassym);
911 //static int count; if (++count == 10) *(char*)0=0;
913 // Reading the AliasDeclaration
914 if (!(adFlags & ignoreRead))
915 adFlags |= wasRead; // can never assign to this AliasDeclaration again
917 if (inuse == 1 && type && _scope)
919 inuse = 2;
920 uint olderrors = global.errors;
921 Dsymbol s = type.toDsymbol(_scope);
922 //printf("[%s] type = %s, s = %p, this = %p\n", loc.toChars(), type.toChars(), s, this);
923 if (global.errors != olderrors)
924 goto Lerr;
925 if (s)
927 s = s.toAlias();
928 if (global.errors != olderrors)
929 goto Lerr;
930 aliassym = s;
931 inuse = 0;
933 else
935 Type t = type.typeSemantic(loc, _scope);
936 if (t.ty == Terror)
937 goto Lerr;
938 if (global.errors != olderrors)
939 goto Lerr;
940 //printf("t = %s\n", t.toChars());
941 inuse = 0;
944 if (inuse)
946 .error(loc, "%s `%s` recursive alias declaration", kind, toPrettyChars);
948 Lerr:
949 // Avoid breaking "recursive alias" state during errors gagged
950 if (global.gag)
951 return this;
952 aliassym = new AliasDeclaration(loc, ident, Type.terror);
953 type = Type.terror;
954 return aliassym;
957 if (semanticRun >= PASS.semanticdone)
959 // semantic is already done.
961 // Do not see aliassym !is null, because of lambda aliases.
963 // Do not see type.deco !is null, even so "alias T = const int;` needs
964 // semantic analysis to take the storage class `const` as type qualifier.
966 else
968 // stop AliasAssign tuple building
969 if (aliassym)
971 if (auto td = aliassym.isTupleDeclaration())
973 if (td.building)
975 td.building = false;
976 semanticRun = PASS.semanticdone;
977 return td;
981 if (_import && _import._scope)
983 /* If this is an internal alias for selective/renamed import,
984 * load the module first.
986 _import.dsymbolSemantic(null);
988 if (_scope)
990 aliasSemantic(this, _scope);
994 inuse = 1;
995 Dsymbol s = aliassym ? aliassym.toAlias() : this;
996 inuse = 0;
997 return s;
1000 override Dsymbol toAlias2()
1002 if (inuse)
1004 .error(loc, "%s `%s` recursive alias declaration", kind, toPrettyChars);
1005 return this;
1007 inuse = 1;
1008 Dsymbol s = aliassym ? aliassym.toAlias2() : this;
1009 inuse = 0;
1010 return s;
1013 override bool isOverloadable() const
1015 // assume overloadable until alias is resolved
1016 return semanticRun < PASS.semanticdone ||
1017 aliassym && aliassym.isOverloadable();
1020 override inout(AliasDeclaration) isAliasDeclaration() inout
1022 return this;
1025 /** Returns: `true` if this instance was created to make a template parameter
1026 visible in the scope of a template body, `false` otherwise */
1027 extern (D) bool isAliasedTemplateParameter() const
1029 return !!(storage_class & STC.templateparameter);
1032 override void accept(Visitor v)
1034 v.visit(this);
1038 /***********************************************************
1040 extern (C++) final class OverDeclaration : Declaration
1042 Dsymbol overnext; // next in overload list
1043 Dsymbol aliassym;
1045 extern (D) this(Identifier ident, Dsymbol s) @safe
1047 super(ident);
1048 this.aliassym = s;
1051 override const(char)* kind() const
1053 return "overload alias"; // todo
1056 override bool equals(const RootObject o) const
1058 if (this == o)
1059 return true;
1061 auto s = isDsymbol(o);
1062 if (!s)
1063 return false;
1065 if (auto od2 = s.isOverDeclaration())
1066 return this.aliassym.equals(od2.aliassym);
1067 return this.aliassym == s;
1070 override bool overloadInsert(Dsymbol s)
1072 //printf("OverDeclaration::overloadInsert('%s') aliassym = %p, overnext = %p\n", s.toChars(), aliassym, overnext);
1073 if (overnext)
1074 return overnext.overloadInsert(s);
1075 if (s == this)
1076 return true;
1077 overnext = s;
1078 return true;
1081 override bool isOverloadable() const
1083 return true;
1086 Dsymbol isUnique()
1088 Dsymbol result = null;
1089 overloadApply(aliassym, (Dsymbol s)
1091 if (result)
1093 result = null;
1094 return 1; // ambiguous, done
1096 else
1098 result = s;
1099 return 0;
1102 return result;
1105 override inout(OverDeclaration) isOverDeclaration() inout
1107 return this;
1110 override void accept(Visitor v)
1112 v.visit(this);
1116 /***********************************************************
1118 extern (C++) class VarDeclaration : Declaration
1120 Initializer _init;
1121 FuncDeclarations nestedrefs; // referenced by these lexically nested functions
1122 TupleDeclaration aliasTuple; // when `this` is really a tuple of declarations
1123 VarDeclaration lastVar; // Linked list of variables for goto-skips-init detection
1124 Expression edtor; // if !=null, does the destruction of the variable
1125 IntRange* range; // if !=null, the variable is known to be within the range
1126 VarDeclarations* maybes; // maybeScope variables that are assigned to this maybeScope variable
1128 uint endlinnum; // line number of end of scope that this var lives in
1129 uint offset;
1130 uint sequenceNumber; // order the variables are declared
1131 structalign_t alignment;
1133 // When interpreting, these point to the value (NULL if value not determinable)
1134 // The index of this variable on the CTFE stack, AdrOnStackNone if not allocated
1135 enum AdrOnStackNone = ~0u;
1136 uint ctfeAdrOnStack;
1138 // `bool` fields that are compacted into bit fields in a string mixin
1139 private extern (D) static struct BitFields
1141 bool isargptr; /// if parameter that _argptr points to
1142 bool ctorinit; /// it has been initialized in a ctor
1143 bool iscatchvar; /// this is the exception object variable in catch() clause
1144 bool isowner; /// this is an Owner, despite it being `scope`
1145 bool setInCtorOnly; /// field can only be set in a constructor, as it is const or immutable
1147 /// It is a class that was allocated on the stack
1149 /// This means the var is not rebindable once assigned,
1150 /// and the destructor gets run when it goes out of scope
1151 bool onstack;
1153 bool overlapped; /// if it is a field and has overlapping
1154 bool overlapUnsafe; /// if it is an overlapping field and the overlaps are unsafe
1155 bool maybeScope; /// allow inferring 'scope' for this variable
1156 bool doNotInferReturn; /// do not infer 'return' for this variable
1158 bool isArgDtorVar; /// temporary created to handle scope destruction of a function argument
1159 bool isCmacro; /// it is a C macro turned into a C declaration
1160 bool dllImport; /// __declspec(dllimport)
1161 bool dllExport; /// __declspec(dllexport)
1162 version (MARS)
1164 bool inClosure; /// is inserted into a GC allocated closure
1165 bool inAlignSection; /// is inserted into an aligned section on stack
1167 bool systemInferred; /// @system was inferred from initializer
1170 import dmd.common.bitfields : generateBitFields;
1171 mixin(generateBitFields!(BitFields, uint));
1173 byte canassign; // it can be assigned to
1174 ubyte isdataseg; // private data for isDataseg 0 unset, 1 true, 2 false
1176 final extern (D) this(const ref Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.undefined_)
1179 assert(ident);
1183 //printf("VarDeclaration('%s')\n", ident.toChars());
1184 super(loc, ident);
1185 debug
1187 if (!type && !_init)
1189 //printf("VarDeclaration('%s')\n", ident.toChars());
1190 //*(char*)0=0;
1194 assert(type || _init);
1195 this.type = type;
1196 this._init = _init;
1197 ctfeAdrOnStack = AdrOnStackNone;
1198 this.storage_class = storage_class;
1201 static VarDeclaration create(const ref Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.undefined_)
1203 return new VarDeclaration(loc, type, ident, _init, storage_class);
1206 override VarDeclaration syntaxCopy(Dsymbol s)
1208 //printf("VarDeclaration::syntaxCopy(%s)\n", toChars());
1209 assert(!s);
1210 auto v = new VarDeclaration(loc, type ? type.syntaxCopy() : null, ident, _init ? _init.syntaxCopy() : null, storage_class);
1211 v.comment = comment;
1212 return v;
1215 override const(char)* kind() const
1217 return "variable";
1220 override final inout(AggregateDeclaration) isThis() inout
1222 if (!(storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.templateparameter | STC.gshared | STC.ctfe)))
1224 /* The casting is necessary because `s = s.parent` is otherwise rejected
1226 for (auto s = cast(Dsymbol)this; s; s = s.parent)
1228 auto ad = (cast(inout)s).isMember();
1229 if (ad)
1230 return ad;
1231 if (!s.parent || !s.parent.isTemplateMixin())
1232 break;
1235 return null;
1238 override final bool needThis()
1240 //printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class);
1241 return isField();
1244 override final bool isExport() const
1246 return visibility.kind == Visibility.Kind.export_ || dllExport;
1249 override final bool isImportedSymbol() const
1251 /* If global variable has `export` and `extern` then it is imported
1252 * export int sym1; // definition: exported
1253 * export extern int sym2; // declaration: imported
1254 * export extern int sym3 = 0; // error, extern cannot have initializer
1256 bool result =
1257 dllImport ||
1258 visibility.kind == Visibility.Kind.export_ &&
1259 storage_class & STC.extern_ &&
1260 (storage_class & STC.static_ || parent.isModule());
1261 //printf("isImportedSymbol() %s %d\n", toChars(), result);
1262 return result;
1265 final bool isCtorinit() const pure nothrow @nogc @safe
1267 return setInCtorOnly;
1270 /*******************************
1271 * Does symbol go into data segment?
1272 * Includes extern variables.
1274 override final bool isDataseg()
1276 version (none)
1278 printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars());
1279 printf("%llx, isModule: %p, isTemplateInstance: %p, isNspace: %p\n",
1280 storage_class & (STC.static_ | STC.const_), parent.isModule(), parent.isTemplateInstance(), parent.isNspace());
1281 printf("parent = '%s'\n", parent.toChars());
1284 if (isdataseg == 0) // the value is not cached
1286 isdataseg = 2; // The Variables does not go into the datasegment
1288 if (!canTakeAddressOf())
1290 return false;
1293 Dsymbol parent = toParent();
1294 if (!parent && !(storage_class & STC.static_))
1296 .error(loc, "%s `%s` forward referenced", kind, toPrettyChars);
1297 type = Type.terror;
1299 else if (storage_class & (STC.static_ | STC.extern_ | STC.gshared) ||
1300 parent.isModule() || parent.isTemplateInstance() || parent.isNspace())
1302 assert(!isParameter() && !isResult());
1303 isdataseg = 1; // It is in the DataSegment
1307 return (isdataseg == 1);
1309 /************************************
1310 * Does symbol go into thread local storage?
1312 override final bool isThreadlocal()
1314 //printf("VarDeclaration::isThreadlocal(%p, '%s')\n", this, toChars());
1315 /* Data defaults to being thread-local. It is not thread-local
1316 * if it is immutable, const or shared.
1318 bool i = isDataseg() && !(storage_class & (STC.immutable_ | STC.const_ | STC.shared_ | STC.gshared));
1319 //printf("\treturn %d\n", i);
1320 return i;
1323 /********************************************
1324 * Can variable be read and written by CTFE?
1326 final bool isCTFE()
1328 return (storage_class & STC.ctfe) != 0; // || !isDataseg();
1331 final bool isOverlappedWith(VarDeclaration v)
1333 const vsz = v.type.size();
1334 const tsz = type.size();
1335 assert(vsz != SIZE_INVALID && tsz != SIZE_INVALID);
1337 // Overlap is checked by comparing bit offsets
1338 auto bitoffset = offset * 8;
1339 auto vbitoffset = v.offset * 8;
1341 // Bitsize of types are overridden by any bit-field widths.
1342 ulong tbitsize = void;
1343 if (auto bf = isBitFieldDeclaration())
1345 bitoffset += bf.bitOffset;
1346 tbitsize = bf.fieldWidth;
1348 else
1349 tbitsize = tsz * 8;
1351 ulong vbitsize = void;
1352 if (auto vbf = v.isBitFieldDeclaration())
1354 vbitoffset += vbf.bitOffset;
1355 vbitsize = vbf.fieldWidth;
1357 else
1358 vbitsize = vsz * 8;
1360 return bitoffset < vbitoffset + vbitsize &&
1361 vbitoffset < bitoffset + tbitsize;
1364 override final bool hasPointers()
1366 //printf("VarDeclaration::hasPointers() %s, ty = %d\n", toChars(), type.ty);
1367 return (!isDataseg() && type.hasPointers());
1370 /*************************************
1371 * Return true if we can take the address of this variable.
1373 final bool canTakeAddressOf()
1375 return !(storage_class & STC.manifest);
1378 /******************************************
1379 * Return true if variable needs to call the destructor.
1381 final bool needsScopeDtor()
1383 //printf("VarDeclaration::needsScopeDtor() %s %d\n", toChars(), edtor && !(storage_class & STC.nodtor));
1384 return edtor && !(storage_class & STC.nodtor);
1387 /******************************************
1388 * If a variable has a scope destructor call, return call for it.
1389 * Otherwise, return NULL.
1391 extern (D) final Expression callScopeDtor(Scope* sc)
1393 //printf("VarDeclaration::callScopeDtor() %s\n", toChars());
1395 // Destruction of STC.field's is handled by buildDtor()
1396 if (storage_class & (STC.nodtor | STC.ref_ | STC.out_ | STC.field))
1398 return null;
1401 if (iscatchvar)
1402 return null; // destructor is built by `void semantic(Catch c, Scope* sc)`, not here
1404 Expression e = null;
1405 // Destructors for structs and arrays of structs
1406 Type tv = type.baseElemOf();
1407 if (tv.ty == Tstruct)
1409 StructDeclaration sd = (cast(TypeStruct)tv).sym;
1410 if (!sd.dtor || sd.errors)
1411 return null;
1413 const sz = type.size();
1414 assert(sz != SIZE_INVALID);
1415 if (!sz)
1416 return null;
1418 if (type.toBasetype().ty == Tstruct)
1420 // v.__xdtor()
1421 e = new VarExp(loc, this);
1423 /* This is a hack so we can call destructors on const/immutable objects.
1424 * Need to add things like "const ~this()" and "immutable ~this()" to
1425 * fix properly.
1427 e.type = e.type.mutableOf();
1429 // Enable calling destructors on shared objects.
1430 // The destructor is always a single, non-overloaded function,
1431 // and must serve both shared and non-shared objects.
1432 e.type = e.type.unSharedOf;
1434 e = new DotVarExp(loc, e, sd.dtor, false);
1435 e = new CallExp(loc, e);
1437 else
1439 // __ArrayDtor(v[0 .. n])
1440 e = new VarExp(loc, this);
1442 const sdsz = sd.type.size();
1443 assert(sdsz != SIZE_INVALID && sdsz != 0);
1444 const n = sz / sdsz;
1445 SliceExp se = new SliceExp(loc, e, new IntegerExp(loc, 0, Type.tsize_t),
1446 new IntegerExp(loc, n, Type.tsize_t));
1448 // Prevent redundant bounds check
1449 se.upperIsInBounds = true;
1450 se.lowerIsLessThanUpper = true;
1452 // This is a hack so we can call destructors on const/immutable objects.
1453 se.type = sd.type.arrayOf();
1455 e = new CallExp(loc, new IdentifierExp(loc, Id.__ArrayDtor), se);
1457 return e;
1459 // Destructors for classes
1460 if (storage_class & (STC.auto_ | STC.scope_) && !(storage_class & STC.parameter))
1462 for (ClassDeclaration cd = type.isClassHandle(); cd; cd = cd.baseClass)
1464 /* We can do better if there's a way with onstack
1465 * classes to determine if there's no way the monitor
1466 * could be set.
1468 //if (cd.isInterfaceDeclaration())
1469 // error("interface `%s` cannot be scope", cd.toChars());
1471 if (onstack) // if any destructors
1473 // delete'ing C++ classes crashes (and delete is deprecated anyway)
1474 if (cd.classKind == ClassKind.cpp)
1476 // Don't call non-existant dtor
1477 if (!cd.dtor)
1478 break;
1480 e = new VarExp(loc, this);
1481 e.type = e.type.mutableOf().unSharedOf(); // Hack for mutable ctor on immutable instances
1482 e = new DotVarExp(loc, e, cd.dtor, false);
1483 e = new CallExp(loc, e);
1484 break;
1487 // delete this;
1488 Expression ec;
1489 ec = new VarExp(loc, this);
1490 e = new DeleteExp(loc, ec, true);
1491 e.type = Type.tvoid;
1492 break;
1496 return e;
1499 /*******************************************
1500 * If variable has a constant expression initializer, get it.
1501 * Otherwise, return null.
1503 extern (D) final Expression getConstInitializer(bool needFullType = true)
1505 assert(type && _init);
1507 // Ungag errors when not speculative
1508 uint oldgag = global.gag;
1509 if (global.gag)
1511 Dsymbol sym = isMember();
1512 if (sym && !sym.isSpeculative())
1513 global.gag = 0;
1516 if (_scope)
1518 inuse++;
1519 _init = _init.initializerSemantic(_scope, type, INITinterpret);
1520 import dmd.semantic2 : lowerStaticAAs;
1521 lowerStaticAAs(this, _scope);
1522 _scope = null;
1523 inuse--;
1526 Expression e = _init.initializerToExpression(needFullType ? type : null);
1527 global.gag = oldgag;
1528 return e;
1531 /*******************************************
1532 * Helper function for the expansion of manifest constant.
1534 extern (D) final Expression expandInitializer(Loc loc)
1536 assert((storage_class & STC.manifest) && _init);
1538 auto e = getConstInitializer();
1539 if (!e)
1541 .error(loc, "cannot make expression out of initializer for `%s`", toChars());
1542 return ErrorExp.get();
1545 e = e.copy();
1546 e.loc = loc; // for better error message
1547 return e;
1550 override final void checkCtorConstInit()
1552 version (none)
1554 /* doesn't work if more than one static ctor */
1555 if (ctorinit == 0 && isCtorinit() && !isField())
1556 error("missing initializer in static constructor for const variable");
1560 /************************************
1561 * Check to see if this variable is actually in an enclosing function
1562 * rather than the current one.
1563 * Update nestedrefs[], closureVars[] and outerVars[].
1564 * Returns: true if error occurs.
1566 extern (D) final bool checkNestedReference(Scope* sc, Loc loc)
1568 //printf("VarDeclaration::checkNestedReference() %s\n", toChars());
1569 if (sc.intypeof == 1 || (sc.flags & SCOPE.ctfe))
1570 return false;
1571 if (!parent || parent == sc.parent)
1572 return false;
1573 if (isDataseg() || (storage_class & STC.manifest))
1574 return false;
1576 // The current function
1577 FuncDeclaration fdthis = sc.parent.isFuncDeclaration();
1578 if (!fdthis)
1579 return false; // out of function scope
1581 Dsymbol p = toParent2();
1583 // Function literals from fdthis to p must be delegates
1584 ensureStaticLinkTo(fdthis, p);
1586 // The function that this variable is in
1587 FuncDeclaration fdv = p.isFuncDeclaration();
1588 if (!fdv || fdv == fdthis)
1589 return false;
1591 // Add fdthis to nestedrefs[] if not already there
1592 if (!nestedrefs.contains(fdthis))
1593 nestedrefs.push(fdthis);
1595 //printf("\tfdv = %s\n", fdv.toChars());
1596 //printf("\tfdthis = %s\n", fdthis.toChars());
1597 if (loc.isValid())
1599 if (fdthis.getLevelAndCheck(loc, sc, fdv, this) == fdthis.LevelError)
1600 return true;
1603 // Add this VarDeclaration to fdv.closureVars[] if not already there
1604 if (!sc.intypeof && !(sc.flags & SCOPE.compile) &&
1605 // https://issues.dlang.org/show_bug.cgi?id=17605
1606 (fdv.skipCodegen || !fdthis.skipCodegen))
1608 if (!fdv.closureVars.contains(this))
1609 fdv.closureVars.push(this);
1612 if (!fdthis.outerVars.contains(this))
1613 fdthis.outerVars.push(this);
1615 //printf("fdthis is %s\n", fdthis.toChars());
1616 //printf("var %s in function %s is nested ref\n", toChars(), fdv.toChars());
1617 // __dollar creates problems because it isn't a real variable
1618 // https://issues.dlang.org/show_bug.cgi?id=3326
1619 if (ident == Id.dollar)
1621 .error(loc, "cannnot use `$` inside a function literal");
1622 return true;
1624 if (ident == Id.withSym) // https://issues.dlang.org/show_bug.cgi?id=1759
1626 ExpInitializer ez = _init.isExpInitializer();
1627 assert(ez);
1628 Expression e = ez.exp;
1629 if (e.op == EXP.construct || e.op == EXP.blit)
1630 e = (cast(AssignExp)e).e2;
1631 return lambdaCheckForNestedRef(e, sc);
1634 return false;
1637 override final Dsymbol toAlias()
1639 //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym);
1640 if ((!type || !type.deco) && _scope)
1641 dsymbolSemantic(this, _scope);
1643 assert(this != aliasTuple);
1644 Dsymbol s = aliasTuple ? aliasTuple.toAlias() : this;
1645 return s;
1648 // Eliminate need for dynamic_cast
1649 override final inout(VarDeclaration) isVarDeclaration() inout
1651 return this;
1654 override void accept(Visitor v)
1656 v.visit(this);
1660 /*******************************************************
1661 * C11 6.7.2.1-4 bit fields
1663 extern (C++) class BitFieldDeclaration : VarDeclaration
1665 Expression width;
1667 uint fieldWidth;
1668 uint bitOffset;
1670 final extern (D) this(const ref Loc loc, Type type, Identifier ident, Expression width)
1672 super(loc, type, ident, null);
1674 this.width = width;
1675 this.storage_class |= STC.field;
1678 override BitFieldDeclaration syntaxCopy(Dsymbol s)
1680 //printf("BitFieldDeclaration::syntaxCopy(%s)\n", toChars());
1681 assert(!s);
1682 auto bf = new BitFieldDeclaration(loc, type ? type.syntaxCopy() : null, ident, width.syntaxCopy());
1683 bf.comment = comment;
1684 return bf;
1687 override final inout(BitFieldDeclaration) isBitFieldDeclaration() inout
1689 return this;
1692 override void accept(Visitor v)
1694 v.visit(this);
1697 /***********************************
1698 * Retrieve the .min or .max values.
1699 * Only valid after semantic analysis.
1700 * Params:
1701 * id = Id.min or Id.max
1702 * Returns:
1703 * the min or max value
1705 final ulong getMinMax(Identifier id)
1707 const width = fieldWidth;
1708 const uns = type.isunsigned();
1709 const min = id == Id.min;
1710 ulong v;
1711 assert(width != 0); // should have been rejected in semantic pass
1712 if (width == ulong.sizeof * 8)
1713 v = uns ? (min ? ulong.min : ulong.max)
1714 : (min ? long.min : long.max);
1715 else
1716 v = uns ? (min ? 0
1717 : (1L << width) - 1)
1718 : (min ? -(1L << (width - 1))
1719 : (1L << (width - 1)) - 1);
1720 return v;
1724 /***********************************************************
1725 * This is a shell around a back end symbol
1727 extern (C++) final class SymbolDeclaration : Declaration
1729 AggregateDeclaration dsym;
1731 extern (D) this(const ref Loc loc, AggregateDeclaration dsym) @safe
1733 super(loc, dsym.ident);
1734 this.dsym = dsym;
1735 storage_class |= STC.const_;
1738 // Eliminate need for dynamic_cast
1739 override inout(SymbolDeclaration) isSymbolDeclaration() inout
1741 return this;
1744 override void accept(Visitor v)
1746 v.visit(this);
1750 /***********************************************************
1752 private Identifier getTypeInfoIdent(Type t)
1754 import dmd.dmangle;
1755 import core.stdc.stdlib;
1756 import dmd.root.rmem;
1757 // _init_10TypeInfo_%s
1758 OutBuffer buf;
1759 buf.reserve(32);
1760 mangleToBuffer(t, buf);
1762 const slice = buf[];
1764 // Allocate buffer on stack, fail over to using malloc()
1765 char[128] namebuf;
1766 const namelen = 19 + size_t.sizeof * 3 + slice.length + 1;
1767 auto name = namelen <= namebuf.length ? namebuf.ptr : cast(char*)Mem.check(malloc(namelen));
1769 const length = snprintf(name, namelen, "_D%lluTypeInfo_%.*s6__initZ",
1770 cast(ulong)(9 + slice.length), cast(int)slice.length, slice.ptr);
1771 //printf("%p %s, deco = %s, name = %s\n", this, toChars(), deco, name);
1772 assert(0 < length && length < namelen); // don't overflow the buffer
1774 auto id = Identifier.idPool(name[0 .. length]);
1776 if (name != namebuf.ptr)
1777 free(name);
1778 return id;
1781 extern (C++) class TypeInfoDeclaration : VarDeclaration
1783 Type tinfo;
1785 final extern (D) this(Type tinfo)
1787 super(Loc.initial, Type.dtypeinfo.type, tinfo.getTypeInfoIdent(), null);
1788 this.tinfo = tinfo;
1789 storage_class = STC.static_ | STC.gshared;
1790 visibility = Visibility(Visibility.Kind.public_);
1791 _linkage = LINK.c;
1792 alignment.set(target.ptrsize);
1795 static TypeInfoDeclaration create(Type tinfo)
1797 return new TypeInfoDeclaration(tinfo);
1800 override final TypeInfoDeclaration syntaxCopy(Dsymbol s)
1802 assert(0); // should never be produced by syntax
1805 override final const(char)* toChars() const
1807 //printf("TypeInfoDeclaration::toChars() tinfo = %s\n", tinfo.toChars());
1808 OutBuffer buf;
1809 buf.writestring("typeid(");
1810 buf.writestring(tinfo.toChars());
1811 buf.writeByte(')');
1812 return buf.extractChars();
1815 override final inout(TypeInfoDeclaration) isTypeInfoDeclaration() inout @nogc nothrow pure @safe
1817 return this;
1820 override void accept(Visitor v)
1822 v.visit(this);
1826 /***********************************************************
1828 extern (C++) final class TypeInfoStructDeclaration : TypeInfoDeclaration
1830 extern (D) this(Type tinfo)
1832 super(tinfo);
1833 if (!Type.typeinfostruct)
1835 ObjectNotFound(Id.TypeInfo_Struct);
1837 type = Type.typeinfostruct.type;
1840 static TypeInfoStructDeclaration create(Type tinfo)
1842 return new TypeInfoStructDeclaration(tinfo);
1845 override void accept(Visitor v)
1847 v.visit(this);
1851 /***********************************************************
1853 extern (C++) final class TypeInfoClassDeclaration : TypeInfoDeclaration
1855 extern (D) this(Type tinfo)
1857 super(tinfo);
1858 if (!Type.typeinfoclass)
1860 ObjectNotFound(Id.TypeInfo_Class);
1862 type = Type.typeinfoclass.type;
1865 static TypeInfoClassDeclaration create(Type tinfo)
1867 return new TypeInfoClassDeclaration(tinfo);
1870 override void accept(Visitor v)
1872 v.visit(this);
1876 /***********************************************************
1878 extern (C++) final class TypeInfoInterfaceDeclaration : TypeInfoDeclaration
1880 extern (D) this(Type tinfo)
1882 super(tinfo);
1883 if (!Type.typeinfointerface)
1885 ObjectNotFound(Id.TypeInfo_Interface);
1887 type = Type.typeinfointerface.type;
1890 static TypeInfoInterfaceDeclaration create(Type tinfo)
1892 return new TypeInfoInterfaceDeclaration(tinfo);
1895 override void accept(Visitor v)
1897 v.visit(this);
1901 /***********************************************************
1903 extern (C++) final class TypeInfoPointerDeclaration : TypeInfoDeclaration
1905 extern (D) this(Type tinfo)
1907 super(tinfo);
1908 if (!Type.typeinfopointer)
1910 ObjectNotFound(Id.TypeInfo_Pointer);
1912 type = Type.typeinfopointer.type;
1915 static TypeInfoPointerDeclaration create(Type tinfo)
1917 return new TypeInfoPointerDeclaration(tinfo);
1920 override void accept(Visitor v)
1922 v.visit(this);
1926 /***********************************************************
1928 extern (C++) final class TypeInfoArrayDeclaration : TypeInfoDeclaration
1930 extern (D) this(Type tinfo)
1932 super(tinfo);
1933 if (!Type.typeinfoarray)
1935 ObjectNotFound(Id.TypeInfo_Array);
1937 type = Type.typeinfoarray.type;
1940 static TypeInfoArrayDeclaration create(Type tinfo)
1942 return new TypeInfoArrayDeclaration(tinfo);
1945 override void accept(Visitor v)
1947 v.visit(this);
1951 /***********************************************************
1953 extern (C++) final class TypeInfoStaticArrayDeclaration : TypeInfoDeclaration
1955 extern (D) this(Type tinfo)
1957 super(tinfo);
1958 if (!Type.typeinfostaticarray)
1960 ObjectNotFound(Id.TypeInfo_StaticArray);
1962 type = Type.typeinfostaticarray.type;
1965 static TypeInfoStaticArrayDeclaration create(Type tinfo)
1967 return new TypeInfoStaticArrayDeclaration(tinfo);
1970 override void accept(Visitor v)
1972 v.visit(this);
1976 /***********************************************************
1978 extern (C++) final class TypeInfoAssociativeArrayDeclaration : TypeInfoDeclaration
1980 extern (D) this(Type tinfo)
1982 super(tinfo);
1983 if (!Type.typeinfoassociativearray)
1985 ObjectNotFound(Id.TypeInfo_AssociativeArray);
1987 type = Type.typeinfoassociativearray.type;
1990 static TypeInfoAssociativeArrayDeclaration create(Type tinfo)
1992 return new TypeInfoAssociativeArrayDeclaration(tinfo);
1995 override void accept(Visitor v)
1997 v.visit(this);
2001 /***********************************************************
2003 extern (C++) final class TypeInfoEnumDeclaration : TypeInfoDeclaration
2005 extern (D) this(Type tinfo)
2007 super(tinfo);
2008 if (!Type.typeinfoenum)
2010 ObjectNotFound(Id.TypeInfo_Enum);
2012 type = Type.typeinfoenum.type;
2015 static TypeInfoEnumDeclaration create(Type tinfo)
2017 return new TypeInfoEnumDeclaration(tinfo);
2020 override void accept(Visitor v)
2022 v.visit(this);
2026 /***********************************************************
2028 extern (C++) final class TypeInfoFunctionDeclaration : TypeInfoDeclaration
2030 extern (D) this(Type tinfo)
2032 super(tinfo);
2033 if (!Type.typeinfofunction)
2035 ObjectNotFound(Id.TypeInfo_Function);
2037 type = Type.typeinfofunction.type;
2040 static TypeInfoFunctionDeclaration create(Type tinfo)
2042 return new TypeInfoFunctionDeclaration(tinfo);
2045 override void accept(Visitor v)
2047 v.visit(this);
2051 /***********************************************************
2053 extern (C++) final class TypeInfoDelegateDeclaration : TypeInfoDeclaration
2055 extern (D) this(Type tinfo)
2057 super(tinfo);
2058 if (!Type.typeinfodelegate)
2060 ObjectNotFound(Id.TypeInfo_Delegate);
2062 type = Type.typeinfodelegate.type;
2065 static TypeInfoDelegateDeclaration create(Type tinfo)
2067 return new TypeInfoDelegateDeclaration(tinfo);
2070 override void accept(Visitor v)
2072 v.visit(this);
2076 /***********************************************************
2078 extern (C++) final class TypeInfoTupleDeclaration : TypeInfoDeclaration
2080 extern (D) this(Type tinfo)
2082 super(tinfo);
2083 if (!Type.typeinfotypelist)
2085 ObjectNotFound(Id.TypeInfo_Tuple);
2087 type = Type.typeinfotypelist.type;
2090 static TypeInfoTupleDeclaration create(Type tinfo)
2092 return new TypeInfoTupleDeclaration(tinfo);
2095 override void accept(Visitor v)
2097 v.visit(this);
2101 /***********************************************************
2103 extern (C++) final class TypeInfoConstDeclaration : TypeInfoDeclaration
2105 extern (D) this(Type tinfo)
2107 super(tinfo);
2108 if (!Type.typeinfoconst)
2110 ObjectNotFound(Id.TypeInfo_Const);
2112 type = Type.typeinfoconst.type;
2115 static TypeInfoConstDeclaration create(Type tinfo)
2117 return new TypeInfoConstDeclaration(tinfo);
2120 override void accept(Visitor v)
2122 v.visit(this);
2126 /***********************************************************
2128 extern (C++) final class TypeInfoInvariantDeclaration : TypeInfoDeclaration
2130 extern (D) this(Type tinfo)
2132 super(tinfo);
2133 if (!Type.typeinfoinvariant)
2135 ObjectNotFound(Id.TypeInfo_Invariant);
2137 type = Type.typeinfoinvariant.type;
2140 static TypeInfoInvariantDeclaration create(Type tinfo)
2142 return new TypeInfoInvariantDeclaration(tinfo);
2145 override void accept(Visitor v)
2147 v.visit(this);
2151 /***********************************************************
2153 extern (C++) final class TypeInfoSharedDeclaration : TypeInfoDeclaration
2155 extern (D) this(Type tinfo)
2157 super(tinfo);
2158 if (!Type.typeinfoshared)
2160 ObjectNotFound(Id.TypeInfo_Shared);
2162 type = Type.typeinfoshared.type;
2165 static TypeInfoSharedDeclaration create(Type tinfo)
2167 return new TypeInfoSharedDeclaration(tinfo);
2170 override void accept(Visitor v)
2172 v.visit(this);
2176 /***********************************************************
2178 extern (C++) final class TypeInfoWildDeclaration : TypeInfoDeclaration
2180 extern (D) this(Type tinfo)
2182 super(tinfo);
2183 if (!Type.typeinfowild)
2185 ObjectNotFound(Id.TypeInfo_Wild);
2187 type = Type.typeinfowild.type;
2190 static TypeInfoWildDeclaration create(Type tinfo)
2192 return new TypeInfoWildDeclaration(tinfo);
2195 override void accept(Visitor v)
2197 v.visit(this);
2201 /***********************************************************
2203 extern (C++) final class TypeInfoVectorDeclaration : TypeInfoDeclaration
2205 extern (D) this(Type tinfo)
2207 super(tinfo);
2208 if (!Type.typeinfovector)
2210 ObjectNotFound(Id.TypeInfo_Vector);
2212 type = Type.typeinfovector.type;
2215 static TypeInfoVectorDeclaration create(Type tinfo)
2217 return new TypeInfoVectorDeclaration(tinfo);
2220 override void accept(Visitor v)
2222 v.visit(this);
2226 /***********************************************************
2227 * For the "this" parameter to member functions
2229 extern (C++) final class ThisDeclaration : VarDeclaration
2231 extern (D) this(const ref Loc loc, Type t)
2233 super(loc, t, Id.This, null);
2234 storage_class |= STC.nodtor;
2237 override ThisDeclaration syntaxCopy(Dsymbol s)
2239 assert(0); // should never be produced by syntax
2242 override inout(ThisDeclaration) isThisDeclaration() inout
2244 return this;
2247 override void accept(Visitor v)
2249 v.visit(this);