From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 44A663858C62 for ; Thu, 19 Jan 2023 18:09:09 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 44A663858C62 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1674151748; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=5qRiiRjok42WeuNJ5RJmQl/8d7CZsEtDT8JddNFeYAU=; b=dJFNHKPbpHEl7Jg/7c5RZSaKmqNSk1ZQsVu/bQ9nMMR0jPSVNghBykrTS0AXJHGfb5n6vE deutU4K2+PpRuSDFnIrnrF8uhvN+JWP2r7M3JT7/D5JHglRB9YjyPtnooal+d/MMvUQchU P2egyG+Ta7iugLDmkzeXkmf28lJdkeY= Received: from mail-qv1-f72.google.com (mail-qv1-f72.google.com [209.85.219.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-210-8yi-sD4kNTSxwkNUvhq5dg-1; Thu, 19 Jan 2023 13:09:07 -0500 X-MC-Unique: 8yi-sD4kNTSxwkNUvhq5dg-1 Received: by mail-qv1-f72.google.com with SMTP id y10-20020a056214016a00b0053545fd8b7fso1339695qvs.5 for ; Thu, 19 Jan 2023 10:09:07 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:in-reply-to:from:references:cc:to :content-language:subject:user-agent:mime-version:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=5qRiiRjok42WeuNJ5RJmQl/8d7CZsEtDT8JddNFeYAU=; b=GFuQYq+BOFZ+275D1vl9rla+2VwZmq9upGqlpW9qMJUCTIEv2zVgUR0Zlr5beYveR7 /QN54YcgiQqMeyaqUXSU/XfW3kp3U/0MK2PatRROPksWOu7AttbAwH3iLwTbWSiX8S/B tkTpo+sfYrU+z1aZNsgzzCM5YzuzKEtCbjiGCEBF4EdAG3YVmbzOv8lxeIcfQ6Fdzykp XPtGBsFIuFJKAorp8bBIeltDcguGEqrosQTb3pkgaprgLCatFjjXKPzzbeFJdyrNFFbt 8ctAOUpQYqm92JAoB4AAEqMLcJZYQlvFfyw9Gtjt6gyLNMbBbAOLYH6vIiFfvHBkYlcT m45A== X-Gm-Message-State: AFqh2koQPGJv3lPVzDT5l9bPn5hJrhsagLMRYhxC1bwuM2vhsQybVfB/ CQbJVil+OYq6X4I61jQSjgl3QrXEu7x2pqFgZZBosR1gxqeOXgggU/AlkYNP7qMp7YO+PcyEnBC 2Cuc//Za1871mx2AZwA== X-Received: by 2002:ac8:70c7:0:b0:3a5:c851:29ff with SMTP id g7-20020ac870c7000000b003a5c85129ffmr14199705qtp.23.1674151746975; Thu, 19 Jan 2023 10:09:06 -0800 (PST) X-Google-Smtp-Source: AMrXdXvzfZls1K0SiSitEY2WaUD53FD+KdHONwY7h1+bZEx7V6btWk2rATT23+rwayfp4vx83/il8A== X-Received: by 2002:ac8:70c7:0:b0:3a5:c851:29ff with SMTP id g7-20020ac870c7000000b003a5c85129ffmr14199685qtp.23.1674151746615; Thu, 19 Jan 2023 10:09:06 -0800 (PST) Received: from [192.168.1.108] (130-44-159-43.s15913.c3-0.arl-cbr1.sbo-arl.ma.cable.rcncustomer.com. [130.44.159.43]) by smtp.gmail.com with ESMTPSA id z24-20020ac84558000000b003b63b8df24asm4442662qtn.36.2023.01.19.10.09.05 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 19 Jan 2023 10:09:05 -0800 (PST) Message-ID: Date: Thu, 19 Jan 2023 13:09:04 -0500 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.6.1 Subject: Re: [PATCH] c++: Fix up handling of non-dependent subscript with static operator[] [PR108437] To: Jakub Jelinek Cc: gcc-patches@gcc.gnu.org References: From: Jason Merrill In-Reply-To: X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Language: en-US Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-6.5 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,NICE_REPLY_A,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: On 1/19/23 03:52, Jakub Jelinek wrote: > Hi! > > As the following testcases shows, when adding static operator[] > support I've missed that the 2 build_min_non_dep_op_overload functions > need to be adjusted. The first one we only use for the single index > case, but as cp_tree_code_length (ARRAY_REF) is 2, we were running > into an assertion there which compared nargs and expected_nargs. > For ARRAY_REF, the operator[] is either a non-static member or newly > static member, never out of class and for the static member case > if user uses single index the operator[] needs to have a single > argument as well, but the function is called with 2 - the object > it is invoked on and the index. This should be in a comment for the new special handling of ARRAY_REF. OK with that change. > We need to evaluate side-effects > of the object and use just a single argument in the call - the index. > The other build_min_non_dep_op_overload overload has been added > solely for ARRAY_REF - CALL_EXPR is the other operator that accepts > variable number of operands but that one goes through different > routines. There we asserted it is a METHOD_TYPE, so again > we shouldn't assert that but handle the case when it is not one > by making sure object's side-effects are evaluated if needed and > passing all the index arguments to the static operator[]. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? > > 2023-01-19 Jakub Jelinek > > PR c++/108437 > * cp-tree.h (keep_unused_object_arg): Declare. > * call.cc (keep_unused_object_arg): No longer static. > * tree.cc (build_min_non_dep_op_overload): Handle ARRAY_REF > with overload being static member function. > > * g++.dg/cpp23/subscript12.C: New test. > * g++.dg/cpp23/subscript13.C: New test. > > --- gcc/cp/cp-tree.h.jj 2023-01-16 11:52:16.067734300 +0100 > +++ gcc/cp/cp-tree.h 2023-01-18 16:47:55.258697839 +0100 > @@ -6599,6 +6599,7 @@ inline tree build_new_op (const op_locat > return build_new_op (loc, code, flags, arg1, arg2, NULL_TREE, NULL_TREE, > NULL, complain); > } > +extern tree keep_unused_object_arg (tree, tree, tree); > extern tree build_op_call (tree, vec **, > tsubst_flags_t); > extern tree build_op_subscript (const op_location_t &, tree, > --- gcc/cp/call.cc.jj 2023-01-16 11:52:16.059734418 +0100 > +++ gcc/cp/call.cc 2023-01-18 16:48:02.966586328 +0100 > @@ -5187,7 +5187,7 @@ build_operator_new_call (tree fnname, ve > or static operator(), in which cases the source expression > would be `obj[...]' or `obj(...)'. */ > > -static tree > +tree > keep_unused_object_arg (tree result, tree obj, tree fn) > { > if (result == NULL_TREE > --- gcc/cp/tree.cc.jj 2023-01-16 11:52:16.093733917 +0100 > +++ gcc/cp/tree.cc 2023-01-18 17:01:08.937242864 +0100 > @@ -3693,14 +3693,14 @@ build_min_non_dep_op_overload (enum tree > { > va_list p; > int nargs, expected_nargs; > - tree fn, call; > + tree fn, call, obj = NULL_TREE; > > non_dep = extract_call_expr (non_dep); > > nargs = call_expr_nargs (non_dep); > > expected_nargs = cp_tree_code_length (op); > - if (TREE_CODE (TREE_TYPE (overload)) == METHOD_TYPE) > + if (TREE_CODE (TREE_TYPE (overload)) == METHOD_TYPE || op == ARRAY_REF) > expected_nargs -= 1; > if ((op == POSTINCREMENT_EXPR > || op == POSTDECREMENT_EXPR) > @@ -3715,6 +3715,8 @@ build_min_non_dep_op_overload (enum tree > if (TREE_CODE (TREE_TYPE (overload)) == FUNCTION_TYPE) > { > fn = overload; > + if (op == ARRAY_REF) > + obj = va_arg (p, tree); > for (int i = 0; i < nargs; i++) > { > tree arg = va_arg (p, tree); > @@ -3746,6 +3748,8 @@ build_min_non_dep_op_overload (enum tree > CALL_EXPR_ORDERED_ARGS (call_expr) = CALL_EXPR_ORDERED_ARGS (non_dep); > CALL_EXPR_REVERSE_ARGS (call_expr) = CALL_EXPR_REVERSE_ARGS (non_dep); > > + if (obj) > + return keep_unused_object_arg (call, obj, overload); > return call; > } > > @@ -3759,11 +3763,15 @@ build_min_non_dep_op_overload (tree non_ > non_dep = extract_call_expr (non_dep); > > unsigned int nargs = call_expr_nargs (non_dep); > - gcc_assert (TREE_CODE (TREE_TYPE (overload)) == METHOD_TYPE); > - tree binfo = TYPE_BINFO (TREE_TYPE (object)); > - tree method = build_baselink (binfo, binfo, overload, NULL_TREE); > - tree fn = build_min (COMPONENT_REF, TREE_TYPE (overload), > - object, method, NULL_TREE); > + tree fn = overload; > + if (TREE_CODE (TREE_TYPE (overload)) == METHOD_TYPE) > + { > + tree binfo = TYPE_BINFO (TREE_TYPE (object)); > + tree method = build_baselink (binfo, binfo, overload, NULL_TREE); > + fn = build_min (COMPONENT_REF, TREE_TYPE (overload), > + object, method, NULL_TREE); > + object = NULL_TREE; > + } > gcc_assert (vec_safe_length (args) == nargs); > > tree call = build_min_non_dep_call_vec (non_dep, fn, args); > @@ -3774,6 +3782,8 @@ build_min_non_dep_op_overload (tree non_ > CALL_EXPR_ORDERED_ARGS (call_expr) = CALL_EXPR_ORDERED_ARGS (non_dep); > CALL_EXPR_REVERSE_ARGS (call_expr) = CALL_EXPR_REVERSE_ARGS (non_dep); > > + if (object) > + return keep_unused_object_arg (call, object, overload); > return call; > } > > --- gcc/testsuite/g++.dg/cpp23/subscript12.C.jj 2023-01-18 17:15:04.963153521 +0100 > +++ gcc/testsuite/g++.dg/cpp23/subscript12.C 2023-01-18 17:14:40.816503156 +0100 > @@ -0,0 +1,34 @@ > +// PR c++/108437 > +// { dg-do run { target c++23 } } > + > +struct S { static int &operator[] (int x) { static int a[2]; return a[x]; } }; > +struct U { static int &operator[] (int x, int y, int z) { static int a[2]; return a[x + y + z]; } }; > +struct V { static int &operator[] () { static int a; return a; } }; > + > +template void > +foo () > +{ > + S s; > + s[0]++; > + T t; > + t[0]++; > + U u; > + u[0, 0, 0]++; > + V v; > + v[]++; > + W w; > + w[0, 0, 0]++; > + X x; > + x[]++; > +} > + > +int > +main () > +{ > + S::operator[] (0) = 1; > + U::operator[] (0, 0, 0) = 2; > + V::operator[] () = 3; > + foo (); > + if (S::operator[] (0) != 3 || U::operator[] (0, 0, 0) != 4 || V::operator[] () != 5) > + __builtin_abort (); > +} > --- gcc/testsuite/g++.dg/cpp23/subscript13.C.jj 2023-01-18 17:15:08.110107955 +0100 > +++ gcc/testsuite/g++.dg/cpp23/subscript13.C 2023-01-18 17:14:55.833285718 +0100 > @@ -0,0 +1,43 @@ > +// PR c++/108437 > +// { dg-do run { target c++23 } } > + > +struct S { static int &operator[] (int x) { static int a[2]; return a[x]; } }; > +struct U { static int &operator[] (int x, int y, int z) { static int a[2]; return a[x + y + z]; } }; > +struct V { static int &operator[] () { static int a; return a; } }; > +int cnt; > + > +template > +T & > +bar (T &x) > +{ > + ++cnt; > + return x; > +} > + > +template void > +foo () > +{ > + S s; > + bar (s)[0]++; > + T t; > + bar (t)[0]++; > + U u; > + bar (u)[0, 0, 0]++; > + V v; > + bar (v)[]++; > + W w; > + bar (w)[0, 0, 0]++; > + X x; > + bar (x)[]++; > +} > + > +int > +main () > +{ > + S::operator[] (0) = 1; > + U::operator[] (0, 0, 0) = 2; > + V::operator[] () = 3; > + foo (); > + if (S::operator[] (0) != 3 || U::operator[] (0, 0, 0) != 4 || V::operator[] () != 5 || cnt != 6) > + __builtin_abort (); > +} > > Jakub >