This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH: PR 29732


This patch fixes PR c++/29732, an ICE-on-invalid regiression.  We were
not checking that functions had the right number of template parameter
lists if they were defined in the class.  Fixing that exposed a bug in
the function that did that check: it was not stopping when it found an
explicit specialization, which could make it get the wrong answer, so
I fixed that too.

Tested on x86_64-unknown-linux-gnu, applied on the mainline.  I will
apply this to 4.2 and 4.1 when testing completes. 

--
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713

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_declarator_template_parameters): Stop looking for
	template classes when we find an explicit specialization.

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.

Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h	(revision 119478)
+++ gcc/cp/cp-tree.h	(working copy)
@@ -2879,8 +2879,14 @@ extern void decl_shadowed_for_var_insert
    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		(t
 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: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c	(revision 119500)
+++ gcc/cp/pt.c	(working copy)
@@ -1316,6 +1316,17 @@ register_local_specialization (tree spec
   *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: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 119601)
+++ gcc/cp/parser.c	(working copy)
@@ -11139,6 +11139,10 @@ cp_parser_init_declarator (cp_parser* pa
   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);
@@ -11258,10 +11262,6 @@ cp_parser_init_declarator (cp_parser* pa
   /* 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.  */
@@ -15307,10 +15307,14 @@ cp_parser_check_declarator_template_para
 
 		 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: gcc/testsuite/g++.dg/template/spec16.C
===================================================================
--- gcc/testsuite/g++.dg/template/spec16.C	(revision 119478)
+++ gcc/testsuite/g++.dg/template/spec16.C	(working copy)
@@ -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" }
 } 
Index: gcc/testsuite/g++.dg/template/crash65.C
===================================================================
--- gcc/testsuite/g++.dg/template/crash65.C	(revision 0)
+++ gcc/testsuite/g++.dg/template/crash65.C	(revision 0)
@@ -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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]