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-2022 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
;
39 import dmd
.common
.outbuffer
;
40 import dmd
.root
.rootobject
;
46 /************************************
47 * Check to see the aggregate type is nested and its context pointer is
48 * accessible from the current scope.
49 * Returns true if error occurs.
51 bool checkFrameAccess(Loc loc
, Scope
* sc
, AggregateDeclaration ad
, size_t iStart
= 0)
53 Dsymbol sparent
= ad
.toParentLocal();
54 Dsymbol sparent2
= ad
.toParent2();
56 if (ad
.isNested() && s
)
58 //printf("ad = %p %s [%s], parent:%p\n", ad, ad.toChars(), ad.loc.toChars(), ad.parent);
59 //printf("sparent = %p %s [%s], parent: %s\n", sparent, sparent.toChars(), sparent.loc.toChars(), sparent.parent,toChars());
60 //printf("sparent2 = %p %s [%s], parent: %s\n", sparent2, sparent2.toChars(), sparent2.loc.toChars(), sparent2.parent,toChars());
61 if (!ensureStaticLinkTo(s
, sparent
) || sparent
!= sparent2
&& !ensureStaticLinkTo(s
, sparent2
))
63 error(loc
, "cannot access frame pointer of `%s`", ad
.toPrettyChars());
69 for (size_t i
= iStart
; i
< ad
.fields
.dim
; i
++)
71 VarDeclaration vd
= ad
.fields
[i
];
72 Type tb
= vd
.type
.baseElemOf();
75 result |
= checkFrameAccess(loc
, sc
, (cast(TypeStruct
)tb
).sym
);
81 /***********************************************
82 * Mark variable v as modified if it is inside a constructor that var
85 bool modifyFieldVar(Loc loc
, Scope
* sc
, VarDeclaration var
, Expression e1
)
87 //printf("modifyFieldVar(var = %s)\n", var.toChars());
91 FuncDeclaration fd
= null;
93 fd
= s
.isFuncDeclaration();
95 ((fd
.isCtorDeclaration() && var
.isField()) ||
96 (fd
.isStaticCtorDeclaration() && !var
.isField())) &&
97 fd
.toParentDecl() == var
.toParent2() &&
98 (!e1 || e1
.op
== EXP
.this_
))
103 //printf("setting ctorinit\n");
105 if (var
.isField() && sc
.ctorflow
.fieldinit
.length
&& !sc
.intypeof
)
108 auto mustInit
= ((var
.storage_class
& STC
.nodefaultctor
) != 0 ||
109 var
.type
.needsNested());
111 const dim
= sc
.ctorflow
.fieldinit
.length
;
112 auto ad
= fd
.isMemberDecl();
115 for (i
= 0; i
< dim
; i
++) // same as findFieldIndexByName in ctfeexp.c ?
117 if (ad
.fields
[i
] == var
)
121 auto fieldInit
= &sc
.ctorflow
.fieldinit
[i
];
122 const fi
= fieldInit
.csx
;
124 if (fi
& CSX
.this_ctor
)
126 if (var
.type
.isMutable() && e1
.type
.isMutable())
130 const(char)* modStr
= !var
.type
.isMutable() ?
MODtoChars(var
.type
.mod
) : MODtoChars(e1
.type
.mod
);
131 .error(loc
, "%s field `%s` initialized multiple times", modStr
, var
.toChars());
132 .errorSupplemental(fieldInit
.loc
, "Previous initialization is here.");
135 else if (sc
.inLoop ||
(fi
& CSX
.label
))
137 if (!mustInit
&& var
.type
.isMutable() && e1
.type
.isMutable())
141 const(char)* modStr
= !var
.type
.isMutable() ?
MODtoChars(var
.type
.mod
) : MODtoChars(e1
.type
.mod
);
142 .error(loc
, "%s field `%s` initialization is not allowed in loops or after labels", modStr
, var
.toChars());
146 fieldInit
.csx |
= CSX
.this_ctor
;
147 fieldInit
.loc
= e1
.loc
;
148 if (var
.overlapped
) // https://issues.dlang.org/show_bug.cgi?id=15258
150 foreach (j
, v
; ad
.fields
)
152 if (v
is var ||
!var
.isOverlappedWith(v
))
155 sc
.ctorflow
.fieldinit
[j
].csx
= CSX
.this_ctor
;
159 else if (fd
!= sc
.func
)
161 if (var
.type
.isMutable())
163 else if (sc
.func
.fes
)
165 const(char)* p
= var
.isField() ?
"field" : var
.kind();
166 .error(loc
, "%s %s `%s` initialization is not allowed in foreach loop",
167 MODtoChars(var
.type
.mod
), p
, var
.toChars());
171 const(char)* p
= var
.isField() ?
"field" : var
.kind();
172 .error(loc
, "%s %s `%s` initialization is not allowed in nested function `%s`",
173 MODtoChars(var
.type
.mod
), p
, var
.toChars(), sc
.func
.toChars());
176 else if (fd
.isStaticCtorDeclaration() && !fd
.isSharedStaticCtorDeclaration() &&
177 var
.type
.isImmutable())
179 .error(loc
, "%s %s `%s` initialization is not allowed in `static this`",
180 MODtoChars(var
.type
.mod
), var
.kind(), var
.toChars());
181 errorSupplemental(loc
, "Use `shared static this` instead.");
189 s
= s
.toParentP(var
.toParent2());
198 /******************************************
200 extern (C
++) void ObjectNotFound(Identifier id
)
202 error(Loc
.initial
, "`%s` not found. object.d may be incorrectly installed or corrupt.", id
.toChars());
206 /* Accumulator for successive matches.
208 struct MatchAccumulator
210 int count
; // number of matches found so far
211 MATCH last
= MATCH
.nomatch
; // match level of lastf
212 FuncDeclaration lastf
; // last matching function we found
213 FuncDeclaration nextf
; // if ambiguous match, this is the "other" function
216 /***********************************************************
218 extern (C
++) abstract class Declaration
: Dsymbol
221 Type originalType
; // before semantic analysis
222 StorageClass storage_class
= STC
.undefined_
;
223 Visibility visibility
;
224 LINK linkage
= LINK
.default_
;
225 short inuse
; // used to detect cycles
227 ubyte adFlags
; // control re-assignment of AliasDeclaration (put here for packing reasons)
228 enum wasRead
= 1; // set if AliasDeclaration was read
229 enum ignoreRead
= 2; // ignore any reads of AliasDeclaration
231 Symbol
* isym
; // import version of csym
233 // overridden symbol with pragma(mangle, "...")
234 const(char)[] mangleOverride
;
236 final extern (D
) this(Identifier ident
)
239 visibility
= Visibility(Visibility
.Kind
.undefined
);
242 final extern (D
) this(const ref Loc loc
, Identifier ident
)
245 visibility
= Visibility(Visibility
.Kind
.undefined
);
248 override const(char)* kind() const
250 return "declaration";
253 override final uinteger_t
size(const ref Loc loc
)
256 const sz
= type
.size();
257 if (sz
== SIZE_INVALID
)
263 * Issue an error if an attempt to call a disabled method is made
265 * If the declaration is disabled but inside a disabled function,
266 * returns `true` but do not issue an error message.
269 * loc = Location information of the call
270 * sc = Scope in which the call occurs
271 * isAliasedDeclaration = if `true` searches overload set
274 * `true` if this `Declaration` is `@disable`d, `false` otherwise.
276 extern (D
) final bool checkDisabled(Loc loc
, Scope
* sc
, bool isAliasedDeclaration
= false)
278 if (!(storage_class
& STC
.disable
))
281 if (sc
.func
&& sc
.func
.storage_class
& STC
.disable
)
284 if (auto p
= toParent())
286 if (auto postblit
= isPostBlitDeclaration())
288 /* https://issues.dlang.org/show_bug.cgi?id=21885
290 * If the generated postblit is disabled, it
291 * means that one of the fields has a disabled
292 * postblit. Print the first field that has
293 * a disabled postblit.
295 if (postblit
.isGenerated())
297 auto sd
= p
.isStructDeclaration();
299 for (size_t i
= 0; i
< sd
.fields
.dim
; i
++)
301 auto structField
= sd
.fields
[i
];
302 if (structField
.overlapped
)
304 Type tv
= structField
.type
.baseElemOf();
305 if (tv
.ty
!= Tstruct
)
307 auto sdv
= (cast(TypeStruct
)tv
).sym
;
310 if (sdv
.postblit
.isDisabled())
312 p
.error(loc
, "is not copyable because field `%s` is not copyable", structField
.toChars());
317 p
.error(loc
, "is not copyable because it has a disabled postblit");
322 // if the function is @disabled, maybe there
323 // is an overload in the overload set that isn't
324 if (isAliasedDeclaration
)
326 FuncDeclaration fd
= isFuncDeclaration();
329 for (FuncDeclaration ovl
= fd
; ovl
; ovl
= cast(FuncDeclaration
)ovl
.overnext
)
330 if (!(ovl
.storage_class
& STC
.disable
))
335 if (auto ctor
= isCtorDeclaration())
337 if (ctor
.isCpCtor
&& ctor
.isGenerated())
339 .error(loc
, "Generating an `inout` copy constructor for `struct %s` failed, therefore instances of it are uncopyable", parent
.toPrettyChars());
343 error(loc
, "cannot be used because it is annotated with `@disable`");
347 /*************************************
348 * Check to see if declaration can be modified in this context (sc).
349 * Issue error if not.
351 * loc = location for error messages
352 * e1 = `null` or `this` expression when this declaration is a field
354 * flag = if the first bit is set it means do not issue error message for
355 * invalid modification; if the second bit is set, it means that
356 this declaration is a field and a subfield of it is modified.
358 * Modifiable.yes or Modifiable.initialization
360 extern (D
) final Modifiable
checkModify(Loc loc
, Scope
* sc
, Expression e1
, ModifyFlags flag
)
362 VarDeclaration v
= isVarDeclaration();
363 if (v
&& v
.canassign
)
364 return Modifiable
.initialization
;
366 if (isParameter() ||
isResult())
368 for (Scope
* scx
= sc
; scx
; scx
= scx
.enclosing
)
370 if (scx
.func
== parent
&& (scx
.flags
& SCOPE
.contract
))
372 const(char)* s
= isParameter() && parent
.ident
!= Id
.ensure ?
"parameter" : "result";
373 if (!(flag
& ModifyFlags
.noError
))
374 error(loc
, "cannot modify %s `%s` in contract", s
, toChars());
375 return Modifiable
.initialization
; // do not report type related errors
380 if (e1
&& e1
.op
== EXP
.this_
&& isField())
382 VarDeclaration vthis
= (cast(ThisExp
)e1
).var
;
383 for (Scope
* scx
= sc
; scx
; scx
= scx
.enclosing
)
385 if (scx
.func
== vthis
.parent
&& (scx
.flags
& SCOPE
.contract
))
387 if (!(flag
& ModifyFlags
.noError
))
388 error(loc
, "cannot modify parameter `this` in contract");
389 return Modifiable
.initialization
; // do not report type related errors
394 if (v
&& (v
.isCtorinit() ||
isField()))
396 // It's only modifiable if inside the right constructor
397 if ((storage_class
& (STC
.foreach_ | STC
.ref_
)) == (STC
.foreach_ | STC
.ref_
))
398 return Modifiable
.initialization
;
399 if (flag
& ModifyFlags
.fieldAssign
)
400 return Modifiable
.yes
;
401 return modifyFieldVar(loc
, sc
, v
, e1
) ? Modifiable
.initialization
: Modifiable
.yes
;
403 return Modifiable
.yes
;
406 override final Dsymbol
search(const ref Loc loc
, Identifier ident
, int flags
= SearchLocalsOnly
)
408 Dsymbol s
= Dsymbol
.search(loc
, ident
, flags
);
411 s
= type
.toDsymbol(_scope
);
413 s
= s
.search(loc
, ident
, flags
);
418 final bool isStatic() const pure nothrow @nogc @safe
420 return (storage_class
& STC
.static_
) != 0;
438 bool isCodeseg() const pure nothrow @nogc @safe
443 final bool isFinal() const pure nothrow @nogc @safe
445 return (storage_class
& STC
.final_
) != 0;
450 return (storage_class
& STC
.abstract_
) != 0;
453 final bool isConst() const pure nothrow @nogc @safe
455 return (storage_class
& STC
.const_
) != 0;
458 final bool isImmutable() const pure nothrow @nogc @safe
460 return (storage_class
& STC
.immutable_
) != 0;
463 final bool isWild() const pure nothrow @nogc @safe
465 return (storage_class
& STC
.wild
) != 0;
468 final bool isAuto() const pure nothrow @nogc @safe
470 return (storage_class
& STC
.auto_
) != 0;
473 final bool isScope() const pure nothrow @nogc @safe
475 return (storage_class
& STC
.scope_
) != 0;
478 final bool isSynchronized() const pure nothrow @nogc @safe
480 return (storage_class
& STC
.synchronized_
) != 0;
483 final bool isParameter() const pure nothrow @nogc @safe
485 return (storage_class
& STC
.parameter
) != 0;
488 override final bool isDeprecated() const pure nothrow @nogc @safe
490 return (storage_class
& STC
.deprecated_
) != 0;
493 final bool isDisabled() const pure nothrow @nogc @safe
495 return (storage_class
& STC
.disable
) != 0;
498 final bool isOverride() const pure nothrow @nogc @safe
500 return (storage_class
& STC
.override_
) != 0;
503 final bool isResult() const pure nothrow @nogc @safe
505 return (storage_class
& STC
.result
) != 0;
508 final bool isField() const pure nothrow @nogc @safe
510 return (storage_class
& STC
.field
) != 0;
513 final bool isIn() const pure nothrow @nogc @safe
515 return (storage_class
& STC
.in_
) != 0;
518 final bool isOut() const pure nothrow @nogc @safe
520 return (storage_class
& STC
.out_
) != 0;
523 final bool isRef() const pure nothrow @nogc @safe
525 return (storage_class
& STC
.ref_
) != 0;
528 /// Returns: Whether the variable is a reference, annotated with `out` or `ref`
529 final bool isReference() const pure nothrow @nogc @safe
531 return (storage_class
& (STC
.ref_ | STC
.out_
)) != 0;
534 final bool isFuture() const pure nothrow @nogc @safe
536 return (storage_class
& STC
.future
) != 0;
539 override final Visibility
visible() pure nothrow @nogc @safe
544 override final inout(Declaration
) isDeclaration() inout pure nothrow @nogc @safe
549 override void accept(Visitor v
)
555 /***********************************************************
557 extern (C
++) final class TupleDeclaration
: Declaration
560 bool isexp
; // true: expression tuple
561 TypeTuple tupletype
; // !=null if this is a type tuple
563 extern (D
) this(const ref Loc loc
, Identifier ident
, Objects
* objects
)
566 this.objects
= objects
;
569 override TupleDeclaration
syntaxCopy(Dsymbol s
)
574 override const(char)* kind() const
579 override Type
getType()
581 /* If this tuple represents a type, return that type
584 //printf("TupleDeclaration::getType() %s\n", toChars());
589 /* It's only a type tuple if all the Object's are types
591 for (size_t i
= 0; i
< objects
.dim
; i
++)
593 RootObject o
= (*objects
)[i
];
594 if (o
.dyncast() != DYNCAST
.type
)
596 //printf("\tnot[%d], %p, %d\n", i, o, o.dyncast());
601 /* We know it's a type tuple, so build the TypeTuple
603 Types
* types
= cast(Types
*)objects
;
604 auto args
= new Parameters(objects
.dim
);
607 for (size_t i
= 0; i
< types
.dim
; i
++)
609 Type t
= (*types
)[i
];
610 //printf("type = %s\n", t.toChars());
613 buf
.printf("_%s_%d", ident
.toChars(), i
);
614 const len
= buf
.offset
;
615 const name
= buf
.extractSlice().ptr
;
616 auto id
= Identifier
.idPool(name
, len
);
617 auto arg
= new Parameter(STC
.in_
, t
, id
, null);
621 auto arg
= new Parameter(0, t
, null, null, null);
628 tupletype
= new TypeTuple(args
);
630 return tupletype
.typeSemantic(Loc
.initial
, null);
635 override Dsymbol
toAlias2()
637 //printf("TupleDeclaration::toAlias2() '%s' objects = %s\n", toChars(), objects.toChars());
638 for (size_t i
= 0; i
< objects
.dim
; i
++)
640 RootObject o
= (*objects
)[i
];
641 if (Dsymbol s
= isDsymbol(o
))
650 override bool needThis()
652 //printf("TupleDeclaration::needThis(%s)\n", toChars());
653 for (size_t i
= 0; i
< objects
.dim
; i
++)
655 RootObject o
= (*objects
)[i
];
656 if (o
.dyncast() == DYNCAST
.expression
)
658 Expression e
= cast(Expression
)o
;
659 if (e
.op
== EXP
.dSymbol
)
661 DsymbolExp ve
= cast(DsymbolExp
)e
;
662 Declaration d
= ve
.s
.isDeclaration();
663 if (d
&& d
.needThis())
673 override inout(TupleDeclaration
) isTupleDeclaration() inout
678 override void accept(Visitor v
)
684 /***********************************************************
685 * https://dlang.org/spec/declaration.html#AliasDeclaration
687 extern (C
++) final class AliasDeclaration
: Declaration
689 Dsymbol aliassym
; // alias ident = aliassym;
691 Dsymbol overnext
; // next in overload list
692 Dsymbol _import
; // !=null if unresolved internal alias for selective import
694 extern (D
) this(const ref Loc loc
, Identifier ident
, Type type
)
697 //printf("AliasDeclaration(id = '%s', type = %p)\n", id.toChars(), type);
698 //printf("type = '%s'\n", type.toChars());
703 extern (D
) this(const ref Loc loc
, Identifier ident
, Dsymbol s
)
706 //printf("AliasDeclaration(id = '%s', s = %p)\n", id.toChars(), s);
712 static AliasDeclaration
create(const ref Loc loc
, Identifier id
, Type type
)
714 return new AliasDeclaration(loc
, id
, type
);
717 override AliasDeclaration
syntaxCopy(Dsymbol s
)
719 //printf("AliasDeclaration::syntaxCopy()\n");
721 AliasDeclaration sa
= type ?
new AliasDeclaration(loc
, ident
, type
.syntaxCopy()) : new AliasDeclaration(loc
, ident
, aliassym
.syntaxCopy(null));
722 sa
.comment
= comment
;
723 sa
.storage_class
= storage_class
;
727 override bool overloadInsert(Dsymbol s
)
729 //printf("[%s] AliasDeclaration::overloadInsert('%s') s = %s %s @ [%s]\n",
730 // loc.toChars(), toChars(), s.kind(), s.toChars(), s.loc.toChars());
732 /** Aliases aren't overloadable themselves, but if their Aliasee is
733 * overloadable they are converted to an overloadable Alias (either
734 * FuncAliasDeclaration or OverDeclaration).
736 * This is done by moving the Aliasee into such an overloadable alias
737 * which is then used to replace the existing Aliasee. The original
738 * Alias (_this_) remains a useless shell.
740 * This is a horrible mess. It was probably done to avoid replacing
741 * existing AST nodes and references, but it needs a major
742 * simplification b/c it's too complex to maintain.
744 * A simpler approach might be to merge any colliding symbols into a
745 * simple Overload class (an array) and then later have that resolve
748 if (semanticRun
>= PASS
.semanticdone
)
750 /* Semantic analysis is already finished, and the aliased entity
751 * is not overloadable.
756 /* When s is added in member scope by static if, mixin("code") or others,
757 * aliassym is determined already. See the case in: test/compilable/test61.d
759 auto sa
= aliassym
.toAlias();
761 if (auto td
= s
.toAlias().isTemplateDeclaration())
762 s
= td
.funcroot ? td
.funcroot
: td
;
764 if (auto fd
= sa
.isFuncDeclaration())
766 auto fa
= new FuncAliasDeclaration(ident
, fd
);
767 fa
.visibility
= visibility
;
770 return aliassym
.overloadInsert(s
);
772 if (auto td
= sa
.isTemplateDeclaration())
774 auto od
= new OverDeclaration(ident
, td
.funcroot ? td
.funcroot
: td
);
775 od
.visibility
= visibility
;
778 return aliassym
.overloadInsert(s
);
780 if (auto od
= sa
.isOverDeclaration())
782 if (sa
.ident
!= ident || sa
.parent
!= parent
)
784 od
= new OverDeclaration(ident
, od
);
785 od
.visibility
= visibility
;
789 return od
.overloadInsert(s
);
791 if (auto os
= sa
.isOverloadSet())
793 if (sa
.ident
!= ident || sa
.parent
!= parent
)
795 os
= new OverloadSet(ident
, os
);
796 // TODO: visibility is lost here b/c OverloadSets have no visibility attribute
797 // Might no be a practical issue, b/c the code below fails to resolve the overload anyhow.
801 // private alias merged = foo; // private alias to overload set of a.foo and b.foo
805 // public alias merged = bar; // public alias to overload set of a.bar and b.bar
809 // void test() { merged(123); } // should only look at os2.merged
811 // os.visibility = visibility;
821 /* Don't know yet what the aliased symbol is, so assume it can
822 * be overloaded and check later for correctness.
825 return overnext
.overloadInsert(s
);
832 override const(char)* kind() const
837 override Type
getType()
841 return toAlias().getType();
844 override Dsymbol
toAlias()
846 //printf("[%s] AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s', inuse = %d)\n",
847 // loc.toChars(), toChars(), this, aliassym, aliassym ? aliassym.kind() : "", inuse);
848 assert(this != aliassym
);
849 //static int count; if (++count == 10) *(char*)0=0;
851 // Reading the AliasDeclaration
852 if (!(adFlags
& ignoreRead
))
853 adFlags |
= wasRead
; // can never assign to this AliasDeclaration again
855 if (inuse
== 1 && type
&& _scope
)
858 uint olderrors
= global
.errors
;
859 Dsymbol s
= type
.toDsymbol(_scope
);
860 //printf("[%s] type = %s, s = %p, this = %p\n", loc.toChars(), type.toChars(), s, this);
861 if (global
.errors
!= olderrors
)
866 if (global
.errors
!= olderrors
)
873 Type t
= type
.typeSemantic(loc
, _scope
);
876 if (global
.errors
!= olderrors
)
878 //printf("t = %s\n", t.toChars());
884 error("recursive alias declaration");
887 // Avoid breaking "recursive alias" state during errors gagged
890 aliassym
= new AliasDeclaration(loc
, ident
, Type
.terror
);
895 if (semanticRun
>= PASS
.semanticdone
)
897 // semantic is already done.
899 // Do not see aliassym !is null, because of lambda aliases.
901 // Do not see type.deco !is null, even so "alias T = const int;` needs
902 // semantic analysis to take the storage class `const` as type qualifier.
906 if (_import
&& _import
._scope
)
908 /* If this is an internal alias for selective/renamed import,
909 * load the module first.
911 _import
.dsymbolSemantic(null);
915 aliasSemantic(this, _scope
);
920 Dsymbol s
= aliassym ? aliassym
.toAlias() : this;
925 override Dsymbol
toAlias2()
929 error("recursive alias declaration");
933 Dsymbol s
= aliassym ? aliassym
.toAlias2() : this;
938 override bool isOverloadable() const
940 // assume overloadable until alias is resolved
941 return semanticRun
< PASS
.semanticdone ||
942 aliassym
&& aliassym
.isOverloadable();
945 override inout(AliasDeclaration
) isAliasDeclaration() inout
950 /** Returns: `true` if this instance was created to make a template parameter
951 visible in the scope of a template body, `false` otherwise */
952 extern (D
) bool isAliasedTemplateParameter() const
954 return !!(storage_class
& STC
.templateparameter
);
957 override void accept(Visitor v
)
963 /***********************************************************
965 extern (C
++) final class OverDeclaration
: Declaration
967 Dsymbol overnext
; // next in overload list
970 extern (D
) this(Identifier ident
, Dsymbol s
)
976 override const(char)* kind() const
978 return "overload alias"; // todo
981 override bool equals(const RootObject o
) const
986 auto s
= isDsymbol(o
);
990 if (auto od2
= s
.isOverDeclaration())
991 return this.aliassym
.equals(od2
.aliassym
);
992 return this.aliassym
== s
;
995 override bool overloadInsert(Dsymbol s
)
997 //printf("OverDeclaration::overloadInsert('%s') aliassym = %p, overnext = %p\n", s.toChars(), aliassym, overnext);
999 return overnext
.overloadInsert(s
);
1006 override bool isOverloadable() const
1013 Dsymbol result
= null;
1014 overloadApply(aliassym
, (Dsymbol s
)
1019 return 1; // ambiguous, done
1030 override inout(OverDeclaration
) isOverDeclaration() inout
1035 override void accept(Visitor v
)
1041 /***********************************************************
1043 extern (C
++) class VarDeclaration
: Declaration
1046 FuncDeclarations nestedrefs
; // referenced by these lexically nested functions
1047 Dsymbol aliassym
; // if redone as alias to another symbol
1048 VarDeclaration lastVar
; // Linked list of variables for goto-skips-init detection
1049 Expression edtor
; // if !=null, does the destruction of the variable
1050 IntRange
* range
; // if !=null, the variable is known to be within the range
1051 VarDeclarations
* maybes
; // STC.maybescope variables that are assigned to this STC.maybescope variable
1053 uint endlinnum
; // line number of end of scope that this var lives in
1055 uint sequenceNumber
; // order the variables are declared
1056 structalign_t alignment
;
1058 // When interpreting, these point to the value (NULL if value not determinable)
1059 // The index of this variable on the CTFE stack, AdrOnStackNone if not allocated
1060 enum AdrOnStackNone
= ~0u;
1061 uint ctfeAdrOnStack
;
1063 // `bool` fields that are compacted into bit fields in a string mixin
1064 private extern (D
) static struct BitFields
1066 bool isargptr
; /// if parameter that _argptr points to
1067 bool ctorinit
; /// it has been initialized in a ctor
1068 bool iscatchvar
; /// this is the exception object variable in catch() clause
1069 bool isowner
; /// this is an Owner, despite it being `scope`
1070 bool setInCtorOnly
; /// field can only be set in a constructor, as it is const or immutable
1072 /// It is a class that was allocated on the stack
1074 /// This means the var is not rebindable once assigned,
1075 /// and the destructor gets run when it goes out of scope
1078 bool overlapped
; /// if it is a field and has overlapping
1079 bool overlapUnsafe
; /// if it is an overlapping field and the overlaps are unsafe
1080 bool doNotInferScope
; /// do not infer 'scope' for this variable
1081 bool doNotInferReturn
; /// do not infer 'return' for this variable
1083 bool isArgDtorVar
; /// temporary created to handle scope destruction of a function argument
1086 import dmd
.common
.bitfields
: generateBitFields
;
1087 mixin(generateBitFields
!(BitFields
, ushort));
1089 byte canassign
; // it can be assigned to
1090 ubyte isdataseg
; // private data for isDataseg 0 unset, 1 true, 2 false
1092 final extern (D
) this(const ref Loc loc
, Type type
, Identifier ident
, Initializer _init
, StorageClass storage_class
= STC
.undefined_
)
1099 //printf("VarDeclaration('%s')\n", ident.toChars());
1103 if (!type
&& !_init
)
1105 //printf("VarDeclaration('%s')\n", ident.toChars());
1110 assert(type || _init
);
1113 ctfeAdrOnStack
= AdrOnStackNone
;
1114 this.storage_class
= storage_class
;
1117 static VarDeclaration
create(const ref Loc loc
, Type type
, Identifier ident
, Initializer _init
, StorageClass storage_class
= STC
.undefined_
)
1119 return new VarDeclaration(loc
, type
, ident
, _init
, storage_class
);
1122 override VarDeclaration
syntaxCopy(Dsymbol s
)
1124 //printf("VarDeclaration::syntaxCopy(%s)\n", toChars());
1126 auto v
= new VarDeclaration(loc
, type ? type
.syntaxCopy() : null, ident
, _init ? _init
.syntaxCopy() : null, storage_class
);
1127 v
.comment
= comment
;
1131 override void setFieldOffset(AggregateDeclaration ad
, ref FieldState fieldState
, bool isunion
)
1133 //printf("VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars());
1137 // If this variable was really a tuple, set the offsets for the tuple fields
1138 TupleDeclaration v2
= aliassym
.isTupleDeclaration();
1140 for (size_t i
= 0; i
< v2
.objects
.dim
; i
++)
1142 RootObject o
= (*v2
.objects
)[i
];
1143 assert(o
.dyncast() == DYNCAST
.expression
);
1144 Expression e
= cast(Expression
)o
;
1145 assert(e
.op
== EXP
.dSymbol
);
1146 DsymbolExp se
= cast(DsymbolExp
)e
;
1147 se
.s
.setFieldOffset(ad
, fieldState
, isunion
);
1154 assert(!(storage_class
& (STC
.static_ | STC
.extern_ | STC
.parameter
)));
1156 //printf("+VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars());
1158 /* Fields that are tuples appear both as part of TupleDeclarations and
1159 * as members. That means ignore them if they are already a field.
1164 fieldState
.offset
= ad
.structsize
; // https://issues.dlang.org/show_bug.cgi?id=13613
1167 for (size_t i
= 0; i
< ad
.fields
.dim
; i
++)
1169 if (ad
.fields
[i
] == this)
1172 fieldState
.offset
= ad
.structsize
; // https://issues.dlang.org/show_bug.cgi?id=13613
1177 // Check for forward referenced types which will fail the size() call
1178 Type t
= type
.toBasetype();
1179 if (storage_class
& STC
.ref_
)
1181 // References are the size of a pointer
1184 Type tv
= t
.baseElemOf();
1185 if (tv
.ty
== Tstruct
)
1187 auto ts
= cast(TypeStruct
)tv
;
1188 assert(ts
.sym
!= ad
); // already checked in ad.determineFields()
1189 if (!ts
.sym
.determineSize(loc
))
1197 // List in ad.fields. Even if the type is error, it's necessary to avoid
1198 // pointless error diagnostic "more initializers than fields" on struct literal.
1199 ad
.fields
.push(this);
1204 /* If coming after a bit field in progress,
1205 * advance past the field
1207 fieldState
.inFlight
= false;
1209 const sz
= t
.size(loc
);
1210 assert(sz
!= SIZE_INVALID
&& sz
< uint.max
);
1211 uint memsize
= cast(uint)sz
; // size of member
1212 uint memalignsize
= target
.fieldalign(t
); // size of member for alignment purposes
1213 offset
= AggregateDeclaration
.placeField(
1215 memsize
, memalignsize
, alignment
,
1216 &ad
.structsize
, &ad
.alignsize
,
1219 //printf("\t%s: memalignsize = %d\n", toChars(), memalignsize);
1220 //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize);
1223 override const(char)* kind() const
1228 override final inout(AggregateDeclaration
) isThis() inout
1230 if (!(storage_class
& (STC
.static_ | STC
.extern_ | STC
.manifest | STC
.templateparameter | STC
.gshared | STC
.ctfe
)))
1232 /* The casting is necessary because `s = s.parent` is otherwise rejected
1234 for (auto s
= cast(Dsymbol
)this; s
; s
= s
.parent
)
1236 auto ad
= (cast(inout)s
).isMember();
1239 if (!s
.parent ||
!s
.parent
.isTemplateMixin())
1246 override final bool needThis()
1248 //printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class);
1252 override final bool isExport() const
1254 return visibility
.kind
== Visibility
.Kind
.export_
;
1257 override final bool isImportedSymbol() const
1259 if (visibility
.kind
== Visibility
.Kind
.export_
&& !_init
&& (storage_class
& STC
.static_ || parent
.isModule()))
1264 final bool isCtorinit() const pure nothrow @nogc @safe
1266 return setInCtorOnly
;
1269 /*******************************
1270 * Does symbol go into data segment?
1271 * Includes extern variables.
1273 override final bool isDataseg()
1277 printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars());
1278 printf("%llx, isModule: %p, isTemplateInstance: %p, isNspace: %p\n",
1279 storage_class
& (STC
.static_ | STC
.const_
), parent
.isModule(), parent
.isTemplateInstance(), parent
.isNspace());
1280 printf("parent = '%s'\n", parent
.toChars());
1283 if (isdataseg
== 0) // the value is not cached
1285 isdataseg
= 2; // The Variables does not go into the datasegment
1287 if (!canTakeAddressOf())
1292 Dsymbol parent
= toParent();
1293 if (!parent
&& !(storage_class
& STC
.static_
))
1295 error("forward referenced");
1298 else if (storage_class
& (STC
.static_ | STC
.extern_ | STC
.gshared
) ||
1299 parent
.isModule() || parent
.isTemplateInstance() || parent
.isNspace())
1301 assert(!isParameter() && !isResult());
1302 isdataseg
= 1; // It is in the DataSegment
1306 return (isdataseg
== 1);
1308 /************************************
1309 * Does symbol go into thread local storage?
1311 override final bool isThreadlocal()
1313 //printf("VarDeclaration::isThreadlocal(%p, '%s')\n", this, toChars());
1314 /* Data defaults to being thread-local. It is not thread-local
1315 * if it is immutable, const or shared.
1317 bool i
= isDataseg() && !(storage_class
& (STC
.immutable_ | STC
.const_ | STC
.shared_ | STC
.gshared
));
1318 //printf("\treturn %d\n", i);
1322 /********************************************
1323 * Can variable be read and written by CTFE?
1327 return (storage_class
& STC
.ctfe
) != 0; // || !isDataseg();
1330 final bool isOverlappedWith(VarDeclaration v
)
1332 const vsz
= v
.type
.size();
1333 const tsz
= type
.size();
1334 assert(vsz
!= SIZE_INVALID
&& tsz
!= SIZE_INVALID
);
1336 // Overlap is checked by comparing bit offsets
1337 auto bitoffset
= offset
* 8;
1338 auto vbitoffset
= v
.offset
* 8;
1340 // Bitsize of types are overridden by any bit-field widths.
1341 ulong tbitsize
= void;
1342 if (auto bf
= isBitFieldDeclaration())
1344 bitoffset
+= bf
.bitOffset
;
1345 tbitsize
= bf
.fieldWidth
;
1350 ulong vbitsize
= void;
1351 if (auto vbf
= v
.isBitFieldDeclaration())
1353 vbitoffset
+= vbf
.bitOffset
;
1354 vbitsize
= vbf
.fieldWidth
;
1359 return bitoffset
< vbitoffset
+ vbitsize
&&
1360 vbitoffset
< bitoffset
+ tbitsize
;
1363 override final bool hasPointers()
1365 //printf("VarDeclaration::hasPointers() %s, ty = %d\n", toChars(), type.ty);
1366 return (!isDataseg() && type
.hasPointers());
1369 /*************************************
1370 * Return true if we can take the address of this variable.
1372 final bool canTakeAddressOf()
1374 return !(storage_class
& STC
.manifest
);
1377 /******************************************
1378 * Return true if variable needs to call the destructor.
1380 final bool needsScopeDtor()
1382 //printf("VarDeclaration::needsScopeDtor() %s\n", toChars());
1383 return edtor
&& !(storage_class
& STC
.nodtor
);
1386 /******************************************
1387 * If a variable has a scope destructor call, return call for it.
1388 * Otherwise, return NULL.
1390 extern (D
) final Expression
callScopeDtor(Scope
* sc
)
1392 //printf("VarDeclaration::callScopeDtor() %s\n", toChars());
1394 // Destruction of STC.field's is handled by buildDtor()
1395 if (storage_class
& (STC
.nodtor | STC
.ref_ | STC
.out_ | STC
.field
))
1401 return null; // destructor is built by `void semantic(Catch c, Scope* sc)`, not here
1403 Expression e
= null;
1404 // Destructors for structs and arrays of structs
1405 Type tv
= type
.baseElemOf();
1406 if (tv
.ty
== Tstruct
)
1408 StructDeclaration sd
= (cast(TypeStruct
)tv
).sym
;
1409 if (!sd
.dtor || sd
.errors
)
1412 const sz
= type
.size();
1413 assert(sz
!= SIZE_INVALID
);
1417 if (type
.toBasetype().ty
== Tstruct
)
1420 e
= new VarExp(loc
, this);
1422 /* This is a hack so we can call destructors on const/immutable objects.
1423 * Need to add things like "const ~this()" and "immutable ~this()" to
1426 e
.type
= e
.type
.mutableOf();
1428 // Enable calling destructors on shared objects.
1429 // The destructor is always a single, non-overloaded function,
1430 // and must serve both shared and non-shared objects.
1431 e
.type
= e
.type
.unSharedOf
;
1433 e
= new DotVarExp(loc
, e
, sd
.dtor
, false);
1434 e
= new CallExp(loc
, e
);
1438 // __ArrayDtor(v[0 .. n])
1439 e
= new VarExp(loc
, this);
1441 const sdsz
= sd
.type
.size();
1442 assert(sdsz
!= SIZE_INVALID
&& sdsz
!= 0);
1443 const n
= sz
/ sdsz
;
1444 e
= new SliceExp(loc
, e
, new IntegerExp(loc
, 0, Type
.tsize_t
), new IntegerExp(loc
, n
, Type
.tsize_t
));
1446 // Prevent redundant bounds check
1447 (cast(SliceExp
)e
).upperIsInBounds
= true;
1448 (cast(SliceExp
)e
).lowerIsLessThanUpper
= true;
1450 // This is a hack so we can call destructors on const/immutable objects.
1451 e
.type
= sd
.type
.arrayOf();
1453 e
= new CallExp(loc
, new IdentifierExp(loc
, Id
.__ArrayDtor
), e
);
1457 // Destructors for classes
1458 if (storage_class
& (STC
.auto_ | STC
.scope_
) && !(storage_class
& STC
.parameter
))
1460 for (ClassDeclaration cd
= type
.isClassHandle(); cd
; cd
= cd
.baseClass
)
1462 /* We can do better if there's a way with onstack
1463 * classes to determine if there's no way the monitor
1466 //if (cd.isInterfaceDeclaration())
1467 // error("interface `%s` cannot be scope", cd.toChars());
1469 if (onstack
) // if any destructors
1471 // delete'ing C++ classes crashes (and delete is deprecated anyway)
1472 if (cd
.classKind
== ClassKind
.cpp
)
1474 // Don't call non-existant dtor
1478 e
= new VarExp(loc
, this);
1479 e
.type
= e
.type
.mutableOf().unSharedOf(); // Hack for mutable ctor on immutable instances
1480 e
= new DotVarExp(loc
, e
, cd
.dtor
, false);
1481 e
= new CallExp(loc
, e
);
1487 ec
= new VarExp(loc
, this);
1488 e
= new DeleteExp(loc
, ec
, true);
1489 e
.type
= Type
.tvoid
;
1497 /*******************************************
1498 * If variable has a constant expression initializer, get it.
1499 * Otherwise, return null.
1501 extern (D
) final Expression
getConstInitializer(bool needFullType
= true)
1503 assert(type
&& _init
);
1505 // Ungag errors when not speculative
1506 uint oldgag
= global
.gag
;
1509 Dsymbol sym
= toParent().isAggregateDeclaration();
1510 if (sym
&& !sym
.isSpeculative())
1517 _init
= _init
.initializerSemantic(_scope
, type
, INITinterpret
);
1522 Expression e
= _init
.initializerToExpression(needFullType ? type
: null);
1523 global
.gag
= oldgag
;
1527 /*******************************************
1528 * Helper function for the expansion of manifest constant.
1530 extern (D
) final Expression
expandInitializer(Loc loc
)
1532 assert((storage_class
& STC
.manifest
) && _init
);
1534 auto e
= getConstInitializer();
1537 .error(loc
, "cannot make expression out of initializer for `%s`", toChars());
1538 return ErrorExp
.get();
1542 e
.loc
= loc
; // for better error message
1546 override final void checkCtorConstInit()
1550 /* doesn't work if more than one static ctor */
1551 if (ctorinit
== 0 && isCtorinit() && !isField())
1552 error("missing initializer in static constructor for const variable");
1556 /************************************
1557 * Check to see if this variable is actually in an enclosing function
1558 * rather than the current one.
1559 * Update nestedrefs[], closureVars[] and outerVars[].
1560 * Returns: true if error occurs.
1562 extern (D
) final bool checkNestedReference(Scope
* sc
, Loc loc
)
1564 //printf("VarDeclaration::checkNestedReference() %s\n", toChars());
1565 if (sc
.intypeof
== 1 ||
(sc
.flags
& SCOPE
.ctfe
))
1567 if (!parent || parent
== sc
.parent
)
1569 if (isDataseg() ||
(storage_class
& STC
.manifest
))
1572 // The current function
1573 FuncDeclaration fdthis
= sc
.parent
.isFuncDeclaration();
1575 return false; // out of function scope
1577 Dsymbol p
= toParent2();
1579 // Function literals from fdthis to p must be delegates
1580 ensureStaticLinkTo(fdthis
, p
);
1582 // The function that this variable is in
1583 FuncDeclaration fdv
= p
.isFuncDeclaration();
1584 if (!fdv || fdv
== fdthis
)
1587 // Add fdthis to nestedrefs[] if not already there
1588 if (!nestedrefs
.contains(fdthis
))
1589 nestedrefs
.push(fdthis
);
1591 //printf("\tfdv = %s\n", fdv.toChars());
1592 //printf("\tfdthis = %s\n", fdthis.toChars());
1595 if (fdthis
.getLevelAndCheck(loc
, sc
, fdv
, this) == fdthis
.LevelError
)
1599 // Add this VarDeclaration to fdv.closureVars[] if not already there
1600 if (!sc
.intypeof
&& !(sc
.flags
& SCOPE
.compile
) &&
1601 // https://issues.dlang.org/show_bug.cgi?id=17605
1602 (fdv
.flags
& FUNCFLAG
.compileTimeOnly ||
!(fdthis
.flags
& FUNCFLAG
.compileTimeOnly
))
1605 if (!fdv
.closureVars
.contains(this))
1606 fdv
.closureVars
.push(this);
1609 if (!fdthis
.outerVars
.contains(this))
1610 fdthis
.outerVars
.push(this);
1612 //printf("fdthis is %s\n", fdthis.toChars());
1613 //printf("var %s in function %s is nested ref\n", toChars(), fdv.toChars());
1614 // __dollar creates problems because it isn't a real variable
1615 // https://issues.dlang.org/show_bug.cgi?id=3326
1616 if (ident
== Id
.dollar
)
1618 .error(loc
, "cannnot use `$` inside a function literal");
1621 if (ident
== Id
.withSym
) // https://issues.dlang.org/show_bug.cgi?id=1759
1623 ExpInitializer ez
= _init
.isExpInitializer();
1625 Expression e
= ez
.exp
;
1626 if (e
.op
== EXP
.construct || e
.op
== EXP
.blit
)
1627 e
= (cast(AssignExp
)e
).e2
;
1628 return lambdaCheckForNestedRef(e
, sc
);
1634 override final Dsymbol
toAlias()
1636 //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym);
1637 if ((!type ||
!type
.deco
) && _scope
)
1638 dsymbolSemantic(this, _scope
);
1640 assert(this != aliassym
);
1641 Dsymbol s
= aliassym ? aliassym
.toAlias() : this;
1645 // Eliminate need for dynamic_cast
1646 override final inout(VarDeclaration
) isVarDeclaration() inout
1651 override void accept(Visitor v
)
1657 /*******************************************************
1658 * C11 6.7.2.1-4 bit fields
1660 extern (C
++) class BitFieldDeclaration
: VarDeclaration
1667 final extern (D
) this(const ref Loc loc
, Type type
, Identifier ident
, Expression width
)
1669 super(loc
, type
, ident
, null);
1672 this.storage_class |
= STC
.field
;
1675 override BitFieldDeclaration
syntaxCopy(Dsymbol s
)
1677 //printf("BitFieldDeclaration::syntaxCopy(%s)\n", toChars());
1679 auto bf
= new BitFieldDeclaration(loc
, type ? type
.syntaxCopy() : null, ident
, width
.syntaxCopy());
1680 bf
.comment
= comment
;
1684 override final inout(BitFieldDeclaration
) isBitFieldDeclaration() inout
1689 override void accept(Visitor v
)
1694 override final void setFieldOffset(AggregateDeclaration ad
, ref FieldState fieldState
, bool isunion
)
1696 //printf("BitFieldDeclaration::setFieldOffset(ad: %s, field: %s)\n", ad.toChars(), toChars());
1697 static void print(const ref FieldState fieldState
)
1699 printf("FieldState.offset = %d bytes\n", fieldState
.offset
);
1700 printf(" .fieldOffset = %d bytes\n", fieldState
.fieldOffset
);
1701 printf(" .bitOffset = %d bits\n", fieldState
.bitOffset
);
1702 printf(" .fieldSize = %d bytes\n", fieldState
.fieldSize
);
1703 printf(" .inFlight = %d\n\n", fieldState
.inFlight
);
1705 //print(fieldState);
1707 Type t
= type
.toBasetype();
1708 const bool anon
= isAnonymous();
1710 // List in ad.fields. Even if the type is error, it's necessary to avoid
1711 // pointless error diagnostic "more initializers than fields" on struct literal.
1713 ad
.fields
.push(this);
1718 const sz
= t
.size(loc
);
1719 assert(sz
!= SIZE_INVALID
&& sz
< uint.max
);
1720 uint memsize
= cast(uint)sz
; // size of member
1721 uint memalignsize
= target
.fieldalign(t
); // size of member for alignment purposes
1723 if (fieldWidth
== 0 && !anon
)
1724 error(loc
, "named bit fields cannot have 0 width");
1725 if (fieldWidth
> memsize
* 8)
1726 error(loc
, "bit field width %d is larger than type", fieldWidth
);
1728 const style
= target
.c
.bitFieldStyle
;
1730 void startNewField()
1733 if (style
== TargetC
.BitFieldStyle
.Gcc_Clang
)
1735 if (fieldWidth
> 32)
1736 alignsize
= memalignsize
;
1737 else if (fieldWidth
> 16)
1739 else if (fieldWidth
> 8)
1745 alignsize
= memsize
; // not memalignsize
1748 offset
= AggregateDeclaration
.placeField(
1750 memsize
, alignsize
, alignment
,
1752 (anon
&& style
== TargetC
.BitFieldStyle
.Gcc_Clang
) ?
&dummy
: &ad
.alignsize
,
1755 fieldState
.inFlight
= true;
1756 fieldState
.fieldOffset
= offset
;
1757 fieldState
.bitOffset
= 0;
1758 fieldState
.fieldSize
= memsize
;
1761 if (style
== TargetC
.BitFieldStyle
.Gcc_Clang
)
1763 if (fieldWidth
== 0)
1767 // Use type of zero width field to align to next field
1768 fieldState
.offset
= (fieldState
.offset
+ memalignsize
- 1) & ~(memalignsize
- 1);
1769 ad
.structsize
= fieldState
.offset
;
1772 fieldState
.inFlight
= false;
1776 if (ad
.alignsize
== 0)
1779 ad
.alignsize
< memalignsize
)
1780 ad
.alignsize
= memalignsize
;
1782 else if (style
== TargetC
.BitFieldStyle
.MS
)
1784 if (ad
.alignsize
== 0)
1786 if (fieldWidth
== 0)
1788 if (fieldState
.inFlight
&& !isunion
)
1790 // documentation says align to next int
1791 //const alsz = cast(uint)Type.tint32.size();
1792 const alsz
= memsize
; // but it really does this
1793 fieldState
.offset
= (fieldState
.offset
+ alsz
- 1) & ~(alsz
- 1);
1794 ad
.structsize
= fieldState
.offset
;
1797 fieldState
.inFlight
= false;
1801 else if (style
== TargetC
.BitFieldStyle
.DM
)
1803 if (anon
&& fieldWidth
&& (!fieldState
.inFlight || fieldState
.bitOffset
== 0))
1804 return; // this probably should be a bug in DMC
1805 if (ad
.alignsize
== 0)
1807 if (fieldWidth
== 0)
1809 if (fieldState
.inFlight
&& !isunion
)
1811 const alsz
= memsize
;
1812 fieldState
.offset
= (fieldState
.offset
+ alsz
- 1) & ~(alsz
- 1);
1813 ad
.structsize
= fieldState
.offset
;
1816 fieldState
.inFlight
= false;
1821 if (!fieldState
.inFlight
)
1825 else if (style
== TargetC
.BitFieldStyle
.Gcc_Clang
)
1827 if (fieldState
.bitOffset
+ fieldWidth
> memsize
* 8)
1829 //printf("start1 fieldState.bitOffset:%u fieldWidth:%u memsize:%u\n", fieldState.bitOffset, fieldWidth, memsize);
1834 // if alignment boundary is crossed
1835 uint start
= fieldState
.fieldOffset
* 8 + fieldState
.bitOffset
;
1836 uint end
= start
+ fieldWidth
;
1837 //printf("%s start: %d end: %d memalignsize: %d\n", ad.toChars(), start, end, memalignsize);
1838 if (start
/ (memalignsize
* 8) != (end
- 1) / (memalignsize
* 8))
1840 //printf("alignment is crossed\n");
1845 else if (style
== TargetC
.BitFieldStyle
.DM ||
1846 style
== TargetC
.BitFieldStyle
.MS
)
1848 if (memsize
!= fieldState
.fieldSize ||
1849 fieldState
.bitOffset
+ fieldWidth
> fieldState
.fieldSize
* 8)
1857 offset
= fieldState
.fieldOffset
;
1858 bitOffset
= fieldState
.bitOffset
;
1860 const pastField
= bitOffset
+ fieldWidth
;
1861 if (style
== TargetC
.BitFieldStyle
.Gcc_Clang
)
1863 auto size
= (pastField
+ 7) / 8;
1864 fieldState
.fieldSize
= size
;
1865 //printf(" offset: %d, size: %d\n", offset, size);
1866 ad
.structsize
= offset
+ size
;
1869 fieldState
.fieldSize
= memsize
;
1870 //printf("at end: ad.structsize = %d\n", cast(int)ad.structsize);
1871 //print(fieldState);
1875 fieldState
.offset
= offset
+ fieldState
.fieldSize
;
1876 fieldState
.bitOffset
= pastField
;
1879 //printf("\t%s: memalignsize = %d\n", toChars(), memalignsize);
1880 //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize);
1884 /***********************************************************
1885 * This is a shell around a back end symbol
1887 extern (C
++) final class SymbolDeclaration
: Declaration
1889 AggregateDeclaration dsym
;
1891 extern (D
) this(const ref Loc loc
, AggregateDeclaration dsym
)
1893 super(loc
, dsym
.ident
);
1895 storage_class |
= STC
.const_
;
1898 // Eliminate need for dynamic_cast
1899 override inout(SymbolDeclaration
) isSymbolDeclaration() inout
1904 override void accept(Visitor v
)
1910 /***********************************************************
1912 extern (C
++) class TypeInfoDeclaration
: VarDeclaration
1916 final extern (D
) this(Type tinfo
)
1918 super(Loc
.initial
, Type
.dtypeinfo
.type
, tinfo
.getTypeInfoIdent(), null);
1920 storage_class
= STC
.static_ | STC
.gshared
;
1921 visibility
= Visibility(Visibility
.Kind
.public_
);
1923 alignment
.set(target
.ptrsize
);
1926 static TypeInfoDeclaration
create(Type tinfo
)
1928 return new TypeInfoDeclaration(tinfo
);
1931 override final TypeInfoDeclaration
syntaxCopy(Dsymbol s
)
1933 assert(0); // should never be produced by syntax
1936 override final const(char)* toChars() const
1938 //printf("TypeInfoDeclaration::toChars() tinfo = %s\n", tinfo.toChars());
1940 buf
.writestring("typeid(");
1941 buf
.writestring(tinfo
.toChars());
1943 return buf
.extractChars();
1946 override final inout(TypeInfoDeclaration
) isTypeInfoDeclaration() inout @nogc nothrow pure @safe
1951 override void accept(Visitor v
)
1957 /***********************************************************
1959 extern (C
++) final class TypeInfoStructDeclaration
: TypeInfoDeclaration
1961 extern (D
) this(Type tinfo
)
1964 if (!Type
.typeinfostruct
)
1966 ObjectNotFound(Id
.TypeInfo_Struct
);
1968 type
= Type
.typeinfostruct
.type
;
1971 static TypeInfoStructDeclaration
create(Type tinfo
)
1973 return new TypeInfoStructDeclaration(tinfo
);
1976 override void accept(Visitor v
)
1982 /***********************************************************
1984 extern (C
++) final class TypeInfoClassDeclaration
: TypeInfoDeclaration
1986 extern (D
) this(Type tinfo
)
1989 if (!Type
.typeinfoclass
)
1991 ObjectNotFound(Id
.TypeInfo_Class
);
1993 type
= Type
.typeinfoclass
.type
;
1996 static TypeInfoClassDeclaration
create(Type tinfo
)
1998 return new TypeInfoClassDeclaration(tinfo
);
2001 override void accept(Visitor v
)
2007 /***********************************************************
2009 extern (C
++) final class TypeInfoInterfaceDeclaration
: TypeInfoDeclaration
2011 extern (D
) this(Type tinfo
)
2014 if (!Type
.typeinfointerface
)
2016 ObjectNotFound(Id
.TypeInfo_Interface
);
2018 type
= Type
.typeinfointerface
.type
;
2021 static TypeInfoInterfaceDeclaration
create(Type tinfo
)
2023 return new TypeInfoInterfaceDeclaration(tinfo
);
2026 override void accept(Visitor v
)
2032 /***********************************************************
2034 extern (C
++) final class TypeInfoPointerDeclaration
: TypeInfoDeclaration
2036 extern (D
) this(Type tinfo
)
2039 if (!Type
.typeinfopointer
)
2041 ObjectNotFound(Id
.TypeInfo_Pointer
);
2043 type
= Type
.typeinfopointer
.type
;
2046 static TypeInfoPointerDeclaration
create(Type tinfo
)
2048 return new TypeInfoPointerDeclaration(tinfo
);
2051 override void accept(Visitor v
)
2057 /***********************************************************
2059 extern (C
++) final class TypeInfoArrayDeclaration
: TypeInfoDeclaration
2061 extern (D
) this(Type tinfo
)
2064 if (!Type
.typeinfoarray
)
2066 ObjectNotFound(Id
.TypeInfo_Array
);
2068 type
= Type
.typeinfoarray
.type
;
2071 static TypeInfoArrayDeclaration
create(Type tinfo
)
2073 return new TypeInfoArrayDeclaration(tinfo
);
2076 override void accept(Visitor v
)
2082 /***********************************************************
2084 extern (C
++) final class TypeInfoStaticArrayDeclaration
: TypeInfoDeclaration
2086 extern (D
) this(Type tinfo
)
2089 if (!Type
.typeinfostaticarray
)
2091 ObjectNotFound(Id
.TypeInfo_StaticArray
);
2093 type
= Type
.typeinfostaticarray
.type
;
2096 static TypeInfoStaticArrayDeclaration
create(Type tinfo
)
2098 return new TypeInfoStaticArrayDeclaration(tinfo
);
2101 override void accept(Visitor v
)
2107 /***********************************************************
2109 extern (C
++) final class TypeInfoAssociativeArrayDeclaration
: TypeInfoDeclaration
2111 extern (D
) this(Type tinfo
)
2114 if (!Type
.typeinfoassociativearray
)
2116 ObjectNotFound(Id
.TypeInfo_AssociativeArray
);
2118 type
= Type
.typeinfoassociativearray
.type
;
2121 static TypeInfoAssociativeArrayDeclaration
create(Type tinfo
)
2123 return new TypeInfoAssociativeArrayDeclaration(tinfo
);
2126 override void accept(Visitor v
)
2132 /***********************************************************
2134 extern (C
++) final class TypeInfoEnumDeclaration
: TypeInfoDeclaration
2136 extern (D
) this(Type tinfo
)
2139 if (!Type
.typeinfoenum
)
2141 ObjectNotFound(Id
.TypeInfo_Enum
);
2143 type
= Type
.typeinfoenum
.type
;
2146 static TypeInfoEnumDeclaration
create(Type tinfo
)
2148 return new TypeInfoEnumDeclaration(tinfo
);
2151 override void accept(Visitor v
)
2157 /***********************************************************
2159 extern (C
++) final class TypeInfoFunctionDeclaration
: TypeInfoDeclaration
2161 extern (D
) this(Type tinfo
)
2164 if (!Type
.typeinfofunction
)
2166 ObjectNotFound(Id
.TypeInfo_Function
);
2168 type
= Type
.typeinfofunction
.type
;
2171 static TypeInfoFunctionDeclaration
create(Type tinfo
)
2173 return new TypeInfoFunctionDeclaration(tinfo
);
2176 override void accept(Visitor v
)
2182 /***********************************************************
2184 extern (C
++) final class TypeInfoDelegateDeclaration
: TypeInfoDeclaration
2186 extern (D
) this(Type tinfo
)
2189 if (!Type
.typeinfodelegate
)
2191 ObjectNotFound(Id
.TypeInfo_Delegate
);
2193 type
= Type
.typeinfodelegate
.type
;
2196 static TypeInfoDelegateDeclaration
create(Type tinfo
)
2198 return new TypeInfoDelegateDeclaration(tinfo
);
2201 override void accept(Visitor v
)
2207 /***********************************************************
2209 extern (C
++) final class TypeInfoTupleDeclaration
: TypeInfoDeclaration
2211 extern (D
) this(Type tinfo
)
2214 if (!Type
.typeinfotypelist
)
2216 ObjectNotFound(Id
.TypeInfo_Tuple
);
2218 type
= Type
.typeinfotypelist
.type
;
2221 static TypeInfoTupleDeclaration
create(Type tinfo
)
2223 return new TypeInfoTupleDeclaration(tinfo
);
2226 override void accept(Visitor v
)
2232 /***********************************************************
2234 extern (C
++) final class TypeInfoConstDeclaration
: TypeInfoDeclaration
2236 extern (D
) this(Type tinfo
)
2239 if (!Type
.typeinfoconst
)
2241 ObjectNotFound(Id
.TypeInfo_Const
);
2243 type
= Type
.typeinfoconst
.type
;
2246 static TypeInfoConstDeclaration
create(Type tinfo
)
2248 return new TypeInfoConstDeclaration(tinfo
);
2251 override void accept(Visitor v
)
2257 /***********************************************************
2259 extern (C
++) final class TypeInfoInvariantDeclaration
: TypeInfoDeclaration
2261 extern (D
) this(Type tinfo
)
2264 if (!Type
.typeinfoinvariant
)
2266 ObjectNotFound(Id
.TypeInfo_Invariant
);
2268 type
= Type
.typeinfoinvariant
.type
;
2271 static TypeInfoInvariantDeclaration
create(Type tinfo
)
2273 return new TypeInfoInvariantDeclaration(tinfo
);
2276 override void accept(Visitor v
)
2282 /***********************************************************
2284 extern (C
++) final class TypeInfoSharedDeclaration
: TypeInfoDeclaration
2286 extern (D
) this(Type tinfo
)
2289 if (!Type
.typeinfoshared
)
2291 ObjectNotFound(Id
.TypeInfo_Shared
);
2293 type
= Type
.typeinfoshared
.type
;
2296 static TypeInfoSharedDeclaration
create(Type tinfo
)
2298 return new TypeInfoSharedDeclaration(tinfo
);
2301 override void accept(Visitor v
)
2307 /***********************************************************
2309 extern (C
++) final class TypeInfoWildDeclaration
: TypeInfoDeclaration
2311 extern (D
) this(Type tinfo
)
2314 if (!Type
.typeinfowild
)
2316 ObjectNotFound(Id
.TypeInfo_Wild
);
2318 type
= Type
.typeinfowild
.type
;
2321 static TypeInfoWildDeclaration
create(Type tinfo
)
2323 return new TypeInfoWildDeclaration(tinfo
);
2326 override void accept(Visitor v
)
2332 /***********************************************************
2334 extern (C
++) final class TypeInfoVectorDeclaration
: TypeInfoDeclaration
2336 extern (D
) this(Type tinfo
)
2339 if (!Type
.typeinfovector
)
2341 ObjectNotFound(Id
.TypeInfo_Vector
);
2343 type
= Type
.typeinfovector
.type
;
2346 static TypeInfoVectorDeclaration
create(Type tinfo
)
2348 return new TypeInfoVectorDeclaration(tinfo
);
2351 override void accept(Visitor v
)
2357 /***********************************************************
2358 * For the "this" parameter to member functions
2360 extern (C
++) final class ThisDeclaration
: VarDeclaration
2362 extern (D
) this(const ref Loc loc
, Type t
)
2364 super(loc
, t
, Id
.This
, null);
2365 storage_class |
= STC
.nodtor
;
2368 override ThisDeclaration
syntaxCopy(Dsymbol s
)
2370 assert(0); // should never be produced by syntax
2373 override inout(ThisDeclaration
) isThisDeclaration() inout
2378 override void accept(Visitor v
)