Skip to content

Commit

Permalink
Merge pull request #562 from 9rnsr/fix6534
Browse files Browse the repository at this point in the history
Issue 6534 & 7065 & 7172 - Parser improvements for inner aggregates
  • Loading branch information
yebblies committed Oct 8, 2012
2 parents 9aea891 + 3f56dce commit 381eec8
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 36 deletions.
1 change: 1 addition & 0 deletions src/class.c
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,7 @@ void ClassDeclaration::semantic(Scope *sc)
error("static class cannot inherit from nested class %s", baseClass->toChars());
if (toParent2() != baseClass->toParent2() &&
(!toParent2() ||
!baseClass->toParent2()->getType() ||
!baseClass->toParent2()->getType()->isBaseOf(toParent2()->getType(), NULL)))
{
if (toParent2())
Expand Down
94 changes: 58 additions & 36 deletions src/parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,13 +183,6 @@ Dsymbols *Parser::parseDeclDefs(int once)
break;
}

case TOKstruct:
case TOKunion:
case TOKclass:
case TOKinterface:
s = parseAggregate();
break;

case TOKimport:
s = parseImport(decldefs, 0);
break;
Expand Down Expand Up @@ -233,6 +226,10 @@ Dsymbols *Parser::parseDeclDefs(int once)
case TOKtypeof:
case TOKdot:
case TOKvector:
case TOKstruct:
case TOKunion:
case TOKclass:
case TOKinterface:
Ldeclaration:
a = parseDeclarations(STCundefined, NULL);
decldefs->append(a);
Expand Down Expand Up @@ -2750,6 +2747,7 @@ Dsymbols *Parser::parseDeclarations(StorageClass storage_class, unsigned char *c
Dsymbols *a;
enum TOK tok = TOKreserved;
enum LINK link = linkage;
unsigned structalign = 0;

//printf("parseDeclarations() %s\n", token.toChars());
if (!comment)
Expand Down Expand Up @@ -2853,6 +2851,25 @@ Dsymbols *Parser::parseDeclarations(StorageClass storage_class, unsigned char *c
link = parseLinkage();
continue;

case TOKalign:
{
nextToken();
if (token.value == TOKlparen)
{
nextToken();
if (token.value == TOKint32v && token.uns64value > 0)
structalign = (unsigned)token.uns64value;
else
{ error("positive integer expected, not %s", token.toChars());
structalign = 1;
}
nextToken();
check(TOKrparen);
}
else
structalign = global.structalign; // default
continue;
}
default:
break;
}
Expand All @@ -2869,12 +2886,28 @@ Dsymbols *Parser::parseDeclarations(StorageClass storage_class, unsigned char *c
return parseAutoDeclarations(storage_class, comment);
}

if (token.value == TOKclass)
if (token.value == TOKstruct ||
token.value == TOKunion ||
token.value == TOKclass ||
token.value == TOKinterface)
{
AggregateDeclaration *s = (AggregateDeclaration *)parseAggregate();
s->storage_class |= storage_class;
Dsymbol *s = parseAggregate();
Dsymbols *a = new Dsymbols();
a->push(s);

if (storage_class)
{
s = new StorageClassDeclaration(storage_class, a);
a = new Dsymbols();
a->push(s);
}
if (structalign != 0)
{
s = new AlignDeclaration(structalign, a);
a = new Dsymbols();
a->push(s);
}

addComment(s, comment);
return a;
}
Expand Down Expand Up @@ -3477,7 +3510,6 @@ void Parser::checkDanglingElse(Loc elseloc)

Statement *Parser::parseStatement(int flags)
{ Statement *s;
Token *t;
Condition *condition;
Statement *ifbody;
Statement *elsebody;
Expand All @@ -3492,10 +3524,10 @@ Statement *Parser::parseStatement(int flags)
switch (token.value)
{
case TOKidentifier:
/* A leading identifier can be a declaration, label, or expression.
{ /* A leading identifier can be a declaration, label, or expression.
* The easiest case to check first is label:
*/
t = peek(&token);
Token *t = peek(&token);
if (t->value == TOKcolon)
{ // It's a label

Expand All @@ -3507,6 +3539,7 @@ Statement *Parser::parseStatement(int flags)
break;
}
// fallthrough to TOKdot
}
case TOKdot:
case TOKtypeof:
case TOKvector:
Expand Down Expand Up @@ -3581,16 +3614,6 @@ Statement *Parser::parseStatement(int flags)
condition = parseStaticIfCondition();
goto Lcondition;
}
if (t->value == TOKstruct || t->value == TOKunion || t->value == TOKclass)
{
nextToken();
Dsymbols *a = parseBlock();
Dsymbol *d = new StorageClassDeclaration(STCstatic, a);
s = new ExpStatement(loc, d);
if (flags & PSscope)
s = new ScopeStatement(loc, s);
break;
}
if (t->value == TOKimport)
{ nextToken();
Dsymbols *imports = new Dsymbols();
Expand Down Expand Up @@ -3618,7 +3641,9 @@ Statement *Parser::parseStatement(int flags)
case TOKalias:
case TOKconst:
case TOKauto:
case TOKabstract:
case TOKextern:
case TOKalign:
case TOKinvariant:
#if DMDV2
case TOKimmutable:
Expand All @@ -3631,6 +3656,10 @@ Statement *Parser::parseStatement(int flags)
case TOKgshared:
case TOKat:
#endif
case TOKstruct:
case TOKunion:
case TOKclass:
case TOKinterface:
Ldeclaration:
{ Dsymbols *a;

Expand Down Expand Up @@ -3659,17 +3688,6 @@ Statement *Parser::parseStatement(int flags)
break;
}

case TOKstruct:
case TOKunion:
case TOKclass:
case TOKinterface:
{ Dsymbol *d;

d = parseAggregate();
s = new ExpStatement(loc, d);
break;
}

case TOKenum:
{ /* Determine if this is a manifest constant declaration,
* or a conventional enum.
Expand All @@ -3694,7 +3712,7 @@ Statement *Parser::parseStatement(int flags)
}

case TOKmixin:
{ t = peek(&token);
{ Token *t = peek(&token);
if (t->value == TOKlparen)
{ // mixin(string)
Expression *e = parseAssignExp();
Expand Down Expand Up @@ -4235,6 +4253,10 @@ Statement *Parser::parseStatement(int flags)
{ Expression *exp;
Statement *body;

Token *t = peek(&token);
if (skipAttributes(t, &t) && t->value == TOKclass)
goto Ldeclaration;

nextToken();
if (token.value == TOKlparen)
{
Expand Down Expand Up @@ -4362,7 +4384,7 @@ Statement *Parser::parseStatement(int flags)
if (!toklist)
{
// Look ahead to see if it is a label
t = peek(&token);
Token *t = peek(&token);
if (t->value == TOKcolon)
{ // It's a label
label = token.ident;
Expand Down
39 changes: 39 additions & 0 deletions test/compilable/test6534.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
void main()
{
class MC{ int x; }
const class CC{ int x; } static assert(is(typeof( CC.x) == const));
immutable class IC{ int x; } static assert(is(typeof( IC.x) == immutable));
shared class SC{ int x; } static assert(is(typeof( SC.x) == shared));
shared const class SCC{ int x; } static assert(is(typeof(SCC.x) == shared) && is(typeof(SCC.x) == const));

struct MS{ int x; }
const struct CS{ int x; } static assert(is(typeof( CS.x) == const));
immutable struct IS{ int x; } static assert(is(typeof( IS.x) == immutable));
shared struct SS{ int x; } static assert(is(typeof( SS.x) == shared));
shared const struct SCS{ int x; } static assert(is(typeof(SCS.x) == shared) && is(typeof(SCS.x) == const));

union MU{ int x; }
const union CU{ int x; } static assert(is(typeof( CU.x) == const));
immutable union IU{ int x; } static assert(is(typeof( IU.x) == immutable));
shared union SU{ int x; } static assert(is(typeof( SU.x) == shared));
shared const union SCU{ int x; } static assert(is(typeof(SCU.x) == shared) && is(typeof(SCU.x) == const));


static class S_MC{ int x; }
const static class S_CC{ int x; } static assert(is(typeof( S_CC.x) == const));
immutable static class S_IC{ int x; } static assert(is(typeof( S_IC.x) == immutable));
shared static class S_SC{ int x; } static assert(is(typeof( S_SC.x) == shared));
shared const static class S_SCC{ int x; } static assert(is(typeof(S_SCC.x) == shared) && is(typeof(S_SCC.x) == const));

static struct S_MS{ int x; }
const static struct S_CS{ int x; } static assert(is(typeof( S_CS.x) == const));
immutable static struct S_IS{ int x; } static assert(is(typeof( S_IS.x) == immutable));
shared static struct S_SS{ int x; } static assert(is(typeof( S_SS.x) == shared));
shared const static struct S_SCS{ int x; } static assert(is(typeof(S_SCS.x) == shared) && is(typeof(S_SCS.x) == const));

static union S_MU{ int x; }
const static union S_CU{ int x; } static assert(is(typeof( S_CU.x) == const));
immutable static union S_IU{ int x; } static assert(is(typeof( S_IU.x) == immutable));
shared static union S_SU{ int x; } static assert(is(typeof( S_SU.x) == shared));
shared const static union S_SCU{ int x; } static assert(is(typeof(S_SCU.x) == shared) && is(typeof(S_SCU.x) == const));
}
38 changes: 38 additions & 0 deletions test/compilable/test7065.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
void main()
{
align(1)
struct X1 { ubyte b; int n; }
static assert(X1.sizeof == 8);
static assert(X1.b.offsetof == 0);
static assert(X1.n.offsetof == 4);
//X1 x1;
//assert(cast(void*)&x1.b == cast(void*)&x1 + 0);
//assert(cast(void*)&x1.n == cast(void*)&x1 + 1);

struct Y1 { ubyte b; int n; }
static assert(Y1.sizeof == 8);
static assert(Y1.b.offsetof == 0);
static assert(Y1.n.offsetof == 4);
//Y1 y1;
//assert(cast(void*)&y1.b == cast(void*)&y1 + 0);
//assert(cast(void*)&y1.n == cast(void*)&y1 + 4);

int local;

align(1)
struct X2 { ubyte b; int n; int f(){ return local; } }
static assert(X2.sizeof == 8 + (void*).sizeof);
static assert(X2.b.offsetof == 0);
static assert(X2.n.offsetof == 4);
//X2 x2;
//assert(cast(void*)&x2.b == cast(void*)&x2 + 0);
//assert(cast(void*)&x2.n == cast(void*)&x2 + 1);

struct Y2 { ubyte b; int n; int f(){ return local; } }
static assert(Y2.sizeof == 8 + (void*).sizeof);
static assert(Y2.b.offsetof == 0);
static assert(Y2.n.offsetof == 4);
//Y2 y2;
//assert(cast(void*)&y2.b == cast(void*)&y2 + 0);
//assert(cast(void*)&y2.n == cast(void*)&y2 + 4);
}
23 changes: 23 additions & 0 deletions test/compilable/test7172.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
void main()
{
abstract class AbstractC{}
static assert(!__traits(compiles, { new AbstractC(); }));

final class FinalC{}
static assert(!__traits(compiles, { class D : FinalC{} }));

scope class ScopeC{}
static assert(!__traits(compiles, { auto sc = new ScopeC(); }));
static assert( __traits(compiles, { scope sc = new ScopeC(); }));

synchronized class SyncC{ void f(){} }
static assert(SyncC.f.mangleof[$-13..$] == "5SyncC1fMOFZv");

@safe class SCx{ void f(){} }
@trusted class SCy{ void f(){} }
@system class SCz{ void f(){} }

static assert(SCx.f.mangleof[$-12..$] == "3SCx1fMFNfZv"); // Nf: FuncAttrSafe
static assert(SCy.f.mangleof[$-12..$] == "3SCy1fMFNeZv"); // Ne: FuncAttrTrusted
static assert(SCz.f.mangleof[$-10..$] == "3SCz1fMFZv"); // (none)
}

0 comments on commit 381eec8

Please sign in to comment.