re PR c++/29732 (ICE on invalid friend declaration)
authorMark Mitchell <mark@codesourcery.com>
Fri, 8 Dec 2006 06:27:22 +0000 (06:27 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Fri, 8 Dec 2006 06:27:22 +0000 (06:27 +0000)
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

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/parser.c
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/crash65.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/spec16.C

index 213550807c0a086b866e6af42cf60f6dfe52e85f..1a8d126bcf2e28fc5d5270948ab567b1fb18b168 100644 (file)
@@ -1,3 +1,14 @@
+2006-12-07  Mark Mitchell  <mark@codesourcery.com>
+
+       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  <lee.millward@codesourcery.com>
 
         PR c++/29980
index ae250bfbdfef4b14846b42baa47876c72f79c3a4..e59586bde77da4d7e4c28ad8cf13f10d7fb661e6 100644 (file)
@@ -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, int);
-     3=explicit instantiation, e.g. template int min<int> (int, int);
+
+     2=partial or explicit specialization, e.g.:
+
+        template <> int min<int> (int, int),
+
+     3=explicit instantiation, e.g.:
+  
+        template int min<int> (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);
index a0a6a1778550876aabfe4c01ff2fb5da12a9bdd0..d7611ed71ff14b76067d374bc9f25ca64c93751a 100644 (file)
@@ -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<int>::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);
index acaf6bce00f75cf29f4ca8243f74e43e93e8514e..2cfcce501d9f4383479f919307485c87e3107877 100644 (file)
@@ -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
index c5ab9b52fa7b09b7b52f15263fe2cbb7b27f37d3..d1e707cc09422464522e135ae25637c0d99f0306 100644 (file)
@@ -1,3 +1,9 @@
+2006-12-07  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/29732
+       * g++.dg/template/crash65.C: New test.
+       * g++.dg/template/spec16.C: Tweak error markers.
+
 2006-12-07  Andrew Pinski  <andrew_pinski@playstation.sony.com>
 
        * 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 (file)
index 0000000..4d49ecf
--- /dev/null
@@ -0,0 +1,7 @@
+// PR c++/29732
+
+struct A
+{
+  template<int> template<typename T> friend void foo(T) {} // { dg-error "parameter" }
+  void bar() { foo(0); } // { dg-error "foo" }
+};
index c5bd5a95426e8088e581af0f33b4a4a1f1bea590..881d7a091c299d2a92390a2ca0a646259f67b0fd 100644 (file)
@@ -7,5 +7,5 @@ struct A {
   template<int M> void B () ; 
 }; 
 
-void A<0>::B<0>() {    // { dg-error "explicit specialization" }
+void A<0>::B<0>() {    // { dg-error "parameter-lists" }
 }