diff --git a/src/hdrgen.c b/src/hdrgen.c
index 74c029f..25ec226 100644
--- a/src/hdrgen.c
+++ b/src/hdrgen.c
@@ -422,6 +422,18 @@ public:
     void visit(SwitchStatement *s)
     {
         buf->writestring(s->isFinal ? "final switch (" : "switch (");
+        if (Parameter *a = s->arg)
+        {
+            StorageClass stc = a->storageClass;
+            if (!a->type && !stc)
+                stc = STCauto;
+            StorageClassDeclaration::stcToCBuffer(buf, stc);
+            if (a->type)
+                typeToBuffer(a->type, a->ident);
+            else
+                buf->writestring(a->ident->toChars());
+            buf->writestring(" = ");
+        }
         s->condition->accept(this);
         buf->writeByte(')');
         buf->writenl();
diff --git a/src/parse.c b/src/parse.c
index 0dc44a6..6383950 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -5028,12 +5028,34 @@ Statement *Parser::parseStatement(int flags, const utf8_t** endPtr)
 
         Lswitch:
         {
+            Expression *condition = NULL;
+            Parameter *arg = NULL;
+
             nextToken();
             check(TOKlparen);
-            Expression *condition = parseExpression();
+            StorageClass storageClass = parseStorageClass();
+
+            if (storageClass != 0 &&
+                token.value == TOKidentifier &&
+                peek(&token)->value == TOKassign)
+            {
+                Identifier *ai = token.ident;
+                Type *at = NULL;        // infer argument type
+                nextToken();
+                check(TOKassign);
+                arg = new Parameter(storageClass, at, ai, NULL);
+            }
+            else if (isDeclaration(&token, 2, TOKassign, NULL))
+            {
+                Identifier *ai;
+                Type *at = parseType(&ai);
+                check(TOKassign);
+                arg = new Parameter(storageClass, at, ai, NULL);
+            }
+            condition = parseExpression();
             check(TOKrparen);
             Statement *body = parseStatement(PSscope);
-            s = new SwitchStatement(loc, condition, body, isfinal);
+            s = new SwitchStatement(loc, arg, condition, body, isfinal);
             break;
         }
 
diff --git a/src/statement.c b/src/statement.c
index a7c257c..7f6e2a5 100644
--- a/src/statement.c
+++ b/src/statement.c
@@ -2501,7 +2501,7 @@ Statement *ForeachStatement::semantic(Scope *sc)
                 }
 
                 s = new CompoundStatement(loc, a);
-                s = new SwitchStatement(loc, e, s, false);
+                s = new SwitchStatement(loc, NULL, e, s, false);
             }
             s = s->semantic(sc);
             break;
@@ -3067,9 +3067,10 @@ Statement *StaticAssertStatement::semantic(Scope *sc)
 
 /******************************** SwitchStatement ***************************/
 
-SwitchStatement::SwitchStatement(Loc loc, Expression *c, Statement *b, bool isFinal)
+SwitchStatement::SwitchStatement(Loc loc, Parameter *arg, Expression *c, Statement *b, bool isFinal)
     : Statement(loc)
 {
+    this->arg = arg;
     this->condition = c;
     this->body = b;
     this->isFinal = isFinal;
@@ -3083,6 +3084,7 @@ SwitchStatement::SwitchStatement(Loc loc, Expression *c, Statement *b, bool isFi
 Statement *SwitchStatement::syntaxCopy()
 {
     return new SwitchStatement(loc,
+        arg ? arg->syntaxCopy() : NULL,
         condition->syntaxCopy(),
         body->syntaxCopy(),
         isFinal);
@@ -3091,6 +3093,26 @@ Statement *SwitchStatement::syntaxCopy()
 Statement *SwitchStatement::semantic(Scope *sc)
 {
     //printf("SwitchStatement::semantic(%p)\n", this);
+    if (arg)
+    {
+        /* Re-write to
+         * {
+         *   <decl> argname = exp
+         *   switch(argname)
+         *   {
+         *     ...
+         *   }
+         * }
+         */
+        VarDeclaration *wthis = new VarDeclaration(loc, arg->type, arg->ident, new ExpInitializer(loc, condition));
+        wthis->parent = sc->func;
+        wthis->storage_class |= arg->storageClass;
+        ExpStatement *es = new ExpStatement(loc, new DeclarationExp(loc, wthis));
+        condition = new VarExp(loc, wthis);
+        Statement *ss = new ScopeStatement(loc, new CompoundStatement(loc, es, this));
+        arg = NULL; // prevent further rewritings
+        return ss->semantic(sc);
+    }
     tf = sc->tf;
     if (cases)
         return this;            // already run
diff --git a/src/statement.h b/src/statement.h
index 7e9c716..948eb04 100644
--- a/src/statement.h
+++ b/src/statement.h
@@ -417,6 +417,7 @@ public:
 class SwitchStatement : public Statement
 {
 public:
+    Parameter *arg;
     Expression *condition;
     Statement *body;
     bool isFinal;
@@ -428,7 +429,7 @@ public:
     int hasNoDefault;           // !=0 if no default statement
     int hasVars;                // !=0 if has variable case values
 
-    SwitchStatement(Loc loc, Expression *c, Statement *b, bool isFinal);
+    SwitchStatement(Loc loc, Parameter *arg, Expression *c, Statement *b, bool isFinal);
     Statement *syntaxCopy();
     Statement *semantic(Scope *sc);
     bool hasBreak();
