diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a41714cdcd1a860570e02193f6244233664dd701..46bfeb876d37666ce64e3559484dfcb3874ed43e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -8,6 +8,18 @@
 	Return false on error.
         * decl.c (xref_tag): Return error_mark_node if
 	redeclare_class_template returned false.
+
+	PR c++/27667
+        * cp-tree.h (begin_specialization): Return bool 
+	instead of void.
+        * pt.c (check_specialization_scope): Likwise. 
+	Adjust comment. Return false if a specialization 
+	isn't permitted in the current scope.
+        (begin_specialization): Use the return value of  
+        check_specialization_scope.
+        * parser.c (cp_parser_explicit_specialization): If
+        begin_specialization returned false, skip the rest 
+	of the specialization.
 	
 2006-09-21  Mark Mitchell  <mark@codesourcery.com>
 
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 227fc9dfdec0f1cb8e045b415c22e94bd3a60f5e..93c4053ccd6e9cc2da7e6996234c2daf02fd2277 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4086,7 +4086,7 @@ extern void maybe_begin_member_template_processing (tree);
 extern void maybe_end_member_template_processing (void);
 extern tree finish_member_template_decl		(tree);
 extern void begin_template_parm_list		(void);
-extern void begin_specialization		(void);
+extern bool begin_specialization		(void);
 extern void reset_specialization		(void);
 extern void end_specialization			(void);
 extern void begin_explicit_instantiation	(void);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index d0205208eb33b54408abc8c870887b004971b72d..0b7dd3cde476fdc58794003a1ea503ec37790401 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -9455,7 +9455,13 @@ cp_parser_explicit_specialization (cp_parser* parser)
   else
     need_lang_pop = false;
   /* Let the front end know that we are beginning a specialization.  */
-  begin_specialization ();
+  if (!begin_specialization ())
+    {
+      end_specialization ();
+      cp_parser_skip_to_end_of_block_or_statement (parser);
+      return;
+    }
+
   /* If the next keyword is `template', we need to figure out whether
      or not we're looking a template-declaration.  */
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TEMPLATE))
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index daee2522047c313742062b80d09ce2c154ec0364..4e8fad66e5c352090cca48bd513daccd2df719e1 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -142,7 +142,7 @@ static tree most_specialized_class (tree, tree);
 static tree tsubst_aggr_type (tree, tree, tsubst_flags_t, tree, int);
 static tree tsubst_arg_types (tree, tree, tsubst_flags_t, tree);
 static tree tsubst_function_type (tree, tree, tsubst_flags_t, tree);
-static void check_specialization_scope (void);
+static bool check_specialization_scope (void);
 static tree process_partial_specialization (tree);
 static void set_current_access_from_decl (tree);
 static void check_default_tmpl_args (tree, tree, int, int);
@@ -535,9 +535,10 @@ begin_template_parm_list (void)
 }
 
 /* This routine is called when a specialization is declared.  If it is
-   invalid to declare a specialization here, an error is reported.  */
+   invalid to declare a specialization here, an error is reported and
+   false is returned, otherwise this routine will return true.  */
 
-static void
+static bool
 check_specialization_scope (void)
 {
   tree scope = current_scope ();
@@ -552,7 +553,10 @@ check_specialization_scope (void)
      shall be declared in the namespace of which the class template
      is a member.  */
   if (scope && TREE_CODE (scope) != NAMESPACE_DECL)
-    error ("explicit specialization in non-namespace scope %qD", scope);
+    {
+      error ("explicit specialization in non-namespace scope %qD", scope);
+      return false;
+    }
 
   /* [temp.expl.spec]
 
@@ -563,17 +567,22 @@ check_specialization_scope (void)
      explicitly specialize a class member template if its enclosing
      class templates are not explicitly specialized as well.  */
   if (current_template_parms)
-    error ("enclosing class templates are not explicitly specialized");
+    {
+      error ("enclosing class templates are not explicitly specialized");
+      return false;
+    }
+
+  return true;
 }
 
 /* We've just seen template <>.  */
 
-void
+bool
 begin_specialization (void)
 {
   begin_scope (sk_template_spec, NULL);
   note_template_header (1);
-  check_specialization_scope ();
+  return check_specialization_scope ();
 }
 
 /* Called at then end of processing a declaration preceded by
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a511e56253652a719f3638a443c88ec00fba719a..4fc16e5f23df88c611d8111c16cb026af8aba6ab 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -9,6 +9,10 @@
 
         PR c++/27329
         * g++.dg/template/crash59.C: New test.
+
+	PR c++/27667
+        * g++.dg/template/spec33.C: New test.
+        * g++.old-deja/g++.pt/spec20.C: Adjust error markers.
 	
 2006-09-24  Zdenek Dvorak <dvorakz@suse.cz>
 	    Adam Nemet  <anemet@caviumnetworks.com>
diff --git a/gcc/testsuite/g++.dg/template/spec33.C b/gcc/testsuite/g++.dg/template/spec33.C
new file mode 100644
index 0000000000000000000000000000000000000000..809d4f012c1ad886c9f4449c675cecadbd99ca55
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/spec33.C
@@ -0,0 +1,7 @@
+//PR c++/27667
+
+struct A
+{
+    template<int> static void foo   () {}
+    template<>    static void foo<0>() {}  // { dg-error "explicit" }
+}; 
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec20.C b/gcc/testsuite/g++.old-deja/g++.pt/spec20.C
index 064ce1423a7979c12c2b832a1af3cf3f335444a8..b6148e5ded99fba0fde5a91ef360aabc24da9cd3 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/spec20.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/spec20.C
@@ -10,7 +10,7 @@ struct S {
   template <class U> void f(U);
   template <> void f<int>(int); // { dg-error "" } invalid specialization
 
-  template <class V> struct I {};
-  template <class V> struct I<V*> {};
+  template <class V> struct I {};      // { dg-error "template" }
+  template <class V> struct I<V*> {};  // { dg-error "template" }
   template <> struct I<int>; // { dg-error "" } invalid specialization
 };