2 * Miscellaneous declarations, including typedef, alias, variable declarations including the
3 * implicit this declaration, type tuples, ClassInfo, ModuleInfo and various TypeInfos.
5 * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved
6 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright)
7 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
8 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/declaration.d, _declaration.d)
9 * Documentation: https://dlang.org/phobos/dmd_declaration.html
10 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/declaration.d
13 module dmd
.declaration
;
15 import core
.stdc
.stdio
;
17 import dmd
.arraytypes
;
21 import dmd
.delegatize
;
25 import dmd
.dsymbolsem
;
28 import dmd
.expression
;
33 import dmd
.identifier
;
39 import dmd
.common
.outbuffer
;
40 import dmd
.root
.rootobject
;
47 else version (IN_LLVM
) {}
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();
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());
73 for (size_t i
= iStart
; i
< ad
.fields
.length
; i
++)
75 VarDeclaration vd
= ad
.fields
[i
];
76 Type tb
= vd
.type
.baseElemOf();
79 result |
= checkFrameAccess(loc
, sc
, (cast(TypeStruct
)tb
).sym
);
85 /***********************************************
86 * Mark variable v as modified if it is inside a constructor that var
88 * Also used to allow immutable globals to be initialized inside a static constructor.
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());
98 FuncDeclaration fd
= null;
100 fd
= s
.isFuncDeclaration();
102 ((fd
.isCtorDeclaration() && var
.isField()) ||
103 ((fd
.isStaticCtorDeclaration() || fd
.isCrtCtor
) && !var
.isField())) &&
104 fd
.toParentDecl() == var
.toParent2() &&
105 (!e1 || e1
.op
== EXP
.this_
))
110 //printf("setting ctorinit\n");
112 if (var
.isField() && sc
.ctorflow
.fieldinit
.length
&& !sc
.intypeof
)
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();
122 for (i
= 0; i
< dim
; i
++) // same as findFieldIndexByName in ctfeexp.c ?
124 if (ad
.fields
[i
] == var
)
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())
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())
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
))
162 sc
.ctorflow
.fieldinit
[j
].csx
= CSX
.this_ctor
;
166 else if (fd
!= sc
.func
)
168 if (var
.type
.isMutable())
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());
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() &&
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.");
205 s
= s
.toParentP(var
.toParent2());
214 /******************************************
216 extern (C
++) void ObjectNotFound(Identifier id
)
218 error(Loc
.initial
, "`%s` not found. object.d may be incorrectly installed or corrupt.", id
.toChars());
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
237 Type originalType
; // before semantic analysis
238 StorageClass storage_class
= STC
.undefined_
;
239 Visibility visibility
;
240 LINK _linkage
= LINK
.default_
; // may be `LINK.system`; use `resolvedLinkage()` to resolve it
241 short inuse
; // used to detect cycles
243 ubyte adFlags
; // control re-assignment of AliasDeclaration (put here for packing reasons)
244 enum wasRead
= 1; // set if AliasDeclaration was read
245 enum ignoreRead
= 2; // ignore any reads of AliasDeclaration
246 enum nounderscore
= 4; // don't prepend _ to mangled name
248 Symbol
* isym
; // import version of csym
250 // overridden symbol with pragma(mangle, "...")
251 const(char)[] mangleOverride
;
253 final extern (D
) this(Identifier ident
) @safe
256 visibility
= Visibility(Visibility
.Kind
.undefined
);
259 final extern (D
) this(const ref Loc loc
, Identifier ident
) @safe
262 visibility
= Visibility(Visibility
.Kind
.undefined
);
265 override const(char)* kind() const
267 return "declaration";
270 override final uinteger_t
size(const ref Loc loc
)
273 const sz
= type
.size();
274 if (sz
== SIZE_INVALID
)
280 * Issue an error if an attempt to call a disabled method is made
282 * If the declaration is disabled but inside a disabled function,
283 * returns `true` but do not issue an error message.
286 * loc = Location information of the call
287 * sc = Scope in which the call occurs
288 * isAliasedDeclaration = if `true` searches overload set
291 * `true` if this `Declaration` is `@disable`d, `false` otherwise.
293 extern (D
) final bool checkDisabled(Loc loc
, Scope
* sc
, bool isAliasedDeclaration
= false)
295 if (!(storage_class
& STC
.disable
))
298 if (sc
.func
&& sc
.func
.storage_class
& STC
.disable
)
301 if (auto p
= toParent())
303 if (auto postblit
= isPostBlitDeclaration())
305 /* https://issues.dlang.org/show_bug.cgi?id=21885
307 * If the generated postblit is disabled, it
308 * means that one of the fields has a disabled
309 * postblit. Print the first field that has
310 * a disabled postblit.
312 if (postblit
.isGenerated())
314 auto sd
= p
.isStructDeclaration();
316 for (size_t i
= 0; i
< sd
.fields
.length
; i
++)
318 auto structField
= sd
.fields
[i
];
319 if (structField
.overlapped
)
321 Type tv
= structField
.type
.baseElemOf();
322 if (tv
.ty
!= Tstruct
)
324 auto sdv
= (cast(TypeStruct
)tv
).sym
;
327 if (sdv
.postblit
.isDisabled())
329 .error(loc
, "%s `%s` is not copyable because field `%s` is not copyable", p
.kind
, p
.toPrettyChars
, structField
.toChars());
334 .error(loc
, "%s `%s` is not copyable because it has a disabled postblit", p
.kind
, p
.toPrettyChars
);
339 // if the function is @disabled, maybe there
340 // is an overload in the overload set that isn't
341 if (isAliasedDeclaration
)
343 FuncDeclaration fd
= isFuncDeclaration();
346 for (FuncDeclaration ovl
= fd
; ovl
; ovl
= cast(FuncDeclaration
)ovl
.overnext
)
347 if (!(ovl
.storage_class
& STC
.disable
))
352 if (auto ctor
= isCtorDeclaration())
354 if (ctor
.isCpCtor
&& ctor
.isGenerated())
356 .error(loc
, "generating an `inout` copy constructor for `struct %s` failed, therefore instances of it are uncopyable", parent
.toPrettyChars());
360 .error(loc
, "%s `%s` cannot be used because it is annotated with `@disable`", kind
, toPrettyChars
);
364 /*************************************
365 * Check to see if declaration can be modified in this context (sc).
366 * Issue error if not.
368 * loc = location for error messages
369 * e1 = `null` or `this` expression when this declaration is a field
371 * flag = if the first bit is set it means do not issue error message for
372 * invalid modification; if the second bit is set, it means that
373 this declaration is a field and a subfield of it is modified.
375 * Modifiable.yes or Modifiable.initialization
377 extern (D
) final Modifiable
checkModify(Loc loc
, Scope
* sc
, Expression e1
, ModifyFlags flag
)
379 VarDeclaration v
= isVarDeclaration();
380 if (v
&& v
.canassign
)
381 return Modifiable
.initialization
;
383 if (isParameter() ||
isResult())
385 for (Scope
* scx
= sc
; scx
; scx
= scx
.enclosing
)
387 if (scx
.func
== parent
&& (scx
.flags
& SCOPE
.contract
))
389 const(char)* s
= isParameter() && parent
.ident
!= Id
.ensure ?
"parameter" : "result";
390 if (!(flag
& ModifyFlags
.noError
))
391 error(loc
, "%s `%s` cannot modify %s `%s` in contract", kind
, toPrettyChars
, s
, toChars());
392 return Modifiable
.initialization
; // do not report type related errors
397 if (e1
&& e1
.op
== EXP
.this_
&& isField())
399 VarDeclaration vthis
= e1
.isThisExp().var
;
400 for (Scope
* scx
= sc
; scx
; scx
= scx
.enclosing
)
402 if (scx
.func
== vthis
.parent
&& (scx
.flags
& SCOPE
.contract
))
404 if (!(flag
& ModifyFlags
.noError
))
405 error(loc
, "%s `%s` cannot modify parameter `this` in contract", kind
, toPrettyChars
);
406 return Modifiable
.initialization
; // do not report type related errors
411 if (v
&& (v
.isCtorinit() ||
isField()))
413 // It's only modifiable if inside the right constructor
414 if ((storage_class
& (STC
.foreach_ | STC
.ref_
)) == (STC
.foreach_ | STC
.ref_
))
415 return Modifiable
.initialization
;
416 if (flag
& ModifyFlags
.fieldAssign
)
417 return Modifiable
.yes
;
418 return modifyFieldVar(loc
, sc
, v
, e1
) ? Modifiable
.initialization
: Modifiable
.yes
;
420 return Modifiable
.yes
;
423 override final Dsymbol
search(const ref Loc loc
, Identifier ident
, int flags
= SearchLocalsOnly
)
425 Dsymbol s
= Dsymbol
.search(loc
, ident
, flags
);
428 s
= type
.toDsymbol(_scope
);
430 s
= s
.search(loc
, ident
, flags
);
435 final bool isStatic() const pure nothrow @nogc @safe
437 return (storage_class
& STC
.static_
) != 0;
440 /// Returns the linkage, resolving the target-specific `System` one.
441 final LINK
resolvedLinkage() const
443 return _linkage
== LINK
.system ? target
.systemLinkage() : _linkage
;
461 bool isCodeseg() const pure nothrow @nogc @safe
466 final bool isFinal() const pure nothrow @nogc @safe
468 return (storage_class
& STC
.final_
) != 0;
473 return (storage_class
& STC
.abstract_
) != 0;
476 final bool isConst() const pure nothrow @nogc @safe
478 return (storage_class
& STC
.const_
) != 0;
481 final bool isImmutable() const pure nothrow @nogc @safe
483 return (storage_class
& STC
.immutable_
) != 0;
486 final bool isWild() const pure nothrow @nogc @safe
488 return (storage_class
& STC
.wild
) != 0;
491 final bool isAuto() const pure nothrow @nogc @safe
493 return (storage_class
& STC
.auto_
) != 0;
496 final bool isScope() const pure nothrow @nogc @safe
498 return (storage_class
& STC
.scope_
) != 0;
501 final bool isReturn() const pure nothrow @nogc @safe
503 return (storage_class
& STC
.return_
) != 0;
506 final bool isSynchronized() const pure nothrow @nogc @safe
508 return (storage_class
& STC
.synchronized_
) != 0;
511 final bool isParameter() const pure nothrow @nogc @safe
513 return (storage_class
& STC
.parameter
) != 0;
516 override final bool isDeprecated() const pure nothrow @nogc @safe
518 return (storage_class
& STC
.deprecated_
) != 0;
521 final bool isDisabled() const pure nothrow @nogc @safe
523 return (storage_class
& STC
.disable
) != 0;
526 final bool isOverride() const pure nothrow @nogc @safe
528 return (storage_class
& STC
.override_
) != 0;
531 final bool isResult() const pure nothrow @nogc @safe
533 return (storage_class
& STC
.result
) != 0;
536 final bool isField() const pure nothrow @nogc @safe
538 return (storage_class
& STC
.field
) != 0;
541 final bool isIn() const pure nothrow @nogc @safe
543 return (storage_class
& STC
.in_
) != 0;
546 final bool isOut() const pure nothrow @nogc @safe
548 return (storage_class
& STC
.out_
) != 0;
551 final bool isRef() const pure nothrow @nogc @safe
553 return (storage_class
& STC
.ref_
) != 0;
556 /// Returns: Whether the variable is a reference, annotated with `out` or `ref`
557 final bool isReference() const pure nothrow @nogc @safe
559 return (storage_class
& (STC
.ref_ | STC
.out_
)) != 0;
562 final bool isFuture() const pure nothrow @nogc @safe
564 return (storage_class
& STC
.future
) != 0;
567 final extern(D
) bool isSystem() const pure nothrow @nogc @safe
569 return (storage_class
& STC
.system
) != 0;
572 override final Visibility
visible() pure nothrow @nogc @safe
577 override final inout(Declaration
) isDeclaration() inout pure nothrow @nogc @safe
582 override void accept(Visitor v
)
588 /***********************************************************
590 extern (C
++) final class TupleDeclaration
: Declaration
593 TypeTuple tupletype
; // !=null if this is a type tuple
594 bool isexp
; // true: expression tuple
595 bool building
; // it's growing in AliasAssign semantic
597 extern (D
) this(const ref Loc loc
, Identifier ident
, Objects
* objects
) @safe
600 this.objects
= objects
;
603 override TupleDeclaration
syntaxCopy(Dsymbol s
)
608 override const(char)* kind() const
613 override Type
getType()
615 /* If this tuple represents a type, return that type
618 //printf("TupleDeclaration::getType() %s\n", toChars());
619 if (isexp || building
)
623 /* It's only a type tuple if all the Object's are types
625 for (size_t i
= 0; i
< objects
.length
; i
++)
627 RootObject o
= (*objects
)[i
];
630 //printf("\tnot[%d], %p, %d\n", i, o, o.dyncast());
635 /* We know it's a type tuple, so build the TypeTuple
637 Types
* types
= cast(Types
*)objects
;
638 auto args
= new Parameters(objects
.length
);
641 for (size_t i
= 0; i
< types
.length
; i
++)
643 Type t
= (*types
)[i
];
644 //printf("type = %s\n", t.toChars());
647 buf
.printf("_%s_%d", ident
.toChars(), i
);
648 auto id
= Identifier
.idPool(buf
.extractSlice());
649 auto arg
= new Parameter(Loc
.initial
, STC
.in_
, t
, id
, null);
653 auto arg
= new Parameter(Loc
.initial
, 0, t
, null, null, null);
660 tupletype
= new TypeTuple(args
);
662 return tupletype
.typeSemantic(Loc
.initial
, null);
667 override Dsymbol
toAlias2()
669 //printf("TupleDeclaration::toAlias2() '%s' objects = %s\n", toChars(), objects.toChars());
670 for (size_t i
= 0; i
< objects
.length
; i
++)
672 RootObject o
= (*objects
)[i
];
673 if (Dsymbol s
= isDsymbol(o
))
682 override bool needThis()
684 //printf("TupleDeclaration::needThis(%s)\n", toChars());
685 return isexp ?
foreachVar((s
) { return s
.needThis(); }) != 0 : false;
688 /***********************************************************
689 * Calls dg(Dsymbol) for each Dsymbol, which should be a VarDeclaration
690 * inside VarExp (isexp == true).
692 * dg = delegate to call for each Dsymbol
694 extern (D
) void foreachVar(scope void delegate(Dsymbol
) dg
)
697 foreach (o
; *objects
)
699 if (auto e
= o
.isExpression())
700 if (auto ve
= e
.isVarExp())
705 /***********************************************************
706 * Calls dg(Dsymbol) for each Dsymbol, which should be a VarDeclaration
707 * inside VarExp (isexp == true).
708 * If dg returns !=0, stops and returns that value else returns 0.
710 * dg = delegate to call for each Dsymbol
712 * last value returned by dg()
714 extern (D
) int foreachVar(scope int delegate(Dsymbol
) dg
)
717 foreach (o
; *objects
)
719 if (auto e
= o
.isExpression())
720 if (auto ve
= e
.isVarExp())
721 if(auto ret = dg(ve
.var
))
727 override inout(TupleDeclaration
) isTupleDeclaration() inout
732 override void accept(Visitor v
)
738 /***********************************************************
739 * https://dlang.org/spec/declaration.html#AliasDeclaration
741 extern (C
++) final class AliasDeclaration
: Declaration
743 Dsymbol aliassym
; // alias ident = aliassym;
745 Dsymbol overnext
; // next in overload list
746 Dsymbol _import
; // !=null if unresolved internal alias for selective import
748 extern (D
) this(const ref Loc loc
, Identifier ident
, Type type
) @safe
751 //printf("AliasDeclaration(id = '%s', type = %p)\n", ident.toChars(), type);
752 //printf("type = '%s'\n", type.toChars());
757 extern (D
) this(const ref Loc loc
, Identifier ident
, Dsymbol s
) @safe
760 //printf("AliasDeclaration(id = '%s', s = %p)\n", ident.toChars(), s);
766 static AliasDeclaration
create(const ref Loc loc
, Identifier id
, Type type
) @safe
768 return new AliasDeclaration(loc
, id
, type
);
771 override AliasDeclaration
syntaxCopy(Dsymbol s
)
773 //printf("AliasDeclaration::syntaxCopy()\n");
775 AliasDeclaration sa
= type ?
new AliasDeclaration(loc
, ident
, type
.syntaxCopy()) : new AliasDeclaration(loc
, ident
, aliassym
.syntaxCopy(null));
776 sa
.comment
= comment
;
777 sa
.storage_class
= storage_class
;
781 override bool overloadInsert(Dsymbol s
)
783 //printf("[%s] AliasDeclaration::overloadInsert('%s') s = %s %s @ [%s]\n",
784 // loc.toChars(), toChars(), s.kind(), s.toChars(), s.loc.toChars());
786 /** Aliases aren't overloadable themselves, but if their Aliasee is
787 * overloadable they are converted to an overloadable Alias (either
788 * FuncAliasDeclaration or OverDeclaration).
790 * This is done by moving the Aliasee into such an overloadable alias
791 * which is then used to replace the existing Aliasee. The original
792 * Alias (_this_) remains a useless shell.
794 * This is a horrible mess. It was probably done to avoid replacing
795 * existing AST nodes and references, but it needs a major
796 * simplification b/c it's too complex to maintain.
798 * A simpler approach might be to merge any colliding symbols into a
799 * simple Overload class (an array) and then later have that resolve
802 if (semanticRun
>= PASS
.semanticdone
)
804 /* Semantic analysis is already finished, and the aliased entity
805 * is not overloadable.
810 If type has been resolved already we could
811 still be inserting an alias from an import.
813 If we are handling an alias then pretend
814 it was inserting and return true, if not then
815 false since we didn't even pretend to insert something.
817 return this._import
&& this.equals(s
);
820 /* When s is added in member scope by static if, mixin("code") or others,
821 * aliassym is determined already. See the case in: test/compilable/test61.d
823 auto sa
= aliassym
.toAlias();
825 if (auto td
= s
.toAlias().isTemplateDeclaration())
826 s
= td
.funcroot ? td
.funcroot
: td
;
828 if (auto fd
= sa
.isFuncDeclaration())
830 auto fa
= new FuncAliasDeclaration(ident
, fd
);
831 fa
.visibility
= visibility
;
834 return aliassym
.overloadInsert(s
);
836 if (auto td
= sa
.isTemplateDeclaration())
838 auto od
= new OverDeclaration(ident
, td
.funcroot ? td
.funcroot
: td
);
839 od
.visibility
= visibility
;
842 return aliassym
.overloadInsert(s
);
844 if (auto od
= sa
.isOverDeclaration())
846 if (sa
.ident
!= ident || sa
.parent
!= parent
)
848 od
= new OverDeclaration(ident
, od
);
849 od
.visibility
= visibility
;
853 return od
.overloadInsert(s
);
855 if (auto os
= sa
.isOverloadSet())
857 if (sa
.ident
!= ident || sa
.parent
!= parent
)
859 os
= new OverloadSet(ident
, os
);
860 // TODO: visibility is lost here b/c OverloadSets have no visibility attribute
861 // Might no be a practical issue, b/c the code below fails to resolve the overload anyhow.
865 // private alias merged = foo; // private alias to overload set of a.foo and b.foo
869 // public alias merged = bar; // public alias to overload set of a.bar and b.bar
873 // void test() { merged(123); } // should only look at os2.merged
875 // os.visibility = visibility;
885 /* Don't know yet what the aliased symbol is, so assume it can
886 * be overloaded and check later for correctness.
889 return overnext
.overloadInsert(s
);
896 override const(char)* kind() const
901 override Type
getType()
905 return toAlias().getType();
908 override Dsymbol
toAlias()
910 //printf("[%s] AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s', inuse = %d)\n",
911 // loc.toChars(), toChars(), this, aliassym, aliassym ? aliassym.kind() : "", inuse);
912 assert(this != aliassym
);
913 //static int count; if (++count == 10) *(char*)0=0;
915 // Reading the AliasDeclaration
916 if (!(adFlags
& ignoreRead
))
917 adFlags |
= wasRead
; // can never assign to this AliasDeclaration again
919 if (inuse
== 1 && type
&& _scope
)
922 uint olderrors
= global
.errors
;
923 Dsymbol s
= type
.toDsymbol(_scope
);
924 //printf("[%s] type = %s, s = %p, this = %p\n", loc.toChars(), type.toChars(), s, this);
925 if (global
.errors
!= olderrors
)
930 if (global
.errors
!= olderrors
)
937 Type t
= type
.typeSemantic(loc
, _scope
);
940 if (global
.errors
!= olderrors
)
942 //printf("t = %s\n", t.toChars());
948 .error(loc
, "%s `%s` recursive alias declaration", kind
, toPrettyChars
);
951 // Avoid breaking "recursive alias" state during errors gagged
954 aliassym
= new AliasDeclaration(loc
, ident
, Type
.terror
);
959 if (semanticRun
>= PASS
.semanticdone
)
961 // semantic is already done.
963 // Do not see aliassym !is null, because of lambda aliases.
965 // Do not see type.deco !is null, even so "alias T = const int;` needs
966 // semantic analysis to take the storage class `const` as type qualifier.
970 // stop AliasAssign tuple building
973 if (auto td
= aliassym
.isTupleDeclaration())
978 semanticRun
= PASS
.semanticdone
;
983 if (_import
&& _import
._scope
)
985 /* If this is an internal alias for selective/renamed import,
986 * load the module first.
988 _import
.dsymbolSemantic(null);
992 aliasSemantic(this, _scope
);
997 Dsymbol s
= aliassym ? aliassym
.toAlias() : this;
1002 override Dsymbol
toAlias2()
1006 .error(loc
, "%s `%s` recursive alias declaration", kind
, toPrettyChars
);
1010 Dsymbol s
= aliassym ? aliassym
.toAlias2() : this;
1015 override bool isOverloadable() const
1017 // assume overloadable until alias is resolved
1018 return semanticRun
< PASS
.semanticdone ||
1019 aliassym
&& aliassym
.isOverloadable();
1022 override inout(AliasDeclaration
) isAliasDeclaration() inout
1027 /** Returns: `true` if this instance was created to make a template parameter
1028 visible in the scope of a template body, `false` otherwise */
1029 extern (D
) bool isAliasedTemplateParameter() const
1031 return !!(storage_class
& STC
.templateparameter
);
1034 override void accept(Visitor v
)
1040 /***********************************************************
1042 extern (C
++) final class OverDeclaration
: Declaration
1044 Dsymbol overnext
; // next in overload list
1047 extern (D
) this(Identifier ident
, Dsymbol s
) @safe
1053 override const(char)* kind() const
1055 return "overload alias"; // todo
1058 override bool equals(const RootObject o
) const
1063 auto s
= isDsymbol(o
);
1067 if (auto od2
= s
.isOverDeclaration())
1068 return this.aliassym
.equals(od2
.aliassym
);
1069 return this.aliassym
== s
;
1072 override bool overloadInsert(Dsymbol s
)
1074 //printf("OverDeclaration::overloadInsert('%s') aliassym = %p, overnext = %p\n", s.toChars(), aliassym, overnext);
1076 return overnext
.overloadInsert(s
);
1083 override bool isOverloadable() const
1090 Dsymbol result
= null;
1091 overloadApply(aliassym
, (Dsymbol s
)
1096 return 1; // ambiguous, done
1107 override inout(OverDeclaration
) isOverDeclaration() inout
1112 override void accept(Visitor v
)
1118 /***********************************************************
1120 extern (C
++) class VarDeclaration
: Declaration
1123 FuncDeclarations nestedrefs
; // referenced by these lexically nested functions
1124 TupleDeclaration aliasTuple
; // when `this` is really a tuple of declarations
1125 VarDeclaration lastVar
; // Linked list of variables for goto-skips-init detection
1126 Expression edtor
; // if !=null, does the destruction of the variable
1127 IntRange
* range
; // if !=null, the variable is known to be within the range
1128 VarDeclarations
* maybes
; // maybeScope variables that are assigned to this maybeScope variable
1130 uint endlinnum
; // line number of end of scope that this var lives in
1132 uint sequenceNumber
; // order the variables are declared
1133 structalign_t alignment
;
1135 // When interpreting, these point to the value (NULL if value not determinable)
1136 // The index of this variable on the CTFE stack, AdrOnStackNone if not allocated
1137 enum AdrOnStackNone
= ~0u;
1138 uint ctfeAdrOnStack
;
1140 // `bool` fields that are compacted into bit fields in a string mixin
1141 private extern (D
) static struct BitFields
1143 bool isargptr
; /// if parameter that _argptr points to
1144 bool ctorinit
; /// it has been initialized in a ctor
1145 bool iscatchvar
; /// this is the exception object variable in catch() clause
1146 bool isowner
; /// this is an Owner, despite it being `scope`
1147 bool setInCtorOnly
; /// field can only be set in a constructor, as it is const or immutable
1149 /// It is a class that was allocated on the stack
1151 /// This means the var is not rebindable once assigned,
1152 /// and the destructor gets run when it goes out of scope
1155 bool overlapped
; /// if it is a field and has overlapping
1156 bool overlapUnsafe
; /// if it is an overlapping field and the overlaps are unsafe
1157 bool maybeScope
; /// allow inferring 'scope' for this variable
1158 bool doNotInferReturn
; /// do not infer 'return' for this variable
1160 bool isArgDtorVar
; /// temporary created to handle scope destruction of a function argument
1161 bool isCmacro
; /// it is a C macro turned into a C declaration
1162 bool dllImport
; /// __declspec(dllimport)
1163 bool dllExport
; /// __declspec(dllexport)
1166 bool inClosure
; /// is inserted into a GC allocated closure
1167 bool inAlignSection
; /// is inserted into an aligned section on stack
1169 bool systemInferred
; /// @system was inferred from initializer
1172 import dmd
.common
.bitfields
: generateBitFields
;
1173 mixin(generateBitFields
!(BitFields
, uint));
1175 byte canassign
; // it can be assigned to
1176 ubyte isdataseg
; // private data for isDataseg 0 unset, 1 true, 2 false
1178 final extern (D
) this(const ref Loc loc
, Type type
, Identifier ident
, Initializer _init
, StorageClass storage_class
= STC
.undefined_
)
1185 //printf("VarDeclaration('%s')\n", ident.toChars());
1189 if (!type
&& !_init
)
1191 //printf("VarDeclaration('%s')\n", ident.toChars());
1196 assert(type || _init
);
1199 ctfeAdrOnStack
= AdrOnStackNone
;
1200 this.storage_class
= storage_class
;
1203 static VarDeclaration
create(const ref Loc loc
, Type type
, Identifier ident
, Initializer _init
, StorageClass storage_class
= STC
.undefined_
)
1205 return new VarDeclaration(loc
, type
, ident
, _init
, storage_class
);
1208 override VarDeclaration
syntaxCopy(Dsymbol s
)
1210 //printf("VarDeclaration::syntaxCopy(%s)\n", toChars());
1212 auto v
= new VarDeclaration(loc
, type ? type
.syntaxCopy() : null, ident
, _init ? _init
.syntaxCopy() : null, storage_class
);
1213 v
.comment
= comment
;
1217 override void setFieldOffset(AggregateDeclaration ad
, ref FieldState fieldState
, bool isunion
)
1219 //printf("VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars());
1223 // If this variable was really a tuple, set the offsets for the tuple fields
1224 aliasTuple
.foreachVar((s
) { s
.setFieldOffset(ad
, fieldState
, isunion
); });
1230 assert(!(storage_class
& (STC
.static_ | STC
.extern_ | STC
.parameter
)));
1232 //printf("+VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars());
1234 /* Fields that are tuples appear both as part of TupleDeclarations and
1235 * as members. That means ignore them if they are already a field.
1240 fieldState
.offset
= ad
.structsize
; // https://issues.dlang.org/show_bug.cgi?id=13613
1243 for (size_t i
= 0; i
< ad
.fields
.length
; i
++)
1245 if (ad
.fields
[i
] == this)
1248 fieldState
.offset
= ad
.structsize
; // https://issues.dlang.org/show_bug.cgi?id=13613
1253 // Check for forward referenced types which will fail the size() call
1254 Type t
= type
.toBasetype();
1255 if (storage_class
& STC
.ref_
)
1257 // References are the size of a pointer
1260 Type tv
= t
.baseElemOf();
1261 if (tv
.ty
== Tstruct
)
1263 auto ts
= cast(TypeStruct
)tv
;
1264 assert(ts
.sym
!= ad
); // already checked in ad.determineFields()
1265 if (!ts
.sym
.determineSize(loc
))
1273 // List in ad.fields. Even if the type is error, it's necessary to avoid
1274 // pointless error diagnostic "more initializers than fields" on struct literal.
1275 ad
.fields
.push(this);
1280 /* If coming after a bit field in progress,
1281 * advance past the field
1283 fieldState
.inFlight
= false;
1285 const sz
= t
.size(loc
);
1286 assert(sz
!= SIZE_INVALID
&& sz
< uint.max
);
1287 uint memsize
= cast(uint)sz
; // size of member
1288 uint memalignsize
= target
.fieldalign(t
); // size of member for alignment purposes
1289 offset
= AggregateDeclaration
.placeField(
1291 memsize
, memalignsize
, alignment
,
1292 &ad
.structsize
, &ad
.alignsize
,
1295 //printf("\t%s: memalignsize = %d\n", toChars(), memalignsize);
1296 //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize);
1299 override const(char)* kind() const
1304 override final inout(AggregateDeclaration
) isThis() inout
1306 if (!(storage_class
& (STC
.static_ | STC
.extern_ | STC
.manifest | STC
.templateparameter | STC
.gshared | STC
.ctfe
)))
1308 /* The casting is necessary because `s = s.parent` is otherwise rejected
1310 for (auto s
= cast(Dsymbol
)this; s
; s
= s
.parent
)
1312 auto ad
= (cast(inout)s
).isMember();
1315 if (!s
.parent ||
!s
.parent
.isTemplateMixin())
1322 override final bool needThis()
1324 //printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class);
1328 override final bool isExport() const
1330 return visibility
.kind
== Visibility
.Kind
.export_ || dllExport
;
1333 override final bool isImportedSymbol() const
1335 /* If global variable has `export` and `extern` then it is imported
1336 * export int sym1; // definition: exported
1337 * export extern int sym2; // declaration: imported
1338 * export extern int sym3 = 0; // error, extern cannot have initializer
1342 visibility
.kind
== Visibility
.Kind
.export_
&&
1343 storage_class
& STC
.extern_
&&
1344 (storage_class
& STC
.static_ || parent
.isModule());
1345 //printf("isImportedSymbol() %s %d\n", toChars(), result);
1349 final bool isCtorinit() const pure nothrow @nogc @safe
1351 return setInCtorOnly
;
1354 /*******************************
1355 * Does symbol go into data segment?
1356 * Includes extern variables.
1358 override final bool isDataseg()
1362 printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars());
1363 printf("%llx, isModule: %p, isTemplateInstance: %p, isNspace: %p\n",
1364 storage_class
& (STC
.static_ | STC
.const_
), parent
.isModule(), parent
.isTemplateInstance(), parent
.isNspace());
1365 printf("parent = '%s'\n", parent
.toChars());
1368 if (isdataseg
== 0) // the value is not cached
1370 isdataseg
= 2; // The Variables does not go into the datasegment
1372 if (!canTakeAddressOf())
1377 Dsymbol parent
= toParent();
1378 if (!parent
&& !(storage_class
& STC
.static_
))
1380 .error(loc
, "%s `%s` forward referenced", kind
, toPrettyChars
);
1383 else if (storage_class
& (STC
.static_ | STC
.extern_ | STC
.gshared
) ||
1384 parent
.isModule() || parent
.isTemplateInstance() || parent
.isNspace())
1386 assert(!isParameter() && !isResult());
1387 isdataseg
= 1; // It is in the DataSegment
1391 return (isdataseg
== 1);
1393 /************************************
1394 * Does symbol go into thread local storage?
1396 override final bool isThreadlocal()
1398 //printf("VarDeclaration::isThreadlocal(%p, '%s')\n", this, toChars());
1399 /* Data defaults to being thread-local. It is not thread-local
1400 * if it is immutable, const or shared.
1402 bool i
= isDataseg() && !(storage_class
& (STC
.immutable_ | STC
.const_ | STC
.shared_ | STC
.gshared
));
1403 //printf("\treturn %d\n", i);
1407 /********************************************
1408 * Can variable be read and written by CTFE?
1412 return (storage_class
& STC
.ctfe
) != 0; // || !isDataseg();
1415 final bool isOverlappedWith(VarDeclaration v
)
1417 const vsz
= v
.type
.size();
1418 const tsz
= type
.size();
1419 assert(vsz
!= SIZE_INVALID
&& tsz
!= SIZE_INVALID
);
1421 // Overlap is checked by comparing bit offsets
1422 auto bitoffset
= offset
* 8;
1423 auto vbitoffset
= v
.offset
* 8;
1425 // Bitsize of types are overridden by any bit-field widths.
1426 ulong tbitsize
= void;
1427 if (auto bf
= isBitFieldDeclaration())
1429 bitoffset
+= bf
.bitOffset
;
1430 tbitsize
= bf
.fieldWidth
;
1435 ulong vbitsize
= void;
1436 if (auto vbf
= v
.isBitFieldDeclaration())
1438 vbitoffset
+= vbf
.bitOffset
;
1439 vbitsize
= vbf
.fieldWidth
;
1444 return bitoffset
< vbitoffset
+ vbitsize
&&
1445 vbitoffset
< bitoffset
+ tbitsize
;
1448 override final bool hasPointers()
1450 //printf("VarDeclaration::hasPointers() %s, ty = %d\n", toChars(), type.ty);
1451 return (!isDataseg() && type
.hasPointers());
1454 /*************************************
1455 * Return true if we can take the address of this variable.
1457 final bool canTakeAddressOf()
1459 return !(storage_class
& STC
.manifest
);
1462 /******************************************
1463 * Return true if variable needs to call the destructor.
1465 final bool needsScopeDtor()
1467 //printf("VarDeclaration::needsScopeDtor() %s\n", toChars());
1468 return edtor
&& !(storage_class
& STC
.nodtor
);
1471 /******************************************
1472 * If a variable has a scope destructor call, return call for it.
1473 * Otherwise, return NULL.
1475 extern (D
) final Expression
callScopeDtor(Scope
* sc
)
1477 //printf("VarDeclaration::callScopeDtor() %s\n", toChars());
1479 // Destruction of STC.field's is handled by buildDtor()
1480 if (storage_class
& (STC
.nodtor | STC
.ref_ | STC
.out_ | STC
.field
))
1486 return null; // destructor is built by `void semantic(Catch c, Scope* sc)`, not here
1488 Expression e
= null;
1489 // Destructors for structs and arrays of structs
1490 Type tv
= type
.baseElemOf();
1491 if (tv
.ty
== Tstruct
)
1493 StructDeclaration sd
= (cast(TypeStruct
)tv
).sym
;
1494 if (!sd
.dtor || sd
.errors
)
1497 const sz
= type
.size();
1498 assert(sz
!= SIZE_INVALID
);
1502 if (type
.toBasetype().ty
== Tstruct
)
1505 e
= new VarExp(loc
, this);
1507 /* This is a hack so we can call destructors on const/immutable objects.
1508 * Need to add things like "const ~this()" and "immutable ~this()" to
1511 e
.type
= e
.type
.mutableOf();
1513 // Enable calling destructors on shared objects.
1514 // The destructor is always a single, non-overloaded function,
1515 // and must serve both shared and non-shared objects.
1516 e
.type
= e
.type
.unSharedOf
;
1518 e
= new DotVarExp(loc
, e
, sd
.dtor
, false);
1519 e
= new CallExp(loc
, e
);
1523 // __ArrayDtor(v[0 .. n])
1524 e
= new VarExp(loc
, this);
1526 const sdsz
= sd
.type
.size();
1527 assert(sdsz
!= SIZE_INVALID
&& sdsz
!= 0);
1528 const n
= sz
/ sdsz
;
1529 SliceExp se
= new SliceExp(loc
, e
, new IntegerExp(loc
, 0, Type
.tsize_t
),
1530 new IntegerExp(loc
, n
, Type
.tsize_t
));
1532 // Prevent redundant bounds check
1533 se
.upperIsInBounds
= true;
1534 se
.lowerIsLessThanUpper
= true;
1536 // This is a hack so we can call destructors on const/immutable objects.
1537 se
.type
= sd
.type
.arrayOf();
1539 e
= new CallExp(loc
, new IdentifierExp(loc
, Id
.__ArrayDtor
), se
);
1543 // Destructors for classes
1544 if (storage_class
& (STC
.auto_ | STC
.scope_
) && !(storage_class
& STC
.parameter
))
1546 for (ClassDeclaration cd
= type
.isClassHandle(); cd
; cd
= cd
.baseClass
)
1548 /* We can do better if there's a way with onstack
1549 * classes to determine if there's no way the monitor
1552 //if (cd.isInterfaceDeclaration())
1553 // error("interface `%s` cannot be scope", cd.toChars());
1555 if (onstack
) // if any destructors
1557 // delete'ing C++ classes crashes (and delete is deprecated anyway)
1558 if (cd
.classKind
== ClassKind
.cpp
)
1560 // Don't call non-existant dtor
1564 e
= new VarExp(loc
, this);
1565 e
.type
= e
.type
.mutableOf().unSharedOf(); // Hack for mutable ctor on immutable instances
1566 e
= new DotVarExp(loc
, e
, cd
.dtor
, false);
1567 e
= new CallExp(loc
, e
);
1573 ec
= new VarExp(loc
, this);
1574 e
= new DeleteExp(loc
, ec
, true);
1575 e
.type
= Type
.tvoid
;
1583 /*******************************************
1584 * If variable has a constant expression initializer, get it.
1585 * Otherwise, return null.
1587 extern (D
) final Expression
getConstInitializer(bool needFullType
= true)
1589 assert(type
&& _init
);
1591 // Ungag errors when not speculative
1592 uint oldgag
= global
.gag
;
1595 Dsymbol sym
= isMember();
1596 if (sym
&& !sym
.isSpeculative())
1603 _init
= _init
.initializerSemantic(_scope
, type
, INITinterpret
);
1604 import dmd
.semantic2
: lowerStaticAAs
;
1605 lowerStaticAAs(this, _scope
);
1610 Expression e
= _init
.initializerToExpression(needFullType ? type
: null);
1611 global
.gag
= oldgag
;
1615 /*******************************************
1616 * Helper function for the expansion of manifest constant.
1618 extern (D
) final Expression
expandInitializer(Loc loc
)
1620 assert((storage_class
& STC
.manifest
) && _init
);
1622 auto e
= getConstInitializer();
1625 .error(loc
, "cannot make expression out of initializer for `%s`", toChars());
1626 return ErrorExp
.get();
1630 e
.loc
= loc
; // for better error message
1634 override final void checkCtorConstInit()
1638 /* doesn't work if more than one static ctor */
1639 if (ctorinit
== 0 && isCtorinit() && !isField())
1640 error("missing initializer in static constructor for const variable");
1644 /************************************
1645 * Check to see if this variable is actually in an enclosing function
1646 * rather than the current one.
1647 * Update nestedrefs[], closureVars[] and outerVars[].
1648 * Returns: true if error occurs.
1650 extern (D
) final bool checkNestedReference(Scope
* sc
, Loc loc
)
1652 //printf("VarDeclaration::checkNestedReference() %s\n", toChars());
1653 if (sc
.intypeof
== 1 ||
(sc
.flags
& SCOPE
.ctfe
))
1655 if (!parent || parent
== sc
.parent
)
1657 if (isDataseg() ||
(storage_class
& STC
.manifest
))
1660 // The current function
1661 FuncDeclaration fdthis
= sc
.parent
.isFuncDeclaration();
1663 return false; // out of function scope
1665 Dsymbol p
= toParent2();
1667 // Function literals from fdthis to p must be delegates
1668 ensureStaticLinkTo(fdthis
, p
);
1670 // The function that this variable is in
1671 FuncDeclaration fdv
= p
.isFuncDeclaration();
1672 if (!fdv || fdv
== fdthis
)
1675 // Add fdthis to nestedrefs[] if not already there
1676 if (!nestedrefs
.contains(fdthis
))
1677 nestedrefs
.push(fdthis
);
1679 //printf("\tfdv = %s\n", fdv.toChars());
1680 //printf("\tfdthis = %s\n", fdthis.toChars());
1683 if (fdthis
.getLevelAndCheck(loc
, sc
, fdv
, this) == fdthis
.LevelError
)
1687 // Add this VarDeclaration to fdv.closureVars[] if not already there
1688 if (!sc
.intypeof
&& !(sc
.flags
& SCOPE
.compile
) &&
1689 // https://issues.dlang.org/show_bug.cgi?id=17605
1690 (fdv
.skipCodegen ||
!fdthis
.skipCodegen
))
1692 if (!fdv
.closureVars
.contains(this))
1693 fdv
.closureVars
.push(this);
1696 if (!fdthis
.outerVars
.contains(this))
1697 fdthis
.outerVars
.push(this);
1699 //printf("fdthis is %s\n", fdthis.toChars());
1700 //printf("var %s in function %s is nested ref\n", toChars(), fdv.toChars());
1701 // __dollar creates problems because it isn't a real variable
1702 // https://issues.dlang.org/show_bug.cgi?id=3326
1703 if (ident
== Id
.dollar
)
1705 .error(loc
, "cannnot use `$` inside a function literal");
1708 if (ident
== Id
.withSym
) // https://issues.dlang.org/show_bug.cgi?id=1759
1710 ExpInitializer ez
= _init
.isExpInitializer();
1712 Expression e
= ez
.exp
;
1713 if (e
.op
== EXP
.construct || e
.op
== EXP
.blit
)
1714 e
= (cast(AssignExp
)e
).e2
;
1715 return lambdaCheckForNestedRef(e
, sc
);
1721 override final Dsymbol
toAlias()
1723 //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym);
1724 if ((!type ||
!type
.deco
) && _scope
)
1725 dsymbolSemantic(this, _scope
);
1727 assert(this != aliasTuple
);
1728 Dsymbol s
= aliasTuple ? aliasTuple
.toAlias() : this;
1732 // Eliminate need for dynamic_cast
1733 override final inout(VarDeclaration
) isVarDeclaration() inout
1738 override void accept(Visitor v
)
1744 /*******************************************************
1745 * C11 6.7.2.1-4 bit fields
1747 extern (C
++) class BitFieldDeclaration
: VarDeclaration
1754 final extern (D
) this(const ref Loc loc
, Type type
, Identifier ident
, Expression width
)
1756 super(loc
, type
, ident
, null);
1759 this.storage_class |
= STC
.field
;
1762 override BitFieldDeclaration
syntaxCopy(Dsymbol s
)
1764 //printf("BitFieldDeclaration::syntaxCopy(%s)\n", toChars());
1766 auto bf
= new BitFieldDeclaration(loc
, type ? type
.syntaxCopy() : null, ident
, width
.syntaxCopy());
1767 bf
.comment
= comment
;
1771 override final inout(BitFieldDeclaration
) isBitFieldDeclaration() inout
1776 override void accept(Visitor v
)
1781 /***********************************
1782 * Retrieve the .min or .max values.
1783 * Only valid after semantic analysis.
1785 * id = Id.min or Id.max
1787 * the min or max value
1789 final ulong getMinMax(Identifier id
)
1791 const width
= fieldWidth
;
1792 const uns
= type
.isunsigned();
1793 const min
= id
== Id
.min
;
1795 assert(width
!= 0); // should have been rejected in semantic pass
1796 if (width
== ulong.sizeof
* 8)
1797 v
= uns ?
(min ?
ulong.min
: ulong.max
)
1798 : (min ?
long.min
: long.max
);
1801 : (1L << width
) - 1)
1802 : (min ?
-(1L << (width
- 1))
1803 : (1L << (width
- 1)) - 1);
1807 override final void setFieldOffset(AggregateDeclaration ad
, ref FieldState fieldState
, bool isunion
)
1812 printf("BitFieldDeclaration::setFieldOffset(ad: %s, field: %s)\n", ad
.toChars(), toChars());
1813 void print(const ref FieldState fieldState
)
1815 printf("FieldState.offset = %d bytes\n", fieldState
.offset
);
1816 printf(" .fieldOffset = %d bytes\n", fieldState
.fieldOffset
);
1817 printf(" .bitOffset = %d bits\n", fieldState
.bitOffset
);
1818 printf(" .fieldSize = %d bytes\n", fieldState
.fieldSize
);
1819 printf(" .inFlight = %d\n", fieldState
.inFlight
);
1820 printf(" fieldWidth = %d bits\n", fieldWidth
);
1825 Type t
= type
.toBasetype();
1826 const bool anon
= isAnonymous();
1828 // List in ad.fields. Even if the type is error, it's necessary to avoid
1829 // pointless error diagnostic "more initializers than fields" on struct literal.
1831 ad
.fields
.push(this);
1836 const sz
= t
.size(loc
);
1837 assert(sz
!= SIZE_INVALID
&& sz
< uint.max
);
1838 uint memsize
= cast(uint)sz
; // size of member
1839 uint memalignsize
= target
.fieldalign(t
); // size of member for alignment purposes
1840 if (log
) printf(" memsize: %u memalignsize: %u\n", memsize
, memalignsize
);
1842 if (fieldWidth
== 0 && !anon
)
1843 error(loc
, "named bit fields cannot have 0 width");
1844 if (fieldWidth
> memsize
* 8)
1845 error(loc
, "bit field width %d is larger than type", fieldWidth
);
1847 const style
= target
.c
.bitFieldStyle
;
1849 void startNewField()
1851 if (log
) printf("startNewField()\n");
1853 if (style
== TargetC
.BitFieldStyle
.Gcc_Clang
)
1855 if (fieldWidth
> 32)
1856 alignsize
= memalignsize
;
1857 else if (fieldWidth
> 16)
1859 else if (fieldWidth
> 8)
1865 alignsize
= memsize
; // not memalignsize
1868 offset
= AggregateDeclaration
.placeField(
1870 memsize
, alignsize
, alignment
,
1872 (anon
&& style
== TargetC
.BitFieldStyle
.Gcc_Clang
) ?
&dummy
: &ad
.alignsize
,
1875 fieldState
.inFlight
= true;
1876 fieldState
.fieldOffset
= offset
;
1877 fieldState
.bitOffset
= 0;
1878 fieldState
.fieldSize
= memsize
;
1881 if (style
== TargetC
.BitFieldStyle
.Gcc_Clang
)
1883 if (fieldWidth
== 0)
1887 // Use type of zero width field to align to next field
1888 fieldState
.offset
= (fieldState
.offset
+ memalignsize
- 1) & ~(memalignsize
- 1);
1889 ad
.structsize
= fieldState
.offset
;
1892 fieldState
.inFlight
= false;
1896 if (ad
.alignsize
== 0)
1899 ad
.alignsize
< memalignsize
)
1900 ad
.alignsize
= memalignsize
;
1902 else if (style
== TargetC
.BitFieldStyle
.MS
)
1904 if (ad
.alignsize
== 0)
1906 if (fieldWidth
== 0)
1908 if (fieldState
.inFlight
&& !isunion
)
1910 // documentation says align to next int
1911 //const alsz = cast(uint)Type.tint32.size();
1912 const alsz
= memsize
; // but it really does this
1913 fieldState
.offset
= (fieldState
.offset
+ alsz
- 1) & ~(alsz
- 1);
1914 ad
.structsize
= fieldState
.offset
;
1917 fieldState
.inFlight
= false;
1921 else if (style
== TargetC
.BitFieldStyle
.DM
)
1923 if (anon
&& fieldWidth
&& (!fieldState
.inFlight || fieldState
.bitOffset
== 0))
1924 return; // this probably should be a bug in DMC
1925 if (ad
.alignsize
== 0)
1927 if (fieldWidth
== 0)
1929 if (fieldState
.inFlight
&& !isunion
)
1931 const alsz
= memsize
;
1932 fieldState
.offset
= (fieldState
.offset
+ alsz
- 1) & ~(alsz
- 1);
1933 ad
.structsize
= fieldState
.offset
;
1936 fieldState
.inFlight
= false;
1941 if (!fieldState
.inFlight
)
1943 //printf("not in flight\n");
1946 else if (style
== TargetC
.BitFieldStyle
.Gcc_Clang
)
1948 // If the bit-field spans more units of alignment than its type,
1949 // start a new field at the next alignment boundary.
1950 if (fieldState
.bitOffset
== fieldState
.fieldSize
* 8 &&
1951 fieldState
.bitOffset
+ fieldWidth
> memalignsize
* 8)
1953 if (log
) printf("more units of alignment than its type\n");
1954 startNewField(); // the bit field is full
1958 // if alignment boundary is crossed
1959 uint start
= fieldState
.fieldOffset
* 8 + fieldState
.bitOffset
;
1960 uint end
= start
+ fieldWidth
;
1961 //printf("%s start: %d end: %d memalignsize: %d\n", ad.toChars(), start, end, memalignsize);
1962 if (start
/ (memalignsize
* 8) != (end
- 1) / (memalignsize
* 8))
1964 if (log
) printf("alignment is crossed\n");
1969 else if (style
== TargetC
.BitFieldStyle
.DM ||
1970 style
== TargetC
.BitFieldStyle
.MS
)
1972 if (memsize
!= fieldState
.fieldSize ||
1973 fieldState
.bitOffset
+ fieldWidth
> fieldState
.fieldSize
* 8)
1975 //printf("new field\n");
1982 offset
= fieldState
.fieldOffset
;
1983 bitOffset
= fieldState
.bitOffset
;
1985 const pastField
= bitOffset
+ fieldWidth
;
1986 if (style
== TargetC
.BitFieldStyle
.Gcc_Clang
)
1988 auto size
= (pastField
+ 7) / 8;
1989 fieldState
.fieldSize
= size
;
1990 //printf(" offset: %d, size: %d\n", offset, size);
1991 ad
.structsize
= offset
+ size
;
1994 fieldState
.fieldSize
= memsize
;
1995 //printf("at end: ad.structsize = %d\n", cast(int)ad.structsize);
1996 //print(fieldState);
2000 fieldState
.offset
= offset
+ fieldState
.fieldSize
;
2001 fieldState
.bitOffset
= pastField
;
2004 //printf("\t%s: offset = %d bitOffset = %d fieldWidth = %d memsize = %d\n", toChars(), offset, bitOffset, fieldWidth, memsize);
2005 //printf("\t%s: memalignsize = %d\n", toChars(), memalignsize);
2006 //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize);
2010 /***********************************************************
2011 * This is a shell around a back end symbol
2013 extern (C
++) final class SymbolDeclaration
: Declaration
2015 AggregateDeclaration dsym
;
2017 extern (D
) this(const ref Loc loc
, AggregateDeclaration dsym
) @safe
2019 super(loc
, dsym
.ident
);
2021 storage_class |
= STC
.const_
;
2024 // Eliminate need for dynamic_cast
2025 override inout(SymbolDeclaration
) isSymbolDeclaration() inout
2030 override void accept(Visitor v
)
2036 /***********************************************************
2038 extern (C
++) class TypeInfoDeclaration
: VarDeclaration
2042 final extern (D
) this(Type tinfo
)
2044 super(Loc
.initial
, Type
.dtypeinfo
.type
, tinfo
.getTypeInfoIdent(), null);
2046 storage_class
= STC
.static_ | STC
.gshared
;
2047 visibility
= Visibility(Visibility
.Kind
.public_
);
2049 alignment
.set(target
.ptrsize
);
2052 static TypeInfoDeclaration
create(Type tinfo
)
2054 return new TypeInfoDeclaration(tinfo
);
2057 override final TypeInfoDeclaration
syntaxCopy(Dsymbol s
)
2059 assert(0); // should never be produced by syntax
2062 override final const(char)* toChars() const
2064 //printf("TypeInfoDeclaration::toChars() tinfo = %s\n", tinfo.toChars());
2066 buf
.writestring("typeid(");
2067 buf
.writestring(tinfo
.toChars());
2069 return buf
.extractChars();
2072 override final inout(TypeInfoDeclaration
) isTypeInfoDeclaration() inout @nogc nothrow pure @safe
2077 override void accept(Visitor v
)
2083 /***********************************************************
2085 extern (C
++) final class TypeInfoStructDeclaration
: TypeInfoDeclaration
2087 extern (D
) this(Type tinfo
)
2090 if (!Type
.typeinfostruct
)
2092 ObjectNotFound(Id
.TypeInfo_Struct
);
2094 type
= Type
.typeinfostruct
.type
;
2097 static TypeInfoStructDeclaration
create(Type tinfo
)
2099 return new TypeInfoStructDeclaration(tinfo
);
2102 override void accept(Visitor v
)
2108 /***********************************************************
2110 extern (C
++) final class TypeInfoClassDeclaration
: TypeInfoDeclaration
2112 extern (D
) this(Type tinfo
)
2115 if (!Type
.typeinfoclass
)
2117 ObjectNotFound(Id
.TypeInfo_Class
);
2119 type
= Type
.typeinfoclass
.type
;
2122 static TypeInfoClassDeclaration
create(Type tinfo
)
2124 return new TypeInfoClassDeclaration(tinfo
);
2127 override void accept(Visitor v
)
2133 /***********************************************************
2135 extern (C
++) final class TypeInfoInterfaceDeclaration
: TypeInfoDeclaration
2137 extern (D
) this(Type tinfo
)
2140 if (!Type
.typeinfointerface
)
2142 ObjectNotFound(Id
.TypeInfo_Interface
);
2144 type
= Type
.typeinfointerface
.type
;
2147 static TypeInfoInterfaceDeclaration
create(Type tinfo
)
2149 return new TypeInfoInterfaceDeclaration(tinfo
);
2152 override void accept(Visitor v
)
2158 /***********************************************************
2160 extern (C
++) final class TypeInfoPointerDeclaration
: TypeInfoDeclaration
2162 extern (D
) this(Type tinfo
)
2165 if (!Type
.typeinfopointer
)
2167 ObjectNotFound(Id
.TypeInfo_Pointer
);
2169 type
= Type
.typeinfopointer
.type
;
2172 static TypeInfoPointerDeclaration
create(Type tinfo
)
2174 return new TypeInfoPointerDeclaration(tinfo
);
2177 override void accept(Visitor v
)
2183 /***********************************************************
2185 extern (C
++) final class TypeInfoArrayDeclaration
: TypeInfoDeclaration
2187 extern (D
) this(Type tinfo
)
2190 if (!Type
.typeinfoarray
)
2192 ObjectNotFound(Id
.TypeInfo_Array
);
2194 type
= Type
.typeinfoarray
.type
;
2197 static TypeInfoArrayDeclaration
create(Type tinfo
)
2199 return new TypeInfoArrayDeclaration(tinfo
);
2202 override void accept(Visitor v
)
2208 /***********************************************************
2210 extern (C
++) final class TypeInfoStaticArrayDeclaration
: TypeInfoDeclaration
2212 extern (D
) this(Type tinfo
)
2215 if (!Type
.typeinfostaticarray
)
2217 ObjectNotFound(Id
.TypeInfo_StaticArray
);
2219 type
= Type
.typeinfostaticarray
.type
;
2222 static TypeInfoStaticArrayDeclaration
create(Type tinfo
)
2224 return new TypeInfoStaticArrayDeclaration(tinfo
);
2227 override void accept(Visitor v
)
2233 /***********************************************************
2235 extern (C
++) final class TypeInfoAssociativeArrayDeclaration
: TypeInfoDeclaration
2237 extern (D
) this(Type tinfo
)
2240 if (!Type
.typeinfoassociativearray
)
2242 ObjectNotFound(Id
.TypeInfo_AssociativeArray
);
2244 type
= Type
.typeinfoassociativearray
.type
;
2247 static TypeInfoAssociativeArrayDeclaration
create(Type tinfo
)
2249 return new TypeInfoAssociativeArrayDeclaration(tinfo
);
2252 override void accept(Visitor v
)
2258 /***********************************************************
2260 extern (C
++) final class TypeInfoEnumDeclaration
: TypeInfoDeclaration
2262 extern (D
) this(Type tinfo
)
2265 if (!Type
.typeinfoenum
)
2267 ObjectNotFound(Id
.TypeInfo_Enum
);
2269 type
= Type
.typeinfoenum
.type
;
2272 static TypeInfoEnumDeclaration
create(Type tinfo
)
2274 return new TypeInfoEnumDeclaration(tinfo
);
2277 override void accept(Visitor v
)
2283 /***********************************************************
2285 extern (C
++) final class TypeInfoFunctionDeclaration
: TypeInfoDeclaration
2287 extern (D
) this(Type tinfo
)
2290 if (!Type
.typeinfofunction
)
2292 ObjectNotFound(Id
.TypeInfo_Function
);
2294 type
= Type
.typeinfofunction
.type
;
2297 static TypeInfoFunctionDeclaration
create(Type tinfo
)
2299 return new TypeInfoFunctionDeclaration(tinfo
);
2302 override void accept(Visitor v
)
2308 /***********************************************************
2310 extern (C
++) final class TypeInfoDelegateDeclaration
: TypeInfoDeclaration
2312 extern (D
) this(Type tinfo
)
2315 if (!Type
.typeinfodelegate
)
2317 ObjectNotFound(Id
.TypeInfo_Delegate
);
2319 type
= Type
.typeinfodelegate
.type
;
2322 static TypeInfoDelegateDeclaration
create(Type tinfo
)
2324 return new TypeInfoDelegateDeclaration(tinfo
);
2327 override void accept(Visitor v
)
2333 /***********************************************************
2335 extern (C
++) final class TypeInfoTupleDeclaration
: TypeInfoDeclaration
2337 extern (D
) this(Type tinfo
)
2340 if (!Type
.typeinfotypelist
)
2342 ObjectNotFound(Id
.TypeInfo_Tuple
);
2344 type
= Type
.typeinfotypelist
.type
;
2347 static TypeInfoTupleDeclaration
create(Type tinfo
)
2349 return new TypeInfoTupleDeclaration(tinfo
);
2352 override void accept(Visitor v
)
2358 /***********************************************************
2360 extern (C
++) final class TypeInfoConstDeclaration
: TypeInfoDeclaration
2362 extern (D
) this(Type tinfo
)
2365 if (!Type
.typeinfoconst
)
2367 ObjectNotFound(Id
.TypeInfo_Const
);
2369 type
= Type
.typeinfoconst
.type
;
2372 static TypeInfoConstDeclaration
create(Type tinfo
)
2374 return new TypeInfoConstDeclaration(tinfo
);
2377 override void accept(Visitor v
)
2383 /***********************************************************
2385 extern (C
++) final class TypeInfoInvariantDeclaration
: TypeInfoDeclaration
2387 extern (D
) this(Type tinfo
)
2390 if (!Type
.typeinfoinvariant
)
2392 ObjectNotFound(Id
.TypeInfo_Invariant
);
2394 type
= Type
.typeinfoinvariant
.type
;
2397 static TypeInfoInvariantDeclaration
create(Type tinfo
)
2399 return new TypeInfoInvariantDeclaration(tinfo
);
2402 override void accept(Visitor v
)
2408 /***********************************************************
2410 extern (C
++) final class TypeInfoSharedDeclaration
: TypeInfoDeclaration
2412 extern (D
) this(Type tinfo
)
2415 if (!Type
.typeinfoshared
)
2417 ObjectNotFound(Id
.TypeInfo_Shared
);
2419 type
= Type
.typeinfoshared
.type
;
2422 static TypeInfoSharedDeclaration
create(Type tinfo
)
2424 return new TypeInfoSharedDeclaration(tinfo
);
2427 override void accept(Visitor v
)
2433 /***********************************************************
2435 extern (C
++) final class TypeInfoWildDeclaration
: TypeInfoDeclaration
2437 extern (D
) this(Type tinfo
)
2440 if (!Type
.typeinfowild
)
2442 ObjectNotFound(Id
.TypeInfo_Wild
);
2444 type
= Type
.typeinfowild
.type
;
2447 static TypeInfoWildDeclaration
create(Type tinfo
)
2449 return new TypeInfoWildDeclaration(tinfo
);
2452 override void accept(Visitor v
)
2458 /***********************************************************
2460 extern (C
++) final class TypeInfoVectorDeclaration
: TypeInfoDeclaration
2462 extern (D
) this(Type tinfo
)
2465 if (!Type
.typeinfovector
)
2467 ObjectNotFound(Id
.TypeInfo_Vector
);
2469 type
= Type
.typeinfovector
.type
;
2472 static TypeInfoVectorDeclaration
create(Type tinfo
)
2474 return new TypeInfoVectorDeclaration(tinfo
);
2477 override void accept(Visitor v
)
2483 /***********************************************************
2484 * For the "this" parameter to member functions
2486 extern (C
++) final class ThisDeclaration
: VarDeclaration
2488 extern (D
) this(const ref Loc loc
, Type t
)
2490 super(loc
, t
, Id
.This
, null);
2491 storage_class |
= STC
.nodtor
;
2494 override ThisDeclaration
syntaxCopy(Dsymbol s
)
2496 assert(0); // should never be produced by syntax
2499 override inout(ThisDeclaration
) isThisDeclaration() inout
2504 override void accept(Visitor v
)