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