diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 00c28711c648254724bbf59e9a235aafd21466b6..fe46e5a5d791cd76f915d31b89d51f80d61ff288 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2003-05-21  Nathan Sidwell  <nathan@codesourcery.com>
+
+	* c-parse.in (fndef): Set DECL_SOURCE_LINE and FILE earlier.
+	(nested_function): Likewise.
+	(notype_nested_function): Likewise.
+
 2003-05-21  Nick Clifton  <nickc@redhat.com>
 
 	* config/stormy16/stormy-abi: Update overflow type for
diff --git a/gcc/c-parse.in b/gcc/c-parse.in
index 62a54f65665f98521cce21483df2976fcf7172be..477ae629fe70a8d9ffdb5e3bf64a405f36965aed 100644
--- a/gcc/c-parse.in
+++ b/gcc/c-parse.in
@@ -434,12 +434,12 @@ fndef:
 					all_prefix_attributes))
 		    YYERROR1;
 		}
-	  old_style_parm_decls
-		{ store_parm_decls (); }
-	  save_filename save_lineno compstmt_or_error
-		{ DECL_SOURCE_FILE (current_function_decl) = $7;
-		  DECL_SOURCE_LINE (current_function_decl) = $8;
-		  finish_function (0, 1);
+	  old_style_parm_decls  save_filename save_lineno
+		{ DECL_SOURCE_FILE (current_function_decl) = $6;
+		  DECL_SOURCE_LINE (current_function_decl) = $7;
+		  store_parm_decls (); }
+	 compstmt_or_error
+		{ finish_function (0, 1);
 		  POP_DECLSPEC_STACK; }
 	| declspecs_ts setspecs declarator error
 		{ POP_DECLSPEC_STACK; }
@@ -448,12 +448,12 @@ fndef:
 					all_prefix_attributes))
 		    YYERROR1;
 		}
-	  old_style_parm_decls
-		{ store_parm_decls (); }
-	  save_filename save_lineno compstmt_or_error
-		{ DECL_SOURCE_FILE (current_function_decl) = $7;
-		  DECL_SOURCE_LINE (current_function_decl) = $8;
-		  finish_function (0, 1);
+	  old_style_parm_decls save_filename save_lineno
+		{ DECL_SOURCE_FILE (current_function_decl) = $6;
+		  DECL_SOURCE_LINE (current_function_decl) = $7;
+		  store_parm_decls (); }
+	  compstmt_or_error
+		{ finish_function (0, 1);
 		  POP_DECLSPEC_STACK; }
 	| declspecs_nots setspecs notype_declarator error
 		{ POP_DECLSPEC_STACK; }
@@ -462,12 +462,12 @@ fndef:
 					all_prefix_attributes))
 		    YYERROR1;
 		}
-	  old_style_parm_decls
-		{ store_parm_decls (); }
-	  save_filename save_lineno compstmt_or_error
-		{ DECL_SOURCE_FILE (current_function_decl) = $6;
-		  DECL_SOURCE_LINE (current_function_decl) = $7;
-		  finish_function (0, 1);
+	  old_style_parm_decls save_filename save_lineno
+		{ DECL_SOURCE_FILE (current_function_decl) = $5;
+		  DECL_SOURCE_LINE (current_function_decl) = $6;
+		  store_parm_decls (); }
+	  compstmt_or_error
+		{ finish_function (0, 1);
 		  POP_DECLSPEC_STACK; }
 	| setspecs notype_declarator error
 		{ POP_DECLSPEC_STACK; }
@@ -1593,18 +1593,19 @@ nested_function:
 		    }
 		  parsing_iso_function_signature = false; /* Don't warn about nested functions.  */
 		}
-	   old_style_parm_decls
-		{ store_parm_decls (); }
+	   old_style_parm_decls save_filename save_lineno
+		{ tree decl = current_function_decl;
+		  DECL_SOURCE_FILE (decl) = $4;
+		  DECL_SOURCE_LINE (decl) = $5;
+		  store_parm_decls (); }
 /* This used to use compstmt_or_error.
    That caused a bug with input `f(g) int g {}',
    where the use of YYERROR1 above caused an error
    which then was handled by compstmt_or_error.
    There followed a repeated execution of that same rule,
    which called YYERROR1 again, and so on.  */
-	  save_filename save_lineno compstmt
+	  compstmt
 		{ tree decl = current_function_decl;
-		  DECL_SOURCE_FILE (decl) = $5;
-		  DECL_SOURCE_LINE (decl) = $6;
 		  finish_function (1, 1);
 		  pop_function_context ();
 		  add_decl_stmt (decl); }
@@ -1624,18 +1625,19 @@ notype_nested_function:
 		    }
 		  parsing_iso_function_signature = false; /* Don't warn about nested functions.  */
 		}
-	  old_style_parm_decls
-		{ store_parm_decls (); }
+	  old_style_parm_decls save_filename save_lineno
+		{ tree decl = current_function_decl;
+		  DECL_SOURCE_FILE (decl) = $4;
+		  DECL_SOURCE_LINE (decl) = $5;
+		  store_parm_decls (); }
 /* This used to use compstmt_or_error.
    That caused a bug with input `f(g) int g {}',
    where the use of YYERROR1 above caused an error
    which then was handled by compstmt_or_error.
    There followed a repeated execution of that same rule,
    which called YYERROR1 again, and so on.  */
-	  save_filename save_lineno compstmt
+	  compstmt
 		{ tree decl = current_function_decl;
-		  DECL_SOURCE_FILE (decl) = $5;
-		  DECL_SOURCE_LINE (decl) = $6;
 		  finish_function (1, 1);
 		  pop_function_context ();
 		  add_decl_stmt (decl); }
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 270103b0cb87c2931be7abd9ad0facf82f0cad08..d0e90519821411b6f362a120bd72cd97b4942b55 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2003-05-21  Nathan Sidwell  <nathan@codesourcery.com>
+
+	* pt.c (register_specialization): Update the decl's location,
+	if necessary.
+	(check_explicit_specialization): Likewise.
+
 2003-05-20  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
 	* error.c (dump_expr): Use HOST_WIDE_INT_PRINT_DOUBLE_HEX.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index e7feab6de05cd00993307abde5fc2bd111d6e6a6..c86a1573c437cd034784b7930400aeafef7747c3 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -1041,7 +1041,12 @@ register_specialization (spec, tmpl, args)
 		}
 	      else if (DECL_TEMPLATE_SPECIALIZATION (fn))
 		{
-		  duplicate_decls (spec, fn);
+		  if (!duplicate_decls (spec, fn) && DECL_INITIAL (spec))
+		    /* Dup decl failed, but this is a new
+		       definition. Set the line number so any errors
+		       match this new definition. */
+		    DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (spec);
+		  
 		  return fn;
 		}
 	    }
@@ -1851,6 +1856,12 @@ check_explicit_specialization (declarator, decl, template_count, flags)
 	    {
 	      SET_DECL_TEMPLATE_SPECIALIZATION (tmpl);
 	      DECL_INITIAL (DECL_TEMPLATE_RESULT (tmpl)) = NULL_TREE;
+	      if (have_def)
+		{
+		  DECL_SOURCE_LOCATION (tmpl) = DECL_SOURCE_LOCATION (decl);
+		  DECL_SOURCE_LOCATION (DECL_TEMPLATE_RESULT (tmpl))
+		    = DECL_SOURCE_LOCATION (decl);
+		}
 	      return tmpl;
 	    }