From patchwork Thu Oct 31 09:47:02 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adam Butcher X-Patchwork-Id: 287961 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 1EB252C00D0 for ; Sat, 2 Nov 2013 21:03:51 +1100 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:in-reply-to:references; q=dns; s= default; b=HKaM0juoRIukBSpNCIM7uojIaR2uGMW3ZzxOqg096p9QBILN/Edp/ 7mBNiY/NVxbaUcGcETGMnI6l3sWfNuo62rDtWwADP6BKjp+OI+5xh4ZMSkzX0ONY VrOWVDNIRcun3geFJwoTEsxA6kyMfbXOj4E5KtOZasIraQeucPz/oQ= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:in-reply-to:references; s= default; bh=B5L5H4NmnU7g6EtWiU2cJUWaHtE=; b=UBbwnQ0x7lXBEmW0/G49 FWdXavAPXFxIpMzWsOY9eHEHaov20imgGr0xygwefdnxiipr7/PLe4FP4EKMK0aV 8SQ/jZoFGAUVqAegRJxoIbOis1VvnaHbWfFAD7wSCyl1KmI9E7RgxPnh1Pu5owkE VRUimG83DuVl+xE81cJMi0E= Received: (qmail 13535 invoked by alias); 2 Nov 2013 10:03:25 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 13436 invoked by uid 89); 2 Nov 2013 10:03:25 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.4 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-Spam-User: qpsmtpd, 2 recipients X-HELO: mail-wg0-f50.google.com Received: from mail-wg0-f50.google.com (HELO mail-wg0-f50.google.com) (74.125.82.50) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Sat, 02 Nov 2013 10:03:20 +0000 Received: by mail-wg0-f50.google.com with SMTP id n12so430936wgh.5 for ; Sat, 02 Nov 2013 03:03:17 -0700 (PDT) X-Received: by 10.180.9.139 with SMTP id z11mr5464341wia.22.1383386597082; Sat, 02 Nov 2013 03:03:17 -0700 (PDT) Received: from sphere.lan (munkyhouse.force9.co.uk. [84.92.244.81]) by mx.google.com with ESMTPSA id dn2sm14732694wid.1.2013.11.02.03.03.15 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sat, 02 Nov 2013 03:03:16 -0700 (PDT) From: Adam Butcher To: Jason Merrill Cc: gcc-patches@gcc.gnu.org, Volker Reichelt , Adam Butcher Subject: [C++ PATCH 1/3] Refactor implicit function template implementation and fix 58534, 58536, 58548, 58549 and 58637. Date: Thu, 31 Oct 2013 09:47:02 +0000 Message-Id: <1383212824-5493-2-git-send-email-adam@jessamine.co.uk> In-Reply-To: <1383212824-5493-1-git-send-email-adam@jessamine.co.uk> References: <1383212824-5493-1-git-send-email-adam@jessamine.co.uk> gcc/ * tree.c (grow_tree_vec_stat): New function ... * tree.h (grow_tree_vec_stat) (grow_tree_vec): ... and its declaration and macro front-end. gcc/cp/ PR c++/58534 PR c++/58536 PR c++/58548 PR c++/58549 PR c++/58637 * parser.h (struct cp_parser): New members implicit_template_parms, implicit_template_scope and auto_is_implicit_function_template_parm_p. * parser.c (add_implicit_template_parms): Refactor as ... (synthesize_implicit_template_parm): ... this to append a new template type parm to the current template parameter list (introducing a new list if necessary). (cp_parser_new): Initialize new cp_parser members. (cp_parser_parameter_declaration_clause): Consider auto as implicit template parm when parsing a parameter declaration (unless paring an explicit specialization). (cp_parser_parameter_declaration_list): Remove local implicit_template_parms counter and reset cp_parser implicit template state when complete. (cp_parser_lambda_expression): Reset implicit template cp_parser members whilst generating lambda class. (cp_parser_function_definition_after_declarator): Reset implicit template cp_parser members whilst parsing function definition. (make_generic_type_name): Respell '' as 'auto:N' which works better with template diagnostics. (cp_parser_simple_type_specifier): Synthesize implicit template parm on parsing 'auto' if auto_is_implicit_function_template_parm_p and provide diagnostics ... * decl.c (grokdeclarator): ... that were previously done here. gcc/testsuite/g++.dg/ * cpp1y/pr58534.C: New testcase. * cpp1y/pr58536.C: New testcase. * cpp1y/pr58548.C: New testcase. * cpp1y/pr58549.C: New testcase. * cpp1y/pr58637.C: New testcase. --- gcc/cp/decl.c | 30 +--- gcc/cp/parser.c | 278 +++++++++++++++++++++++------------ gcc/cp/parser.h | 19 +++ gcc/testsuite/g++.dg/cpp1y/pr58534.C | 9 ++ gcc/testsuite/g++.dg/cpp1y/pr58536.C | 12 ++ gcc/testsuite/g++.dg/cpp1y/pr58548.C | 10 ++ gcc/testsuite/g++.dg/cpp1y/pr58549.C | 10 ++ gcc/testsuite/g++.dg/cpp1y/pr58637.C | 7 + gcc/tree.c | 22 +++ gcc/tree.h | 5 + 10 files changed, 281 insertions(+), 121 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr58534.C create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr58536.C create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr58548.C create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr58549.C create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr58637.C diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 09c1daa..786814c 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -10375,33 +10375,11 @@ grokdeclarator (const cp_declarator *declarator, if (type_uses_auto (type)) { - if (template_parm_flag) - { - error ("template parameter declared %"); - type = error_mark_node; - } - else if (decl_context == CATCHPARM) - { - error ("catch parameter declared %"); - type = error_mark_node; - } - else if (current_class_type && LAMBDA_TYPE_P (current_class_type)) - { - if (cxx_dialect < cxx1y) - pedwarn (location_of (type), 0, - "use of % in lambda parameter declaration " - "only available with " - "-std=c++1y or -std=gnu++1y"); - } - else if (cxx_dialect < cxx1y) - pedwarn (location_of (type), 0, - "use of % in parameter declaration " - "only available with " - "-std=c++1y or -std=gnu++1y"); + if (cxx_dialect >= cxx1y) + error ("% parameter not permitted in this context"); else - pedwarn (location_of (type), OPT_Wpedantic, - "ISO C++ forbids use of % in parameter " - "declaration"); + error ("parameter declared %"); + type = error_mark_node; } /* A parameter declared as an array of T is really a pointer to T. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index bbc8e75..b699ac4 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -2107,8 +2107,8 @@ static bool cp_parser_ctor_initializer_opt_and_function_body static tree cp_parser_late_parsing_omp_declare_simd (cp_parser *, tree); -static tree add_implicit_template_parms - (cp_parser *, size_t, tree); +static tree synthesize_implicit_template_parm + (cp_parser *); static tree finish_fully_implicit_template (cp_parser *, tree); @@ -3443,7 +3443,10 @@ cp_parser_new (void) parser->num_template_parameter_lists = 0; /* Not declaring an implicit function template. */ + parser->auto_is_implicit_function_template_parm_p = false; parser->fully_implicit_function_template_p = false; + parser->implicit_template_parms = 0; + parser->implicit_template_scope = 0; return parser; } @@ -8617,12 +8620,17 @@ cp_parser_lambda_expression (cp_parser* parser) = parser->num_template_parameter_lists; unsigned char in_statement = parser->in_statement; bool in_switch_statement_p = parser->in_switch_statement_p; - bool fully_implicit_function_template_p = parser->fully_implicit_function_template_p; + bool fully_implicit_function_template_p + = parser->fully_implicit_function_template_p; + tree implicit_template_parms = parser->implicit_template_parms; + cp_binding_level* implicit_template_scope = parser->implicit_template_scope; parser->num_template_parameter_lists = 0; parser->in_statement = 0; parser->in_switch_statement_p = false; parser->fully_implicit_function_template_p = false; + parser->implicit_template_parms = 0; + parser->implicit_template_scope = 0; /* By virtue of defining a local class, a lambda expression has access to the private variables of enclosing classes. */ @@ -8646,7 +8654,10 @@ cp_parser_lambda_expression (cp_parser* parser) parser->num_template_parameter_lists = saved_num_template_parameter_lists; parser->in_statement = in_statement; parser->in_switch_statement_p = in_switch_statement_p; - parser->fully_implicit_function_template_p = fully_implicit_function_template_p; + parser->fully_implicit_function_template_p + = fully_implicit_function_template_p; + parser->implicit_template_parms = implicit_template_parms; + parser->implicit_template_scope = implicit_template_scope; } pop_deferring_access_checks (); @@ -14053,7 +14064,7 @@ cp_parser_explicit_specialization (cp_parser* parser) cp_parser_single_declaration (parser, /*checks=*/NULL, /*member_p=*/false, - /*explicit_specialization_p=*/true, + /*explicit_specialization_p=*/true, /*friend_p=*/NULL); /* We're done with the specialization. */ end_specialization (); @@ -14355,10 +14366,33 @@ cp_parser_simple_type_specifier (cp_parser* parser, case RID_VOID: type = void_type_node; break; - + case RID_AUTO: maybe_warn_cpp0x (CPP0X_AUTO); - type = make_auto (); + if (parser->auto_is_implicit_function_template_parm_p) + { + type = synthesize_implicit_template_parm (parser); + + if (current_class_type && LAMBDA_TYPE_P (current_class_type)) + { + if (cxx_dialect < cxx1y) + pedwarn (location_of (type), 0, + "use of % in lambda parameter declaration " + "only available with " + "-std=c++1y or -std=gnu++1y"); + } + else if (cxx_dialect < cxx1y) + pedwarn (location_of (type), 0, + "use of % in parameter declaration " + "only available with " + "-std=c++1y or -std=gnu++1y"); + else + pedwarn (location_of (type), OPT_Wpedantic, + "ISO C++ forbids use of % in parameter " + "declaration"); + } + else + type = make_auto (); break; case RID_DECLTYPE: @@ -17937,6 +17971,20 @@ cp_parser_parameter_declaration_clause (cp_parser* parser) bool ellipsis_p; bool is_error; + struct cleanup { + cp_parser* parser; + int auto_is_implicit_function_template_parm_p; + ~cleanup() { + parser->auto_is_implicit_function_template_parm_p + = auto_is_implicit_function_template_parm_p; + } + } cleanup = { parser, parser->auto_is_implicit_function_template_parm_p }; + + (void) cleanup; + + if (!processing_specialization) + parser->auto_is_implicit_function_template_parm_p = true; + /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); /* Check for trivial parameter-declaration-clauses. */ @@ -18024,7 +18072,6 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error) tree *tail = ¶meters; bool saved_in_unbraced_linkage_specification_p; int index = 0; - int implicit_template_parms = 0; /* Assume all will go well. */ *is_error = false; @@ -18052,18 +18099,11 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error) deprecated_state = DEPRECATED_SUPPRESS; if (parameter) - { - decl = grokdeclarator (parameter->declarator, - ¶meter->decl_specifiers, - PARM, - parameter->default_argument != NULL_TREE, - ¶meter->decl_specifiers.attributes); - - if (TREE_TYPE (decl) != error_mark_node - && parameter->decl_specifiers.type - && is_auto_or_concept (parameter->decl_specifiers.type)) - ++implicit_template_parms; - } + decl = grokdeclarator (parameter->declarator, + ¶meter->decl_specifiers, + PARM, + parameter->default_argument != NULL_TREE, + ¶meter->decl_specifiers.attributes); deprecated_state = DEPRECATED_NORMAL; @@ -18151,10 +18191,12 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error) parser->in_unbraced_linkage_specification_p = saved_in_unbraced_linkage_specification_p; - if (parameters != error_mark_node && implicit_template_parms) - parameters = add_implicit_template_parms (parser, - implicit_template_parms, - parameters); + if (cp_binding_level *its = parser->implicit_template_scope) + if (current_binding_level->level_chain == its) + { + parser->implicit_template_parms = 0; + parser->implicit_template_scope = 0; + } return parameters; } @@ -22406,6 +22448,15 @@ cp_parser_function_definition_after_declarator (cp_parser* parser, bool saved_in_function_body; unsigned saved_num_template_parameter_lists; cp_token *token; + bool fully_implicit_function_template_p + = parser->fully_implicit_function_template_p; + parser->fully_implicit_function_template_p = false; + tree implicit_template_parms + = parser->implicit_template_parms; + parser->implicit_template_parms = 0; + cp_binding_level* implicit_template_scope + = parser->implicit_template_scope; + parser->implicit_template_scope = 0; saved_in_function_body = parser->in_function_body; parser->in_function_body = true; @@ -22478,6 +22529,13 @@ cp_parser_function_definition_after_declarator (cp_parser* parser, = saved_num_template_parameter_lists; parser->in_function_body = saved_in_function_body; + parser->fully_implicit_function_template_p + = fully_implicit_function_template_p; + parser->implicit_template_parms + = implicit_template_parms; + parser->implicit_template_scope + = implicit_template_scope; + if (parser->fully_implicit_function_template_p) finish_fully_implicit_template (parser, /*member_decl_opt=*/0); @@ -31011,7 +31069,7 @@ static tree make_generic_type_name () { char buf[32]; - sprintf (buf, "", ++generic_parm_count); + sprintf (buf, "auto:%d", ++generic_parm_count); return get_identifier (buf); } @@ -31025,110 +31083,140 @@ tree_type_is_auto_or_concept (const_tree t) return TREE_TYPE (t) && is_auto_or_concept (TREE_TYPE (t)); } -/* Add EXPECT_COUNT implicit template parameters gleaned from the generic - type parameters in PARAMETERS to the CURRENT_TEMPLATE_PARMS (creating a new - template parameter list if necessary). Returns PARAMETERS suitably rewritten - to reference the newly created types or ERROR_MARK_NODE on failure. */ +/* Add an implicit template type parameter to the CURRENT_TEMPLATE_PARMS + (creating a new template parameter list if necessary). Returns the newly + created template type parm. */ tree -add_implicit_template_parms (cp_parser *parser, size_t expect_count, - tree parameters) +synthesize_implicit_template_parm (cp_parser *parser) { gcc_assert (current_binding_level->kind == sk_function_parms); - cp_binding_level *fn_parms_scope = current_binding_level; - - bool become_template = - fn_parms_scope->level_chain->kind != sk_template_parms; - - size_t synth_count = 0; + /* We are either continuing a function template that already contains implicit + template parameters, creating a new fully-implicit function template, or + extending an existing explicit function template with implicit template + parameters. */ - /* Roll back a scope level and either introduce a new template parameter list - or update an existing one. The function scope is added back after template - parameter synthesis below. */ - current_binding_level = fn_parms_scope->level_chain; + cp_binding_level *const entry_scope = current_binding_level; - /* TPARMS tracks the function's template parameter list. This is either a new - chain in the case of a fully implicit function template or an extension of - the function's explicitly specified template parameter list. */ - tree tparms = NULL_TREE; + bool become_template = false; + cp_binding_level *parent_scope = 0; - if (become_template) + if (parser->implicit_template_scope) { - push_deferring_access_checks (dk_deferred); - begin_template_parm_list (); + gcc_assert (parser->implicit_template_parms); - parser->fully_implicit_function_template_p = true; - ++parser->num_template_parameter_lists; + current_binding_level = parser->implicit_template_scope; } else { - /* Roll back the innermost template parameter list such that it may be - extended in the loop below as if it were being explicitly declared. */ - - gcc_assert (current_template_parms); + /* Roll back to the existing template parameter scope (in the case of + extending an explicit function template) or introduce a new template + parameter scope ahead of the function parameter scope (or class scope + in the case of out-of-line member definitions). The function scope is + added back after template parameter synthesis below. */ - /* Pop the innermost template parms into TPARMS. */ - tree inner_vec = INNERMOST_TEMPLATE_PARMS (current_template_parms); - current_template_parms = TREE_CHAIN (current_template_parms); + cp_binding_level *scope = entry_scope; - size_t inner_vec_len = TREE_VEC_LENGTH (inner_vec); - if (inner_vec_len != 0) + while (scope->kind == sk_function_parms) { - tree t = tparms = TREE_VEC_ELT (inner_vec, 0); - for (size_t n = 1; n < inner_vec_len; ++n) - t = TREE_CHAIN (t) = TREE_VEC_ELT (inner_vec, n); + parent_scope = scope; + scope = scope->level_chain; } + if (current_class_type && !LAMBDA_TYPE_P (current_class_type) + && parser->num_classes_being_defined == 0) + while (scope->kind == sk_class) + { + parent_scope = scope; + scope = scope->level_chain; + } - ++processing_template_parmlist; - } + current_binding_level = scope; - for (tree p = parameters; p && synth_count < expect_count; p = TREE_CHAIN (p)) - { - tree generic_type_ptr - = find_type_usage (TREE_VALUE (p), tree_type_is_auto_or_concept); - - if (!generic_type_ptr) - continue; + if (scope->kind != sk_template_parms) + { + /* Introduce a new template parameter list for implicit template + parameters. */ - ++synth_count; + become_template = true; - tree synth_id = make_generic_type_name (); - tree synth_tmpl_parm = finish_template_type_parm (class_type_node, - synth_id); - tparms = process_template_parm (tparms, DECL_SOURCE_LOCATION (TREE_VALUE - (p)), - build_tree_list (NULL_TREE, - synth_tmpl_parm), - /*non_type=*/false, - /*param_pack=*/false); + push_deferring_access_checks (dk_deferred); - /* Rewrite the type of P to be the template_parm added above (getdecls is - used to retrieve it since it is the most recent declaration in this - scope). Qualifiers need to be preserved also. */ + parser->implicit_template_scope + = begin_scope (sk_template_parms, NULL); - tree& cur_type = TREE_TYPE (generic_type_ptr); - tree new_type = TREE_TYPE (getdecls ()); + ++processing_template_decl; - if (TYPE_QUALS (cur_type)) - cur_type = cp_build_qualified_type (new_type, TYPE_QUALS (cur_type)); + parser->fully_implicit_function_template_p = true; + ++parser->num_template_parameter_lists; + } else - cur_type = new_type; + { + /* Synthesize implicit template parameters at the end of the explicit + template parameter list. */ + + gcc_assert (current_template_parms); + + parser->implicit_template_scope = scope; + + tree v = INNERMOST_TEMPLATE_PARMS (current_template_parms); + parser->implicit_template_parms + = TREE_VEC_ELT (v, TREE_VEC_LENGTH (v) - 1); + } } - gcc_assert (synth_count == expect_count); + /* Synthesize a new template parameter and track the current template + parameter chain with implicit_template_parms. */ - push_binding_level (fn_parms_scope); + tree synth_id = make_generic_type_name (); + tree synth_tmpl_parm = finish_template_type_parm (class_type_node, + synth_id); + tree new_parm + = process_template_parm (parser->implicit_template_parms, + input_location, + build_tree_list (NULL_TREE, synth_tmpl_parm), + /*non_type=*/false, + /*param_pack=*/false); - end_template_parm_list (tparms); - return parameters; + if (parser->implicit_template_parms) + parser->implicit_template_parms + = TREE_CHAIN (parser->implicit_template_parms); + else + parser->implicit_template_parms = new_parm; + + tree new_type = TREE_TYPE (getdecls ()); + + /* If creating a fully implicit function template, start the new implicit + template parameter list with this synthesized type, otherwise grow the + current template parameter list. */ + + if (become_template) + { + parent_scope->level_chain = current_binding_level; + + tree new_parms = make_tree_vec (1); + TREE_VEC_ELT (new_parms, 0) = parser->implicit_template_parms; + current_template_parms = tree_cons (size_int (processing_template_decl), + new_parms, current_template_parms); + } + else + { + tree& new_parms = INNERMOST_TEMPLATE_PARMS (current_template_parms); + int new_parm_idx = TREE_VEC_LENGTH (new_parms); + new_parms = grow_tree_vec_stat (new_parms, new_parm_idx + 1); + TREE_VEC_ELT (new_parms, new_parm_idx) = parser->implicit_template_parms; + } + + current_binding_level = entry_scope; + + return new_type; } /* Finish the declaration of a fully implicit function template. Such a template has no explicit template parameter list so has not been through the - normal template head and tail processing. add_implicit_template_parms tries - to do the head; this tries to do the tail. MEMBER_DECL_OPT should be + normal template head and tail processing. synthesize_implicit_template_parm + tries to do the head; this tries to do the tail. MEMBER_DECL_OPT should be provided if the declaration is a class member such that its template declaration can be completed. If MEMBER_DECL_OPT is provided the finished form is returned. Otherwise NULL_TREE is returned. */ diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h index 75f327b..1024024 100644 --- a/gcc/cp/parser.h +++ b/gcc/cp/parser.h @@ -360,11 +360,30 @@ typedef struct GTY(()) cp_parser { data structure with everything needed for parsing the clauses. */ cp_omp_declare_simd_data * GTY((skip)) omp_declare_simd; + /* Nonzero if parsing a parameter list where 'auto' should trigger an implicit + template parameter. */ + bool auto_is_implicit_function_template_parm_p; + /* TRUE if the function being declared was made a template due to its parameter list containing generic type specifiers (`auto' or concept identifiers) rather than an explicit template parameter list. */ bool fully_implicit_function_template_p; + /* Tracks the function's template parameter list when declaring a function + using generic type parameters. This is either a new chain in the case of a + fully implicit function template or an extension of the function's existing + template parameter list. This is tracked to optimize calls subsequent + calls to synthesize_implicit_template_parm during + cp_parser_parameter_declaration. */ + tree implicit_template_parms; + + /* The scope into which an implicit template parameter list has been + introduced or an existing template parameter list is being extended with + implicit template paramaters. In most cases this is the sk_function_parms + scope containing the use of a generic type. In the case of an out-of-line + member definition using a generic type, it is the sk_class scope. */ + cp_binding_level* implicit_template_scope; + } cp_parser; /* In parser.c */ diff --git a/gcc/testsuite/g++.dg/cpp1y/pr58534.C b/gcc/testsuite/g++.dg/cpp1y/pr58534.C new file mode 100644 index 0000000..4aa4f43 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/pr58534.C @@ -0,0 +1,9 @@ +// { dg-do compile } +// { dg-options "-std=gnu++1y" } + +// PR c++/58534 + +template void foo(const auto&) {} + +template void foo(const auto&, T...) {} + diff --git a/gcc/testsuite/g++.dg/cpp1y/pr58536.C b/gcc/testsuite/g++.dg/cpp1y/pr58536.C new file mode 100644 index 0000000..8050c19 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/pr58536.C @@ -0,0 +1,12 @@ +// { dg-do compile } +// { dg-options "-std=gnu++1y" } + +// PR c++/58536 + +struct A +{ + A(auto); +}; + +A::A(auto) {} + diff --git a/gcc/testsuite/g++.dg/cpp1y/pr58548.C b/gcc/testsuite/g++.dg/cpp1y/pr58548.C new file mode 100644 index 0000000..0ac2e1c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/pr58548.C @@ -0,0 +1,10 @@ +// { dg-do compile } +// { dg-options "-std=gnu++1y" } + +// PR c++/58548 + +void foo(auto) +{ + struct A { int i; }; +} + diff --git a/gcc/testsuite/g++.dg/cpp1y/pr58549.C b/gcc/testsuite/g++.dg/cpp1y/pr58549.C new file mode 100644 index 0000000..b71bac9 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/pr58549.C @@ -0,0 +1,10 @@ +// { dg-do compile } +// { dg-options "-std=gnu++1y" } + +// PR c++/58549 + +void foo(auto) +{ + void bar(); +} + diff --git a/gcc/testsuite/g++.dg/cpp1y/pr58637.C b/gcc/testsuite/g++.dg/cpp1y/pr58637.C new file mode 100644 index 0000000..46200ff --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/pr58637.C @@ -0,0 +1,7 @@ +// { dg-do compile } +// { dg-options "-std=gnu++1y" } + +// PR c++/58637 + +template<> void foo(auto); // { dg-error "auto|not a template" } + diff --git a/gcc/tree.c b/gcc/tree.c index 332751a..28cbba8 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -1940,6 +1940,28 @@ make_tree_vec_stat (int len MEM_STAT_DECL) return t; } + +/* Grow a TREE_VEC node to new length LEN. */ + +tree +grow_tree_vec_stat (tree v, int len MEM_STAT_DECL) +{ + gcc_assert (TREE_CODE (v) == TREE_VEC); + + int oldlen = TREE_VEC_LENGTH (v); + gcc_assert (len > oldlen); + + int oldlength = (oldlen - 1) * sizeof (tree) + sizeof (struct tree_vec); + int length = (len - 1) * sizeof (tree) + sizeof (struct tree_vec); + + record_node_allocation_statistics (TREE_VEC, length - oldlength); + + v = (tree) ggc_realloc_stat (v, length PASS_MEM_STAT); + + TREE_VEC_LENGTH (v) = len; + + return v; +} /* Return 1 if EXPR is the integer constant zero or a complex constant of zero. */ diff --git a/gcc/tree.h b/gcc/tree.h index 920ad07..8ca89d9 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -3412,6 +3412,11 @@ extern tree make_tree_binfo_stat (unsigned MEM_STAT_DECL); extern tree make_tree_vec_stat (int MEM_STAT_DECL); #define make_tree_vec(t) make_tree_vec_stat (t MEM_STAT_INFO) +/* Grow a TREE_VEC. */ + +extern tree grow_tree_vec_stat (tree v, int MEM_STAT_DECL); +#define grow_tree_vec(v, t) grow_tree_vec_stat (v, t MEM_STAT_INFO) + /* Return the (unique) IDENTIFIER_NODE node for a given name. The name is supplied as a char *. */