Skip to content

Commit

Permalink
fix Issue 2091 - D2 final cannot be applied to variable
Browse files Browse the repository at this point in the history
D2 has `const` ro represent readonly data, therefore the error and suggestion
"perhaps you meant const?" is normally legitimate.
But, if the `final` attribute comes from a label or block style syntax, it's too
restrict against class member layout.

To lift the limitation, display the error only when `final` is *directly* applied on a variable.
Use same method to `synchrionized`, `abstract`, and `override`.
  • Loading branch information
9rnsr committed Jun 7, 2015
1 parent 6b64a46 commit 397752b
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 23 deletions.
33 changes: 14 additions & 19 deletions src/declaration.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "statement.h"
#include "ctfe.h"
#include "target.h"
#include "hdrgen.h"

/************************************
* Check to see the aggregate type is nested and its context pointer is
Expand Down Expand Up @@ -800,9 +801,10 @@ void VarDeclaration::semantic(Scope *sc)
scope = NULL;
}

/* Pick up storage classes from context, but skip synchronized
/* Pick up storage classes from context, but except synchronized,
* override, abstract, and final.
*/
storage_class |= (sc->stc & ~STCsynchronized);
storage_class |= (sc->stc & ~(STCsynchronized | STCoverride | STCabstract | STCfinal));
if (storage_class & STCextern && init)
error("extern symbols cannot have initializers");

Expand Down Expand Up @@ -1107,24 +1109,17 @@ void VarDeclaration::semantic(Scope *sc)
else if (type->isWild())
storage_class |= STCwild;

if (storage_class & (STCmanifest | STCstatic | STCgshared))
if (StorageClass stc = storage_class & (STCsynchronized | STCoverride | STCabstract | STCfinal))
{
}
else if (isSynchronized())
{
error("variable %s cannot be synchronized", toChars());
}
else if (isOverride())
{
error("override cannot be applied to variable");
}
else if (isAbstract())
{
error("abstract cannot be applied to variable");
}
else if (storage_class & STCfinal)
{
error("final cannot be applied to variable, perhaps you meant const?");
if (stc == STCfinal)
error("cannot be final, perhaps you meant const?");
else
{
OutBuffer buf;
stcToBuffer(&buf, stc);
error("cannot be %s", buf.peekString());
}
storage_class &= ~stc; // strip off
}

if (storage_class & (STCstatic | STCextern | STCmanifest | STCtemplateparameter | STCtls | STCgshared | STCctfe))
Expand Down
2 changes: 1 addition & 1 deletion test/fail_compilation/fail170.d
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail170.d(8): Error: variable fail170.foo.x final cannot be applied to variable, perhaps you meant const?
fail_compilation/fail170.d(8): Error: variable fail170.foo.x cannot be final, perhaps you meant const?
---
*/

Expand Down
2 changes: 1 addition & 1 deletion test/fail_compilation/fail179.d
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail179.d(11): Error: variable fail179.main.px final cannot be applied to variable, perhaps you meant const?
fail_compilation/fail179.d(11): Error: variable fail179.main.px cannot be final, perhaps you meant const?
---
*/

Expand Down
4 changes: 2 additions & 2 deletions test/fail_compilation/fail180.d
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ fail_compilation/fail180.d(23): Error: cannot modify const expression this.x
fail_compilation/fail180.d(24): Error: cannot modify const expression this.x
fail_compilation/fail180.d(38): Error: cannot modify const expression this.x
fail_compilation/fail180.d(39): Error: cannot modify const expression this.x
fail_compilation/fail180.d(50): Error: variable fail180.main.t final cannot be applied to variable, perhaps you meant const?
fail_compilation/fail180.d(62): Error: variable fail180.test.d final cannot be applied to variable, perhaps you meant const?
fail_compilation/fail180.d(50): Error: variable fail180.main.t cannot be final, perhaps you meant const?
fail_compilation/fail180.d(62): Error: variable fail180.test.d cannot be final, perhaps you meant const?
---
*/

Expand Down
34 changes: 34 additions & 0 deletions test/fail_compilation/failattr.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// REQUIRED_ARGS: -o-

/*
TEST_OUTPUT:
---
fail_compilation/failattr.d(16): Error: variable failattr.C2901.v1 cannot be synchronized
fail_compilation/failattr.d(17): Error: variable failattr.C2901.v2 cannot be override
fail_compilation/failattr.d(18): Error: variable failattr.C2901.v3 cannot be abstract
fail_compilation/failattr.d(19): Error: variable failattr.C2901.v4 cannot be final, perhaps you meant const?
fail_compilation/failattr.d(31): Error: variable failattr.C2901.v13 cannot be final abstract synchronized override
fail_compilation/failattr.d(33): Error: variable failattr.C2901.v14 cannot be final, perhaps you meant const?
---
*/
class C2901
{
synchronized int v1; // error
override int v2; // error
abstract int v3; // error
final int v4; // error

synchronized { int v5; } // no error
override { int v6; } // no error
abstract { int v7; } // no error
final { int v8; } // no error

synchronized: int v9; // no error
override: int v10; // no error
abstract: int v11; // no error
final: int v12; // no error

synchronized override abstract final int v13; // one line error

static final int v14; // error, even if static is applied at the same time
}

0 comments on commit 397752b

Please sign in to comment.