re PR c++/8591 (g++ crashes while instantiating templates)
authorKriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
Wed, 29 Jan 2003 14:25:06 +0000 (14:25 +0000)
committerKriang Lerdsuwanakij <lerdsuwa@gcc.gnu.org>
Wed, 29 Jan 2003 14:25:06 +0000 (14:25 +0000)
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

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/parse/friend2.C [new file with mode: 0644]

index d84824dbf3d2579c8d43592174cf5b7ad5679fdc..359fdc2b064852dfcb8b0f2a648bd5be092e41bd 100644 (file)
@@ -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
index 1561f4ce0344bad1df2283f053b651a87b8da49a..da9a92fa126e893f402f34f924e4ff85a2b969ec 100644 (file)
@@ -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;
index 6c167282bd05be27c9c3c2a3f1367a57654edc6e..fc39840d455511abe68e7772e52e47d02bbe6ab0 100644 (file)
@@ -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 (file)
index 0000000..2e88845
--- /dev/null
@@ -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;