aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>2020-08-04 09:24:02 -0700
committerNathan Sidwell <nathan@acm.org>2020-08-04 09:32:18 -0700
commit0f4f9bc12201c9cda9558295a4fef58fe0246b44 (patch)
tree0fe04fa020cb1b07bb207d25f0ceaac11bec9ef9 /gcc/cp
parent35ffd4d16d7e3dbba297da788414a673530b7817 (diff)
downloadgcc-0f4f9bc12201c9cda9558295a4fef58fe0246b44.zip
gcc-0f4f9bc12201c9cda9558295a4fef58fe0246b44.tar.gz
gcc-0f4f9bc12201c9cda9558295a4fef58fe0246b44.tar.bz2
c++: fix template parm count leak
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.
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/parser.c51
1 files changed, 26 insertions, 25 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 7657145..1e7cd19 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -17653,7 +17653,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. */
@@ -17664,52 +17663,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;
}