* Miscellaneous declarations, including typedef, alias, variable declarations including the
* implicit this declaration, type tuples, ClassInfo, ModuleInfo and various TypeInfos.
*
- * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved
+ * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 https://www.digitalmars.com, Walter Bright)
* License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/declaration.d, _declaration.d)
import dmd.init;
import dmd.initsem;
import dmd.intrange;
+import dmd.location;
import dmd.mtype;
import dmd.common.outbuffer;
import dmd.root.rootobject;
import dmd.typesem;
import dmd.visitor;
+version (IN_GCC) {}
+else version (IN_LLVM) {}
+else version = MARS;
+
/************************************
* Check to see the aggregate type is nested and its context pointer is
* accessible from the current scope.
}
bool result = false;
- for (size_t i = iStart; i < ad.fields.dim; i++)
+ for (size_t i = iStart; i < ad.fields.length; i++)
{
VarDeclaration vd = ad.fields[i];
Type tb = vd.type.baseElemOf();
/***********************************************
* Mark variable v as modified if it is inside a constructor that var
* is a field in.
+ * Also used to allow immutable globals to be initialized inside a static constructor.
+ * Returns:
+ * true if it's an initialization of v
*/
bool modifyFieldVar(Loc loc, Scope* sc, VarDeclaration var, Expression e1)
{
fd = s.isFuncDeclaration();
if (fd &&
((fd.isCtorDeclaration() && var.isField()) ||
- (fd.isStaticCtorDeclaration() && !var.isField())) &&
+ ((fd.isStaticCtorDeclaration() || fd.isCrtCtor) && !var.isField())) &&
fd.toParentDecl() == var.toParent2() &&
(!e1 || e1.op == EXP.this_))
{
MODtoChars(var.type.mod), var.kind(), var.toChars());
errorSupplemental(loc, "Use `shared static this` instead.");
}
+ else if (fd.isStaticCtorDeclaration() && !fd.isSharedStaticCtorDeclaration() &&
+ var.type.isConst())
+ {
+ // @@@DEPRECATED_2.116@@@
+ // Turn this into an error, merging with the branch above
+ .deprecation(loc, "%s %s `%s` initialization is not allowed in `static this`",
+ MODtoChars(var.type.mod), var.kind(), var.toChars());
+ deprecationSupplemental(loc, "Use `shared static this` instead.");
+ }
return result;
}
else
Type originalType; // before semantic analysis
StorageClass storage_class = STC.undefined_;
Visibility visibility;
- LINK linkage = LINK.default_;
+ LINK _linkage = LINK.default_; // may be `LINK.system`; use `resolvedLinkage()` to resolve it
short inuse; // used to detect cycles
ubyte adFlags; // control re-assignment of AliasDeclaration (put here for packing reasons)
enum wasRead = 1; // set if AliasDeclaration was read
enum ignoreRead = 2; // ignore any reads of AliasDeclaration
+ enum nounderscore = 4; // don't prepend _ to mangled name
Symbol* isym; // import version of csym
// overridden symbol with pragma(mangle, "...")
const(char)[] mangleOverride;
- final extern (D) this(Identifier ident)
+ final extern (D) this(Identifier ident) @safe
{
super(ident);
visibility = Visibility(Visibility.Kind.undefined);
}
- final extern (D) this(const ref Loc loc, Identifier ident)
+ final extern (D) this(const ref Loc loc, Identifier ident) @safe
{
super(loc, ident);
visibility = Visibility(Visibility.Kind.undefined);
* postblit. Print the first field that has
* a disabled postblit.
*/
- if (postblit.generated)
+ if (postblit.isGenerated())
{
auto sd = p.isStructDeclaration();
assert(sd);
- for (size_t i = 0; i < sd.fields.dim; i++)
+ for (size_t i = 0; i < sd.fields.length; i++)
{
auto structField = sd.fields[i];
if (structField.overlapped)
if (auto ctor = isCtorDeclaration())
{
- if (ctor.isCpCtor && ctor.generated)
+ if (ctor.isCpCtor && ctor.isGenerated())
{
- .error(loc, "Generating an `inout` copy constructor for `struct %s` failed, therefore instances of it are uncopyable", parent.toPrettyChars());
+ .error(loc, "generating an `inout` copy constructor for `struct %s` failed, therefore instances of it are uncopyable", parent.toPrettyChars());
return true;
}
}
if (e1 && e1.op == EXP.this_ && isField())
{
- VarDeclaration vthis = (cast(ThisExp)e1).var;
+ VarDeclaration vthis = e1.isThisExp().var;
for (Scope* scx = sc; scx; scx = scx.enclosing)
{
if (scx.func == vthis.parent && (scx.flags & SCOPE.contract))
return (storage_class & STC.static_) != 0;
}
+ /// Returns the linkage, resolving the target-specific `System` one.
+ final LINK resolvedLinkage() const
+ {
+ return _linkage == LINK.system ? target.systemLinkage() : _linkage;
+ }
+
bool isDelete()
{
return false;
return (storage_class & STC.scope_) != 0;
}
+ final bool isReturn() const pure nothrow @nogc @safe
+ {
+ return (storage_class & STC.return_) != 0;
+ }
+
final bool isSynchronized() const pure nothrow @nogc @safe
{
return (storage_class & STC.synchronized_) != 0;
return (storage_class & STC.future) != 0;
}
+ final extern(D) bool isSystem() const pure nothrow @nogc @safe
+ {
+ return (storage_class & STC.system) != 0;
+ }
+
override final Visibility visible() pure nothrow @nogc @safe
{
return visibility;
extern (C++) final class TupleDeclaration : Declaration
{
Objects* objects;
- bool isexp; // true: expression tuple
TypeTuple tupletype; // !=null if this is a type tuple
+ bool isexp; // true: expression tuple
+ bool building; // it's growing in AliasAssign semantic
- extern (D) this(const ref Loc loc, Identifier ident, Objects* objects)
+ extern (D) this(const ref Loc loc, Identifier ident, Objects* objects) @safe
{
super(loc, ident);
this.objects = objects;
override const(char)* kind() const
{
- return "tuple";
+ return "sequence";
}
override Type getType()
*/
//printf("TupleDeclaration::getType() %s\n", toChars());
- if (isexp)
+ if (isexp || building)
return null;
if (!tupletype)
{
/* It's only a type tuple if all the Object's are types
*/
- for (size_t i = 0; i < objects.dim; i++)
+ for (size_t i = 0; i < objects.length; i++)
{
RootObject o = (*objects)[i];
- if (o.dyncast() != DYNCAST.type)
+ if (!o.isType())
{
//printf("\tnot[%d], %p, %d\n", i, o, o.dyncast());
return null;
/* We know it's a type tuple, so build the TypeTuple
*/
Types* types = cast(Types*)objects;
- auto args = new Parameters(objects.dim);
+ auto args = new Parameters(objects.length);
OutBuffer buf;
int hasdeco = 1;
- for (size_t i = 0; i < types.dim; i++)
+ for (size_t i = 0; i < types.length; i++)
{
Type t = (*types)[i];
//printf("type = %s\n", t.toChars());
version (none)
{
buf.printf("_%s_%d", ident.toChars(), i);
- const len = buf.offset;
- const name = buf.extractSlice().ptr;
- auto id = Identifier.idPool(name, len);
+ auto id = Identifier.idPool(buf.extractSlice());
auto arg = new Parameter(STC.in_, t, id, null);
}
else
override Dsymbol toAlias2()
{
//printf("TupleDeclaration::toAlias2() '%s' objects = %s\n", toChars(), objects.toChars());
- for (size_t i = 0; i < objects.dim; i++)
+ for (size_t i = 0; i < objects.length; i++)
{
RootObject o = (*objects)[i];
if (Dsymbol s = isDsymbol(o))
override bool needThis()
{
//printf("TupleDeclaration::needThis(%s)\n", toChars());
- for (size_t i = 0; i < objects.dim; i++)
+ return isexp ? foreachVar((s) { return s.needThis(); }) != 0 : false;
+ }
+
+ /***********************************************************
+ * Calls dg(Dsymbol) for each Dsymbol, which should be a VarDeclaration
+ * inside VarExp (isexp == true).
+ * Params:
+ * dg = delegate to call for each Dsymbol
+ */
+ extern (D) void foreachVar(scope void delegate(Dsymbol) dg)
+ {
+ assert(isexp);
+ foreach (o; *objects)
{
- RootObject o = (*objects)[i];
- if (o.dyncast() == DYNCAST.expression)
- {
- Expression e = cast(Expression)o;
- if (e.op == EXP.dSymbol)
- {
- DsymbolExp ve = cast(DsymbolExp)e;
- Declaration d = ve.s.isDeclaration();
- if (d && d.needThis())
- {
- return true;
- }
- }
- }
+ if (auto e = o.isExpression())
+ if (auto ve = e.isVarExp())
+ dg(ve.var);
}
- return false;
+ }
+
+ /***********************************************************
+ * Calls dg(Dsymbol) for each Dsymbol, which should be a VarDeclaration
+ * inside VarExp (isexp == true).
+ * If dg returns !=0, stops and returns that value else returns 0.
+ * Params:
+ * dg = delegate to call for each Dsymbol
+ * Returns:
+ * last value returned by dg()
+ */
+ extern (D) int foreachVar(scope int delegate(Dsymbol) dg)
+ {
+ assert(isexp);
+ foreach (o; *objects)
+ {
+ if (auto e = o.isExpression())
+ if (auto ve = e.isVarExp())
+ if(auto ret = dg(ve.var))
+ return ret;
+ }
+ return 0;
}
override inout(TupleDeclaration) isTupleDeclaration() inout
Dsymbol overnext; // next in overload list
Dsymbol _import; // !=null if unresolved internal alias for selective import
- extern (D) this(const ref Loc loc, Identifier ident, Type type)
+ extern (D) this(const ref Loc loc, Identifier ident, Type type) @safe
{
super(loc, ident);
- //printf("AliasDeclaration(id = '%s', type = %p)\n", id.toChars(), type);
+ //printf("AliasDeclaration(id = '%s', type = %p)\n", ident.toChars(), type);
//printf("type = '%s'\n", type.toChars());
this.type = type;
assert(type);
}
- extern (D) this(const ref Loc loc, Identifier ident, Dsymbol s)
+ extern (D) this(const ref Loc loc, Identifier ident, Dsymbol s) @safe
{
super(loc, ident);
- //printf("AliasDeclaration(id = '%s', s = %p)\n", id.toChars(), s);
+ //printf("AliasDeclaration(id = '%s', s = %p)\n", ident.toChars(), s);
assert(s != this);
this.aliassym = s;
assert(s);
}
- static AliasDeclaration create(const ref Loc loc, Identifier id, Type type)
+ static AliasDeclaration create(const ref Loc loc, Identifier id, Type type) @safe
{
return new AliasDeclaration(loc, id, type);
}
* is not overloadable.
*/
if (type)
- return false;
+ {
+ /*
+ If type has been resolved already we could
+ still be inserting an alias from an import.
+
+ If we are handling an alias then pretend
+ it was inserting and return true, if not then
+ false since we didn't even pretend to insert something.
+ */
+ return this._import && this.equals(s);
+ }
/* When s is added in member scope by static if, mixin("code") or others,
* aliassym is determined already. See the case in: test/compilable/test61.d
}
else
{
+ // stop AliasAssign tuple building
+ if (aliassym)
+ {
+ if (auto td = aliassym.isTupleDeclaration())
+ {
+ if (td.building)
+ {
+ td.building = false;
+ semanticRun = PASS.semanticdone;
+ return td;
+ }
+ }
+ }
if (_import && _import._scope)
{
/* If this is an internal alias for selective/renamed import,
Dsymbol overnext; // next in overload list
Dsymbol aliassym;
- extern (D) this(Identifier ident, Dsymbol s)
+ extern (D) this(Identifier ident, Dsymbol s) @safe
{
super(ident);
this.aliassym = s;
{
Initializer _init;
FuncDeclarations nestedrefs; // referenced by these lexically nested functions
- Dsymbol aliassym; // if redone as alias to another symbol
+ TupleDeclaration aliasTuple; // when `this` is really a tuple of declarations
VarDeclaration lastVar; // Linked list of variables for goto-skips-init detection
Expression edtor; // if !=null, does the destruction of the variable
IntRange* range; // if !=null, the variable is known to be within the range
- VarDeclarations* maybes; // STC.maybescope variables that are assigned to this STC.maybescope variable
+ VarDeclarations* maybes; // maybeScope variables that are assigned to this maybeScope variable
uint endlinnum; // line number of end of scope that this var lives in
uint offset;
enum AdrOnStackNone = ~0u;
uint ctfeAdrOnStack;
- bool isargptr; // if parameter that _argptr points to
- bool ctorinit; // it has been initialized in a ctor
- bool iscatchvar; // this is the exception object variable in catch() clause
- bool isowner; // this is an Owner, despite it being `scope`
- bool setInCtorOnly; // field can only be set in a constructor, as it is const or immutable
+ // `bool` fields that are compacted into bit fields in a string mixin
+ private extern (D) static struct BitFields
+ {
+ bool isargptr; /// if parameter that _argptr points to
+ bool ctorinit; /// it has been initialized in a ctor
+ bool iscatchvar; /// this is the exception object variable in catch() clause
+ bool isowner; /// this is an Owner, despite it being `scope`
+ bool setInCtorOnly; /// field can only be set in a constructor, as it is const or immutable
- // Both these mean the var is not rebindable once assigned,
- // and the destructor gets run when it goes out of scope
- bool onstack; // it is a class that was allocated on the stack
+ /// It is a class that was allocated on the stack
+ ///
+ /// This means the var is not rebindable once assigned,
+ /// and the destructor gets run when it goes out of scope
+ bool onstack;
+
+ bool overlapped; /// if it is a field and has overlapping
+ bool overlapUnsafe; /// if it is an overlapping field and the overlaps are unsafe
+ bool maybeScope; /// allow inferring 'scope' for this variable
+ bool doNotInferReturn; /// do not infer 'return' for this variable
+
+ bool isArgDtorVar; /// temporary created to handle scope destruction of a function argument
+ bool isCmacro; /// it is a C macro turned into a C declaration
+ bool dllImport; /// __declspec(dllimport)
+ bool dllExport; /// __declspec(dllexport)
+ version (MARS)
+ {
+ bool inClosure; /// is inserted into a GC allocated closure
+ bool inAlignSection; /// is inserted into an aligned section on stack
+ }
+ bool systemInferred; /// @system was inferred from initializer
+ }
+
+ import dmd.common.bitfields : generateBitFields;
+ mixin(generateBitFields!(BitFields, uint));
byte canassign; // it can be assigned to
- bool overlapped; // if it is a field and has overlapping
- bool overlapUnsafe; // if it is an overlapping field and the overlaps are unsafe
- bool doNotInferScope; // do not infer 'scope' for this variable
- bool doNotInferReturn; // do not infer 'return' for this variable
ubyte isdataseg; // private data for isDataseg 0 unset, 1 true, 2 false
- bool isArgDtorVar; // temporary created to handle scope destruction of a function argument
-
final extern (D) this(const ref Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.undefined_)
in
{
{
//printf("VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars());
- if (aliassym)
+ if (aliasTuple)
{
// If this variable was really a tuple, set the offsets for the tuple fields
- TupleDeclaration v2 = aliassym.isTupleDeclaration();
- assert(v2);
- for (size_t i = 0; i < v2.objects.dim; i++)
- {
- RootObject o = (*v2.objects)[i];
- assert(o.dyncast() == DYNCAST.expression);
- Expression e = cast(Expression)o;
- assert(e.op == EXP.dSymbol);
- DsymbolExp se = cast(DsymbolExp)e;
- se.s.setFieldOffset(ad, fieldState, isunion);
- }
+ aliasTuple.foreachVar((s) { s.setFieldOffset(ad, fieldState, isunion); });
return;
}
fieldState.offset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613
return;
}
- for (size_t i = 0; i < ad.fields.dim; i++)
+ for (size_t i = 0; i < ad.fields.length; i++)
{
if (ad.fields[i] == this)
{
override final bool isExport() const
{
- return visibility.kind == Visibility.Kind.export_;
+ return visibility.kind == Visibility.Kind.export_ || dllExport;
}
override final bool isImportedSymbol() const
{
- if (visibility.kind == Visibility.Kind.export_ && !_init && (storage_class & STC.static_ || parent.isModule()))
- return true;
- return false;
+ /* If global variable has `export` and `extern` then it is imported
+ * export int sym1; // definition: exported
+ * export extern int sym2; // declaration: imported
+ * export extern int sym3 = 0; // error, extern cannot have initializer
+ */
+ bool result =
+ dllImport ||
+ visibility.kind == Visibility.Kind.export_ &&
+ storage_class & STC.extern_ &&
+ (storage_class & STC.static_ || parent.isModule());
+ //printf("isImportedSymbol() %s %d\n", toChars(), result);
+ return result;
}
final bool isCtorinit() const pure nothrow @nogc @safe
const sdsz = sd.type.size();
assert(sdsz != SIZE_INVALID && sdsz != 0);
const n = sz / sdsz;
- e = new SliceExp(loc, e, new IntegerExp(loc, 0, Type.tsize_t), new IntegerExp(loc, n, Type.tsize_t));
+ SliceExp se = new SliceExp(loc, e, new IntegerExp(loc, 0, Type.tsize_t),
+ new IntegerExp(loc, n, Type.tsize_t));
// Prevent redundant bounds check
- (cast(SliceExp)e).upperIsInBounds = true;
- (cast(SliceExp)e).lowerIsLessThanUpper = true;
+ se.upperIsInBounds = true;
+ se.lowerIsLessThanUpper = true;
// This is a hack so we can call destructors on const/immutable objects.
- e.type = sd.type.arrayOf();
+ se.type = sd.type.arrayOf();
- e = new CallExp(loc, new IdentifierExp(loc, Id.__ArrayDtor), e);
+ e = new CallExp(loc, new IdentifierExp(loc, Id.__ArrayDtor), se);
}
return e;
}
uint oldgag = global.gag;
if (global.gag)
{
- Dsymbol sym = toParent().isAggregateDeclaration();
+ Dsymbol sym = isMember();
if (sym && !sym.isSpeculative())
global.gag = 0;
}
// Add this VarDeclaration to fdv.closureVars[] if not already there
if (!sc.intypeof && !(sc.flags & SCOPE.compile) &&
// https://issues.dlang.org/show_bug.cgi?id=17605
- (fdv.flags & FUNCFLAG.compileTimeOnly || !(fdthis.flags & FUNCFLAG.compileTimeOnly))
- )
+ (fdv.skipCodegen || !fdthis.skipCodegen))
{
if (!fdv.closureVars.contains(this))
fdv.closureVars.push(this);
if ((!type || !type.deco) && _scope)
dsymbolSemantic(this, _scope);
- assert(this != aliassym);
- Dsymbol s = aliassym ? aliassym.toAlias() : this;
+ assert(this != aliasTuple);
+ Dsymbol s = aliasTuple ? aliasTuple.toAlias() : this;
return s;
}
{
v.visit(this);
}
-
- /**********************************
- * Determine if `this` has a lifetime that lasts past
- * the destruction of `v`
- * Params:
- * v = variable to test against
- * Returns:
- * true if it does
- */
- final bool enclosesLifetimeOf(VarDeclaration v) const pure
- {
- // VarDeclaration's with these STC's need special treatment
- enum special = STC.temp | STC.foreach_;
-
- // Sequence numbers work when there are no special VarDeclaration's involved
- if (!((this.storage_class | v.storage_class) & special))
- {
- assert(this.sequenceNumber != this.sequenceNumber.init);
- assert(v.sequenceNumber != v.sequenceNumber.init);
-
- return (this.sequenceNumber < v.sequenceNumber);
- }
-
- // Assume that semantic produces temporaries according to their lifetime
- // (It won't create a temporary before the actual content)
- if ((this.storage_class & special) && (v.storage_class & special))
- return this.sequenceNumber < v.sequenceNumber;
-
- // Fall back to lexical order
- assert(this.loc != Loc.initial);
- assert(v.loc != Loc.initial);
-
- if (this.loc.linnum != v.loc.linnum)
- return this.loc.linnum < v.loc.linnum;
-
- if (this.loc.charnum != v.loc.charnum)
- return this.loc.charnum < v.loc.charnum;
-
- // Default fallback
- return this.sequenceNumber < v.sequenceNumber;
- }
-
- /***************************************
- * Add variable to maybes[].
- * When a maybescope variable `v` is assigned to a maybescope variable `this`,
- * we cannot determine if `this` is actually scope until the semantic
- * analysis for the function is completed. Thus, we save the data
- * until then.
- * Params:
- * v = an STC.maybescope variable that was assigned to `this`
- */
- final void addMaybe(VarDeclaration v)
- {
- //printf("add %s to %s's list of dependencies\n", v.toChars(), toChars());
- if (!maybes)
- maybes = new VarDeclarations();
- maybes.push(v);
- }
}
/*******************************************************
v.visit(this);
}
+ /***********************************
+ * Retrieve the .min or .max values.
+ * Only valid after semantic analysis.
+ * Params:
+ * id = Id.min or Id.max
+ * Returns:
+ * the min or max value
+ */
+ final ulong getMinMax(Identifier id)
+ {
+ const width = fieldWidth;
+ const uns = type.isunsigned();
+ const min = id == Id.min;
+ ulong v;
+ assert(width != 0); // should have been rejected in semantic pass
+ if (width == ulong.sizeof * 8)
+ v = uns ? (min ? ulong.min : ulong.max)
+ : (min ? long.min : long.max);
+ else
+ v = uns ? (min ? 0
+ : (1L << width) - 1)
+ : (min ? -(1L << (width - 1))
+ : (1L << (width - 1)) - 1);
+ return v;
+ }
+
override final void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion)
{
- //printf("BitFieldDeclaration::setFieldOffset(ad: %s, field: %s)\n", ad.toChars(), toChars());
- static void print(const ref FieldState fieldState)
+ enum log = false;
+ static if (log)
{
- printf("FieldState.offset = %d bytes\n", fieldState.offset);
- printf(" .fieldOffset = %d bytes\n", fieldState.fieldOffset);
- printf(" .bitOffset = %d bits\n", fieldState.bitOffset);
- printf(" .fieldSize = %d bytes\n", fieldState.fieldSize);
- printf(" .inFlight = %d\n\n", fieldState.inFlight);
+ printf("BitFieldDeclaration::setFieldOffset(ad: %s, field: %s)\n", ad.toChars(), toChars());
+ void print(const ref FieldState fieldState)
+ {
+ printf("FieldState.offset = %d bytes\n", fieldState.offset);
+ printf(" .fieldOffset = %d bytes\n", fieldState.fieldOffset);
+ printf(" .bitOffset = %d bits\n", fieldState.bitOffset);
+ printf(" .fieldSize = %d bytes\n", fieldState.fieldSize);
+ printf(" .inFlight = %d\n", fieldState.inFlight);
+ printf(" fieldWidth = %d bits\n", fieldWidth);
+ }
+ print(fieldState);
}
- //print(fieldState);
Type t = type.toBasetype();
const bool anon = isAnonymous();
assert(sz != SIZE_INVALID && sz < uint.max);
uint memsize = cast(uint)sz; // size of member
uint memalignsize = target.fieldalign(t); // size of member for alignment purposes
+ if (log) printf(" memsize: %u memalignsize: %u\n", memsize, memalignsize);
if (fieldWidth == 0 && !anon)
error(loc, "named bit fields cannot have 0 width");
void startNewField()
{
+ if (log) printf("startNewField()\n");
uint alignsize;
if (style == TargetC.BitFieldStyle.Gcc_Clang)
{
if (!fieldState.inFlight)
{
+ //printf("not in flight\n");
startNewField();
}
else if (style == TargetC.BitFieldStyle.Gcc_Clang)
{
- if (fieldState.bitOffset + fieldWidth > memsize * 8)
+ // If the bit-field spans more units of alignment than its type,
+ // start a new field at the next alignment boundary.
+ if (fieldState.bitOffset == fieldState.fieldSize * 8 &&
+ fieldState.bitOffset + fieldWidth > memalignsize * 8)
{
- //printf("start1 fieldState.bitOffset:%u fieldWidth:%u memsize:%u\n", fieldState.bitOffset, fieldWidth, memsize);
- startNewField();
+ if (log) printf("more units of alignment than its type\n");
+ startNewField(); // the bit field is full
}
else
{
//printf("%s start: %d end: %d memalignsize: %d\n", ad.toChars(), start, end, memalignsize);
if (start / (memalignsize * 8) != (end - 1) / (memalignsize * 8))
{
- //printf("alignment is crossed\n");
+ if (log) printf("alignment is crossed\n");
startNewField();
}
}
if (memsize != fieldState.fieldSize ||
fieldState.bitOffset + fieldWidth > fieldState.fieldSize * 8)
{
+ //printf("new field\n");
startNewField();
}
}
fieldState.bitOffset = pastField;
}
+ //printf("\t%s: offset = %d bitOffset = %d fieldWidth = %d memsize = %d\n", toChars(), offset, bitOffset, fieldWidth, memsize);
//printf("\t%s: memalignsize = %d\n", toChars(), memalignsize);
//printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize);
}
{
AggregateDeclaration dsym;
- extern (D) this(const ref Loc loc, AggregateDeclaration dsym)
+ extern (D) this(const ref Loc loc, AggregateDeclaration dsym) @safe
{
super(loc, dsym.ident);
this.dsym = dsym;
this.tinfo = tinfo;
storage_class = STC.static_ | STC.gshared;
visibility = Visibility(Visibility.Kind.public_);
- linkage = LINK.c;
+ _linkage = LINK.c;
alignment.set(target.ptrsize);
}