diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 02262fdeaa20d03a57e0c796a562069855ec34c6..f8710774ef30a2b24c47980b2d253f3963678460 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,12 @@
+2003-01-22  Mark Mitchell  <mark@codesourcery.com>
+
+	PR c++/9298
+	* parser.c (cp_parser_consume_semicolon_at_end_of_statement): New
+	function.
+	(cp_parser_expression_statement): Use it.
+	(cp_parser_explicit_instantiation): Likewise.
+	* pt.c (do_decl_instantiation): Improve error handling logic.
+	
 2003-01-22  Mark Mitchell  <mark@codesourcery.com>
 
 	PR c++/9384
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 7f4eeaf67cb1b6b4c09bf86f9b2408bd1349a1c2..d64f0b4ef499b9d1cf5305a4de5604e29df76c16 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1766,6 +1766,8 @@ static bool cp_parser_skip_to_closing_parenthesis_or_comma
   (cp_parser *);
 static void cp_parser_skip_to_end_of_statement
   PARAMS ((cp_parser *));
+static void cp_parser_consume_semicolon_at_end_of_statement
+  (cp_parser *);
 static void cp_parser_skip_to_end_of_block_or_statement
   PARAMS ((cp_parser *));
 static void cp_parser_skip_to_closing_brace
@@ -2107,6 +2109,25 @@ cp_parser_skip_to_end_of_statement (parser)
     }
 }
 
+/* This function is called at the end of a statement or declaration.
+   If the next token is a semicolon, it is consumed; otherwise, error
+   recovery is attempted.  */
+
+static void
+cp_parser_consume_semicolon_at_end_of_statement (cp_parser *parser)
+{
+  /* Look for the trailing `;'.  */
+  if (!cp_parser_require (parser, CPP_SEMICOLON, "`;'"))
+    {
+      /* If there is additional (erroneous) input, skip to the end of
+	 the statement.  */
+      cp_parser_skip_to_end_of_statement (parser);
+      /* If the next token is now a `;', consume it.  */
+      if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+	cp_lexer_consume_token (parser->lexer);
+    }
+}
+
 /* Skip tokens until we have consumed an entire block, or until we
    have consumed a non-nested `;'.  */
 
@@ -5628,15 +5649,7 @@ cp_parser_expression_statement (parser)
       statement = NULL_TREE;
     }
   /* Consume the final `;'.  */
-  if (!cp_parser_require (parser, CPP_SEMICOLON, "`;'"))
-    {
-      /* If there is additional (erroneous) input, skip to the end of
-	 the statement.  */
-      cp_parser_skip_to_end_of_statement (parser);
-      /* If the next token is now a `;', consume it.  */
-      if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
-	cp_lexer_consume_token (parser->lexer);
-    }
+  cp_parser_consume_semicolon_at_end_of_statement (parser);
 
   return statement;
 }
@@ -8256,8 +8269,7 @@ cp_parser_explicit_instantiation (parser)
   /* Trun access control back on.  */
   scope_chain->check_access = flag_access_control;
 
-  /* Look for the trailing `;'.  */
-  cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+  cp_parser_consume_semicolon_at_end_of_statement (parser);
 }
 
 /* Parse an explicit-specialization.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 9f391ebf0368a57b007c309c5c25e58f7a22675d..ca75cb0b0d65a1cacf85410cca346a8d6c50e121 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -10219,9 +10219,9 @@ do_decl_instantiation (tree decl, tree storage)
 	 should handle VAR_DECLs as it currently handles
 	 FUNCTION_DECLs.  */
       result = lookup_field (DECL_CONTEXT (decl), DECL_NAME (decl), 0, 0);
-      if (result && TREE_CODE (result) != VAR_DECL)
+      if (!result || TREE_CODE (result) != VAR_DECL)
 	{
-	  error ("no matching template for `%D' found", result);
+	  error ("no matching template for `%D' found", decl);
 	  return;
 	}
     }
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 1bc7453636563dca153430b3bc718a96eb884a3a..fed915c899aaee82b36a88f38734f9baab443575 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,8 @@
 2003-01-22  Mark Mitchell  <mark@codesourcery.com>
 
+	PR c++/9298
+	* g++.dg/parse/template1.C: New test.
+
 	PR c++/9384
 	* g++.dg/parse/using1.C: New test.
 
diff --git a/gcc/testsuite/g++.dg/parse/template1.C b/gcc/testsuite/g++.dg/parse/template1.C
new file mode 100644
index 0000000000000000000000000000000000000000..d7bbb073f812416a38a4a961618050afd428958c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/template1.C
@@ -0,0 +1,11 @@
+struct CPU {
+    typedef int (*pfun)();
+
+    template <pfun step1>
+    static int dispatch();
+};
+
+template<int>
+static int foo();
+
+template int CPU::dispatch<&template foo<2> > (); // { dg-error "" }