Skip to content

Commit

Permalink
Merge pull request #5302 from Geod24/fix-12954
Browse files Browse the repository at this point in the history
Fix issue 12954 - Deprecated only works with string literals
  • Loading branch information
9rnsr committed Feb 10, 2016
2 parents c32ccb7 + f04dc8b commit 96b883a
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 16 deletions.
14 changes: 13 additions & 1 deletion changelog.dd
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,26 @@ $(BUGSTITLE Compiler Changes,
)

$(BUGSTITLE Language Changes,
$(LI $(RELATIVE_LINK2 extended-deprecated, Manifest constant can now be used for deprecation message.))
)

$(BUGSTITLE Compiler Changes,

)

$(BUGSTITLE Language Changes,

$(LI $(LNAME2 extended-deprecated, Manifest constant can now be used for deprecation message.)

Manifest constants (enum, static immutable) can now be used for deprecation message, as well as concatenated strings.
$(P Example:)
---
string generateMessage() { return "Some deprecation message"; }
enum DepMsg = generateMessage();

deprecated(DepMsg) class Foo {}
deprecated("Some long deprecation " ~ "message") class Bar {}
---
)
)

Macros:
Expand Down
49 changes: 40 additions & 9 deletions src/attrib.d
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ public:
return new StorageClassDeclaration(stc, Dsymbol.arraySyntaxCopy(decl));
}

override final Scope* newScope(Scope* sc)
override Scope* newScope(Scope* sc)
{
StorageClass scstc = sc.stc;
/* These sets of storage classes are mutually exclusive,
Expand Down Expand Up @@ -394,6 +394,7 @@ extern (C++) final class DeprecatedDeclaration : StorageClassDeclaration
{
public:
Expression msg;
const(char)* msgstr;

extern (D) this(Expression msg, Dsymbols* decl)
{
Expand All @@ -407,19 +408,49 @@ public:
return new DeprecatedDeclaration(msg.syntaxCopy(), Dsymbol.arraySyntaxCopy(decl));
}

override void setScope(Scope* sc)
/**
* Provides a new scope with `STCdeprecated` and `Scope.depdecl` set
*
* Calls `StorageClassDeclaration.newScope` (as it must be called or copied
* in any function overriding `newScope`), then set the `Scope`'s depdecl.
*
* Returns:
* Always a new scope, to use for this `DeprecatedDeclaration`'s members.
*/
override Scope* newScope(Scope* sc)
{
auto scx = super.newScope(sc);
// The enclosing scope is deprecated as well
if (scx == sc)
scx = sc.push();
scx.depdecl = this;
return scx;
}

/**
* Run the DeprecatedDeclaration's semantic2 phase then its members.
*
* The message set via a `DeprecatedDeclaration` can be either of:
* - a string literal
* - an enum
* - a static immutable
* So we need to call ctfe to resolve it.
* Afterward forwards to the members' semantic2.
*/
override void semantic2(Scope* sc)
{
assert(msg);
char* depmsg = null;
sc = sc.startCTFE();
msg = msg.semantic(sc);
msg = resolveProperties(sc, msg);
sc = sc.endCTFE();
msg = msg.ctfeInterpret();
StringExp se = msg.toStringExp();
if (se)
depmsg = se.toStringz();
msgstr = se.toStringz();
else
msg.error("string expected, not '%s'", msg.toChars());
Scope* scx = sc.push();
scx.depmsg = depmsg;
StorageClassDeclaration.setScope(scx);
scx.pop();
msg.error("compile time constant expected, not '%s'", msg.toChars());
super.semantic2(sc);
}

override void accept(Visitor v)
Expand Down
4 changes: 2 additions & 2 deletions src/dscope.d
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ struct Scope
int explicitProtection; // set if in an explicit protection attribute

StorageClass stc; // storage class
char* depmsg; // customized deprecation message
DeprecatedDeclaration depdecl; // customized deprecation message

uint flags;

Expand Down Expand Up @@ -602,7 +602,7 @@ struct Scope
this.protection = sc.protection;
this.explicitProtection = sc.explicitProtection;
this.stc = sc.stc;
this.depmsg = sc.depmsg;
this.depdecl = sc.depdecl;
this.inunion = sc.inunion;
this.nofree = sc.nofree;
this.noctor = sc.noctor;
Expand Down
8 changes: 4 additions & 4 deletions src/dsymbol.d
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ public:
bool errors; // this symbol failed to pass semantic()
PASS semanticRun;

char* depmsg; // customized deprecation message
DeprecatedDeclaration depdecl; // customized deprecation message
UserAttributeDeclaration userAttribDecl; // user defined attributes

// !=null means there's a ddoc unittest associated with this symbol
Expand Down Expand Up @@ -312,7 +312,7 @@ public:
const(char)* message = null;
for (Dsymbol p = this; p; p = p.parent)
{
message = p.depmsg;
message = p.depdecl ? p.depdecl.msgstr : null;
if (message)
break;
}
Expand Down Expand Up @@ -570,8 +570,8 @@ public:
if (!sc.nofree)
sc.setNoFree(); // may need it even after semantic() finishes
_scope = sc;
if (sc.depmsg)
depmsg = sc.depmsg;
if (sc.depdecl)
depdecl = sc.depdecl;
if (!userAttribDecl)
userAttribDecl = sc.userAttribDecl;
}
Expand Down
46 changes: 46 additions & 0 deletions test/fail_compilation/depmsg.d
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ fail_compilation/depmsg.d(24): Deprecation: enum depmsg.main.Inner.E is deprecat
fail_compilation/depmsg.d(26): Deprecation: alias depmsg.main.Inner.G is deprecated - With message!
fail_compilation/depmsg.d(27): Deprecation: variable depmsg.main.Inner.H is deprecated - With message!
fail_compilation/depmsg.d(28): Deprecation: class depmsg.main.Inner.I!().I is deprecated - With message!
fail_compilation/depmsg.d(58): Deprecation: function depmsg.main.Foo.bar1 is deprecated - [C] Use Foo.bar42 instead
fail_compilation/depmsg.d(59): Deprecation: function depmsg.main.Foo.bar2 is deprecated - [E] Use Foo.bar42 instead
fail_compilation/depmsg.d(60): Deprecation: function depmsg.main.Foo.bar3 is deprecated - [S] Use Foo.bar42 instead
fail_compilation/depmsg.d(61): Deprecation: function depmsg.main.Foo.bar4 is deprecated - [F] Use Foo.bar42 instead
fail_compilation/depmsg.d(62): Deprecation: variable depmsg.main.Foo.v2 is deprecated - Forward reference
fail_compilation/depmsg.d(68): Deprecation: class depmsg.main.Obsolete is deprecated
fail_compilation/depmsg.d(68): Deprecation: function depmsg.main.Obsolete.obs is deprecated - Function is obsolete
---
*/

Expand Down Expand Up @@ -48,4 +55,43 @@ void main()
auto h = H;
I!() i;
}

struct Foo {
enum DeprecatedReasonEnum = "[E] Use Foo.bar42 instead";
static const DeprecatedReasonStatic = "[S] Use Foo.bar42 instead";
static immutable DeprecatedReasonFunc = reason("Foo.bar42");

static string reason (string name)
{
return "[F] Use " ~ name ~ " instead";
}

deprecated("[C] Use " ~ `Foo.bar42 instead`)
void bar1 () {}

deprecated(DeprecatedReasonEnum)
void bar2 () {}

deprecated(DeprecatedReasonStatic)
void bar3 () {}

deprecated(DeprecatedReasonFunc)
void bar4 () {}

deprecated(Forward ~ Reference) int v2 = 2;
enum Forward = "Forward ", Reference = "reference";
}

Foo f;
f.bar1;
f.bar2;
f.bar3;
f.bar4;
assert(f.v2 == 2);

deprecated class Obsolete {
deprecated("Function is obsolete") void obs() {}
}

(new Obsolete).obs();
}

0 comments on commit 96b883a

Please sign in to comment.