Showing with 177 additions and 53 deletions.
  1. +0 −2 src/aggregate.h
  2. +4 −8 src/dsymbol.c
  3. +0 −1 src/dsymbol.h
  4. +15 −6 src/expression.c
  5. +12 −1 src/mtype.c
  6. +9 −23 src/struct.c
  7. +36 −12 src/template.c
  8. +76 −0 test/fail_compilation/diag14875.d
  9. +25 −0 test/fail_compilation/diag14876.d
2 changes: 0 additions & 2 deletions src/aggregate.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ class AggregateDeclaration : public ScopeDsymbol
Sizeok sizeok; // set when structsize contains valid data
Dsymbol *deferred; // any deferred semantic2() or semantic3() symbol
bool isdeprecated; // true if deprecated
bool mutedeprecation; // true while analysing RTInfo to avoid deprecation message

Dsymbol *enclosing; /* !=NULL if is nested
* pointing to the dsymbol that directly enclosing it.
Expand Down Expand Up @@ -122,7 +121,6 @@ class AggregateDeclaration : public ScopeDsymbol
int firstFieldInUnion(int indx); // first field in union that includes indx
int numFieldsInUnion(int firstIndex); // #fields in union starting at index
bool isDeprecated(); // is aggregate deprecated?
bool muteDeprecationMessage(); // disable deprecation message on Dsymbol?
bool isNested();
void makeNested();
bool isExport();
Expand Down
12 changes: 4 additions & 8 deletions src/dsymbol.c
Original file line number Diff line number Diff line change
Expand Up @@ -644,11 +644,6 @@ bool Dsymbol::isDeprecated()
return false;
}

bool Dsymbol::muteDeprecationMessage()
{
return false;
}

bool Dsymbol::isOverloadable()
{
return false;
Expand Down Expand Up @@ -745,11 +740,12 @@ void Dsymbol::deprecation(const char *format, ...)

void Dsymbol::checkDeprecated(Loc loc, Scope *sc)
{
if (global.params.useDeprecated != 1 && isDeprecated() && !muteDeprecationMessage())
if (global.params.useDeprecated != 1 && isDeprecated())
{
// Don't complain if we're inside a deprecated symbol's scope
for (Dsymbol *sp = sc->parent; sp; sp = sp->parent)
{ if (sp->isDeprecated())
{
if (sp->isDeprecated())
goto L1;
}

Expand All @@ -763,7 +759,7 @@ void Dsymbol::checkDeprecated(Loc loc, Scope *sc)
goto L1;
}

char *message = NULL;
const char *message = NULL;
for (Dsymbol *p = this; p; p = p->parent)
{
message = p->depmsg;
Expand Down
1 change: 0 additions & 1 deletion src/dsymbol.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,6 @@ class Dsymbol : public RootObject
virtual bool isExport(); // is Dsymbol exported?
virtual bool isImportedSymbol(); // is Dsymbol imported?
virtual bool isDeprecated(); // is Dsymbol deprecated?
virtual bool muteDeprecationMessage(); // disable deprecation message on Dsymbol?
virtual bool isOverloadable();
virtual bool hasOverloads();
virtual LabelDsymbol *isLabel(); // is this a LabelDsymbol?
Expand Down
21 changes: 15 additions & 6 deletions src/expression.c
Original file line number Diff line number Diff line change
Expand Up @@ -3341,13 +3341,22 @@ Expression *DsymbolExp::semantic(Scope *sc)

//printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars());
//printf("s = '%s', s->kind = '%s'\n", s->toChars(), s->kind());
if (!s->isFuncDeclaration()) // functions are checked after overloading
checkDeprecated(sc, s);
Dsymbol *olds = s;
s = s->toAlias();
//printf("s = '%s', s->kind = '%s', s->needThis() = %p\n", s->toChars(), s->kind(), s->needThis());
if (s != olds && !s->isFuncDeclaration())
checkDeprecated(sc, s);
Declaration *d = s->isDeclaration();
if (d && (d->storage_class & STCtemplateparameter))
{
s = s->toAlias();
}
else
{
if (!s->isFuncDeclaration()) // functions are checked after overloading
checkDeprecated(sc, s);
s = s->toAlias();
//printf("s = '%s', s->kind = '%s', s->needThis() = %p\n", s->toChars(), s->kind(), s->needThis());
if (s != olds && !s->isFuncDeclaration())
checkDeprecated(sc, s);
}


if (VarDeclaration *v = s->isVarDeclaration())
{
Expand Down
13 changes: 12 additions & 1 deletion src/mtype.c
Original file line number Diff line number Diff line change
Expand Up @@ -3980,6 +3980,8 @@ void TypeSArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol
}
else
{
if ((*pt)->ty != Terror)
next = *pt; // prevent re-running semantic() on 'next'
Ldefault:
Type::resolve(loc, sc, pe, pt, ps, intypeid);
}
Expand Down Expand Up @@ -4381,6 +4383,8 @@ void TypeDArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol
}
else
{
if ((*pt)->ty != Terror)
next = *pt; // prevent re-running semantic() on 'next'
Ldefault:
Type::resolve(loc, sc, pe, pt, ps, intypeid);
}
Expand Down Expand Up @@ -6435,7 +6439,12 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc,
if (s)
{
//printf("\t1: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind());
s->checkDeprecated(loc, sc); // check for deprecated aliases
Declaration *d = s->isDeclaration();
if (d && (d->storage_class & STCtemplateparameter))
s = s->toAlias();
else
s->checkDeprecated(loc, sc); // check for deprecated aliases

s = s->toAlias();
//printf("\t2: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind());
for (size_t i = 0; i < idents.dim; i++)
Expand Down Expand Up @@ -8929,6 +8938,8 @@ void TypeSlice::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol
}
else
{
if ((*pt)->ty != Terror)
next = *pt; // prevent re-running semantic() on 'next'
Ldefault:
Type::resolve(loc, sc, pe, pt, ps, intypeid);
}
Expand Down
32 changes: 9 additions & 23 deletions src/struct.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,6 @@ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
sizeok = SIZEOKnone; // size not determined yet
deferred = NULL;
isdeprecated = false;
mutedeprecation = false;
inv = NULL;
aggNew = NULL;
aggDelete = NULL;
Expand Down Expand Up @@ -243,35 +242,27 @@ void AggregateDeclaration::semantic3(Scope *sc)
(!isDeprecated() || global.params.useDeprecated) &&
(type && type->ty != Terror))
{
// we do not want to report deprecated uses of this type during RTInfo
// generation, so we disable reporting deprecation temporarily
// WARNING: Muting messages during analysis of RTInfo might silently instantiate
// templates that use (other) deprecated types. If these template instances
// are used in other parts of the program later, they will be reused without
// ever producing the deprecation message. The implementation here restricts
// muting to the types that RTInfo is currently generated for.
bool wasmuted = mutedeprecation;
mutedeprecation = true;

// Evaluate: RTinfo!type
Objects *tiargs = new Objects();
tiargs->push(type);
TemplateInstance *ti = new TemplateInstance(loc, Type::rtinfo, tiargs);
ti->semantic(sc);
ti->semantic2(sc);
ti->semantic3(sc);
Dsymbol *s = ti->toAlias();
Expression *e = new DsymbolExp(Loc(), s, 0);

Scope *sc3 = ti->tempdecl->scope->startCTFE();
sc3->tinst = sc->tinst;
sc3->minst = sc->minst;
if (isDeprecated())
sc3->stc |= STCdeprecated;

ti->semantic(sc3);
ti->semantic2(sc3);
ti->semantic3(sc3);
Expression *e = new DsymbolExp(Loc(), ti->toAlias(), 0);
e = e->semantic(sc3);

sc3->endCTFE();

e = e->ctfeInterpret();
getRTInfo = e;

mutedeprecation = wasmuted;
}

if (sd)
Expand Down Expand Up @@ -413,11 +404,6 @@ bool AggregateDeclaration::isDeprecated()
return isdeprecated;
}

bool AggregateDeclaration::muteDeprecationMessage()
{
return mutedeprecation;
}

bool AggregateDeclaration::isExport()
{
return protection.kind == PROTexport;
Expand Down
48 changes: 36 additions & 12 deletions src/template.c
Original file line number Diff line number Diff line change
Expand Up @@ -2029,16 +2029,16 @@ RootObject *TemplateDeclaration::declareParameter(Scope *sc, TemplateParameter *
{
//printf("TemplateDeclaration::declareParameter('%s', o = %p)\n", tp->ident->toChars(), o);

Type *targ = isType(o);
Type *ta = isType(o);
Expression *ea = isExpression(o);
Dsymbol *sa = isDsymbol(o);
Tuple *va = isTuple(o);

Dsymbol *s;
Declaration *d;
VarDeclaration *v = NULL;

if (ea && ea->op == TOKtype)
targ = ea->type;
ta = ea->type;
else if (ea && ea->op == TOKimport)
sa = ((ScopeExp *)ea)->sds;
else if (ea && (ea->op == TOKthis || ea->op == TOKsuper))
Expand All @@ -2051,15 +2051,15 @@ RootObject *TemplateDeclaration::declareParameter(Scope *sc, TemplateParameter *
sa = ((FuncExp *)ea)->fd;
}

if (targ)
if (ta)
{
//printf("type %s\n", targ->toChars());
s = new AliasDeclaration(Loc(), tp->ident, targ);
//printf("type %s\n", ta->toChars());
d = new AliasDeclaration(Loc(), tp->ident, ta);
}
else if (sa)
{
//printf("Alias %s %s;\n", sa->ident->toChars(), tp->ident->toChars());
s = new AliasDeclaration(Loc(), tp->ident, sa);
d = new AliasDeclaration(Loc(), tp->ident, sa);
}
else if (ea)
{
Expand All @@ -2071,12 +2071,12 @@ RootObject *TemplateDeclaration::declareParameter(Scope *sc, TemplateParameter *

v = new VarDeclaration(loc, t, tp->ident, init);
v->storage_class = STCmanifest | STCtemplateparameter;
s = v;
d = v;
}
else if (va)
{
//printf("\ttuple\n");
s = new TupleDeclaration(loc, tp->ident, &va->objects);
d = new TupleDeclaration(loc, tp->ident, &va->objects);
}
else
{
Expand All @@ -2085,13 +2085,37 @@ RootObject *TemplateDeclaration::declareParameter(Scope *sc, TemplateParameter *
#endif
assert(0);
}
if (!sc->insert(s))

d->storage_class |= STCtemplateparameter;
if (ta)
{
Type *t = ta;
// consistent with Type::checkDeprecated()
while (t->ty != Tenum)
{
if (!t->nextOf()) break;
t = ((TypeNext *)t)->next;
}
if (Dsymbol *s = t->toDsymbol(NULL))
{
if (s->isDeprecated())
d->storage_class |= STCdeprecated;
}
}
else if (sa)
{
if (sa->isDeprecated())
d->storage_class |= STCdeprecated;
}

if (!sc->insert(d))
error("declaration %s is already defined", tp->ident->toChars());
s->semantic(sc);
d->semantic(sc);

/* So the caller's o gets updated with the result of semantic() being run on o
*/
if (v)
return (RootObject *)v->init->toExpression();
o = v->init->toExpression();
return o;
}

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

deprecated class Dep { }
deprecated immutable int depVar = 10;

/*
TEST_OUTPUT:
---
fail_compilation/diag14875.d(16): Deprecation: class diag14875.Dep is deprecated
1: Dep
2: Dep
3: Dep
---
*/

alias X = Foo!Dep; // deprecation

template Foo(T)
{
pragma(msg, "1: ", T); // no message
enum Foo = cast(void*)Bar!T;
}
template Bar(T)
{
pragma(msg, "2: ", T); // no message
enum Bar = &Baz!T;
}
template Baz(T)
{
pragma(msg, "3: ", T); // no message
immutable Baz = 1234;
}

// ---

/*
TEST_OUTPUT:
---
fail_compilation/diag14875.d(47): Deprecation: class diag14875.Dep is deprecated
fail_compilation/diag14875.d(51): Deprecation: variable diag14875.depVar is deprecated
4: Dep
fail_compilation/diag14875.d(58): Deprecation: variable diag14875.depVar is deprecated
fail_compilation/diag14875.d(59): Deprecation: variable diag14875.Vaz!(Dep).Vaz is deprecated
---
*/

alias Y = Voo!Dep; // deprecation

template Voo(T)
{
enum n = depVar; // deprecation
struct A { alias B = T; } // no message
pragma(msg, "4: ", A.B); // B is not deprecated
enum Voo = cast(void*)Var!T;
}
template Var(T)
{
enum n = depVar; // deprecation
enum Var = &Vaz!T; // deprecation
}
deprecated template Vaz(T)
{
enum n = depVar; // no message
immutable Vaz = 1234;
}

/*
TEST_OUTPUT:
---
fail_compilation/diag14875.d(75): Error: static assert (0) is false
---
*/
void main()
{
static assert(0);
}
25 changes: 25 additions & 0 deletions test/fail_compilation/diag14876.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
TEST_OUTPUT:
---
fail_compilation/diag14876.d(17): Deprecation: class diag14876.Dep is deprecated
fail_compilation/diag14876.d(18): Deprecation: class diag14876.Dep is deprecated
fail_compilation/diag14876.d(19): Deprecation: class diag14876.Dep is deprecated
fail_compilation/diag14876.d(20): Deprecation: class diag14876.Dep is deprecated
fail_compilation/diag14876.d(21): Deprecation: class diag14876.Dep is deprecated
fail_compilation/diag14876.d(22): Deprecation: class diag14876.Dep is deprecated
fail_compilation/diag14876.d(23): Deprecation: class diag14876.Dep is deprecated
fail_compilation/diag14876.d(23): Error: can only slice tuple types, not diag14876.Dep
---
*/

deprecated class Dep { class Mem {} }

alias X1 = Foo!(Dep[]);
alias X2 = Foo!(Dep[1]);
alias X3 = Foo!(Dep[int]);
alias X4 = Foo!(int[Dep]);
alias X5 = Foo!(Dep*);
alias X6 = Foo!(Dep.Mem);
alias X7 = Foo!(Dep[3..4]);

template Foo(T) {}