From: Kriang Lerdsuwanakij Date: Wed, 29 Jan 2003 14:25:06 +0000 (+0000) Subject: re PR c++/8591 (g++ crashes while instantiating templates) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=710b73e6f775809e5aeb26ede61ce8af61edc45a;p=gcc.git re PR c++/8591 (g++ crashes while instantiating templates) PR c++/8591 * parser.c (cp_parser_elaborated_type_specifier): Convert TEMPLATE_DECL to TYPE_DECL only when processing template friends. (cp_parser_maybe_treat_template_as_class): Remove redundant tests. * g++.dg/parse/friend2.C: New test. From-SVN: r62076 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d84824dbf3d..359fdc2b064 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2003-01-29 Kriang Lerdsuwanakij + + PR c++/8591 + * parser.c (cp_parser_elaborated_type_specifier): Convert + TEMPLATE_DECL to TYPE_DECL only when processing template friends. + (cp_parser_maybe_treat_template_as_class): Remove redundant tests. + 2003-01-28 Nathan Sidwell PR c++/9437 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 1561f4ce034..da9a92fa126 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -8660,8 +8660,31 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, /*is_type=*/true, /*is_namespace=*/false, /*check_dependency=*/true); + + /* If we are parsing friend declaration, DECL may be a + TEMPLATE_DECL tree node here. However, we need to check + whether this TEMPLATE_DECL results in valid code. Consider + the following example: + + namespace N { + template class C {}; + } + class X { + template friend class N::C; // #1, valid code + }; + template class Y { + friend class N::C; // #2, invalid code + }; + + For both case #1 and #2, we arrive at a TEMPLATE_DECL after + name lookup of `N::C'. We see that friend declaration must + be template for the code to be valid. Note that + processing_template_decl does not work here since it is + always 1 for the above two cases. */ + decl = (cp_parser_maybe_treat_template_as_class - (decl, /*tag_name_p=*/is_friend)); + (decl, /*tag_name_p=*/is_friend + && parser->num_template_parameter_lists)); if (TREE_CODE (decl) != TYPE_DECL) { @@ -13187,18 +13210,8 @@ cp_parser_resolve_typename_type (cp_parser* parser, tree type) static tree cp_parser_maybe_treat_template_as_class (tree decl, bool tag_name_p) { - /* If the DECL is a TEMPLATE_DECL for a class type, and we are in - the scope of the class, then treat the TEMPLATE_DECL as a - class-name. For example, in: - - template struct S { - S s; - }; - - is OK. - - If the TEMPLATE_DECL is being declared as part of a class-head, - the same translation occurs: + /* If the TEMPLATE_DECL is being declared as part of a class-head, + the translation from TEMPLATE_DECL to TYPE_DECL occurs: struct A { template struct B; @@ -13214,12 +13227,18 @@ cp_parser_maybe_treat_template_as_class (tree decl, bool tag_name_p) template friend struct N::X; }; - */ - if (DECL_CLASS_TEMPLATE_P (decl) - && (tag_name_p - || (current_class_type - && same_type_p (TREE_TYPE (DECL_TEMPLATE_RESULT (decl)), - current_class_type)))) + However, if the DECL refers to a class type, and we are in + the scope of the class, then the name lookup automatically + finds the TYPE_DECL created by build_self_reference rather + than a TEMPLATE_DECL. For example, in: + + template struct S { + S s; + }; + + there is no need to handle such case. */ + + if (DECL_CLASS_TEMPLATE_P (decl) && tag_name_p) return DECL_TEMPLATE_RESULT (decl); return decl; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6c167282bd0..fc39840d455 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2003-01-29 Kriang Lerdsuwanakij + + PR c++/8591 + * g++.dg/parse/friend2.C: New test. + 2003-01-29 Nathan Sidwell PR c++/9437 diff --git a/gcc/testsuite/g++.dg/parse/friend2.C b/gcc/testsuite/g++.dg/parse/friend2.C new file mode 100644 index 00000000000..2e88845cceb --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/friend2.C @@ -0,0 +1,16 @@ +// { dg-do compile } +// Origin: + +// PR c++/8591 +// Template or class detection in friend declaration + +namespace NS { + template + struct C {}; +} + +template class X { + friend class NS::C; // { dg-error "expected|friend" } +}; + +X c;