cmd/compile: "invalid variable name x in type switch", where x is a name of a constant

Small fix: looks like a short variable declaration with a type switch
checks to make sure the variable used had valid shape (ONAME, OTYPE, or
ONONAME) and rejects everything else. Then a new variable is declared.
If the symbol contained in the declaration was a named OLITERAL (still a
valid identifier obviously) it would be rejected, even though a new
variable would have been declared.

Fix adds this case to the check.

Added a test case from issue12413.

Fixes #12413

Change-Id: I150dadafa8ee5612c867d58031027f2dca8c6ebc
Reviewed-on: https://go-review.googlesource.com/15760
Reviewed-by: Minux Ma <minux@golang.org>
Run-TryBot: Minux Ma <minux@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/src/cmd/compile/internal/gc/go.y b/src/cmd/compile/internal/gc/go.y
index 599449f..2bec5b6 100644
--- a/src/cmd/compile/internal/gc/go.y
+++ b/src/cmd/compile/internal/gc/go.y
@@ -510,7 +510,7 @@
 			}
 			if $1.Next != nil {
 				Yyerror("argument count mismatch: %d = %d", count($1), 1);
-			} else if ($1.N.Op != ONAME && $1.N.Op != OTYPE && $1.N.Op != ONONAME) || isblank($1.N) {
+			} else if ($1.N.Op != ONAME && $1.N.Op != OTYPE && $1.N.Op != ONONAME && ($1.N.Op != OLITERAL || $1.N.Name == nil)) || isblank($1.N) {
 				Yyerror("invalid variable name %s in type switch", $1.N);
 			} else {
 				$$.Left = dclname($1.N.Sym);
diff --git a/src/cmd/compile/internal/gc/y.go b/src/cmd/compile/internal/gc/y.go
index dfb0fa4..b8aff3c 100644
--- a/src/cmd/compile/internal/gc/y.go
+++ b/src/cmd/compile/internal/gc/y.go
@@ -1586,7 +1586,7 @@
 				}
 				if yyDollar[1].list.Next != nil {
 					Yyerror("argument count mismatch: %d = %d", count(yyDollar[1].list), 1)
-				} else if (yyDollar[1].list.N.Op != ONAME && yyDollar[1].list.N.Op != OTYPE && yyDollar[1].list.N.Op != ONONAME) || isblank(yyDollar[1].list.N) {
+				} else if (yyDollar[1].list.N.Op != ONAME && yyDollar[1].list.N.Op != OTYPE && yyDollar[1].list.N.Op != ONONAME && (yyDollar[1].list.N.Op != OLITERAL || yyDollar[1].list.N.Name == nil)) || isblank(yyDollar[1].list.N) {
 					Yyerror("invalid variable name %s in type switch", yyDollar[1].list.N)
 				} else {
 					yyVAL.node.Left = dclname(yyDollar[1].list.N.Sym)
diff --git a/test/fixedbugs/issue12413.go b/test/fixedbugs/issue12413.go
new file mode 100644
index 0000000..a054765
--- /dev/null
+++ b/test/fixedbugs/issue12413.go
@@ -0,0 +1,19 @@
+// compile
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 12413: invalid variable name x in type switch: code would fail
+// to compile if the variable used in the short variable declaration was
+// previously declared as a constant.
+
+package main
+
+func main() {
+	const x = 42
+	switch x := interface{}(nil).(type) {
+	default:
+		_ = x
+	}
+}