From patchwork Mon Mar 20 22:06:52 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Polacek X-Patchwork-Id: 66660 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 047C13858C2D for ; Mon, 20 Mar 2023 22:08:36 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 047C13858C2D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1679350116; bh=cqhD+Vfb0Co29Os6cmvJ4Gt6bcZmiYiFEfc5OoRqvrg=; h=Date:To:Cc:Subject:References:In-Reply-To:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=dT+gsCdBInZ+fW36Gq0Lweq0cc77+AwGYOtrxn94pbdaagkRYTa9ad/Eak2b53B6A GdljLiwZRmvMfVOvnqdnX8PKKo10ECjQGWtGzcklMYND7rnis1iwUHOFgyDGPV7X2N FOJj5Gs2badDCvjARrxGj9a89zeMgzdrhc6noNFI= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org 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 C0D863858C74 for ; Mon, 20 Mar 2023 22:06:58 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C0D863858C74 Received: from mail-qt1-f199.google.com (mail-qt1-f199.google.com [209.85.160.199]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-148-cSxleFmWN7SnlguKQKuvbQ-1; Mon, 20 Mar 2023 18:06:56 -0400 X-MC-Unique: cSxleFmWN7SnlguKQKuvbQ-1 Received: by mail-qt1-f199.google.com with SMTP id s4-20020a05622a1a8400b003dbc6fc558aso5449804qtc.3 for ; Mon, 20 Mar 2023 15:06:55 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1679350015; h=user-agent:in-reply-to:content-disposition:mime-version:references :message-id:subject:cc:to:from:date:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=cqhD+Vfb0Co29Os6cmvJ4Gt6bcZmiYiFEfc5OoRqvrg=; b=t92k7nxnMOFiz3fHJjCWVr2+pH86jysj0f2BrSL3MBtmGLYc780YpxOIfVdA8j2W/H 1V9qADdd5ubGLgYieal0izNWckDCOq66a43Hp7Xlkgce6NMIcKBVLt2/xp0TO8u05/av FRupx5xFoWGNTNo7ytAbFRA90KvgiXolew1Xwf1E6Igwqd0xuxuDk+EN/qcLSpbfCxxe /eR3xJKCcbyLTt6rgU7ATqfWYvAxz5g7S1x6i2NBPFaTooT974ADIUp0ytgGdR42emo+ nu6P0q9smwnokApFX+UXPBLXjeaWVcZyBK+v+OV3onoZOVgxTpXf/b40cSMeAZKQ3vKJ t8qw== X-Gm-Message-State: AO0yUKVokJr7XKNu3IHQUknsdRjPueyjrAtiLSUAtqPVlLOg6Rp9GPBJ jTJcywWXn9f5sH+eHxs8zUjgUVK5bZBCl4Iwi4GK+cHVZN7NGAx6ypvEjxl5tKLhCS/BBRNThCc YIP1PKJiVfGdToh7/0FiK0SjZYg== X-Received: by 2002:ac8:5a96:0:b0:3c0:3d0b:e433 with SMTP id c22-20020ac85a96000000b003c03d0be433mr1468873qtc.10.1679350015331; Mon, 20 Mar 2023 15:06:55 -0700 (PDT) X-Google-Smtp-Source: AK7set/kgXaaRBYPdEBbVQDIW+IHK/EIQZQ1xa5rS2RN1oxfNnw7It5KL/b/zvZRKfZLLefeQA2LeA== X-Received: by 2002:ac8:5a96:0:b0:3c0:3d0b:e433 with SMTP id c22-20020ac85a96000000b003c03d0be433mr1468841qtc.10.1679350015026; Mon, 20 Mar 2023 15:06:55 -0700 (PDT) Received: from redhat.com (2603-7000-9500-34a5-0000-0000-0000-1db4.res6.spectrum.com. [2603:7000:9500:34a5::1db4]) by smtp.gmail.com with ESMTPSA id k18-20020ac84792000000b003ba19e53e43sm4122407qtq.25.2023.03.20.15.06.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 20 Mar 2023 15:06:54 -0700 (PDT) Date: Mon, 20 Mar 2023 18:06:52 -0400 To: Jason Merrill Cc: GCC Patches Subject: [PATCH v2] c++: further -Wdangling-reference refinement [PR107532] Message-ID: References: <20230317202908.42800-1-polacek@redhat.com> MIME-Version: 1.0 In-Reply-To: User-Agent: Mutt/2.2.9 (2022-11-12) X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-12.5 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, 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 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Marek Polacek via Gcc-patches From: Marek Polacek Reply-To: Marek Polacek Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" On Sat, Mar 18, 2023 at 08:35:36AM -0400, Jason Merrill wrote: > On 3/17/23 16:29, Marek Polacek wrote: > > Based on , > > it seems like we should treat *any* class with a reference member > > as a reference wrapper. This simplifies the code so I'm happy to > > make that change. > > > > The patch, however, does not suppress the warning in > > > > int i = 42; > > auto const& v = std::get<0>(std::tuple(i)); > > Why not? tuple has an int& member, doesn't it? Do we need to look > into bases as well? Indeed. I don't know why I didn't do it right away; it's really not that complicated: Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? -- >8 -- Based on , it seems like we should treat *any* class with a reference member as a reference wrapper. To suppress the warning in int i = 42; auto const& v = std::get<0>(std::tuple(i)); we have to look into base classes as well. For std::tuple, this means that we have to check the _Head_base subobject, which is a non-direct base class of std::tuple. So I've employed a DFS walk. PR c++/107532 gcc/cp/ChangeLog: * call.cc (class_has_reference_member_p): New. (class_has_reference_member_p_r): New. (reference_like_class_p): Don't look for a specific constructor. Use a DFS walk with class_has_reference_member_p_r. gcc/testsuite/ChangeLog: * g++.dg/warn/Wdangling-reference11.C: New test. * g++.dg/warn/Wdangling-reference12.C: New test. --- gcc/cp/call.cc | 63 +++++++++++-------- .../g++.dg/warn/Wdangling-reference11.C | 23 +++++++ .../g++.dg/warn/Wdangling-reference12.C | 12 ++++ 3 files changed, 72 insertions(+), 26 deletions(-) create mode 100644 gcc/testsuite/g++.dg/warn/Wdangling-reference11.C create mode 100644 gcc/testsuite/g++.dg/warn/Wdangling-reference12.C base-commit: a226590fefb35ed66adf73d85cefe49048a78ab8 diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index c52a09b9be2..429170e43ea 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -13783,8 +13783,31 @@ std_pair_ref_ref_p (tree t) /* Return true if a class CTYPE is either std::reference_wrapper or std::ref_view, or a reference wrapper class. We consider a class - a reference wrapper class if it has a reference member and a - constructor taking the same reference type. */ + a reference wrapper class if it has a reference member. We no + longer check that it has a constructor taking the same reference type + since that approach still generated too many false positives. */ + +static bool +class_has_reference_member_p (tree t) +{ + for (tree fields = TYPE_FIELDS (t); + fields; + fields = DECL_CHAIN (fields)) + if (TREE_CODE (fields) == FIELD_DECL + && !DECL_ARTIFICIAL (fields) + && TYPE_REF_P (TREE_TYPE (fields))) + return true; + return false; +} + +/* A wrapper for the above suitable as a callback for dfs_walk_once. */ + +static tree +class_has_reference_member_p_r (tree binfo, void *) +{ + return (class_has_reference_member_p (BINFO_TYPE (binfo)) + ? integer_one_node : NULL_TREE); +} static bool reference_like_class_p (tree ctype) @@ -13800,31 +13823,19 @@ reference_like_class_p (tree ctype) if (decl_in_std_namespace_p (tdecl)) { tree name = DECL_NAME (tdecl); - return (name - && (id_equal (name, "reference_wrapper") - || id_equal (name, "span") - || id_equal (name, "ref_view"))); - } - for (tree fields = TYPE_FIELDS (ctype); - fields; - fields = DECL_CHAIN (fields)) - { - if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields)) - continue; - tree type = TREE_TYPE (fields); - if (!TYPE_REF_P (type)) - continue; - /* OK, the field is a reference member. Do we have a constructor - taking its type? */ - for (tree fn : ovl_range (CLASSTYPE_CONSTRUCTORS (ctype))) - { - tree args = FUNCTION_FIRST_USER_PARMTYPE (fn); - if (args - && same_type_p (TREE_VALUE (args), type) - && TREE_CHAIN (args) == void_list_node) - return true; - } + if (name + && (id_equal (name, "reference_wrapper") + || id_equal (name, "span") + || id_equal (name, "ref_view"))) + return true; } + + /* Some classes, such as std::tuple, have the reference member in its + (non-direct) base class. */ + if (dfs_walk_once (TYPE_BINFO (ctype), class_has_reference_member_p_r, + nullptr, nullptr)) + return true; + return false; } diff --git a/gcc/testsuite/g++.dg/warn/Wdangling-reference11.C b/gcc/testsuite/g++.dg/warn/Wdangling-reference11.C new file mode 100644 index 00000000000..667618e7196 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wdangling-reference11.C @@ -0,0 +1,23 @@ +// PR c++/107532 +// { dg-do compile { target c++11 } } +// { dg-options "-Wdangling-reference" } + +struct R +{ + int& r; + int& get() { return r; } + int&& rget() { return static_cast(r); } +}; + +int main() +{ + int i = 42; + int& l = R{i}.get(); // { dg-bogus "dangling reference" } + int const& cl = R{i}.get(); // { dg-bogus "dangling reference" } + int&& r = R{i}.rget(); // { dg-bogus "dangling reference" } + int const&& cr = R{i}.rget(); // { dg-bogus "dangling reference" } + (void) l; + (void) r; + (void) cr; + (void) cl; +} diff --git a/gcc/testsuite/g++.dg/warn/Wdangling-reference12.C b/gcc/testsuite/g++.dg/warn/Wdangling-reference12.C new file mode 100644 index 00000000000..85e01f01a50 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wdangling-reference12.C @@ -0,0 +1,12 @@ +// PR c++/107532 +// { dg-do compile { target c++11 } } +// { dg-options "-Wdangling-reference" } + +#include + +int main() +{ + int i = 42; + auto const& v = std::get<0>(std::tuple(i)); // { dg-bogus "dangling reference" } + (void) v; +}