I noticed that we could leak parser->num_template_parameter_lists with
erroneous specializations. We'd increment, notice a problem and then
bail out. This refactors cp_parser_explicit_specialization to avoid
that code path. A couple of tests get different diagnostics because of
the fix. pr39425 then goes to unbounded template instantiation and
exceeds the implementation limit.
gcc/cp/
* parser.c (cp_parser_explicit_specialization): Refactor
to avoid leak of num_template_parameter_lists value.
gcc/testsuite/
* g++.dg/template/pr39425.C: Adjust errors, (unbounded
template recursion).
* g++.old-deja/g++.pt/spec20.C: Remove fallout diagnostics.
pushed,
nathan
--
Nathan Sidwell
diff --git i/gcc/cp/parser.c w/gcc/cp/parser.c
index ab088874ba7..9946acdb42f 100644
--- i/gcc/cp/parser.c
+++ w/gcc/cp/parser.c
@@ -17640,7 +17640,6 @@ cp_parser_explicit_instantiation (cp_parser* parser)
static void
cp_parser_explicit_specialization (cp_parser* parser)
{
- bool need_lang_pop;
cp_token *token = cp_lexer_peek_token (parser->lexer);
/* Look for the `template' keyword. */
@@ -17651,52 +17650,54 @@ cp_parser_explicit_specialization (cp_parser* parser)
cp_parser_require (parser, CPP_GREATER, RT_GREATER);
/* We have processed another parameter list. */
++parser->num_template_parameter_lists;
+
/* [temp]
A template ... explicit specialization ... shall not have C
linkage. */
- if (current_lang_name == lang_name_c)
+ bool need_lang_pop = current_lang_name == lang_name_c;
+ if (need_lang_pop)
{
error_at (token->location, "template specialization with C linkage");
maybe_show_extern_c_location ();
+
/* Give it C++ linkage to avoid confusing other parts of the
front end. */
push_lang_context (lang_name_cplusplus);
need_lang_pop = true;
}
- else
- need_lang_pop = false;
- /* Let the front end know that we are beginning a specialization. */
- if (!begin_specialization ())
- {
- end_specialization ();
- 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))
+ /* Let the front end know that we are beginning a specialization. */
+ if (begin_specialization ())
{
- if (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_LESS
- && cp_lexer_peek_nth_token (parser->lexer, 3)->type != CPP_GREATER)
- cp_parser_template_declaration_after_export (parser,
- /*member_p=*/false);
+ /* 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))
+ {
+ if (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_LESS
+ && cp_lexer_peek_nth_token (parser->lexer, 3)->type != CPP_GREATER)
+ cp_parser_template_declaration_after_export (parser,
+ /*member_p=*/false);
+ else
+ cp_parser_explicit_specialization (parser);
+ }
else
- cp_parser_explicit_specialization (parser);
+ /* Parse the dependent declaration. */
+ cp_parser_single_declaration (parser,
+ /*checks=*/NULL,
+ /*member_p=*/false,
+ /*explicit_specialization_p=*/true,
+ /*friend_p=*/NULL);
}
- else
- /* Parse the dependent declaration. */
- cp_parser_single_declaration (parser,
- /*checks=*/NULL,
- /*member_p=*/false,
- /*explicit_specialization_p=*/true,
- /*friend_p=*/NULL);
+
/* We're done with the specialization. */
end_specialization ();
+
/* For the erroneous case of a template with C linkage, we pushed an
implicit C++ linkage scope; exit that scope now. */
if (need_lang_pop)
pop_lang_context ();
+
/* We're done with this parameter list. */
--parser->num_template_parameter_lists;
}
diff --git i/gcc/testsuite/g++.dg/template/pr39425.C w/gcc/testsuite/g++.dg/template/pr39425.C
index d55f547e253..cd304896a61 100644
--- i/gcc/testsuite/g++.dg/template/pr39425.C
+++ w/gcc/testsuite/g++.dg/template/pr39425.C
@@ -5,14 +5,16 @@ class a {
template<unsigned int s>
struct _rec {
- static const char size = _rec< (s >> 1) >::size;
+ static const char size = _rec< (s >> 1) >::size; // { dg-error "depth" }
};
template<> // { dg-error "explicit" }
- struct _rec <0> {
+ struct _rec <0> { // { dg-error "too few" }
static const char size = 0;
};
static const unsigned int value = _rec < 1 >::size;
-} // { dg-error "after class definition" }
+};
+
+// { dg-prune-output "compilation terminated" }
diff --git i/gcc/testsuite/g++.old-deja/g++.pt/spec20.C w/gcc/testsuite/g++.old-deja/g++.pt/spec20.C
index 610e6c73371..51bc26906eb 100644
--- i/gcc/testsuite/g++.old-deja/g++.pt/spec20.C
+++ w/gcc/testsuite/g++.old-deja/g++.pt/spec20.C
@@ -10,7 +10,8 @@ struct S {
template <class U> void f(U);
template <> void f<int>(int); // { dg-error "20:template-id .f<int>. in declaration|explicit specialization" }
- template <class V> struct I {}; // { dg-error "template" }
- template <class V> struct I<V*> {}; // { dg-error "template" }
+ template <class V> struct I {};
+ template <class V> struct I<V*> {};
+
template <> struct I<int>; // { dg-error "" } invalid specialization
};