From: Mark Mitchell Date: Fri, 8 Dec 2006 06:27:22 +0000 (+0000) Subject: re PR c++/29732 (ICE on invalid friend declaration) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=9ba7a2f2926541d4db21c6df15acc783b73e1f4f;p=gcc.git re PR c++/29732 (ICE on invalid friend declaration) PR c++/29732 * cp-tree.h (DECL_USE_TEMPLATE): Mention partial specializations. (explicit_class_specialization_p): Declare. * pt.c (explicit_class_specialization_p): New function. * parser.c (cp_parser_init_declarator): Check correct number of template parameters for in-class function definitions. (cp_parser_check_declrator_template_parameters): Stop looking for template classes when we find an explicit specialization. PR c++/29732 * g++.dg/template/crash65.C: New test. * g++.dg/template/spec16.C: Tweak error markers. From-SVN: r119649 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 213550807c0..1a8d126bcf2 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +2006-12-07 Mark Mitchell + + PR c++/29732 + * cp-tree.h (DECL_USE_TEMPLATE): Mention partial specializations. + (explicit_class_specialization_p): Declare. + * pt.c (explicit_class_specialization_p): New function. + * parser.c (cp_parser_init_declarator): Check correct number of + template parameters for in-class function definitions. + (cp_parser_check_declrator_template_parameters): Stop looking for + template classes when we find an explicit specialization. + 2006-12-07 Lee Millward PR c++/29980 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index ae250bfbdfe..e59586bde77 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2879,8 +2879,14 @@ extern void decl_shadowed_for_var_insert (tree, tree); indicates the type of specializations: 1=implicit instantiation - 2=explicit specialization, e.g. int min (int, int); - 3=explicit instantiation, e.g. template int min (int, int); + + 2=partial or explicit specialization, e.g.: + + template <> int min (int, int), + + 3=explicit instantiation, e.g.: + + template int min (int, int); Note that NODE will be marked as a specialization even if the template it is instantiating is not a primary template. For @@ -4168,6 +4174,7 @@ extern tree build_non_dependent_expr (tree); extern tree build_non_dependent_args (tree); extern bool reregister_specialization (tree, tree, tree); extern tree fold_non_dependent_expr (tree); +extern bool explicit_class_specialization_p (tree); /* in repo.c */ extern void init_repo (void); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index a0a6a177855..d7611ed71ff 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -11144,6 +11144,10 @@ cp_parser_init_declarator (cp_parser* parser, if (declarator == cp_error_declarator) return error_mark_node; + /* Check that the number of template-parameter-lists is OK. */ + if (!cp_parser_check_declarator_template_parameters (parser, declarator)) + return error_mark_node; + if (declares_class_or_enum & 2) cp_parser_check_for_definition_in_return_type (declarator, decl_specifiers->type); @@ -11263,10 +11267,6 @@ cp_parser_init_declarator (cp_parser* parser, /* Check to see whether or not this declaration is a friend. */ friend_p = cp_parser_friend_p (decl_specifiers); - /* Check that the number of template-parameter-lists is OK. */ - if (!cp_parser_check_declarator_template_parameters (parser, declarator)) - return error_mark_node; - /* Enter the newly declared entry in the symbol table. If we're processing a declaration in a class-specifier, we wait until after processing the initializer. */ @@ -15312,10 +15312,14 @@ cp_parser_check_declarator_template_parameters (cp_parser* parser, is correct; there shouldn't be a `template <>' for the definition of `S::f'. */ - if (CLASSTYPE_TEMPLATE_INFO (scope) - && (CLASSTYPE_TEMPLATE_INSTANTIATION (scope) - || uses_template_parms (CLASSTYPE_TI_ARGS (scope))) - && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (scope))) + if (!CLASSTYPE_TEMPLATE_INFO (scope)) + /* If SCOPE does not have template information of any + kind, then it is not a template, nor is it nested + within a template. */ + break; + if (explicit_class_specialization_p (scope)) + break; + if (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (scope))) ++num_templates; scope = TYPE_CONTEXT (scope); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index acaf6bce00f..2cfcce501d9 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -1316,6 +1316,17 @@ register_local_specialization (tree spec, tree tmpl) *slot = build_tree_list (spec, tmpl); } +/* TYPE is a class type. Returns true if TYPE is an explicitly + specialized class. */ + +bool +explicit_class_specialization_p (tree type) +{ + if (!CLASSTYPE_TEMPLATE_SPECIALIZATION (type)) + return false; + return !uses_template_parms (CLASSTYPE_TI_ARGS (type)); +} + /* Print the list of candidate FNS in an error message. */ void diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c5ab9b52fa7..d1e707cc094 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2006-12-07 Mark Mitchell + + PR c++/29732 + * g++.dg/template/crash65.C: New test. + * g++.dg/template/spec16.C: Tweak error markers. + 2006-12-07 Andrew Pinski * gcc.target/spu: New directory. diff --git a/gcc/testsuite/g++.dg/template/crash65.C b/gcc/testsuite/g++.dg/template/crash65.C new file mode 100644 index 00000000000..4d49ecf3145 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/crash65.C @@ -0,0 +1,7 @@ +// PR c++/29732 + +struct A +{ + template template friend void foo(T) {} // { dg-error "parameter" } + void bar() { foo(0); } // { dg-error "foo" } +}; diff --git a/gcc/testsuite/g++.dg/template/spec16.C b/gcc/testsuite/g++.dg/template/spec16.C index c5bd5a95426..881d7a091c2 100644 --- a/gcc/testsuite/g++.dg/template/spec16.C +++ b/gcc/testsuite/g++.dg/template/spec16.C @@ -7,5 +7,5 @@ struct A { template void B () ; }; -void A<0>::B<0>() { // { dg-error "explicit specialization" } +void A<0>::B<0>() { // { dg-error "parameter-lists" } }