aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorKriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>2003-01-29 14:25:06 +0000
committerKriang Lerdsuwanakij <lerdsuwa@gcc.gnu.org>2003-01-29 14:25:06 +0000
commit710b73e6f775809e5aeb26ede61ce8af61edc45a (patch)
treeb36a2f8b18ee20da99ba21d4ba6ff7537045ee58 /gcc
parent2f12fb2b8b6b31c2cebc7b731d424bbdd1cfe22e (diff)
downloadgcc-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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/parser.c57
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/parse/friend2.C16
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;