From patchwork Fri Jan 22 16:17:41 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Palka X-Patchwork-Id: 571737 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)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 2E6FF1402DD for ; Sat, 23 Jan 2016 03:18:04 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=Nf7DA3UI; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :date:to:cc:subject:in-reply-to:message-id:references :mime-version:content-type; q=dns; s=default; b=fMRQj91PzUVCvffE 95+E4Xc3OnbwgGIbvywS4DZMZTZmOwjkKb3Gj3+Bkf5s7O/EEmudB13pdmfD7avF eXJYWmvKGY05q4lQdcAQ+LaUKRj8IfyCVx/zoQrUIBfgwij3p8AC4fVczMW/UzSW 04G/pmzH6EHXtb1DxbWS4c9Ns8g= 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 :date:to:cc:subject:in-reply-to:message-id:references :mime-version:content-type; s=default; bh=kXlqEesEoPSg2/xQccdTWB zKzAI=; b=Nf7DA3UITgdahFCoX9Vn1r6ghKPy8KiXhR2sd/W7KeV2gHaUd6y2Ja pHNo1lXcIInhgsMteHD/3brzQ89OQvuwPxgJI98sc/ZtG94AhpMXvCDZP4dWS7wT Trpjsjxwu09wxsSXnTiYbKClixmB+B1umQ8ocuELlImOyJSd14Nbw= Received: (qmail 93790 invoked by alias); 22 Jan 2016 16:17:57 -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 93767 invoked by uid 89); 22 Jan 2016 16:17:56 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.2 spammy=corresponds, 1, 22, ref1 X-HELO: mail-qk0-f169.google.com Received: from mail-qk0-f169.google.com (HELO mail-qk0-f169.google.com) (209.85.220.169) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Fri, 22 Jan 2016 16:17:45 +0000 Received: by mail-qk0-f169.google.com with SMTP id s68so30350780qkh.3 for ; Fri, 22 Jan 2016 08:17:45 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:date:to:cc:subject:in-reply-to:message-id :references:user-agent:mime-version:content-type; bh=GyPPVHmJx0yrQnaUEsNT4zVHYCf6hnm9LMmSmOL3zaI=; b=RRAcV+1FT8g5l87v3Wu+rprThClHptJz3nHBYt1efjuyL9qhT600GC104CuXRKU5eB GGkqZAE7hLT/YLI1k8qv56/I8AECa8o1ShwS0VGGnsehhpel7TydTI6jDfph7styCu3S CFAG8b6+aOCzcBoHdAUDO+lM1XNyWPFTP3M8BTFSkYyphihLVay0+KfCl3QTO4/CbCWu Uqlpc7EYjbFGknJsNq5PXLzBeGRZOPakDv0a6er+qoYmRcvsV2ZFXGVT4L3ixmXZDSyX Dh01tB3oJgRVMASNaBz8PrOqMssJcUkqLClAcg0wI9ih+/LstJJkJCVgQVRgVqjHZyWy FwWw== X-Gm-Message-State: AG10YOQoG96xLYDIsJmh6brGNjSgz+qD939ai+DwVKoRvvP9UeyDKIZSXJG1MD3jkTTEGA== X-Received: by 10.55.41.91 with SMTP id p88mr4666410qkh.86.1453479463689; Fri, 22 Jan 2016 08:17:43 -0800 (PST) Received: from [192.168.1.130] (ool-4353abbc.dyn.optonline.net. [67.83.171.188]) by smtp.gmail.com with ESMTPSA id j188sm3018907qhj.12.2016.01.22.08.17.42 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 22 Jan 2016 08:17:42 -0800 (PST) From: Patrick Palka X-Google-Original-From: Patrick Palka Date: Fri, 22 Jan 2016 11:17:41 -0500 (EST) To: Patrick Palka cc: Jason Merrill , GCC Patches Subject: Re: [PATCH] Fix the remaining PR c++/24666 blockers (arrays decay to pointers too early) In-Reply-To: Message-ID: References: <1450979869-5575-1-git-send-email-patrick@parcs.ath.cx> <567CACC0.5010705@redhat.com> <569D060F.6070708@redhat.com> <569D5360.1010805@redhat.com> <56A126C7.908@redhat.com> User-Agent: Alpine 2.20.9 (DEB 106 2015-09-22) MIME-Version: 1.0 On Thu, 21 Jan 2016, Patrick Palka wrote: > On Thu, 21 Jan 2016, Jason Merrill wrote: > >> On 01/19/2016 10:30 PM, Patrick Palka wrote: >>> * g++.dg/template/unify17.C: XFAIL. >> >> Hmm, I'm not comfortable with deliberately regressing this testcase. >> >>> template >>> -void bar (void (T[5])); // { dg-error "array of 'void'" } >>> +void bar (void (T[5])); // { dg-error "array of 'void'" "" { xfail >>> *-*-* } } >> >> Can we work it so that T[5] also is un-decayed in the DECL_ARGUMENTS of >> bar, but decayed in the TYPE_ARG_TYPES? > > I think so, I'll try it. Well, I tried it and the result is really ugly and it only "somewhat" works. (Maybe I'm just missing something obvious though.) The ugliness comes from the fact that decaying an array parameter type of a function type embedded deep within some tree structure requires rebuilding all the tree structures in between to avoid issues due to tree sharing. This approach only "somewhat" works because it currently looks through function, pointer, reference and array types. And I just noticed that this approach does not work at all for USING_DECLs because no PARM_DECL is ever retained anyway in that case. I think a better, complete fix for this issue would be to, one way or another, be able to get at the PARM_DECLs that correspond to a given FUNCTION_TYPE. Say, if, the TREE_CHAIN of a FUNCTION_TYPE optionally pointed to its PARM_DECLs, or something. What do you think? In the meantime, at this stage, I am personally most comfortable with the previous patch (the one that XFAILs unify17.C). diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index f4604b6..c70eb12 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -9082,6 +9082,92 @@ check_var_type (tree identifier, tree type) return type; } +/* Given a type T, return a copy of T within which each array parameter type of + each function type embedded in T has been decayed to the corresponding + pointer type. If no decaying was done, return T. + + For example, if T corresponds to the type + + void (** (char, void (&) (int[5]), char[7])) (int (*) (long[10])); + ~~~~~~ ~~~~~~~ ~~~~~~~ + + then the type returned by this function corresponds to + + void (** (char, void (&) (int *), char *)) (int (*) (long *)) + ~~~~~ ~~~~~~ ~~~~~~ +*/ + +static tree +decay_array_parms_r (tree t) +{ + if (t == NULL_TREE) + return t; + + if (FUNC_OR_METHOD_TYPE_P (t)) + { + auto_vec new_types; + new_types.reserve (8); + bool any_changed_p = false; + + for (tree arg = TYPE_ARG_TYPES (t); + arg != NULL_TREE && arg != void_list_node; + arg = TREE_CHAIN (arg)) + { + tree old_type = TREE_VALUE (arg); + tree new_type; + + if (TREE_CODE (old_type) == ARRAY_TYPE) + new_type = decay_array_parms_r (type_decays_to (old_type)); + else + new_type = decay_array_parms_r (old_type); + + if (old_type != new_type) + any_changed_p = true; + + new_types.safe_push (new_type); + } + + tree old_ret_type = TREE_TYPE (t); + tree new_ret_type = decay_array_parms_r (old_ret_type); + if (old_ret_type != new_ret_type) + any_changed_p = true; + + if (!any_changed_p) + return t; + + tree new_type_arg_types = NULL_TREE; + tree arg; + int i = 0; + for (arg = TYPE_ARG_TYPES (t); + arg != NULL_TREE && arg != void_list_node; + arg = TREE_CHAIN (arg), i++) + new_type_arg_types = tree_cons (TREE_PURPOSE (arg), + new_types[i], + new_type_arg_types); + new_type_arg_types = nreverse (new_type_arg_types); + if (arg == void_list_node) + new_type_arg_types = chainon (new_type_arg_types, void_list_node); + + return build_function_type (new_ret_type, new_type_arg_types); + } + else if (TREE_CODE (t) == POINTER_TYPE) + { + tree old_type_type = TREE_TYPE (t); + tree new_type_type = decay_array_parms_r (old_type_type); + if (old_type_type != new_type_type) + return build_pointer_type (new_type_type); + } + else if (TREE_CODE (t) == REFERENCE_TYPE) + { + tree old_type_type = TREE_TYPE (t); + tree new_type_type = decay_array_parms_r (old_type_type); + if (old_type_type != new_type_type) + return cp_build_reference_type (new_type_type, TYPE_REF_IS_RVALUE (t)); + } + + return t; +} + /* Given declspecs and a declarator (abstract or otherwise), determine the name and type of the object declared and construct a DECL node for it. @@ -10213,6 +10299,15 @@ grokdeclarator (const cp_declarator *declarator, type = build_function_type (type, arg_types); + /* Decay all the (dependent) array parameter types embedded in this + function type into their corresponding pointer types. This is + only done once, recursively, at the top-level declarator, + not when processing a nested function declarator, designated by + DECL_CONTEXT == PARM, so that the PARM_DECLS built will + contain the un-decayed types. */ + if (decl_context != PARM && processing_template_decl) + type = decay_array_parms_r (type); + tree attrs = declarator->std_attributes; if (tx_qual) { diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 3733ee0..596b129 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -11795,6 +11795,10 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) complain, t); DECL_RESULT (r) = NULL_TREE; + for (tree parm = DECL_ARGUMENTS (r); parm; parm = DECL_CHAIN (parm)) + if (TREE_TYPE (parm) == error_mark_node) + RETURN (error_mark_node); + TREE_STATIC (r) = 0; TREE_PUBLIC (r) = TREE_PUBLIC (t); DECL_EXTERNAL (r) = 1; @@ -17797,23 +17801,6 @@ fn_type_unification (tree fn, return r; } -/* TYPE is the type of a function parameter. If TYPE is a (dependent) - ARRAY_TYPE, return the corresponding POINTER_TYPE to which it decays. - Otherwise return TYPE. (We shouldn't see non-dependent ARRAY_TYPE - parameters because they get decayed as soon as they are declared.) */ - -static tree -decay_dependent_array_parm_type (tree type) -{ - if (TREE_CODE (type) == ARRAY_TYPE) - { - gcc_assert (uses_template_parms (type)); - return type_decays_to (type); - } - - return type; -} - /* Adjust types before performing type deduction, as described in [temp.deduct.call] and [temp.deduct.conv]. The rules in these two sections are symmetric. PARM is the type of a function parameter @@ -18252,8 +18239,6 @@ type_unification_real (tree tparms, arg = args[ia]; ++ia; - parm = decay_dependent_array_parm_type (parm); - if (unify_one_argument (tparms, targs, parm, arg, subr, strict, explain_p)) return 1; @@ -20287,9 +20272,6 @@ more_specialized_fn (tree pat1, tree pat2, int len) len = 0; } - arg1 = decay_dependent_array_parm_type (arg1); - arg2 = decay_dependent_array_parm_type (arg2); - if (TREE_CODE (arg1) == REFERENCE_TYPE) { ref1 = TYPE_REF_IS_RVALUE (arg1) + 1; @@ -20575,10 +20557,7 @@ get_bindings (tree fn, tree decl, tree explicit_args, bool check_rettype) for (arg = decl_arg_types, ix = 0; arg != NULL_TREE && arg != void_list_node; arg = TREE_CHAIN (arg), ++ix) - { - args[ix] = TREE_VALUE (arg); - args[ix] = decay_dependent_array_parm_type (args[ix]); - } + args[ix] = TREE_VALUE (arg); if (fn_type_unification (fn, explicit_args, targs, args, ix, diff --git a/gcc/testsuite/g++.dg/template/mangle2.C b/gcc/testsuite/g++.dg/template/mangle2.C new file mode 100644 index 0000000..f9ea040 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/mangle2.C @@ -0,0 +1,22 @@ +template +int foo (T [I]); + +template +int bar (T [7]); + +template +int baz (int [I]); + +extern int x, y, z; + +int +main () +{ + x = foo (0); + y = bar (0); + z = baz<9> (0); +} + +// { dg-final { scan-assembler "_Z3fooIiLi5EEiPT_" } } +// { dg-final { scan-assembler "_Z3barIcEiPT_" } } +// { dg-final { scan-assembler "_Z3bazILi9EEiPi" } }