diff options
author | Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net> | 2003-01-29 14:25:06 +0000 |
---|---|---|
committer | Kriang Lerdsuwanakij <lerdsuwa@gcc.gnu.org> | 2003-01-29 14:25:06 +0000 |
commit | 710b73e6f775809e5aeb26ede61ce8af61edc45a (patch) | |
tree | b36a2f8b18ee20da99ba21d4ba6ff7537045ee58 | |
parent | 2f12fb2b8b6b31c2cebc7b731d424bbdd1cfe22e (diff) | |
download | gcc-710b73e6f775809e5aeb26ede61ce8af61edc45a.zip gcc-710b73e6f775809e5aeb26ede61ce8af61edc45a.tar.gz gcc-710b73e6f775809e5aeb26ede61ce8af61edc45a.tar.bz2 |
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
-rw-r--r-- | gcc/cp/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/parser.c | 57 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/friend2.C | 16 |
4 files changed, 66 insertions, 19 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d84824d..359fdc2 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2003-01-29 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net> + + 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 <nathan@codesourcery.com> PR c++/9437 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 1561f4c..da9a92f 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 T> class C {}; + } + class X { + template <class T> friend class N::C; // #1, valid code + }; + template <class T> 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 <class T> 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 <typename T> struct B; @@ -13214,12 +13227,18 @@ cp_parser_maybe_treat_template_as_class (tree decl, bool tag_name_p) template <typename T> 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 <class T> 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 6c16728..fc39840 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2003-01-29 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net> + + PR c++/8591 + * g++.dg/parse/friend2.C: New test. + 2003-01-29 Nathan Sidwell <nathan@codesourcery.com> 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 0000000..2e88845 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/friend2.C @@ -0,0 +1,16 @@ +// { dg-do compile } +// Origin: <struppi@acm.org> + +// PR c++/8591 +// Template or class detection in friend declaration + +namespace NS { + template <class T1, class T2, class T3 = int, class T4 = int> + struct C {}; +} + +template <class T> class X { + friend class NS::C; // { dg-error "expected|friend" } +}; + +X<int> c; |