From patchwork Thu Aug 1 12:25:28 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adam Butcher X-Patchwork-Id: 264422 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 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "localhost", Issuer "www.qmailtoaster.com" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 706432C0091 for ; Sat, 3 Aug 2013 23:30:12 +1000 (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=iSkpQvIcUYSSgwfJGbRD7mXC7JO82FCRaJWlzJz5tZ7uCrPqmm/2V 8v6KtFkMuhZSHflJyX/1vXJsNHKW6YQOHfmcNLOYvcffZYrySiom/SGHVH5/pb4K pzelR89xFi5jpsKzV7e6I/6dJkT8zqHoheawOLF8lFHi9R3veyhPXI= 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=gPdby1E5C7g5fADNyZslBYeGX48=; b=qRkFb0d39rgc/V5J2ncU Uq1FR/M0LwsEouGcfwTrhsIbJPM8b9kg+2JCxWt6yudR01lOQVwRJs0PXGNoOb4K ywU1m3f5tK8iyCFF4W93FmxL+faIHXQSNBel8v8lOq++K//JEEqYe/JD6IQuI5r4 NSrbUiHj1BWr87DJzaFBdtw= Received: (qmail 9806 invoked by alias); 3 Aug 2013 13:29:41 -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 9738 invoked by uid 89); 3 Aug 2013 13:29:41 -0000 X-Spam-SWARE-Status: No, score=-3.0 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, KHOP_THREADED, RCVD_IN_DNSWL_LOW, RCVD_IN_HOSTKARMA_YE, RDNS_NONE, SPF_PASS autolearn=ham version=3.3.1 Received: from Unknown (HELO mail-we0-f181.google.com) (74.125.82.181) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Sat, 03 Aug 2013 13:29:39 +0000 Received: by mail-we0-f181.google.com with SMTP id p58so1278499wes.40 for ; Sat, 03 Aug 2013 06:29:31 -0700 (PDT) X-Received: by 10.194.122.103 with SMTP id lr7mr8042955wjb.15.1375536571776; Sat, 03 Aug 2013 06:29:31 -0700 (PDT) Received: from archbang.lan (munkyhouse.force9.co.uk. [84.92.244.81]) by mx.google.com with ESMTPSA id z2sm9436380wiv.11.2013.08.03.06.29.30 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sat, 03 Aug 2013 06:29:31 -0700 (PDT) From: Adam Butcher To: Jason Merrill Cc: gcc-patches@gcc.gnu.org, Gabriel Dos Reis , Andrew Sutton , Adam Butcher Subject: [PATCH 2/4] [lambda] Support implicit conversion of a stateless generic lambda to a function pointer. Date: Thu, 1 Aug 2013 13:25:28 +0100 Message-Id: <1375359930-12871-3-git-send-email-adam@jessamine.co.uk> In-Reply-To: <1375359930-12871-1-git-send-email-adam@jessamine.co.uk> References: <51E96FB9.6090108@redhat.com> <1375359930-12871-1-git-send-email-adam@jessamine.co.uk> --- gcc/cp/lambda.c | 77 ++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 20 deletions(-) diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c index 98a7925..cf662bb 100644 --- a/gcc/cp/lambda.c +++ b/gcc/cp/lambda.c @@ -759,12 +759,9 @@ maybe_add_lambda_conv_op (tree type) if (processing_template_decl) return; - if (DECL_TEMPLATE_INFO (callop) && DECL_TEMPLATE_RESULT - (DECL_TI_TEMPLATE (callop)) == callop) - { - warning (0, "Conversion of a generic lambda to a function pointer is not currently implemented."); - return; - } + bool generic_lambda_p + = DECL_TEMPLATE_INFO (callop) + && DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (callop)) == callop; if (DECL_INITIAL (callop) == NULL_TREE) { @@ -773,7 +770,38 @@ maybe_add_lambda_conv_op (tree type) return; } - stattype = build_function_type (TREE_TYPE (TREE_TYPE (callop)), + tree fn_result = TREE_TYPE (TREE_TYPE (callop)); + tree fn_args = copy_list (DECL_CHAIN (DECL_ARGUMENTS (callop))); + + if (generic_lambda_p) + { + /* Construct the dependent member call for the static member function + '_FUN' and remove 'auto' from it's return type to allow for simple + implementation of the conversion operator. */ + + tree instance = build_nop (type, null_pointer_node); + argvec = make_tree_vector (); + for (arg = fn_args; arg; arg = DECL_CHAIN (arg)) + { + mark_exp_read (arg); + vec_safe_push (argvec, arg); + } + + tree objfn = build_min (COMPONENT_REF, NULL_TREE, + instance, DECL_NAME (callop), NULL_TREE); + call = build_nt_call_vec (objfn, argvec); + + if (type_uses_auto (fn_result)) + { + ++processing_template_decl; + fn_result = finish_decltype_type + (call, /*id_expression_or_member_access_p=*/false, + tf_warning_or_error); + --processing_template_decl; + } + } + + stattype = build_function_type (fn_result, FUNCTION_ARG_CHAIN (callop)); /* First build up the conversion op. */ @@ -801,6 +829,9 @@ maybe_add_lambda_conv_op (tree type) if (nested) DECL_INTERFACE_KNOWN (fn) = 1; + if (generic_lambda_p) + fn = add_inherited_template_parms (fn, DECL_TI_TEMPLATE (callop)); + add_method (type, fn, NULL_TREE); /* Generic thunk code fails for varargs; we'll complain in mark_used if @@ -827,8 +858,8 @@ maybe_add_lambda_conv_op (tree type) DECL_NOT_REALLY_EXTERN (fn) = 1; DECL_DECLARED_INLINE_P (fn) = 1; DECL_STATIC_FUNCTION_P (fn) = 1; - DECL_ARGUMENTS (fn) = copy_list (DECL_CHAIN (DECL_ARGUMENTS (callop))); - for (arg = DECL_ARGUMENTS (fn); arg; arg = DECL_CHAIN (arg)) + DECL_ARGUMENTS (fn) = fn_args; + for (arg = fn_args; arg; arg = DECL_CHAIN (arg)) { /* Avoid duplicate -Wshadow warnings. */ DECL_NAME (arg) = NULL_TREE; @@ -837,6 +868,9 @@ maybe_add_lambda_conv_op (tree type) if (nested) DECL_INTERFACE_KNOWN (fn) = 1; + if (generic_lambda_p) + fn = add_inherited_template_parms (fn, DECL_TI_TEMPLATE (callop)); + add_method (type, fn, NULL_TREE); if (nested) @@ -860,19 +894,22 @@ maybe_add_lambda_conv_op (tree type) body = begin_function_body (); compound_stmt = begin_compound_stmt (0); - arg = build1 (NOP_EXPR, TREE_TYPE (DECL_ARGUMENTS (callop)), - null_pointer_node); - argvec = make_tree_vector (); - argvec->quick_push (arg); - for (arg = DECL_ARGUMENTS (statfn); arg; arg = DECL_CHAIN (arg)) + if (!generic_lambda_p) { - mark_exp_read (arg); - vec_safe_push (argvec, arg); + arg = build1 (NOP_EXPR, TREE_TYPE (DECL_ARGUMENTS (callop)), + null_pointer_node); + argvec = make_tree_vector (); + argvec->quick_push (arg); + for (arg = DECL_ARGUMENTS (statfn); arg; arg = DECL_CHAIN (arg)) + { + mark_exp_read (arg); + vec_safe_push (argvec, arg); + } + call = build_call_a (callop, argvec->length (), argvec->address ()); + CALL_FROM_THUNK_P (call) = 1; + if (MAYBE_CLASS_TYPE_P (TREE_TYPE (call))) + call = build_cplus_new (TREE_TYPE (call), call, tf_warning_or_error); } - call = build_call_a (callop, argvec->length (), argvec->address ()); - CALL_FROM_THUNK_P (call) = 1; - if (MAYBE_CLASS_TYPE_P (TREE_TYPE (call))) - call = build_cplus_new (TREE_TYPE (call), call, tf_warning_or_error); call = convert_from_reference (call); finish_return_stmt (call);