Skip to content

Commit

Permalink
Issue 12954 - Deprecated only works with string literals
Browse files Browse the repository at this point in the history
  • Loading branch information
ibuclaw committed Jul 23, 2017
1 parent a96b39b commit 58b7f1c
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 21 deletions.
73 changes: 60 additions & 13 deletions src/attrib.c
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,7 @@ DeprecatedDeclaration::DeprecatedDeclaration(Expression *msg, Dsymbols *decl)
: StorageClassDeclaration(STCdeprecated, decl)
{
this->msg = msg;
this->msgstr = NULL;
}

Dsymbol *DeprecatedDeclaration::syntaxCopy(Dsymbol *s)
Expand All @@ -410,20 +411,67 @@ Dsymbol *DeprecatedDeclaration::syntaxCopy(Dsymbol *s)
return new DeprecatedDeclaration(msg->syntaxCopy(), Dsymbol::arraySyntaxCopy(decl));
}

/**
* 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.
*/
Scope *DeprecatedDeclaration::newScope(Scope *sc)
{
Scope *scx = StorageClassDeclaration::newScope(sc);
// The enclosing scope is deprecated as well
if (scx == sc)
scx = sc->push();
scx->depdecl = this;
return scx;
}

void DeprecatedDeclaration::setScope(Scope *sc)
{
assert(msg);
char *depmsg = NULL;
StringExp *se = msg->toStringExp();
if (se)
depmsg = (char *)se->string;
else
msg->error("string expected, not '%s'", msg->toChars());
//printf("DeprecatedDeclaration::setScope() %p\n", this);
if (decl)
Dsymbol::setScope(sc); // for forward reference
return AttribDeclaration::setScope(sc);
}

Scope *scx = sc->push();
scx->depmsg = depmsg;
StorageClassDeclaration::setScope(scx);
scx->pop();
/**
* 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.
*/
void DeprecatedDeclaration::semantic2(Scope *sc)
{
getMessage();
StorageClassDeclaration::semantic2(sc);
}

const char *DeprecatedDeclaration::getMessage()
{
if (Scope *sc = _scope)
{
_scope = NULL;

sc = sc->startCTFE();
msg = msg->semantic(sc);
msg = resolveProperties(sc, msg);
sc = sc->endCTFE();
msg = msg->ctfeInterpret();

if (StringExp *se = msg->toStringExp())
msgstr = (char *)se->string;
else
msg->error("compile time constant expected, not '%s'", msg->toChars());
}
return msgstr;
}

/********************************* LinkDeclaration ****************************/
Expand Down Expand Up @@ -1418,9 +1466,8 @@ Expressions *UserAttributeDeclaration::concat(Expressions *udas1, Expressions *u

Expressions *UserAttributeDeclaration::getAttributes()
{
if (_scope)
if (Scope *sc = _scope)
{
Scope *sc = _scope;
_scope = NULL;
arrayExpressionSemantic(atts, sc);
}
Expand Down
4 changes: 4 additions & 0 deletions src/attrib.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,14 @@ class DeprecatedDeclaration : public StorageClassDeclaration
{
public:
Expression *msg;
const char *msgstr;

DeprecatedDeclaration(Expression *msg, Dsymbols *decl);
Dsymbol *syntaxCopy(Dsymbol *s);
Scope *newScope(Scope *sc);
void setScope(Scope *sc);
void semantic2(Scope *sc);
const char *getMessage();
void accept(Visitor *v) { v->visit(this); }
};

Expand Down
10 changes: 5 additions & 5 deletions src/dsymbol.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Dsymbol::Dsymbol()
this->prettystring = NULL;
this->semanticRun = PASSinit;
this->errors = false;
this->depmsg = NULL;
this->depdecl = NULL;
this->userAttribDecl = NULL;
this->ddocUnittest = NULL;
}
Expand All @@ -69,7 +69,7 @@ Dsymbol::Dsymbol(Identifier *ident)
this->prettystring = NULL;
this->semanticRun = PASSinit;
this->errors = false;
this->depmsg = NULL;
this->depdecl = NULL;
this->userAttribDecl = NULL;
this->ddocUnittest = NULL;
}
Expand Down Expand Up @@ -418,8 +418,8 @@ void Dsymbol::setScope(Scope *sc)
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 Expand Up @@ -750,7 +750,7 @@ void Dsymbol::checkDeprecated(Loc loc, Scope *sc)
const char *message = NULL;
for (Dsymbol *p = this; p; p = p->parent)
{
message = p->depmsg;
message = p->depdecl ? p->depdecl->getMessage() : NULL;
if (message)
break;
}
Expand Down
2 changes: 1 addition & 1 deletion src/dsymbol.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ class Dsymbol : public RootObject
const utf8_t *prettystring;
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
UnitTestDeclaration *ddocUnittest; // !=NULL means there's a ddoc unittest associated with this symbol (only use this with ddoc)

Expand Down
2 changes: 1 addition & 1 deletion src/scope.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ Scope::Scope()
this->protection = Prot(PROTpublic);
this->explicitProtection = 0;
this->stc = 0;
this->depmsg = NULL;
this->depdecl = NULL;
this->inunion = 0;
this->nofree = 0;
this->noctor = 0;
Expand Down
3 changes: 2 additions & 1 deletion src/scope.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,8 @@ 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

unsigned flags;

Expand Down

0 comments on commit 58b7f1c

Please sign in to comment.