aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2006-12-08 06:27:22 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2006-12-08 06:27:22 +0000
commit9ba7a2f2926541d4db21c6df15acc783b73e1f4f (patch)
tree7ba5569ae3e14325934f7a9e8cdf809c494d4870
parentcf71109bd6749b28e07670d2cf8eb7d3c216f531 (diff)
downloadgcc-9ba7a2f2926541d4db21c6df15acc783b73e1f4f.zip
gcc-9ba7a2f2926541d4db21c6df15acc783b73e1f4f.tar.gz
gcc-9ba7a2f2926541d4db21c6df15acc783b73e1f4f.tar.bz2
re PR c++/29732 (ICE on invalid friend declaration)
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
-rw-r--r--gcc/cp/ChangeLog11
-rw-r--r--gcc/cp/cp-tree.h11
-rw-r--r--gcc/cp/parser.c20
-rw-r--r--gcc/cp/pt.c11
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/template/crash65.C7
-rw-r--r--gcc/testsuite/g++.dg/template/spec16.C2
7 files changed, 57 insertions, 11 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 2135508..1a8d126 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index ae250bf..e59586b 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index a0a6a17..d7611ed 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index acaf6bc..2cfcce5 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c5ab9b5..d1e707c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..4d49ecf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/crash65.C
@@ -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" }
+};
diff --git a/gcc/testsuite/g++.dg/template/spec16.C b/gcc/testsuite/g++.dg/template/spec16.C
index c5bd5a9..881d7a0 100644
--- a/gcc/testsuite/g++.dg/template/spec16.C
+++ b/gcc/testsuite/g++.dg/template/spec16.C
@@ -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" }
}