diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c
index aa2489d9a104b2ea03848fe9899b1f7c67d72307..45945467b91afaea3ff71ab41e415af1187a6156 100644
--- a/src/cmd/gc/dcl.c
+++ b/src/cmd/gc/dcl.c
@@ -225,8 +225,12 @@ declare(Node *n, int ctxt)
 	if(ctxt == PAUTO)
 		n->xoffset = 0;
 
-	if(s->block == block)
-		redeclare(s, "in this block");
+	if(s->block == block) {
+		// functype will print errors about duplicate function arguments.
+		// Don't repeat the error here.
+		if(ctxt != PPARAM && ctxt != PPARAMOUT)
+			redeclare(s, "in this block");
+	}
 
 	s->block = block;
 	s->lastlineno = parserline();
@@ -824,22 +828,24 @@ structfield(Node *n)
 	return f;
 }
 
+static uint32 uniqgen;
+
 static void
 checkdupfields(Type *t, char* what)
 {
-	Type* t1;
 	int lno;
 
 	lno = lineno;
 
-	for( ; t; t=t->down)
-		if(t->sym && t->nname && !isblank(t->nname))
-			for(t1=t->down; t1; t1=t1->down)
-				if(t1->sym == t->sym) {
-					lineno = t->nname->lineno;
-					yyerror("duplicate %s %s", what, t->sym->name);
-					break;
-				}
+	for( ; t; t=t->down) {
+		if(t->sym && t->nname && !isblank(t->nname)) {
+			if(t->sym->uniqgen == uniqgen) {
+				lineno = t->nname->lineno;
+				yyerror("duplicate %s %s", what, t->sym->name);
+			} else
+				t->sym->uniqgen = uniqgen;
+		}
+	}
 
 	lineno = lno;
 }
@@ -865,6 +871,7 @@ tostruct(NodeList *l)
 		if(f->broke)
 			t->broke = 1;
 
+	uniqgen++;
 	checkdupfields(t->type, "field");
 
 	if (!t->broke)
@@ -897,7 +904,6 @@ tofunargs(NodeList *l)
 		if(f->broke)
 			t->broke = 1;
 
-	checkdupfields(t->type, "argument");
 	return t;
 }
 
@@ -1004,6 +1010,7 @@ tointerface(NodeList *l)
 		if(f->broke)
 			t->broke = 1;
 
+	uniqgen++;
 	checkdupfields(t->type, "method");
 	t = sortinter(t);
 	checkwidth(t);
@@ -1187,6 +1194,11 @@ functype(Node *this, NodeList *in, NodeList *out)
 	t->type->down = tofunargs(out);
 	t->type->down->down = tofunargs(in);
 
+	uniqgen++;
+	checkdupfields(t->type->type, "argument");
+	checkdupfields(t->type->down->type, "argument");
+	checkdupfields(t->type->down->down->type, "argument");
+
 	if (t->type->broke || t->type->down->broke || t->type->down->down->broke)
 		t->broke = 1;
 
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index 7e5e1b7356260bcab14d3a1971e8ca8b4f82d048..4bfb73e5b7f700a9e82e01a003a5571a2479d5bf 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -369,6 +369,7 @@ struct	Sym
 	uchar	sym;		// huffman encoding in object file
 	Sym*	link;
 	int32	npkg;	// number of imported packages with this name
+	uint32	uniqgen;
 
 	// saved and restored by dcopy
 	Pkg*	pkg;
diff --git a/test/fixedbugs/bug040.go b/test/fixedbugs/bug040.go
index 007f47f9f56a3cd0efe840aaa608b996e30ee570..d2cf88afcb24ff04a9c2f6514c731a7ed174bdd7 100644
--- a/test/fixedbugs/bug040.go
+++ b/test/fixedbugs/bug040.go
@@ -7,5 +7,5 @@
 package main
 
 func f (x,		// GCCGO_ERROR "previous"
-	x int) {	// ERROR "redeclared|redefinition" "duplicate"
+	x int) {	// ERROR "duplicate argument|redefinition"
 }
diff --git a/test/fixedbugs/bug342.go b/test/fixedbugs/bug342.go
index 5f1efbdfe1e30838789c4f0a63c3ea31609b06ec..ffcb668116070e104a1fdeb56f6e3377e9ba4c00 100644
--- a/test/fixedbugs/bug342.go
+++ b/test/fixedbugs/bug342.go
@@ -9,11 +9,7 @@
 package p
 
 type a interface {
-	foo(x int) (x int) // ERROR "redeclared|redefinition"
-}
-
-var b interface {
-	bar(y int) (y int) // ERROR "redeclared|redefinition"
+	foo(x int) (x int) // ERROR "duplicate argument|redefinition"
 }
 
 /*
diff --git a/test/fixedbugs/bug412.go b/test/fixedbugs/bug412.go
index 8dd0a5fcc15d7c548b7fa6a05fb98c57257bfc2c..c7ddc0cac83d345a716f22aa98f74c1db57825fe 100644
--- a/test/fixedbugs/bug412.go
+++ b/test/fixedbugs/bug412.go
@@ -7,8 +7,8 @@
 package p
 
 type t struct {
-	x int  // ERROR "duplicate field x|duplicate field name .x."
-	x int
+	x int  // GCCGO_ERROR "duplicate field name .x."
+	x int  // GC_ERROR "duplicate field x"
 }
 
 func f(t *t) int {
diff --git a/test/fixedbugs/bug469.go b/test/fixedbugs/bug469.go
deleted file mode 100644
index 71157a4c41cd3e938f2362db823ef6d1e635545f..0000000000000000000000000000000000000000
--- a/test/fixedbugs/bug469.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// compile
-
-// Copyright 2012 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.
-
-// The gccgo compiler would complain about a redefinition of i, but
-// the spec imposes no requirements on parameter names in a function
-// type.
-
-package p
-
-type F func(i int) (i int)
diff --git a/test/func1.go b/test/func1.go
index c89f7ff2eae777ffb99e594ab635284ee4bc4a07..fb6f56184fac2b683efd4c9f7d77856cf582a68b 100644
--- a/test/func1.go
+++ b/test/func1.go
@@ -14,6 +14,6 @@ func f1(a int) (int, float32) {
 }
 
 
-func f2(a int) (a int, b float32) { // ERROR "redeclared|definition"
+func f2(a int) (a int, b float32) { // ERROR "duplicate argument a|definition"
 	return 8, 8.0
 }
diff --git a/test/funcdup.go b/test/funcdup.go
new file mode 100644
index 0000000000000000000000000000000000000000..706dd63ca130cf1e106161432c7e5b0252d282bc
--- /dev/null
+++ b/test/funcdup.go
@@ -0,0 +1,27 @@
+// errorcheck
+
+// Copyright 2013 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.
+
+package p
+
+type T interface {
+	F1(i int) (i int) // ERROR "duplicate argument i"
+	F2(i, i int) // ERROR "duplicate argument i"
+	F3() (i, i int) // ERROR "duplicate argument i"
+}
+
+type T1 func(i, i int) // ERROR "duplicate argument i"
+type T2 func(i int) (i int) // ERROR "duplicate argument i"
+type T3 func() (i, i int) // ERROR "duplicate argument i"
+
+type R struct{}
+
+func (i *R) F1(i int)         {} // ERROR "duplicate argument i"
+func (i *R) F2() (i int)      {return 0} // ERROR "duplicate argument i"
+func (i *R) F3(j int) (j int) {return 0} // ERROR "duplicate argument j"
+
+func F1(i, i int)      {} // ERROR "duplicate argument i"
+func F2(i int) (i int) {return 0} // ERROR "duplicate argument i"
+func F3() (i, i int)   {return 0, 0} // ERROR "duplicate argument i"
diff --git a/test/funcdup2.go b/test/funcdup2.go
new file mode 100644
index 0000000000000000000000000000000000000000..aeb5f7eb6165c1d15c1bc660c3032863bdb021f9
--- /dev/null
+++ b/test/funcdup2.go
@@ -0,0 +1,17 @@
+// errorcheck
+
+// Copyright 2013 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.
+
+package p
+
+var T interface {
+	F1(i int) (i int) // ERROR "duplicate argument i"
+	F2(i, i int) // ERROR "duplicate argument i"
+	F3() (i, i int) // ERROR "duplicate argument i"
+}
+
+var T1 func(i, i int) // ERROR "duplicate argument i"
+var T2 func(i int) (i int) // ERROR "duplicate argument i"
+var T3 func() (i, i int) // ERROR "duplicate argument i"