diff options
author | Nathan Sidwell <nathan@acm.org> | 2020-08-04 09:24:02 -0700 |
---|---|---|
committer | Nathan Sidwell <nathan@acm.org> | 2020-08-04 09:32:18 -0700 |
commit | 0f4f9bc12201c9cda9558295a4fef58fe0246b44 (patch) | |
tree | 0fe04fa020cb1b07bb207d25f0ceaac11bec9ef9 /gcc/cp | |
parent | 35ffd4d16d7e3dbba297da788414a673530b7817 (diff) | |
download | gcc-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.c | 51 |
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; } |