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 };