Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions changelog.dd
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ $(BUGSTITLE Language Changes,
It is up to the programmer to call them appropriately.
)
)

$(LI $(RELATIVE_LINK2 align_by_ctfe, Align attribute can be used with CTFEable expression.))
)

$(BUGSTITLE Compiler Changes,
Expand Down Expand Up @@ -51,6 +53,28 @@ $(BUGSTITLE Language Changes,
}
---
)
$(LI $(LNAME2 align_by_ctfe, Align attribute can be used with CTFEable expression.)

$(P Example:)

---
version (D_LP64)
enum n = 8;
else
enum n = 4;
align (n) struct Data
{
align (n == 8 ? 2 : 1):
ubyte[3] buffer;
int flags;
}

version (D_LP64)
static assert(Data.flags.offsetof == 4);
else
static assert(Data.flags.offsetof == 3);
---
)
)

$(BUGSTITLE Compiler Changes,
Expand Down
2 changes: 1 addition & 1 deletion src/aggregate.d
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
sc2.inunion = 1;
sc2.protection = Prot(PROTpublic);
sc2.explicitProtection = 0;
sc2.structalign = STRUCTALIGN_DEFAULT;
sc2.aligndecl = null;
sc2.userAttribDecl = null;
return sc2;
}
Expand Down
101 changes: 82 additions & 19 deletions src/attrib.d
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,18 @@ extern (C++) abstract class AttribDeclaration : Dsymbol
* If the returned scope != sc, the caller should pop
* the scope after it used.
*/
static Scope* createNewScope(Scope* sc, StorageClass stc, LINK linkage, CPPMANGLE cppmangle, Prot protection, int explicitProtection, structalign_t structalign, PINLINE inlining)
static Scope* createNewScope(Scope* sc, StorageClass stc, LINK linkage,
CPPMANGLE cppmangle, Prot protection, int explicitProtection,
AlignDeclaration aligndecl, PINLINE inlining)
{
Scope* sc2 = sc;
if (stc != sc.stc || linkage != sc.linkage || cppmangle != sc.cppmangle || !protection.isSubsetOf(sc.protection) || explicitProtection != sc.explicitProtection || structalign != sc.structalign || inlining != sc.inlining)
if (stc != sc.stc ||
linkage != sc.linkage ||
cppmangle != sc.cppmangle ||
!protection.isSubsetOf(sc.protection) ||
explicitProtection != sc.explicitProtection ||
aligndecl !is sc.aligndecl ||
inlining != sc.inlining)
{
// create new one for changes
sc2 = sc.copy();
Expand All @@ -89,7 +97,7 @@ extern (C++) abstract class AttribDeclaration : Dsymbol
sc2.cppmangle = cppmangle;
sc2.protection = protection;
sc2.explicitProtection = explicitProtection;
sc2.structalign = structalign;
sc2.aligndecl = aligndecl;
sc2.inlining = inlining;
}
return sc2;
Expand Down Expand Up @@ -351,7 +359,8 @@ extern (C++) class StorageClassDeclaration : AttribDeclaration
scstc &= ~(STCsafe | STCtrusted | STCsystem);
scstc |= stc;
//printf("scstc = x%llx\n", scstc);
return createNewScope(sc, scstc, sc.linkage, sc.cppmangle, sc.protection, sc.explicitProtection, sc.structalign, sc.inlining);
return createNewScope(sc, scstc, sc.linkage, sc.cppmangle,
sc.protection, sc.explicitProtection, sc.aligndecl, sc.inlining);
}

override final bool oneMember(Dsymbol* ps, Identifier ident)
Expand Down Expand Up @@ -496,7 +505,8 @@ extern (C++) final class LinkDeclaration : AttribDeclaration

override Scope* newScope(Scope* sc)
{
return createNewScope(sc, sc.stc, this.linkage, sc.cppmangle, sc.protection, sc.explicitProtection, sc.structalign, sc.inlining);
return createNewScope(sc, sc.stc, this.linkage, sc.cppmangle, sc.protection, sc.explicitProtection,
sc.aligndecl, sc.inlining);
}

override const(char)* toChars() const
Expand Down Expand Up @@ -531,7 +541,8 @@ extern (C++) final class CPPMangleDeclaration : AttribDeclaration

override Scope* newScope(Scope* sc)
{
return createNewScope(sc, sc.stc, LINKcpp, cppmangle, sc.protection, sc.explicitProtection, sc.structalign, sc.inlining);
return createNewScope(sc, sc.stc, LINKcpp, cppmangle, sc.protection, sc.explicitProtection,
sc.aligndecl, sc.inlining);
}

override const(char)* toChars() const
Expand Down Expand Up @@ -594,7 +605,7 @@ extern (C++) final class ProtDeclaration : AttribDeclaration
{
if (pkg_identifiers)
semantic(sc);
return createNewScope(sc, sc.stc, sc.linkage, sc.cppmangle, this.protection, 1, sc.structalign, sc.inlining);
return createNewScope(sc, sc.stc, sc.linkage, sc.cppmangle, this.protection, 1, sc.aligndecl, sc.inlining);
}

override void addMember(Scope* sc, ScopeDsymbol sds)
Expand Down Expand Up @@ -641,23 +652,72 @@ extern (C++) final class ProtDeclaration : AttribDeclaration
*/
extern (C++) final class AlignDeclaration : AttribDeclaration
{
uint salign;
Expression ealign;
structalign_t salign = STRUCTALIGN_DEFAULT;

extern (D) this(uint sa, Dsymbols* decl)
extern (D) this(Loc loc, Expression ealign, Dsymbols* decl)
{
super(decl);
salign = sa;
this.loc = loc;
this.ealign = ealign;
}

override Dsymbol syntaxCopy(Dsymbol s)
{
assert(!s);
return new AlignDeclaration(salign, Dsymbol.arraySyntaxCopy(decl));
return new AlignDeclaration(loc,
ealign.syntaxCopy(), Dsymbol.arraySyntaxCopy(decl));
}

override Scope* newScope(Scope* sc)
{
return createNewScope(sc, sc.stc, sc.linkage, sc.cppmangle, sc.protection, sc.explicitProtection, this.salign, sc.inlining);
return createNewScope(sc, sc.stc, sc.linkage, sc.cppmangle, sc.protection, sc.explicitProtection, this, sc.inlining);
}

override void setScope(Scope* sc)
{
//printf("AlignDeclaration::setScope() %p\n", this);
if (ealign && decl)
Dsymbol.setScope(sc); // for forward reference
return AttribDeclaration.setScope(sc);
}

override void semantic2(Scope* sc)
{
getAlignment();
super.semantic2(sc);
}

structalign_t getAlignment()
{
if (!ealign)
return STRUCTALIGN_DEFAULT;

if (auto sc = _scope)
{
_scope = null;

sc = sc.startCTFE();
ealign = ealign.semantic(sc);
ealign = resolveProperties(sc, ealign);
sc = sc.endCTFE();
ealign = ealign.ctfeInterpret();

if (ealign.op == TOKerror)
return STRUCTALIGN_DEFAULT;

Type tb = ealign.type.toBasetype();
auto n = ealign.toInteger();

if (n < 1 || n & (n - 1) || structalign_t.max < n || !tb.isintegral())
{
.error(loc, "alignment must be an integer positive power of 2, not %s", ealign.toChars());
return STRUCTALIGN_DEFAULT;
}

salign = cast(structalign_t)n;
}
return salign;
}

override void accept(Visitor v)
Expand All @@ -671,7 +731,6 @@ extern (C++) final class AlignDeclaration : AttribDeclaration
extern (C++) final class AnonDeclaration : AttribDeclaration
{
bool isunion;
structalign_t alignment;
int sem; // 1 if successful semantic()
uint anonoffset; // offset of anonymous struct
uint anonstructsize; // size of anonymous struct
Expand All @@ -692,22 +751,23 @@ extern (C++) final class AnonDeclaration : AttribDeclaration

override void setScope(Scope* sc)
{
super.setScope(sc);
alignment = sc.structalign;
if (decl)
Dsymbol.setScope(sc);
return AttribDeclaration.setScope(sc);
}

override void semantic(Scope* sc)
{
//printf("\tAnonDeclaration::semantic %s %p\n", isunion ? "union" : "struct", this);
assert(sc.parent);
Dsymbol p = sc.parent.pastMixin();
AggregateDeclaration ad = p.isAggregateDeclaration();
auto p = sc.parent.pastMixin();
auto ad = p.isAggregateDeclaration();
if (!ad)
{
.error(loc, "%s can only be a part of an aggregate, not %s %s", kind(), p.kind(), p.toChars());
return;
}
alignment = sc.structalign;

if (decl)
{
sc = sc.push();
Expand Down Expand Up @@ -775,6 +835,9 @@ extern (C++) final class AnonDeclaration : AttribDeclaration
anonalignsize = 1;
}

assert(_scope);
auto alignment = _scope.alignment();

/* Given the anon 'member's size and alignment,
* go ahead and place it.
*/
Expand Down Expand Up @@ -861,7 +924,7 @@ extern (C++) final class PragmaDeclaration : AttribDeclaration
else if (e.isBool(false))
inlining = PINLINEnever;
}
return createNewScope(sc, sc.stc, sc.linkage, sc.cppmangle, sc.protection, sc.explicitProtection, sc.structalign, inlining);
return createNewScope(sc, sc.stc, sc.linkage, sc.cppmangle, sc.protection, sc.explicitProtection, sc.aligndecl, inlining);
}
return sc;
}
Expand Down
9 changes: 6 additions & 3 deletions src/attrib.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,19 +120,22 @@ class ProtDeclaration : public AttribDeclaration

class AlignDeclaration : public AttribDeclaration
{
public:
unsigned salign;
Expression *ealign;
structalign_t salign;

AlignDeclaration(Loc loc, Expression *ealign, Dsymbols *decl);
Dsymbol *syntaxCopy(Dsymbol *s);
Scope *newScope(Scope *sc);
void setScope(Scope *sc);
void semantic2(Scope *sc);
structalign_t getAlignment();
void accept(Visitor *v) { v->visit(this); }
};

class AnonDeclaration : public AttribDeclaration
{
public:
bool isunion;
structalign_t alignment;
int sem; // 1 if successful semantic()
unsigned anonoffset; // offset of anonymous struct
unsigned anonstructsize; // size of anonymous struct
Expand Down
2 changes: 1 addition & 1 deletion src/declaration.d
Original file line number Diff line number Diff line change
Expand Up @@ -1116,7 +1116,7 @@ extern (C++) class VarDeclaration : Declaration
/* If scope's alignment is the default, use the type's alignment,
* otherwise the scope overrrides.
*/
alignment = sc.structalign;
alignment = sc.alignment();
if (alignment == STRUCTALIGN_DEFAULT)
alignment = type.alignment(); // use type's alignment

Expand Down
12 changes: 10 additions & 2 deletions src/dscope.d
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ struct Scope
size_t fieldinit_dim;

// alignment for struct members
structalign_t structalign = STRUCTALIGN_DEFAULT;
AlignDeclaration aligndecl;

// linkage for external functions
LINK linkage = LINKd;
Expand Down Expand Up @@ -725,7 +725,7 @@ struct Scope
this.scontinue = sc.scontinue;
this.fes = sc.fes;
this.callsc = sc.callsc;
this.structalign = sc.structalign;
this.aligndecl = sc.aligndecl;
this.func = sc.func;
this.slabel = sc.slabel;
this.linkage = sc.linkage;
Expand All @@ -749,4 +749,12 @@ struct Scope
this.prevAnchor = sc.prevAnchor;
this.userAttribDecl = sc.userAttribDecl;
}

structalign_t alignment()
{
if (aligndecl)
return aligndecl.getAlignment();
else
return STRUCTALIGN_DEFAULT;
}
}
2 changes: 1 addition & 1 deletion src/dstruct.d
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ extern (C++) class StructDeclaration : AggregateDeclaration
{
protection = sc.protection;

alignment = sc.structalign;
alignment = sc.alignment();

storage_class |= sc.stc;
if (storage_class & STCdeprecated)
Expand Down
2 changes: 1 addition & 1 deletion src/func.d
Original file line number Diff line number Diff line change
Expand Up @@ -1444,7 +1444,7 @@ extern (C++) class FuncDeclaration : Declaration
sc2.stc &= ~(STCauto | STCscope | STCstatic | STCabstract | STCdeprecated | STCoverride | STC_TYPECTOR | STCfinal | STCtls | STCgshared | STCref | STCreturn | STCproperty | STCnothrow | STCpure | STCsafe | STCtrusted | STCsystem);
sc2.protection = Prot(PROTpublic);
sc2.explicitProtection = 0;
sc2.structalign = STRUCTALIGN_DEFAULT;
sc2.aligndecl = null;
if (this.ident != Id.require && this.ident != Id.ensure)
sc2.flags = sc.flags & ~SCOPEcontract;
sc2.flags &= ~SCOPEcompile;
Expand Down
6 changes: 3 additions & 3 deletions src/hdrgen.d
Original file line number Diff line number Diff line change
Expand Up @@ -1221,10 +1221,10 @@ public:

override void visit(AlignDeclaration d)
{
if (d.salign == STRUCTALIGN_DEFAULT)
buf.printf("align");
if (!d.ealign)
buf.printf("align ");
else
buf.printf("align (%d)", d.salign);
buf.printf("align (%s) ", d.ealign.toChars());
visit(cast(AttribDeclaration)d);
}

Expand Down
Loading