aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLee Millward <lee.millward@codesourcery.com>2006-09-25 19:58:10 +0000
committerLee Millward <lmillward@gcc.gnu.org>2006-09-25 19:58:10 +0000
commit9b910171a09f1ea69821c0c8a7f53cc0c33401f7 (patch)
tree2c56dcc26e3d0df9849f035f979db2f24b1c0063
parent60feef2c2dd41cc6c6e9cd492c3e1199595326d8 (diff)
downloadgcc-9b910171a09f1ea69821c0c8a7f53cc0c33401f7.zip
gcc-9b910171a09f1ea69821c0c8a7f53cc0c33401f7.tar.gz
gcc-9b910171a09f1ea69821c0c8a7f53cc0c33401f7.tar.bz2
re PR c++/27667 (ICE with in-class specialization)
PR c++/27667 * cp-tree.h (begin_specialization): Return bool instead of void. * pt.c (check_specialization_scope): Likwise. Adjust comment. Return false if a specialization isn't permitted in the current scope,. (begin_specialization): Use the return value of check_specialization_scope. * parser.c (cp_parser_explicit_specialization): If begin_specialization returned false, skip the rest of the specialization. * g++.dg/template/spec33.C: New test. * g++.old-deja/g++.pt/spec20.C: Adjust error markers. From-SVN: r117206
-rw-r--r--gcc/cp/ChangeLog12
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/parser.c8
-rw-r--r--gcc/cp/pt.c23
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/template/spec33.C7
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/spec20.C4
7 files changed, 49 insertions, 11 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a41714c..46bfeb8 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -8,6 +8,18 @@
Return false on error.
* decl.c (xref_tag): Return error_mark_node if
redeclare_class_template returned false.
+
+ PR c++/27667
+ * cp-tree.h (begin_specialization): Return bool
+ instead of void.
+ * pt.c (check_specialization_scope): Likwise.
+ Adjust comment. Return false if a specialization
+ isn't permitted in the current scope.
+ (begin_specialization): Use the return value of
+ check_specialization_scope.
+ * parser.c (cp_parser_explicit_specialization): If
+ begin_specialization returned false, skip the rest
+ of the specialization.
2006-09-21 Mark Mitchell <mark@codesourcery.com>
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 227fc9d..93c4053 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4086,7 +4086,7 @@ extern void maybe_begin_member_template_processing (tree);
extern void maybe_end_member_template_processing (void);
extern tree finish_member_template_decl (tree);
extern void begin_template_parm_list (void);
-extern void begin_specialization (void);
+extern bool begin_specialization (void);
extern void reset_specialization (void);
extern void end_specialization (void);
extern void begin_explicit_instantiation (void);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index d020520..0b7dd3c 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -9455,7 +9455,13 @@ cp_parser_explicit_specialization (cp_parser* parser)
else
need_lang_pop = false;
/* Let the front end know that we are beginning a specialization. */
- begin_specialization ();
+ if (!begin_specialization ())
+ {
+ end_specialization ();
+ cp_parser_skip_to_end_of_block_or_statement (parser);
+ return;
+ }
+
/* If the next keyword is `template', we need to figure out whether
or not we're looking a template-declaration. */
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TEMPLATE))
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index daee252..4e8fad6 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -142,7 +142,7 @@ static tree most_specialized_class (tree, tree);
static tree tsubst_aggr_type (tree, tree, tsubst_flags_t, tree, int);
static tree tsubst_arg_types (tree, tree, tsubst_flags_t, tree);
static tree tsubst_function_type (tree, tree, tsubst_flags_t, tree);
-static void check_specialization_scope (void);
+static bool check_specialization_scope (void);
static tree process_partial_specialization (tree);
static void set_current_access_from_decl (tree);
static void check_default_tmpl_args (tree, tree, int, int);
@@ -535,9 +535,10 @@ begin_template_parm_list (void)
}
/* This routine is called when a specialization is declared. If it is
- invalid to declare a specialization here, an error is reported. */
+ invalid to declare a specialization here, an error is reported and
+ false is returned, otherwise this routine will return true. */
-static void
+static bool
check_specialization_scope (void)
{
tree scope = current_scope ();
@@ -552,7 +553,10 @@ check_specialization_scope (void)
shall be declared in the namespace of which the class template
is a member. */
if (scope && TREE_CODE (scope) != NAMESPACE_DECL)
- error ("explicit specialization in non-namespace scope %qD", scope);
+ {
+ error ("explicit specialization in non-namespace scope %qD", scope);
+ return false;
+ }
/* [temp.expl.spec]
@@ -563,17 +567,22 @@ check_specialization_scope (void)
explicitly specialize a class member template if its enclosing
class templates are not explicitly specialized as well. */
if (current_template_parms)
- error ("enclosing class templates are not explicitly specialized");
+ {
+ error ("enclosing class templates are not explicitly specialized");
+ return false;
+ }
+
+ return true;
}
/* We've just seen template <>. */
-void
+bool
begin_specialization (void)
{
begin_scope (sk_template_spec, NULL);
note_template_header (1);
- check_specialization_scope ();
+ return check_specialization_scope ();
}
/* Called at then end of processing a declaration preceded by
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a511e56..4fc16e5 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -9,6 +9,10 @@
PR c++/27329
* g++.dg/template/crash59.C: New test.
+
+ PR c++/27667
+ * g++.dg/template/spec33.C: New test.
+ * g++.old-deja/g++.pt/spec20.C: Adjust error markers.
2006-09-24 Zdenek Dvorak <dvorakz@suse.cz>
Adam Nemet <anemet@caviumnetworks.com>
diff --git a/gcc/testsuite/g++.dg/template/spec33.C b/gcc/testsuite/g++.dg/template/spec33.C
new file mode 100644
index 0000000..809d4f0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/spec33.C
@@ -0,0 +1,7 @@
+//PR c++/27667
+
+struct A
+{
+ template<int> static void foo () {}
+ template<> static void foo<0>() {} // { dg-error "explicit" }
+};
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec20.C b/gcc/testsuite/g++.old-deja/g++.pt/spec20.C
index 064ce14..b6148e5 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/spec20.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/spec20.C
@@ -10,7 +10,7 @@ struct S {
template <class U> void f(U);
template <> void f<int>(int); // { dg-error "" } invalid specialization
- template <class V> struct I {};
- template <class V> struct I<V*> {};
+ template <class V> struct I {}; // { dg-error "template" }
+ template <class V> struct I<V*> {}; // { dg-error "template" }
template <> struct I<int>; // { dg-error "" } invalid specialization
};