Skip to content

Commit

Permalink
Merge pull request #3540 from 9rnsr/fix10326
Browse files Browse the repository at this point in the history
Issue 10326 - Disallow 'invariant' for immutable, allow class/struct invariants without (), and later disallow usage of ()
  • Loading branch information
WalterBright committed May 12, 2014
2 parents 7bda1b0 + 040c29a commit 6f08c33
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 66 deletions.
18 changes: 11 additions & 7 deletions src/mtype.c
Expand Up @@ -1557,7 +1557,7 @@ char *MODtoChars(unsigned char mod)
/********************************
* Name mangling.
* Input:
* flag 0x100 do not do const/invariant
* flag 0x100 do not do modifiers
*/

void Type::toDecoBuffer(OutBuffer *buf, int flag)
Expand Down Expand Up @@ -8168,7 +8168,7 @@ bool TypeStruct::isAssignable()
bool assignable = true;
unsigned offset;

/* If any of the fields are const or invariant,
/* If any of the fields are const or immutable,
* then one cannot assign this struct.
*/
for (size_t i = 0; i < sym->fields.dim; i++)
Expand Down Expand Up @@ -8488,15 +8488,17 @@ Expression *TypeClass::dotExp(Scope *sc, Expression *e, Identifier *ident, int f
e->type = t; // do this so we don't get redundant dereference
}
else
{ /* For class objects, the classinfo reference is the first
{
/* For class objects, the classinfo reference is the first
* entry in the vtbl[]
*/
e = new PtrExp(e->loc, e);
e->type = t->pointerTo();
if (sym->isInterfaceDeclaration())
{
if (sym->isCPPinterface())
{ /* C++ interface vtbl[]s are different in that the
{
/* C++ interface vtbl[]s are different in that the
* first entry is always pointer to the first virtual
* function, not classinfo.
* We can't get a .classinfo for it.
Expand All @@ -8518,8 +8520,9 @@ Expression *TypeClass::dotExp(Scope *sc, Expression *e, Identifier *ident, int f
}

if (ident == Id::__vptr)
{ /* The pointer to the vtbl[]
* *cast(invariant(void*)**)e
{
/* The pointer to the vtbl[]
* *cast(immutable(void*)**)e
*/
e = e->castTo(sc, tvoidptr->immutableOf()->pointerTo()->pointerTo());
e = new PtrExp(e->loc, e);
Expand All @@ -8528,7 +8531,8 @@ Expression *TypeClass::dotExp(Scope *sc, Expression *e, Identifier *ident, int f
}

if (ident == Id::__monitor)
{ /* The handle to the monitor (call it a void*)
{
/* The handle to the monitor (call it a void*)
* *(cast(void**)e + 1)
*/
e = e->castTo(sc, tvoidptr->pointerTo());
Expand Down
81 changes: 22 additions & 59 deletions src/parse.c
Expand Up @@ -309,24 +309,17 @@ Dsymbols *Parser::parseDeclDefs(int once, Dsymbol **pLastDecl)
case TOKinvariant:
{
Token *t = peek(&token);
if (t->value == TOKlparen)
if (t->value == TOKlparen && peek(t)->value == TOKrparen ||
t->value == TOKlcurly)
{
if (peek(t)->value == TOKrparen)
{
// invariant() forms start of class invariant
s = parseInvariant();
}
else
{
// invariant(type)
goto Ldeclaration;
}
// invariant {}
// invariant() {}
s = parseInvariant();
}
else
{
error("use 'immutable' instead of 'invariant'");
stc = STCimmutable;
goto Lstc;
error("invariant body expected, not '%s'", token.toChars());
goto Lerror;
}
break;
}
Expand Down Expand Up @@ -873,8 +866,6 @@ StorageClass Parser::parsePostfix(Expressions **pudas)
switch (token.value)
{
case TOKconst: stc |= STCconst; break;
case TOKinvariant:
error("use 'immutable' instead of 'invariant'");
case TOKimmutable: stc |= STCimmutable; break;
case TOKshared: stc |= STCshared; break;
case TOKwild: stc |= STCwild; break;
Expand Down Expand Up @@ -918,8 +909,6 @@ StorageClass Parser::parseTypeCtor()
switch (token.value)
{
case TOKconst: stc |= STCconst; break;
case TOKinvariant:
error("use 'immutable' instead of 'invariant'");
case TOKimmutable: stc |= STCimmutable; break;
case TOKshared: stc |= STCshared; break;
case TOKwild: stc |= STCwild; break;
Expand Down Expand Up @@ -1584,12 +1573,9 @@ Parameters *Parser::parseParameters(int *pvarargs, TemplateParameters **tpl)
stc = STCconst;
goto L2;

case TOKinvariant:
case TOKimmutable:
if (peek(&token)->value == TOKlparen)
goto Ldefault;
if (token.value == TOKinvariant)
error("use 'immutable' instead of 'invariant'");
stc = STCimmutable;
goto L2;

Expand Down Expand Up @@ -2636,12 +2622,9 @@ Type *Parser::parseType(Identifier **pident, TemplateParameters **tpl)
nextToken();
continue;

case TOKinvariant:
case TOKimmutable:
if (peekNext() == TOKlparen)
break;
if (token.value == TOKinvariant)
error("use 'immutable' instead of 'invariant'");
stc |= STCimmutable;
nextToken();
continue;
Expand Down Expand Up @@ -2774,10 +2757,8 @@ Type *Parser::parseBasicType()
check(TOKrparen);
break;

case TOKinvariant:
error("use 'immutable' instead of 'invariant'");
case TOKimmutable:
// invariant(type)
// immutable(type)
nextToken();
check(TOKlparen);
t = parseType()->addSTC(STCimmutable);
Expand Down Expand Up @@ -3215,12 +3196,9 @@ Dsymbols *Parser::parseDeclarations(bool autodecl, StorageClass storage_class, c
stc = STCconst; // const as storage class
goto L1;

case TOKinvariant:
case TOKimmutable:
if (peek(&token)->value == TOKlparen)
break;
if (token.value == TOKinvariant)
error("use 'immutable' instead of 'invariant'");
stc = STCimmutable;
goto L1;

Expand Down Expand Up @@ -4189,7 +4167,6 @@ Statement *Parser::parseStatement(int flags, const utf8_t** endPtr)
case TOKabstract:
case TOKextern:
case TOKalign:
case TOKinvariant:
case TOKimmutable:
case TOKshared:
case TOKwild:
Expand Down Expand Up @@ -4433,13 +4410,10 @@ Statement *Parser::parseStatement(int flags, const utf8_t** endPtr)
goto Lagain;
}
break;
case TOKinvariant:
case TOKimmutable:
if (peekNext() != TOKlparen)
{
stc = STCimmutable;
if (token.value == TOKinvariant)
error("use 'immutable' instead of 'invariant'");
goto Lagain;
}
break;
Expand Down Expand Up @@ -4538,13 +4512,10 @@ Statement *Parser::parseStatement(int flags, const utf8_t** endPtr)
goto LagainStc;
}
break;
case TOKinvariant:
case TOKimmutable:
if (peekNext() != TOKlparen)
{
stc = STCimmutable;
if (token.value == TOKinvariant)
error("use 'immutable' instead of 'invariant'");
goto LagainStc;
}
break;
Expand Down Expand Up @@ -5177,12 +5148,12 @@ int Parser::isDeclaration(Token *t, int needId, TOK endtok, Token **pt)
while (1)
{
if ((t->value == TOKconst ||
t->value == TOKinvariant ||
t->value == TOKimmutable ||
t->value == TOKwild ||
t->value == TOKshared) &&
peek(t)->value != TOKlparen)
{ /* const type
{
/* const type
* immutable type
* shared type
* wild type
Expand All @@ -5202,7 +5173,8 @@ int Parser::isDeclaration(Token *t, int needId, TOK endtok, Token **pt)
if ( needId == 1 ||
(needId == 0 && !haveId) ||
(needId == 2 && haveId))
{ if (pt)
{
if (pt)
*pt = t;
goto Lis;
}
Expand Down Expand Up @@ -5332,7 +5304,6 @@ int Parser::isBasicType(Token **pt)
goto L3;

case TOKconst:
case TOKinvariant:
case TOKimmutable:
case TOKshared:
case TOKwild:
Expand Down Expand Up @@ -5504,7 +5475,6 @@ int Parser::isDeclarator(Token **pt, int *haveId, int *haveTpl, TOK endtok)
switch (t->value)
{
case TOKconst:
case TOKinvariant:
case TOKimmutable:
case TOKshared:
case TOKwild:
Expand Down Expand Up @@ -5583,7 +5553,6 @@ int Parser::isParameters(Token **pt)
continue;

case TOKconst:
case TOKinvariant:
case TOKimmutable:
case TOKshared:
case TOKwild:
Expand Down Expand Up @@ -5799,7 +5768,6 @@ int Parser::skipAttributes(Token *t, Token **pt)
switch (t->value)
{
case TOKconst:
case TOKinvariant:
case TOKimmutable:
case TOKshared:
case TOKwild:
Expand All @@ -5820,7 +5788,8 @@ int Parser::skipAttributes(Token *t, Token **pt)
case TOKat:
t = peek(t);
if (t->value == TOKidentifier)
{ /* @identifier
{
/* @identifier
* @identifier!arg
* @identifier!(arglist)
* any of the above followed by (arglist)
Expand All @@ -5838,7 +5807,8 @@ int Parser::skipAttributes(Token *t, Token **pt)
{
t = peek(t);
if (t->value == TOKlparen)
{ // @identifier!(arglist)
{
// @identifier!(arglist)
if (!skipParens(t, &t))
goto Lerror;
// t is on the next of closing parenthesis
Expand All @@ -5848,7 +5818,8 @@ int Parser::skipAttributes(Token *t, Token **pt)
// @identifier!arg
// Do low rent skipTemplateArgument
if (t->value == TOKvector)
{ // identifier!__vector(type)
{
// identifier!__vector(type)
t = peek(t);
if (!skipParens(t, &t))
goto Lerror;
Expand All @@ -5867,7 +5838,8 @@ int Parser::skipAttributes(Token *t, Token **pt)
continue;
}
if (t->value == TOKlparen)
{ // @( ArgumentList )
{
// @( ArgumentList )
if (!skipParens(t, &t))
goto Lerror;
// t is on the next of closing parenthesis
Expand Down Expand Up @@ -6211,7 +6183,6 @@ Expression *Parser::parsePrimaryExp()
token.value == TOKargTypes ||
token.value == TOKparameters ||
token.value == TOKconst && peek(&token)->value == TOKrparen ||
token.value == TOKinvariant && peek(&token)->value == TOKrparen ||
token.value == TOKimmutable && peek(&token)->value == TOKrparen ||
token.value == TOKshared && peek(&token)->value == TOKrparen ||
token.value == TOKwild && peek(&token)->value == TOKrparen ||
Expand All @@ -6220,11 +6191,6 @@ Expression *Parser::parsePrimaryExp()
token.value == TOKreturn))
{
tok2 = token.value;
if (token.value == TOKinvariant)
{
error("use 'immutable' instead of 'invariant'");
tok2 = TOKimmutable;
}
nextToken();
}
else
Expand Down Expand Up @@ -6632,12 +6598,9 @@ Expression *Parser::parseUnaryExp()
nextToken();
continue;

case TOKinvariant:
case TOKimmutable:
if (peekNext() == TOKlparen)
break;
if (token.value == TOKinvariant)
error("use 'immutable' instead of 'invariant'");
m |= MODimmutable;
nextToken();
continue;
Expand Down Expand Up @@ -6681,7 +6644,6 @@ Expression *Parser::parseUnaryExp()
case TOKwild:
case TOKshared:
case TOKconst:
case TOKinvariant:
case TOKimmutable: // immutable(type)(arguments) / immutable(type).init
{
StorageClass stc = parseTypeCtor();
Expand All @@ -6692,7 +6654,8 @@ Expression *Parser::parseUnaryExp()
{
nextToken();
if (token.value != TOKidentifier)
{ error("Identifier expected following (type).");
{
error("Identifier expected following (type).");
return NULL;
}
e = typeDotIdExp(loc, t, token.ident);
Expand Down
10 changes: 10 additions & 0 deletions test/compilable/compile1.d
Expand Up @@ -511,6 +511,16 @@ static if (is(object.ModuleInfo == class))
__traits(classInstanceSize, ModuleInfo));
}

/***************************************************/
// 10326

class C10326
{
int val;
invariant { assert(val == 0); }
invariant() { assert(val == 0); }
}

/***************************************************/
// 11554

Expand Down

0 comments on commit 6f08c33

Please sign in to comment.