Skip to content

Commit

Permalink
Merge pull request #5880 from WalterBright/fix9766
Browse files Browse the repository at this point in the history
reboot 5750: fix Issue 9766 - align(n) with n compile-time constant
  • Loading branch information
rainers committed Jun 24, 2016
2 parents 20e1c81 + 3524708 commit 4b9b4e4
Show file tree
Hide file tree
Showing 19 changed files with 302 additions and 97 deletions.
24 changes: 24 additions & 0 deletions changelog.dd
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
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
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
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
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
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
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
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
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

0 comments on commit 4b9b4e4

Please sign in to comment.