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 | |
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.
-rw-r--r-- | gcc/cp/parser.c | 51 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/pr39425.C | 8 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/spec20.C | 5 |
3 files changed, 34 insertions, 30 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; } diff --git a/gcc/testsuite/g++.dg/template/pr39425.C b/gcc/testsuite/g++.dg/template/pr39425.C index d55f547..cd30489 100644 --- a/gcc/testsuite/g++.dg/template/pr39425.C +++ b/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 a/gcc/testsuite/g++.old-deja/g++.pt/spec20.C b/gcc/testsuite/g++.old-deja/g++.pt/spec20.C index 610e6c7..51bc269 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/spec20.C +++ b/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 }; |