d: Support deprecated, @disable, and user-defined attributes on enum members

Reviewed-on: https://github.com/dlang/dmd/pull/12108

gcc/d/ChangeLog:

	* dmd/MERGE: Merge upstream dmd 9bba772fa.
This commit is contained in:
Iain Buclaw 2021-01-07 22:00:24 +01:00
parent acae7b21bc
commit 7a103daef7
31 changed files with 601 additions and 80 deletions

View File

@ -1,4 +1,4 @@
e598f69c0726ad1bf6b2e15e0b60d7cead737fad
9bba772fa67c6864e551bc87097402f691d947d4
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.

View File

@ -155,6 +155,51 @@ int Declaration::checkModify(Loc loc, Scope *sc, Type *, Expression *e1, int fla
return 1;
}
/**
* Issue an error if an attempt to call a disabled method is made
*
* If the declaration is disabled but inside a disabled function,
* returns `true` but do not issue an error message.
*
* Params:
* loc = Location information of the call
* sc = Scope in which the call occurs
* isAliasedDeclaration = if `true` searches overload set
*
* Returns:
* `true` if this `Declaration` is `@disable`d, `false` otherwise.
*/
bool Declaration::checkDisabled(Loc loc, Scope *sc, bool isAliasedDeclaration)
{
if (!(storage_class & STCdisable))
return false;
if (sc->func && (sc->func->storage_class & STCdisable))
return true;
Dsymbol *p = toParent();
if (p && isPostBlitDeclaration())
{
p->error(loc, "is not copyable because it is annotated with `@disable`");
return true;
}
// if the function is @disabled, maybe there
// is an overload in the overload set that isn't
if (isAliasedDeclaration)
{
FuncDeclaration *fd = isFuncDeclaration();
if (fd)
{
for (FuncDeclaration *ovl = fd; ovl; ovl = (FuncDeclaration *)ovl->overnext)
if (!(ovl->storage_class & STCdisable))
return false;
}
}
error(loc, "cannot be used because it is annotated with `@disable`");
return true;
}
Dsymbol *Declaration::search(const Loc &loc, Identifier *ident, int flags)
{
Dsymbol *s = Dsymbol::search(loc, ident, flags);

View File

@ -139,6 +139,7 @@ public:
void semantic(Scope *sc);
const char *kind() const;
d_uns64 size(Loc loc);
bool checkDisabled(Loc loc, Scope *sc, bool isAliasedDeclaration = false);
int checkModify(Loc loc, Scope *sc, Type *t, Expression *e1, int flag);
Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly);

View File

@ -13,6 +13,7 @@
#include "errors.h"
#include "enum.h"
#include "attrib.h"
#include "mtype.h"
#include "scope.h"
#include "id.h"
@ -504,6 +505,18 @@ EnumMember::EnumMember(Loc loc, Identifier *id, Expression *value, Type *origTyp
this->origType = origType;
}
EnumMember::EnumMember(Loc loc, Identifier *id, Expression *value, Type *memType,
StorageClass stc, UserAttributeDeclaration *uad, DeprecatedDeclaration *dd)
: VarDeclaration(loc, NULL, id ? id : Id::empty, new ExpInitializer(loc, value))
{
this->ed = NULL;
this->origValue = value;
this->origType = memType;
this->storage_class = stc;
this->userAttribDecl = uad;
this->depdecl = dd;
}
Expression *&EnumMember::value()
{
return ((ExpInitializer*)_init)->exp;
@ -536,6 +549,7 @@ void EnumMember::semantic(Scope *sc)
return;
}
assert(ed);
ed->semantic(sc);
if (ed->errors)
goto Lerrors;
@ -552,8 +566,16 @@ void EnumMember::semantic(Scope *sc)
protection = ed->isAnonymous() ? ed->protection : Prot(Prot::public_);
linkage = LINKd;
storage_class = STCmanifest;
userAttribDecl = ed->isAnonymous() ? ed->userAttribDecl : NULL;
storage_class |= STCmanifest;
// https://issues.dlang.org/show_bug.cgi?id=9701
if (ed->isAnonymous())
{
if (userAttribDecl)
userAttribDecl->userAttribDecl = ed->userAttribDecl;
else
userAttribDecl = ed->userAttribDecl;
}
// The first enum member is special
bool first = (this == (*ed->members)[0]);
@ -743,6 +765,14 @@ void EnumMember::semantic(Scope *sc)
Expression *EnumMember::getVarExp(Loc loc, Scope *sc)
{
semantic(sc);
if (errors)
return new ErrorExp();
checkDisabled(loc, sc);
if (depdecl && !depdecl->_scope)
depdecl->_scope = sc;
checkDeprecated(loc, sc);
if (errors)
return new ErrorExp();
Expression *e = new VarExp(loc, this);

View File

@ -760,7 +760,7 @@ void Dsymbol::deprecation(const char *format, ...)
va_end(ap);
}
void Dsymbol::checkDeprecated(Loc loc, Scope *sc)
bool Dsymbol::checkDeprecated(Loc loc, Scope *sc)
{
if (global.params.useDeprecated != DIAGNOSTICoff && isDeprecated())
{
@ -768,17 +768,17 @@ void Dsymbol::checkDeprecated(Loc loc, Scope *sc)
for (Dsymbol *sp = sc->parent; sp; sp = sp->parent)
{
if (sp->isDeprecated())
goto L1;
return false;
}
for (Scope *sc2 = sc; sc2; sc2 = sc2->enclosing)
{
if (sc2->scopesym && sc2->scopesym->isDeprecated())
goto L1;
return false;
// If inside a StorageClassDeclaration that is deprecated
if (sc2->stc & STCdeprecated)
goto L1;
return false;
}
const char *message = NULL;
@ -793,20 +793,11 @@ void Dsymbol::checkDeprecated(Loc loc, Scope *sc)
deprecation(loc, "is deprecated - %s", message);
else
deprecation(loc, "is deprecated");
return true;
}
L1:
Declaration *d = isDeclaration();
if (d && d->storage_class & STCdisable)
{
if (!(sc->func && sc->func->storage_class & STCdisable))
{
if (d->toParent() && d->isPostBlitDeclaration())
d->toParent()->error(loc, "is not copyable because it is annotated with @disable");
else
error(loc, "is not callable because it is annotated with @disable");
}
}
return false;
}
/**********************************

View File

@ -175,7 +175,7 @@ public:
void error(const char *format, ...);
void deprecation(Loc loc, const char *format, ...);
void deprecation(const char *format, ...);
void checkDeprecated(Loc loc, Scope *sc);
bool checkDeprecated(Loc loc, Scope *sc);
Module *getModule();
Module *getAccessModule();
Dsymbol *pastMixin();

View File

@ -85,6 +85,8 @@ public:
EnumDeclaration *ed;
EnumMember(Loc loc, Identifier *id, Expression *value, Type *origType);
EnumMember(Loc loc, Identifier *id, Expression *value, Type *memType,
StorageClass stc, UserAttributeDeclaration *uad, DeprecatedDeclaration *dd);
Dsymbol *syntaxCopy(Dsymbol *s);
const char *kind() const;
void semantic(Scope *sc);

View File

@ -2344,9 +2344,18 @@ bool Expression::checkArithmetic()
return checkValue();
}
void Expression::checkDeprecated(Scope *sc, Dsymbol *s)
bool Expression::checkDeprecated(Scope *sc, Dsymbol *s)
{
s->checkDeprecated(loc, sc);
return s->checkDeprecated(loc, sc);
}
bool Expression::checkDisabled(Scope *sc, Dsymbol *s)
{
if (Declaration *d = s->isDeclaration())
{
return d->checkDisabled(loc, sc);
}
return false;
}
/*********************************************
@ -2661,11 +2670,8 @@ bool Expression::checkPostblit(Scope *sc, Type *t)
StructDeclaration *sd = ((TypeStruct *)t)->sym;
if (sd->postblit)
{
if (sd->postblit->storage_class & STCdisable)
{
sd->error(loc, "is not copyable because it is annotated with @disable");
if (sd->postblit->checkDisabled(loc, sc))
return true;
}
//checkDeprecated(sc, sd->postblit); // necessary?
checkPurity(sc, sd->postblit);
checkSafety(sc, sd->postblit);
@ -3715,14 +3721,22 @@ Lagain:
else
{
if (!s->isFuncDeclaration()) // functions are checked after overloading
{
s->checkDeprecated(loc, sc);
if (d)
d->checkDisabled(loc, sc);
}
// Bugzilla 12023: if 's' is a tuple variable, the tuple is returned.
s = s->toAlias();
//printf("s = '%s', s->kind = '%s', s->needThis() = %p\n", s->toChars(), s->kind(), s->needThis());
if (s != olds && !s->isFuncDeclaration())
{
s->checkDeprecated(loc, sc);
if (d)
d->checkDisabled(loc, sc);
}
}
if (EnumMember *em = s->isEnumMember())

View File

@ -181,7 +181,8 @@ public:
bool checkNoBool();
bool checkIntegral();
bool checkArithmetic();
void checkDeprecated(Scope *sc, Dsymbol *s);
bool checkDeprecated(Scope *sc, Dsymbol *s);
bool checkDisabled(Scope *sc, Dsymbol *s);
bool checkPurity(Scope *sc, FuncDeclaration *f);
bool checkPurity(Scope *sc, VarDeclaration *v);
bool checkSafety(Scope *sc, FuncDeclaration *f);

View File

@ -1218,6 +1218,7 @@ public:
if (!f || f->errors)
return setError();
exp->checkDeprecated(sc, f);
exp->checkDisabled(sc, f);
exp->checkPurity(sc, f);
exp->checkSafety(sc, f);
exp->checkNogc(sc, f);
@ -1246,6 +1247,7 @@ public:
if (!f || f->errors)
return setError();
exp->checkDeprecated(sc, f);
exp->checkDisabled(sc, f);
exp->checkPurity(sc, f);
exp->checkSafety(sc, f);
exp->checkNogc(sc, f);
@ -1313,6 +1315,7 @@ public:
if (!f || f->errors)
return setError();
exp->checkDeprecated(sc, f);
exp->checkDisabled(sc, f);
exp->checkPurity(sc, f);
exp->checkSafety(sc, f);
exp->checkNogc(sc, f);
@ -1341,6 +1344,7 @@ public:
if (!f || f->errors)
return setError();
exp->checkDeprecated(sc, f);
exp->checkDisabled(sc, f);
exp->checkPurity(sc, f);
exp->checkSafety(sc, f);
exp->checkNogc(sc, f);
@ -3214,6 +3218,7 @@ public:
}
exp->checkDeprecated(sc, exp->f);
exp->checkDisabled(sc, exp->f);
exp->checkPurity(sc, exp->f);
exp->checkSafety(sc, exp->f);
exp->checkNogc(sc, exp->f);
@ -3307,6 +3312,7 @@ public:
if (!exp->f || exp->f->errors)
return setError();
exp->checkDeprecated(sc, exp->f);
exp->checkDisabled(sc, exp->f);
exp->checkPurity(sc, exp->f);
exp->checkSafety(sc, exp->f);
exp->checkNogc(sc, exp->f);
@ -3345,6 +3351,7 @@ public:
if (!exp->f || exp->f->errors)
return setError();
exp->checkDeprecated(sc, exp->f);
exp->checkDisabled(sc, exp->f);
exp->checkPurity(sc, exp->f);
exp->checkSafety(sc, exp->f);
exp->checkNogc(sc, exp->f);
@ -3587,6 +3594,7 @@ public:
}
exp->checkDeprecated(sc, exp->f);
exp->checkDisabled(sc, exp->f);
exp->checkPurity(sc, exp->f);
exp->checkSafety(sc, exp->f);
exp->checkNogc(sc, exp->f);
@ -8381,6 +8389,7 @@ Expression *semanticY(DotIdExp *exp, Scope *sc, int flag)
s = s->toAlias();
exp->checkDeprecated(sc, s);
exp->checkDisabled(sc, s);
EnumMember *em = s->isEnumMember();
if (em)

View File

@ -1762,10 +1762,10 @@ bool Type::needsNested()
void Type::checkDeprecated(Loc loc, Scope *sc)
{
Dsymbol *s = toDsymbol(sc);
if (s)
if (Dsymbol *s = toDsymbol(sc))
{
s->checkDeprecated(loc, sc);
}
}
@ -6956,7 +6956,12 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc,
if (d && (d->storage_class & STCtemplateparameter))
s = s->toAlias();
else
s->checkDeprecated(loc, sc); // check for deprecated aliases
{
// check for deprecated aliases
s->checkDeprecated(loc, sc);
if (d)
d->checkDisabled(loc, sc, true);
}
s = s->toAlias();
//printf("\t2: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind());
@ -8045,7 +8050,11 @@ L1:
// return noMember(sc, e, ident, flag);
}
if (!s->isFuncDeclaration()) // because of overloading
{
s->checkDeprecated(e->loc, sc);
if (Declaration *d = s->isDeclaration())
d->checkDisabled(e->loc, sc);
}
s = s->toAlias();
EnumMember *em = s->isEnumMember();
@ -8749,7 +8758,11 @@ L1:
// return noMember(sc, e, ident, flag);
}
if (!s->isFuncDeclaration()) // because of overloading
{
s->checkDeprecated(e->loc, sc);
if (Declaration *d = s->isDeclaration())
d->checkDisabled(e->loc, sc);
}
s = s->toAlias();
EnumMember *em = s->isEnumMember();

View File

@ -216,6 +216,24 @@ Lerr:
return new Dsymbols();
}
static StorageClass parseDeprecatedAttribute(Parser *p, Expression **msg)
{
if (p->peekNext() != TOKlparen)
return STCdeprecated;
p->nextToken();
p->check(TOKlparen);
Expression *e = p->parseAssignExp();
p->check(TOKrparen);
if (*msg)
{
p->error("conflicting storage class `deprecated(%s)` and `deprecated(%s)`",
(*msg)->toChars(), e->toChars());
}
*msg = e;
return STCundefined;
}
struct PrefixAttributes
{
StorageClass storageClass;
@ -626,21 +644,12 @@ Dsymbols *Parser::parseDeclDefs(int once, Dsymbol **pLastDecl, PrefixAttributes
case TOKdeprecated:
{
if (peek(&token)->value != TOKlparen)
Expression *e = NULL;
if (StorageClass _stc = parseDeprecatedAttribute(this, &pAttrs->depmsg))
{
stc = STCdeprecated;
stc = _stc;
goto Lstc;
}
nextToken();
check(TOKlparen);
Expression *e = parseAssignExp();
check(TOKrparen);
if (pAttrs->depmsg)
{
error("conflicting storage class 'deprecated(%s)' and 'deprecated(%s)'",
pAttrs->depmsg->toChars(), e->toChars());
}
pAttrs->depmsg = e;
a = parseBlock(pLastDecl, pAttrs);
if (pAttrs->depmsg)
{
@ -2185,7 +2194,7 @@ EnumDeclaration *Parser::parseEnum()
Type *memtype;
Loc loc = token.loc;
//printf("Parser::parseEnum()\n");
// printf("Parser::parseEnum()\n");
nextToken();
if (token.value == TOKidentifier)
{
@ -2213,36 +2222,96 @@ EnumDeclaration *Parser::parseEnum()
nextToken();
else if (token.value == TOKlcurly)
{
bool isAnonymousEnum = !id;
//printf("enum definition\n");
e->members = new Dsymbols();
nextToken();
const utf8_t *comment = token.blockComment;
while (token.value != TOKrcurly)
{
/* Can take the following forms:
/* Can take the following forms...
* 1. ident
* 2. ident = value
* 3. type ident = value
* ... prefixed by valid attributes
*/
loc = token.loc;
Type *type = NULL;
Identifier *ident = NULL;
Token *tp = peek(&token);
if (token.value == TOKidentifier &&
(tp->value == TOKassign || tp->value == TOKcomma || tp->value == TOKrcurly))
Expressions *udas = NULL;
StorageClass stc = STCundefined;
Expression *deprecationMessage = NULL;
while (token.value != TOKrcurly &&
token.value != TOKcomma &&
token.value != TOKassign)
{
ident = token.ident;
type = NULL;
nextToken();
switch (token.value)
{
case TOKat:
if (StorageClass _stc = parseAttribute(&udas))
{
if (_stc == STCdisable)
stc |= _stc;
else
{
OutBuffer buf;
stcToBuffer(&buf, _stc);
error("`%s` is not a valid attribute for enum members", buf.peekChars());
}
nextToken();
}
break;
case TOKdeprecated:
if (StorageClass _stc = parseDeprecatedAttribute(this, &deprecationMessage))
{
stc |= _stc;
nextToken();
}
break;
case TOKidentifier:
{
Token *tp = peek(&token);
if (tp->value == TOKassign || tp->value == TOKcomma || tp->value == TOKrcurly)
{
ident = token.ident;
type = NULL;
nextToken();
}
else
{
goto Ldefault;
}
break;
}
default:
Ldefault:
if (isAnonymousEnum)
{
type = parseType(&ident, NULL);
if (type == Type::terror)
{
type = NULL;
nextToken();
}
}
else
{
error("`%s` is not a valid attribute for enum members", token.toChars());
nextToken();
}
break;
}
}
else
if (type && type != Type::terror)
{
type = parseType(&ident, NULL);
if (!ident)
error("no identifier for declarator %s", type->toChars());
if (id || memtype)
if (!isAnonymousEnum)
error("type only allowed if anonymous enum and no enum type");
}
@ -2255,11 +2324,22 @@ EnumDeclaration *Parser::parseEnum()
else
{
value = NULL;
if (type)
if (type && type != Type::terror && isAnonymousEnum)
error("if type, there must be an initializer");
}
EnumMember *em = new EnumMember(loc, ident, value, type);
UserAttributeDeclaration *uad = NULL;
if (udas)
uad = new UserAttributeDeclaration(udas, NULL);
DeprecatedDeclaration *dd = NULL;
if (deprecationMessage)
{
dd = new DeprecatedDeclaration(deprecationMessage, NULL);
stc |= STCdeprecated;
}
EnumMember *em = new EnumMember(loc, ident, value, type, stc, uad, dd);
e->members->push(em);
if (token.value == TOKrcurly)

View File

@ -313,7 +313,6 @@ static Expression *isDsymX(TraitsExp *e, bool (*fp)(Dsymbol *s))
return True(e);
}
static bool isFuncDisabled(FuncDeclaration *f) { return f->isDisabled(); }
static bool isFuncAbstractFunction(FuncDeclaration *f) { return f->isAbstract(); }
static bool isFuncVirtualFunction(FuncDeclaration *f) { return f->isVirtual(); }
static bool isFuncVirtualMethod(FuncDeclaration *f) { return f->isVirtualMethod(); }
@ -337,6 +336,7 @@ static Expression *isFuncX(TraitsExp *e, bool (*fp)(FuncDeclaration *f))
return True(e);
}
static bool isDeclDisabled(Declaration *d) { return d->isDisabled(); }
static bool isDeclFuture(Declaration *d) { return d->isFuture(); }
static bool isDeclRef(Declaration *d) { return d->isRef(); }
static bool isDeclOut(Declaration *d) { return d->isOut(); }
@ -811,7 +811,7 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
if (dim != 1)
return dimError(e, 1, dim);
return isFuncX(e, &isFuncDisabled);
return isDeclX(e, &isDeclDisabled);
}
else if (e->ident == Id::isAbstractFunction)
{

View File

@ -0,0 +1,17 @@
// PERMUTE ARGS:
@disable void foo() {}
void foo(int) {}
alias g = foo;
// make sure the order of declaration
// doesn't change anything
void bar(int) {}
@disable void bar() {}
alias h = bar;
void main()
{
g(10);
h(10);
}

View File

@ -0,0 +1,58 @@
// https://issues.dlang.org/show_bug.cgi?id=9701
template AliasSeq(TList...)
{
alias AliasSeq = TList;
}
enum
{
uda4,
uda5,
uda6,
uda8,
uda9
}
enum Enum
{
value0,
@("uda1") value1,
@("uda2", "uda3", 42) value2,
@uda4 value3,
@uda5 @uda6 value4,
@("uda7") @uda8 value5,
@uda9 @("uda10") value6,
deprecated value7,
deprecated("message") value8,
}
@("uda0")
enum
{
value0,
@("uda1") value1,
@("uda2") @("uda3") value2,
@uda4 value3,
@uda5 @uda6 value4,
@("uda7") @uda8 value5,
@uda9 @("uda10") value6
}
static assert(__traits(getAttributes, Enum.value0).length == 0);
static assert(__traits(getAttributes, Enum.value1) == AliasSeq!("uda1"));
static assert(__traits(getAttributes, Enum.value2) == AliasSeq!("uda2", "uda3", 42));
static assert(__traits(getAttributes, Enum.value3) == AliasSeq!(uda4));
static assert(__traits(getAttributes, Enum.value4) == AliasSeq!(uda5, uda6));
static assert(__traits(getAttributes, Enum.value5) == AliasSeq!("uda7", uda8));
static assert(__traits(getAttributes, Enum.value6) == AliasSeq!(uda9, "uda10"));
static assert(__traits(isDeprecated, Enum.value7));
static assert(__traits(isDeprecated, Enum.value8));
static assert(__traits(getAttributes, value0) == AliasSeq!("uda0"));
static assert(__traits(getAttributes, value1) == AliasSeq!("uda0", "uda1"));
static assert(__traits(getAttributes, value2) == AliasSeq!("uda0", "uda2", "uda3"));
static assert(__traits(getAttributes, value3) == AliasSeq!("uda0", uda4));
static assert(__traits(getAttributes, value4) == AliasSeq!("uda0", uda5, uda6));
static assert(__traits(getAttributes, value5) == AliasSeq!("uda0", "uda7", uda8));
static assert(__traits(getAttributes, value6) == AliasSeq!("uda0", uda9, "uda10"));

View File

@ -0,0 +1,43 @@
module vcg;
// REQUIRED_ARGS: -vcg-ast -o-
// PERMUTE_ARGS:
template Seq(A...)
{
alias Seq = A;
}
auto a = Seq!(1,2,3);
template R(T)
{
struct _R { T elem; }
}
typeof(R!int._R.elem) x;
static foreach(enum i; 0..3)
{
mixin("int a" ~ i.stringof ~ " = 1;");
}
void foo()
{
static foreach(enum i; 0..3)
{
mixin("int a" ~ i.stringof ~ " = 1;");
}
}
class C
{
invariant {}
invariant (true);
int foo() in{} out{} out(r){} in(true) out(; true) out(r; true)
{
return 2;
}
}

View File

@ -1,15 +1,16 @@
/*
TEST_OUTPUT:
---
fail_compilation/disable.d(50): Error: function disable.DisabledOpAssign.opAssign is not callable because it is annotated with @disable
fail_compilation/disable.d(53): Error: function disable.DisabledPostblit.opAssign is not callable because it is annotated with @disable
fail_compilation/disable.d(56): Error: function disable.HasDtor.opAssign is not callable because it is annotated with @disable
fail_compilation/disable.d(60): Error: generated function disable.Nested!(DisabledOpAssign).Nested.opAssign is not callable because it is annotated with @disable
fail_compilation/disable.d(63): Error: generated function disable.Nested!(DisabledPostblit).Nested.opAssign is not callable because it is annotated with @disable
fail_compilation/disable.d(66): Error: generated function disable.Nested!(HasDtor).Nested.opAssign is not callable because it is annotated with @disable
fail_compilation/disable.d(70): Error: generated function disable.NestedDtor!(DisabledOpAssign).NestedDtor.opAssign is not callable because it is annotated with @disable
fail_compilation/disable.d(73): Error: generated function disable.NestedDtor!(DisabledPostblit).NestedDtor.opAssign is not callable because it is annotated with @disable
fail_compilation/disable.d(76): Error: generated function disable.NestedDtor!(HasDtor).NestedDtor.opAssign is not callable because it is annotated with @disable
fail_compilation/disable.d(56): Error: function `disable.DisabledOpAssign.opAssign` cannot be used because it is annotated with `@disable`
fail_compilation/disable.d(59): Error: function `disable.DisabledPostblit.opAssign` cannot be used because it is annotated with `@disable`
fail_compilation/disable.d(62): Error: function `disable.HasDtor.opAssign` cannot be used because it is annotated with `@disable`
fail_compilation/disable.d(66): Error: generated function `disable.Nested!(DisabledOpAssign).Nested.opAssign` cannot be used because it is annotated with `@disable`
fail_compilation/disable.d(69): Error: generated function `disable.Nested!(DisabledPostblit).Nested.opAssign` cannot be used because it is annotated with `@disable`
fail_compilation/disable.d(72): Error: generated function `disable.Nested!(HasDtor).Nested.opAssign` cannot be used because it is annotated with `@disable`
fail_compilation/disable.d(76): Error: generated function `disable.NestedDtor!(DisabledOpAssign).NestedDtor.opAssign` cannot be used because it is annotated with `@disable`
fail_compilation/disable.d(79): Error: generated function `disable.NestedDtor!(DisabledPostblit).NestedDtor.opAssign` cannot be used because it is annotated with `@disable`
fail_compilation/disable.d(82): Error: generated function `disable.NestedDtor!(HasDtor).NestedDtor.opAssign` cannot be used because it is annotated with `@disable`
fail_compilation/disable.d(84): Error: enum member `disable.Enum1.value` cannot be used because it is annotated with `@disable`
---
*/
struct DisabledOpAssign {
@ -44,6 +45,11 @@ struct NestedDtor (T)
~this() {}
}
enum Enum1
{
@disable value
}
void main ()
{
DisabledOpAssign o;
@ -74,4 +80,6 @@ void main ()
NestedDtor!(HasDtor) ndd;
ndd = NestedDtor!(HasDtor)();
auto v1 = Enum1.value;
}

View File

@ -43,12 +43,12 @@ void bar() pure @safe
/*
TEST_OUTPUT:
---
fail_compilation/fail10968.d(66): Error: struct fail10968.SD is not copyable because it is annotated with @disable
fail_compilation/fail10968.d(67): Error: struct fail10968.SD is not copyable because it is annotated with @disable
fail_compilation/fail10968.d(68): Error: struct fail10968.SD is not copyable because it is annotated with @disable
fail_compilation/fail10968.d(71): Error: struct fail10968.SD is not copyable because it is annotated with @disable
fail_compilation/fail10968.d(72): Error: struct fail10968.SD is not copyable because it is annotated with @disable
fail_compilation/fail10968.d(73): Error: struct fail10968.SD is not copyable because it is annotated with @disable
fail_compilation/fail10968.d(66): Error: struct fail10968.SD is not copyable because it is annotated with `@disable`
fail_compilation/fail10968.d(67): Error: struct fail10968.SD is not copyable because it is annotated with `@disable`
fail_compilation/fail10968.d(68): Error: struct fail10968.SD is not copyable because it is annotated with `@disable`
fail_compilation/fail10968.d(71): Error: struct fail10968.SD is not copyable because it is annotated with `@disable`
fail_compilation/fail10968.d(72): Error: struct fail10968.SD is not copyable because it is annotated with `@disable`
fail_compilation/fail10968.d(73): Error: struct fail10968.SD is not copyable because it is annotated with `@disable`
---
*/

View File

@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail11355.d(28): Error: struct fail11355.A is not copyable because it is annotated with @disable
fail_compilation/fail11355.d(28): Error: struct fail11355.A is not copyable because it is annotated with `@disable`
---
*/

View File

@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail15044.d(30): Error: generated function fail15044.V.opAssign is not callable because it is annotated with @disable
fail_compilation/fail15044.d(30): Error: generated function `fail15044.V.opAssign` cannot be used because it is annotated with `@disable`
---
*/

View File

@ -1,8 +1,8 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail341.d(26): Error: struct fail341.S is not copyable because it is annotated with @disable
fail_compilation/fail341.d(27): Error: function fail341.foo is not callable because it is annotated with @disable
fail_compilation/fail341.d(26): Error: struct fail341.S is not copyable because it is annotated with `@disable`
fail_compilation/fail341.d(27): Error: function `fail341.foo` cannot be used because it is annotated with `@disable`
---
*/

View File

@ -1,8 +1,8 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail9346.d(26): Error: struct fail9346.S is not copyable because it is annotated with @disable
fail_compilation/fail9346.d(27): Error: struct fail9346.S is not copyable because it is annotated with @disable
fail_compilation/fail9346.d(26): Error: struct fail9346.S is not copyable because it is annotated with `@disable`
fail_compilation/fail9346.d(27): Error: struct fail9346.S is not copyable because it is annotated with `@disable`
---
*/

View File

@ -0,0 +1,8 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail_contracts1.d(8): Error: `(identifier) { ... }` or `(identifier; expression)` following `out` expected, not `)`
---
*/
void foo() out()){}

View File

@ -0,0 +1,8 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail_contracts2.d(8): Error: missing `do { ... }` after `in` or `out`
---
*/
void foo()in{}{}

View File

@ -0,0 +1,14 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail_contracts3.d(13): Error: function `fail_contracts3.D.foo` cannot have an in contract when overridden function `fail_contracts3.C.foo` does not have an in contract
---
*/
class C {
void foo(){}
}
class D : C {
override void foo()in{}do{}
}

View File

@ -0,0 +1,8 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail_contracts4.d(8): Error: missing `do { ... }` for function literal
---
*/
enum x = delegate int()in(true) out(;true) out(r; true) in{} out(r){};

View File

@ -0,0 +1,15 @@
/*
TEST_OUTPUT:
---
fail_compilation/test17908a.d(10): Error: function `test17908a.foo` cannot be used because it is annotated with `@disable`
---
*/
@disable void foo();
@disable void foo(int) {}
alias g = foo;
void main()
{
g(10);
}

View File

@ -0,0 +1,14 @@
/*
TEST_OUTPUT:
---
fail_compilation/test17908b.d(13): Error: function `test17908b.foobar` cannot be used because it is annotated with `@disable`
---
*/
void foobar() {}
@disable void foobar(int) {}
alias i = foobar;
void main()
{
i(10);
}

View File

@ -0,0 +1,63 @@
/*
TEST_OUTPUT
---
fail_compilation/test9701.d(38): Error: `@safe` is not a valid attribute for enum members
fail_compilation/test9701.d(39): Error: `@system` is not a valid attribute for enum members
fail_compilation/test9701.d(40): Error: `@trusted` is not a valid attribute for enum members
fail_compilation/test9701.d(41): Error: `@nogc` is not a valid attribute for enum members
fail_compilation/test9701.d(42): Error: `pure` is not a valid attribute for enum members
fail_compilation/test9701.d(43): Error: `shared` is not a valid attribute for enum members
fail_compilation/test9701.d(44): Error: `inout` is not a valid attribute for enum members
fail_compilation/test9701.d(45): Error: `immutable` is not a valid attribute for enum members
fail_compilation/test9701.d(46): Error: `const` is not a valid attribute for enum members
fail_compilation/test9701.d(47): Error: `synchronized` is not a valid attribute for enum members
fail_compilation/test9701.d(48): Error: `scope` is not a valid attribute for enum members
fail_compilation/test9701.d(49): Error: `auto` is not a valid attribute for enum members
fail_compilation/test9701.d(50): Error: `ref` is not a valid attribute for enum members
fail_compilation/test9701.d(51): Error: `__gshared` is not a valid attribute for enum members
fail_compilation/test9701.d(52): Error: `final` is not a valid attribute for enum members
fail_compilation/test9701.d(53): Error: `extern` is not a valid attribute for enum members
fail_compilation/test9701.d(54): Error: `export` is not a valid attribute for enum members
fail_compilation/test9701.d(55): Error: `nothrow` is not a valid attribute for enum members
fail_compilation/test9701.d(56): Error: `public` is not a valid attribute for enum members
fail_compilation/test9701.d(57): Error: `private` is not a valid attribute for enum members
fail_compilation/test9701.d(58): Error: `package` is not a valid attribute for enum members
fail_compilation/test9701.d(59): Error: `static` is not a valid attribute for enum members
fail_compilation/test9701.d(60): Error: `static` is not a valid attribute for enum members
fail_compilation/test9701.d(61): Error: `static` is not a valid attribute for enum members
fail_compilation/test9701.d(62): Error: `static` is not a valid attribute for enum members
---
*/
// This test exists to verify that parsing of enum member attributes rejects invalid attributes
// https://issues.dlang.org/show_bug.cgi?id=9701
enum Enum
{
@safe safe,
@system system,
@trusted trusted,
@nogc nogc,
pure pure_,
shared shared_,
inout inout_,
immutable immutable_,
const const_,
synchronized synchronized_,
scope scope_,
auto auto_,
ref ref_,
__gshared __gshared_,
final final_,
extern extern_,
export export_,
nothrow nothrow_,
public public_,
private private_,
package package_,
static static1,
@("a") static static2,
static @("a") static3,
@("a") static @("b") static3,
}

View File

@ -0,0 +1,22 @@
/*
REQUIRED_ARGS: -de
TEST_OUTPUT
---
fail_compilation/test9701b.d(20): Deprecation: enum member `test9701b.Enum.e0` is deprecated
fail_compilation/test9701b.d(21): Deprecation: enum member `test9701b.Enum.e1` is deprecated - message
---
*/
// https://issues.dlang.org/show_bug.cgi?id=9701
enum Enum
{
deprecated e0,
deprecated("message") e1,
}
void main()
{
auto value = Enum.e0;
auto value2 = Enum.e1;
}

View File

@ -0,0 +1,57 @@
/*
TEST_OUTPUT:
---
fail_compilation/udaparams.d(31): Error: variadic parameter cannot have user-defined attributes
fail_compilation/udaparams.d(32): Error: variadic parameter cannot have user-defined attributes
fail_compilation/udaparams.d(34): Error: user-defined attributes cannot appear as postfixes
fail_compilation/udaparams.d(35): Error: user-defined attributes cannot appear as postfixes
fail_compilation/udaparams.d(36): Error: user-defined attributes cannot appear as postfixes
fail_compilation/udaparams.d(38): Error: `@safe` attribute for function parameter is not supported
fail_compilation/udaparams.d(39): Error: `@safe` attribute for function parameter is not supported
fail_compilation/udaparams.d(40): Error: `@safe` attribute for function parameter is not supported
fail_compilation/udaparams.d(43): Error: `@system` attribute for function parameter is not supported
fail_compilation/udaparams.d(44): Error: `@trusted` attribute for function parameter is not supported
fail_compilation/udaparams.d(45): Error: `@nogc` attribute for function parameter is not supported
fail_compilation/udaparams.d(51): Error: Cannot put a storage-class in an alias declaration.
fail_compilation/udaparams.d(52): Error: Cannot put a storage-class in an alias declaration.
fail_compilation/udaparams.d(53): Error: semicolon expected to close `alias` declaration
fail_compilation/udaparams.d(53): Error: declaration expected, not `=>`
fail_compilation/udaparams.d(54): Error: semicolon expected to close `alias` declaration
fail_compilation/udaparams.d(54): Error: declaration expected, not `=>`
fail_compilation/udaparams.d(57): Error: basic type expected, not `@`
fail_compilation/udaparams.d(57): Error: identifier expected for template value parameter
fail_compilation/udaparams.d(57): Error: found `@` when expecting `)`
fail_compilation/udaparams.d(57): Error: basic type expected, not `3`
fail_compilation/udaparams.d(57): Error: found `3` when expecting `)`
fail_compilation/udaparams.d(57): Error: semicolon expected following function declaration
fail_compilation/udaparams.d(57): Error: declaration expected, not `)`
---
*/
void vararg1(int a, @(10) ...);
extern(C) void vararg2(int a, @(10) ...);
void rhsuda(int a @(10));
void rhsuda2(int @(10));
void rhsuda3(int[] arr @(10) ...);
void wrongAttr1(@safe int);
void wrongAttr2(@safe void function());
void wrongAttr3(@safe void delegate());
void test16(A)(A a @system);
void test16(A)(A a @trusted);
void test16(A)(A a @nogc);
// lambdas without parentheses
alias test19a = @safe b => 1 + 2;
alias test19b = @system b => 1 + 2;
alias test19c = @nogc b => 1 + 2;
alias test19d = @(2) @system b => 1 + 2;
alias test19e = @safe @(2) b => 1 + 2;
alias test19f = extern(C++) b => 1 + 2;
alias test19g = align(2) b => 1 + 2;
// UDAs on Template parameter aren't supported
void test21(@(3) T)(T t) {}