diff mbox series

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

Message ID 20210109230032.2612042-1-ibuclaw@gdcproject.org
State New
Headers show
Series [committed] d: Support deprecated, @disable, and user-defined attributes on enum members | expand

Commit Message

Iain Buclaw Jan. 9, 2021, 11 p.m. UTC
Hi,

This patch merges the D front-end with upstream dmd 9bba772fa, adding
support for `deprecated`, `@disable` and user-defined attributes to be
applied to enum members.

Bootstrapped and regression tested on x86_64-linux-gnu/-m32/-mx32, and
committed to mainline.

Regards
Iain.

---
gcc/d/ChangeLog:

	* dmd/MERGE: Merge upstream dmd 9bba772fa.
---
 gcc/d/dmd/MERGE                               |   2 +-
 gcc/d/dmd/declaration.c                       |  45 ++++++
 gcc/d/dmd/declaration.h                       |   1 +
 gcc/d/dmd/denum.c                             |  34 ++++-
 gcc/d/dmd/dsymbol.c                           |  23 +--
 gcc/d/dmd/dsymbol.h                           |   2 +-
 gcc/d/dmd/enum.h                              |   2 +
 gcc/d/dmd/expression.c                        |  26 +++-
 gcc/d/dmd/expression.h                        |   3 +-
 gcc/d/dmd/expressionsem.c                     |   9 ++
 gcc/d/dmd/mtype.c                             |  21 ++-
 gcc/d/dmd/parse.c                             | 132 ++++++++++++++----
 gcc/d/dmd/traits.c                            |   4 +-
 gcc/testsuite/gdc.test/compilable/test17908.d |  17 +++
 gcc/testsuite/gdc.test/compilable/test9701.d  |  58 ++++++++
 gcc/testsuite/gdc.test/compilable/vcg-ast.d   |  43 ++++++
 .../gdc.test/fail_compilation/disable.d       |  26 ++--
 .../gdc.test/fail_compilation/fail10968.d     |  12 +-
 .../gdc.test/fail_compilation/fail11355.d     |   2 +-
 .../gdc.test/fail_compilation/fail15044.d     |   2 +-
 .../gdc.test/fail_compilation/fail341.d       |   4 +-
 .../gdc.test/fail_compilation/fail9346.d      |   4 +-
 .../fail_compilation/fail_contracts1.d        |   8 ++
 .../fail_compilation/fail_contracts2.d        |   8 ++
 .../fail_compilation/fail_contracts3.d        |  14 ++
 .../fail_compilation/fail_contracts4.d        |   8 ++
 .../gdc.test/fail_compilation/test17908a.d    |  15 ++
 .../gdc.test/fail_compilation/test17908b.d    |  14 ++
 .../gdc.test/fail_compilation/test9701.d      |  63 +++++++++
 .../gdc.test/fail_compilation/test9701b.d     |  22 +++
 .../gdc.test/fail_compilation/udaparams.d     |  57 ++++++++
 31 files changed, 601 insertions(+), 80 deletions(-)
 create mode 100644 gcc/testsuite/gdc.test/compilable/test17908.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/test9701.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/vcg-ast.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/fail_contracts1.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/fail_contracts2.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/fail_contracts3.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/fail_contracts4.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/test17908a.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/test17908b.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/test9701.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/test9701b.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/udaparams.d

Comments

Andreas Schwab Jan. 10, 2021, 8:08 a.m. UTC | #1
../../gcc/d/dmd/parse.c: In member function 'Dsymbols* Parser::parseDeclDefs(int, Dsymbol**, PrefixAttributes*)':
../../gcc/d/dmd/parse.c:647:29: error: unused variable 'e' [-Werror=unused-variable]
  647 |                 Expression *e = NULL;
      |                             ^

Andreas.
Iain Buclaw Jan. 11, 2021, 11:37 a.m. UTC | #2
Excerpts from Andreas Schwab's message of January 10, 2021 9:08 am:
> ../../gcc/d/dmd/parse.c: In member function 'Dsymbols* Parser::parseDeclDefs(int, Dsymbol**, PrefixAttributes*)':
> ../../gcc/d/dmd/parse.c:647:29: error: unused variable 'e' [-Werror=unused-variable]
>   647 |                 Expression *e = NULL;
>       |                             ^
> 

Thanks for spotting, this was dealt with in the last merge in r11-6586.

Iain.
diff mbox series

Patch

diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index f6c8f6f02cf..a34fd4138d7 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -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.
diff --git a/gcc/d/dmd/declaration.c b/gcc/d/dmd/declaration.c
index f196bc825a2..72a07d9b8f5 100644
--- a/gcc/d/dmd/declaration.c
+++ b/gcc/d/dmd/declaration.c
@@ -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);
diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h
index 19e4d1a5aa8..a464f9beb71 100644
--- a/gcc/d/dmd/declaration.h
+++ b/gcc/d/dmd/declaration.h
@@ -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);
diff --git a/gcc/d/dmd/denum.c b/gcc/d/dmd/denum.c
index b881fb6df15..d15d94a3157 100644
--- a/gcc/d/dmd/denum.c
+++ b/gcc/d/dmd/denum.c
@@ -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);
diff --git a/gcc/d/dmd/dsymbol.c b/gcc/d/dmd/dsymbol.c
index d74fe6cfdd5..5b4fad4ebb7 100644
--- a/gcc/d/dmd/dsymbol.c
+++ b/gcc/d/dmd/dsymbol.c
@@ -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");
-    }
 
-  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 true;
     }
+
+    return false;
 }
 
 /**********************************
diff --git a/gcc/d/dmd/dsymbol.h b/gcc/d/dmd/dsymbol.h
index 5fa509be9ca..6555f12e7b4 100644
--- a/gcc/d/dmd/dsymbol.h
+++ b/gcc/d/dmd/dsymbol.h
@@ -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();
diff --git a/gcc/d/dmd/enum.h b/gcc/d/dmd/enum.h
index 481ff0c1cd3..6d389ed76e0 100644
--- a/gcc/d/dmd/enum.h
+++ b/gcc/d/dmd/enum.h
@@ -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);
diff --git a/gcc/d/dmd/expression.c b/gcc/d/dmd/expression.c
index a3c3f72d261..395dc56748c 100644
--- a/gcc/d/dmd/expression.c
+++ b/gcc/d/dmd/expression.c
@@ -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())
diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h
index ccfaa65f764..d84878f0d6e 100644
--- a/gcc/d/dmd/expression.h
+++ b/gcc/d/dmd/expression.h
@@ -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);
diff --git a/gcc/d/dmd/expressionsem.c b/gcc/d/dmd/expressionsem.c
index f519389571a..ecafd9d2066 100644
--- a/gcc/d/dmd/expressionsem.c
+++ b/gcc/d/dmd/expressionsem.c
@@ -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)
diff --git a/gcc/d/dmd/mtype.c b/gcc/d/dmd/mtype.c
index 42f90fa9e04..ceee70ac7c3 100644
--- a/gcc/d/dmd/mtype.c
+++ b/gcc/d/dmd/mtype.c
@@ -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();
diff --git a/gcc/d/dmd/parse.c b/gcc/d/dmd/parse.c
index 80aaac089ec..2664af2e706 100644
--- a/gcc/d/dmd/parse.c
+++ b/gcc/d/dmd/parse.c
@@ -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)
diff --git a/gcc/d/dmd/traits.c b/gcc/d/dmd/traits.c
index 2f00c883706..46b7d968621 100644
--- a/gcc/d/dmd/traits.c
+++ b/gcc/d/dmd/traits.c
@@ -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)
     {
diff --git a/gcc/testsuite/gdc.test/compilable/test17908.d b/gcc/testsuite/gdc.test/compilable/test17908.d
new file mode 100644
index 00000000000..3520b5f44ee
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test17908.d
@@ -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);
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test9701.d b/gcc/testsuite/gdc.test/compilable/test9701.d
new file mode 100644
index 00000000000..8f822add531
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test9701.d
@@ -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"));
diff --git a/gcc/testsuite/gdc.test/compilable/vcg-ast.d b/gcc/testsuite/gdc.test/compilable/vcg-ast.d
new file mode 100644
index 00000000000..7cc376fbec5
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/vcg-ast.d
@@ -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;
+    }
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/disable.d b/gcc/testsuite/gdc.test/fail_compilation/disable.d
index 517fddd9940..7e7d9c2d48d 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/disable.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/disable.d
@@ -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;
 }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail10968.d b/gcc/testsuite/gdc.test/fail_compilation/fail10968.d
index ef75f910180..257d739bbd3 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail10968.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail10968.d
@@ -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`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail11355.d b/gcc/testsuite/gdc.test/fail_compilation/fail11355.d
index 474d376794f..c41a4c492e3 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail11355.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail11355.d
@@ -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`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail15044.d b/gcc/testsuite/gdc.test/fail_compilation/fail15044.d
index 8674b8d08c6..964dcf913c2 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail15044.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail15044.d
@@ -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`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail341.d b/gcc/testsuite/gdc.test/fail_compilation/fail341.d
index af78e8145b9..8677d485a40 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail341.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail341.d
@@ -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`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail9346.d b/gcc/testsuite/gdc.test/fail_compilation/fail9346.d
index d3c7a593db2..57d420f76ef 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail9346.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail9346.d
@@ -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`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail_contracts1.d b/gcc/testsuite/gdc.test/fail_compilation/fail_contracts1.d
new file mode 100644
index 00000000000..572b821e982
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail_contracts1.d
@@ -0,0 +1,8 @@ 
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail_contracts1.d(8): Error: `(identifier) { ... }` or `(identifier; expression)` following `out` expected, not `)`
+---
+*/
+
+void foo() out()){}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail_contracts2.d b/gcc/testsuite/gdc.test/fail_compilation/fail_contracts2.d
new file mode 100644
index 00000000000..2a07a60e5f3
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail_contracts2.d
@@ -0,0 +1,8 @@ 
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail_contracts2.d(8): Error: missing `do { ... }` after `in` or `out`
+---
+*/
+
+void foo()in{}{}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail_contracts3.d b/gcc/testsuite/gdc.test/fail_compilation/fail_contracts3.d
new file mode 100644
index 00000000000..de3e9bb7081
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail_contracts3.d
@@ -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{}
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail_contracts4.d b/gcc/testsuite/gdc.test/fail_compilation/fail_contracts4.d
new file mode 100644
index 00000000000..f1b664477cc
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail_contracts4.d
@@ -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){};
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test17908a.d b/gcc/testsuite/gdc.test/fail_compilation/test17908a.d
new file mode 100644
index 00000000000..907239734d4
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test17908a.d
@@ -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);
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test17908b.d b/gcc/testsuite/gdc.test/fail_compilation/test17908b.d
new file mode 100644
index 00000000000..e2c4d84abed
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test17908b.d
@@ -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);
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test9701.d b/gcc/testsuite/gdc.test/fail_compilation/test9701.d
new file mode 100644
index 00000000000..384c51444b1
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test9701.d
@@ -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,
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test9701b.d b/gcc/testsuite/gdc.test/fail_compilation/test9701b.d
new file mode 100644
index 00000000000..16c25413ecb
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test9701b.d
@@ -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;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/udaparams.d b/gcc/testsuite/gdc.test/fail_compilation/udaparams.d
new file mode 100644
index 00000000000..ec760bd60b7
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/udaparams.d
@@ -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) {}