From patchwork Wed Oct 16 15:43:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Simon Martin X-Patchwork-Id: 1998132 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=nasilyan.com header.i=@nasilyan.com header.a=rsa-sha256 header.s=tey23rxsjton5kop5bydp3vc5ylkyjkg header.b=gbuceWVp; dkim=pass (1024-bit key; unprotected) header.d=amazonses.com header.i=@amazonses.com header.a=rsa-sha256 header.s=uku4taia5b5tsbglxyj6zym32efj7xqv header.b=DENz1oWn; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XTFcg0CBRz1xv6 for ; Thu, 17 Oct 2024 02:43:47 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 38AFD3858423 for ; Wed, 16 Oct 2024 15:43:45 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from a2-50.smtp-out.eu-west-1.amazonses.com (a2-50.smtp-out.eu-west-1.amazonses.com [54.240.2.50]) by sourceware.org (Postfix) with ESMTPS id 3B70B3858D20 for ; Wed, 16 Oct 2024 15:43:14 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 3B70B3858D20 Authentication-Results: sourceware.org; dmarc=fail (p=quarantine dis=none) header.from=nasilyan.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=eu-west-1.amazonses.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 3B70B3858D20 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=54.240.2.50 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1729093398; cv=none; b=Gqsq4vhxxZm3pV3j/J2AuQrhNOlWKnChJGkASMJBAVDMDSVFQ6OHsac93KyXQpO3sF/j+cTbKIrpF9LGc0tnFGlCXUzozJGmF9Ymay5CNJUuyIbccTAQyXSSE2uJZCtXOZTf9Z780IqoEM1lcxXWehvXsdSZo8RiAJl/Y2LRBH4= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1729093398; c=relaxed/simple; bh=vNuf8qJdHKGAWNFzUHs+fo/rUEVCfANgnCBCJVX95gQ=; h=DKIM-Signature:DKIM-Signature:Subject:From:To:Date:Mime-Version: Message-ID; b=KIp+QufP1FmVuACZI3Mm3FoaeQkJX5jlAuJ8BOiZUDHVtNLsskpzd8nzJLwt/J6C7I1AVa142R/HTjxa3rqpnrhX+NKgbvVVNNMvLfZ8EGkIJ6pr5IcskMaERkDp3zxGBpy0ZtZ4dT5p7irt3D6TD42FeGeUS10mGFvKcUMqQ6w= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/simple; s=tey23rxsjton5kop5bydp3vc5ylkyjkg; d=nasilyan.com; t=1729093392; h=Subject:From:To:Cc:Date:Mime-Version:Content-Type:In-Reply-To:References:Message-Id; bh=vNuf8qJdHKGAWNFzUHs+fo/rUEVCfANgnCBCJVX95gQ=; b=gbuceWVpbQuqtKex5J+s+Z6vG69MYAfzhekhTdnK1i8jRBdlk1KP3vPOeOFdnREX lXEYJy0o4yuDaOSI8PuAVmFKGxYzfTBdO3OWcvMNucf9B7kWhSXtNG/T7DZk79Ii+Hv kyIqdNh2Voj4cQZCzqlef52EJd8PpqfwRGmuft4g= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/simple; s=uku4taia5b5tsbglxyj6zym32efj7xqv; d=amazonses.com; t=1729093392; h=Subject:From:To:Cc:Date:Mime-Version:Content-Type:In-Reply-To:References:Message-Id:Feedback-ID; bh=vNuf8qJdHKGAWNFzUHs+fo/rUEVCfANgnCBCJVX95gQ=; b=DENz1oWn2RmA6T2Tru0B5pY3zFgK3vlk4lznBdVZUQkKUUw+nI3nBLkUtTlo+siq sE+fZZgBRkF/2meqLyUa1+ZRmzjTREwfU6GECm69D6EK/5TzFqyrYRQK6iK2q6JmmG8 d5XsqTWZuZnoVWKypJRAV8dwYJgOEZc9O8sOISgY= Subject: [PATCH v8] c++: Fix overeager Woverloaded-virtual with conversion operators [PR109918] From: =?utf-8?q?Simon_Martin?= To: =?utf-8?q?Jason_Merrill?= Cc: =?utf-8?q?gcc-patches=40gcc=2Egnu=2Eorg?= Date: Wed, 16 Oct 2024 15:43:12 +0000 Mime-Version: 1.0 In-Reply-To: <829a7ff3-7af8-4cf0-958b-bdc760dea8c4@redhat.com> References: <20240823164445.43068-1-simon@nasilyan.com> <0D326163-EE9F-43E9-B671-A7B4F290DA90@nasilyan.com> <01020191c1d9cb51-95732577-5209-45d1-bc38-82d20e2a2eab-000000@eu-west-1.amazonses.com> <60bc8abd-d590-48d4-adbe-7c1ef5e80732@redhat.com> <15AE26F0-D087-4462-A148-9E90D4B50CA6@nasilyan.com> <01020191ff225f9c-15dbb645-46c1-49cb-b281-1bc5d9e52c22-000000@eu-west-1.amazonses.com> <0b14601f-dd64-4b24-9302-3e59c10f51a4@redhat.com> <2DC4F8EB-8D0A-4AB7-BBC0-B24B1339128E@nasilyan.com> <01020192679745e5-e6abde90-5e06-4bbc-a913-b9b3c4498991-000000@eu-west-1.amazonses.com> <4dbca63b-7139-4884-93d4-3ae9cfa3154b@redhat.com> <01020192687abf00-c2a0fb36-6b24-4b2b-9157-4c38fda38f27-000000@eu-west-1.amazonses.com> <51b45980-bb88-437a-a2dd-1c7559474226@redhat.com> <16002849-97B2-4A72-8985-55A38C6ECB5C@nasilyan.com> <010201927b3ed2b9-adcff8a2-f921-4a01-9a48-cf095b74d5d9-000000@eu-west-1.amazonses.com> <829a7ff3-7af8-4cf0-958b-bdc760dea8c4@redhat.com> <35856862-2304-4F0E-9675-1F4695E8D15F@nasilyan.com> X-Mailer: Amazon WorkMail Thread-Index: AQHa9XvDTglWjAXfRpS1guIc9xLdcAAq8naPAD1FlfYAZFgG2ACYQZEQAckM+RICWkmFRwKB1z3FAo5gmSkE2FAHNATpMpgWCNRln7wI156/CgjdEvEZCXpP5BwJlFXRhAm1ftFFCpmV5tQ= Thread-Topic: [PATCH v8] c++: Fix overeager Woverloaded-virtual with conversion operators [PR109918] X-Original-Mailer: MailMate (1.13.2r5673) X-Wm-Sent-Timestamp: 1729093391 Message-ID: <0102019295ff5769-8f7d53cc-1264-4a73-9e6d-ff07b3093c37-000000@eu-west-1.amazonses.com> Feedback-ID: ::1.eu-west-1.b24dn6frgCi6dh20skzbuMRr7UL8M6Soir/3ogtEjHQ=:AmazonSES X-SES-Outgoing: 2024.10.16-54.240.2.50 X-Spam-Status: No, score=-12.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, HEADER_FROM_DIFFERENT_DOMAINS, PDS_BAD_THREAD_QP_64, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, 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.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org Hi Jason, On 12 Oct 2024, at 4:51, Jason Merrill wrote: > On 10/11/24 7:02 AM, Simon Martin wrote: >> Hi Jason, >> >> On 11 Oct 2024, at 0:35, Jason Merrill wrote: >> >>> On 10/7/24 3:35 PM, Simon Martin wrote: >>>> On 7 Oct 2024, at 18:58, Jason Merrill wrote: >>>>> On 10/7/24 11:27 AM, Simon Martin wrote: >>> >>>>>> /* Now give a warning for all base functions without overriders, >>>>>> as they are hidden. */ >>>>>> for (tree base_fndecl : base_fndecls) >>>>>> + { >>>>>> + if (!base_fndecl || overriden_base_fndecls.contains >>>>>> (base_fndecl)) >>>>>> + continue; >>>>>> + tree *hider = hidden_base_fndecls.get (base_fndecl); >>>>>> + if (hider) >>>>> >>>>> How about looping over hidden_base_fndecls instead of base_fndecls? >>> >>>> Unfortunately it does not work because a given base method can be >>>> hidden >>>> by one overload and overriden by another, in which case we don’t >>>> want >>>> to warn (see for example AA:foo(int) in Woverloaded-virt7.C). So we >>>> need >>>> to take both collections into account. >>> >>> Yes, you'd still need to check overridden_base_fndecls.contains, but >>> that doesn't seem any different iterating over hidden_base_fndecls >>> instead of base_fndecls. >> Sure, and I guess iterating over hidden_base_fndecls is more coherent >> >> with what the warning is about. Changed in the attached updated patch, >> successfully tested on x86_64-pc-linux-gnu. OK? > > OK, thanks. As you know the patch had to be reverted due to PR117114, that highlighted a bunch of issues with comparing DECL_VINDEXes: it might give false positives in case of multiple inheritance (the case in PR117114), but also if there’s single inheritance by the hierarchy has more than two levels (another issue I found while bootstrapping with rust enabled). The attached updated patch introduces an overrides_p function, based on the existing check_final_overrider, and uses it when the signatures match. It’s been successfully tested on x86_64-pc-linux-gnu, and bootstrap works fine with —enable-languages=all (and rust properly configured, so included here). OK for trunk? Thanks, Simon From f7dd5910423b4d09d06e07c9c2d29086d09edc30 Mon Sep 17 00:00:00 2001 From: Simon Martin Date: Tue, 15 Oct 2024 15:18:30 +0200 Subject: [PATCH] c++: Fix overeager Woverloaded-virtual with conversion operators [PR109918] We currently emit an incorrect -Woverloaded-virtual warning upon the following test case === cut here === struct A { virtual operator int() { return 42; } virtual operator char() = 0; }; struct B : public A { operator char() { return 'A'; } }; === cut here === The problem is that when iterating over ovl_range (fns), warn_hidden gets confused by the conversion operator marker, concludes that seen_non_override is true and therefore emits a warning for all conversion operators in A that do not convert to char, even if -Woverloaded-virtual is 1 (e.g. with -Wall, the case reported). A second set of problems is highlighted when -Woverloaded-virtual is 2. First, with the same test case, since base_fndecls contains all conversion operators in A (except the one to char, that's been removed when iterating over ovl_range (fns)), we emit a spurious warning for the conversion operator to int, even though it's unrelated. Second, in case there are several conversion operators with different cv-qualifiers to the same type in A, we rightfully emit a warning, however the note uses the location of the conversion operator marker instead of the right one; location_of should go over conv_op_marker. This patch fixes all these by explicitly keeping track of (1) base methods that are overriden, as well as (2) base methods that are hidden but not overriden (and by what), and warning about methods that are in (2) but not (1). It also ignores non virtual base methods, per "definition" of -Woverloaded-virtual. Successfully tested on x86_64-pc-linux-gnu. PR c++/117114 PR c++/109918 gcc/cp/ChangeLog: * class.cc (warn_hidden): Keep track of overloaded and of hidden base methods. Mention the actual hiding function in the warning, not the first overload. * cp-tree.h (overrides_p): New. * error.cc (location_of): Skip over conv_op_marker. * search.cc (check_final_overrider): Add parameter to control whether diagnostics should be emitted. (overrides_p): New. gcc/testsuite/ChangeLog: * g++.dg/warn/Woverloaded-virt1.C: Check that no warning is emitted for non virtual base methods. * g++.dg/warn/Woverloaded-virt10.C: New test. * g++.dg/warn/Woverloaded-virt11.C: New test. * g++.dg/warn/Woverloaded-virt12.C: New test. * g++.dg/warn/Woverloaded-virt13.C: New test. * g++.dg/warn/Woverloaded-virt5.C: New test. * g++.dg/warn/Woverloaded-virt6.C: New test. * g++.dg/warn/Woverloaded-virt7.C: New test. * g++.dg/warn/Woverloaded-virt8.C: New test. * g++.dg/warn/Woverloaded-virt9.C: New test. --- gcc/cp/class.cc | 95 ++++++++++++------- gcc/cp/cp-tree.h | 1 + gcc/cp/error.cc | 3 +- gcc/cp/search.cc | 36 ++++++- gcc/testsuite/g++.dg/warn/Woverloaded-virt1.C | 2 + .../g++.dg/warn/Woverloaded-virt10.C | 11 +++ .../g++.dg/warn/Woverloaded-virt11.C | 25 +++++ .../g++.dg/warn/Woverloaded-virt12.C | 23 +++++ .../g++.dg/warn/Woverloaded-virt13.C | 28 ++++++ gcc/testsuite/g++.dg/warn/Woverloaded-virt5.C | 12 +++ gcc/testsuite/g++.dg/warn/Woverloaded-virt6.C | 12 +++ gcc/testsuite/g++.dg/warn/Woverloaded-virt7.C | 31 ++++++ gcc/testsuite/g++.dg/warn/Woverloaded-virt8.C | 15 +++ gcc/testsuite/g++.dg/warn/Woverloaded-virt9.C | 14 +++ 14 files changed, 268 insertions(+), 40 deletions(-) create mode 100644 gcc/testsuite/g++.dg/warn/Woverloaded-virt10.C create mode 100644 gcc/testsuite/g++.dg/warn/Woverloaded-virt11.C create mode 100644 gcc/testsuite/g++.dg/warn/Woverloaded-virt12.C create mode 100644 gcc/testsuite/g++.dg/warn/Woverloaded-virt13.C create mode 100644 gcc/testsuite/g++.dg/warn/Woverloaded-virt5.C create mode 100644 gcc/testsuite/g++.dg/warn/Woverloaded-virt6.C create mode 100644 gcc/testsuite/g++.dg/warn/Woverloaded-virt7.C create mode 100644 gcc/testsuite/g++.dg/warn/Woverloaded-virt8.C create mode 100644 gcc/testsuite/g++.dg/warn/Woverloaded-virt9.C diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc index 8c39bb4a76b..8bb87da84c7 100644 --- a/gcc/cp/class.cc +++ b/gcc/cp/class.cc @@ -3243,10 +3243,15 @@ warn_hidden (tree t) continue; tree name = OVL_NAME (fns); + size_t num_fns = 0; /* The number of fndecls in fns. */ auto_vec base_fndecls; tree base_binfo; tree binfo; unsigned j; + hash_set overriden_base_fndecls, overrider_fndecls; + /* base_fndecls that are hidden but not overriden. The "value" + contains a vector of fndecls that hide the "key". */ + hash_map > hidden_base_fndecls; if (IDENTIFIER_CDTOR_P (name)) continue; @@ -3264,47 +3269,69 @@ warn_hidden (tree t) if (base_fndecls.is_empty ()) continue; - /* Remove any overridden functions. */ - bool seen_non_override = false; + /* Find all the base_fndecls that are overridden, as well as those + that are hidden, in T. */ for (tree fndecl : ovl_range (fns)) { - bool any_override = false; - if (TREE_CODE (fndecl) == FUNCTION_DECL - && DECL_VINDEX (fndecl)) + fndecl = STRIP_TEMPLATE (fndecl); + if (TREE_CODE (fndecl) != FUNCTION_DECL + || fndecl == conv_op_marker) + continue; + num_fns++; + for (size_t k = 0; k < base_fndecls.length (); k++) { - /* If the method from the base class has the same - signature as the method from the derived class, it - has been overridden. Note that we can't move on - after finding one match: fndecl might override - multiple base fns. */ - for (size_t k = 0; k < base_fndecls.length (); k++) - if (base_fndecls[k] - && same_signature_p (fndecl, base_fndecls[k])) - { - base_fndecls[k] = NULL_TREE; - any_override = true; - } + if (!base_fndecls[k] || !DECL_VINDEX (base_fndecls[k])) + continue; + if (IDENTIFIER_CONV_OP_P (name) + && !same_type_p (DECL_CONV_FN_TYPE (fndecl), + DECL_CONV_FN_TYPE (base_fndecls[k]))) + /* If base_fndecl[k] and fndecl are conversion operators + to different types, they're unrelated. */ + ; + else if (same_signature_p (fndecl, base_fndecls[k]) + && overrides_p (fndecl, base_fndecls[k])) + { + /* We cannot simply compare DECL_VINDEX (it won't work if + there's multiple inheritance, or single inheritance with + bases with bases), so we determine whether fndecl + overrides base_fndecls[k] by first comparing the + signatures and if they match, using the more expensive + is_overrider function. */ + overriden_base_fndecls.add (base_fndecls[k]); + overrider_fndecls.add (fndecl); + } + else + { + /* fndecls hides base_fndecls[k]. */ + auto_vec &hiders = + hidden_base_fndecls.get_or_insert (base_fndecls[k]); + if (!hiders.contains (fndecl)) + hiders.safe_push (fndecl); + } } - if (!any_override) - seen_non_override = true; } - if (!seen_non_override && warn_overloaded_virtual == 1) - /* All the derived fns override base virtuals. */ - return; + if (warn_overloaded_virtual == 1 + && overrider_fndecls.elements () == num_fns) + /* All the fns override a base virtual. */ + continue; - /* Now give a warning for all base functions without overriders, - as they are hidden. */ - for (tree base_fndecl : base_fndecls) - if (base_fndecl) - { - auto_diagnostic_group d; - /* Here we know it is a hider, and no overrider exists. */ - if (warning_at (location_of (base_fndecl), - OPT_Woverloaded_virtual_, - "%qD was hidden", base_fndecl)) - inform (location_of (fns), " by %qD", fns); - } + /* Now give a warning for all hidden methods. Note that a method that + is both in hidden_base_fndecls and overriden_base_fndecls is not + hidden. */ + for (auto hidden_base_fndecl : hidden_base_fndecls) + { + tree hidden_fndecl = hidden_base_fndecl.first; + if (!hidden_fndecl + || overriden_base_fndecls.contains (hidden_fndecl)) + continue; + auto_diagnostic_group d; + if (warning_at (location_of (hidden_fndecl), + OPT_Woverloaded_virtual_, + "%qD was hidden", hidden_fndecl)) + for (auto h : hidden_base_fndecl.second) + inform (location_of (h), " by %qD", h); + } } } diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 94ee550bd9c..56d72d707c8 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7744,6 +7744,7 @@ extern tree type_context_for_name_lookup (tree); extern tree lookup_conversions (tree); extern tree binfo_from_vbase (tree); extern tree binfo_for_vbase (tree, tree); +extern bool overrides_p (tree, tree); extern tree look_for_overrides_here (tree, tree); #define dfs_skip_bases ((tree)1) extern tree dfs_walk_all (tree, tree (*) (tree, void *), diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc index 65f70c595cf..3d0dad4ee59 100644 --- a/gcc/cp/error.cc +++ b/gcc/cp/error.cc @@ -3397,7 +3397,8 @@ location_of (tree t) return input_location; } else if (TREE_CODE (t) == OVERLOAD) - t = OVL_FIRST (t); + t = OVL_FIRST (t) != conv_op_marker ? OVL_FIRST (t) + : OVL_FIRST (OVL_CHAIN (t)); if (DECL_P (t)) return DECL_SOURCE_LOCATION (t); diff --git a/gcc/cp/search.cc b/gcc/cp/search.cc index b0421ee0524..432c919a1e9 100644 --- a/gcc/cp/search.cc +++ b/gcc/cp/search.cc @@ -2014,10 +2014,12 @@ maybe_check_overriding_exception_spec (tree overrider, tree basefn) } /* Check that virtual overrider OVERRIDER is acceptable for base function - BASEFN. Issue diagnostic, and return zero, if unacceptable. */ + BASEFN. Issue diagnostic if COMPLAIN & TF_ERROR, and return zero, if + unacceptable. */ static int -check_final_overrider (tree overrider, tree basefn) +check_final_overrider (tree overrider, tree basefn, + tsubst_flags_t complain = tf_error) { tree over_type = TREE_TYPE (overrider); tree base_type = TREE_TYPE (basefn); @@ -2080,8 +2082,10 @@ check_final_overrider (tree overrider, tree basefn) converting to void *, or qualification conversion. */ { auto_diagnostic_group d; - if (pedwarn (DECL_SOURCE_LOCATION (overrider), 0, - "invalid covariant return type for %q#D", overrider)) + if ((complain & tf_error) + && pedwarn (DECL_SOURCE_LOCATION (overrider), 0, + "invalid covariant return type for %q#D", + overrider)) inform (DECL_SOURCE_LOCATION (basefn), "overridden function is %q#D", basefn); } @@ -2095,6 +2099,8 @@ check_final_overrider (tree overrider, tree basefn) else { auto_diagnostic_group d; + if (!(complain & tf_error)) + return 0; if (fail == 1) error ("invalid covariant return type for %q+#D", overrider); else @@ -2114,6 +2120,8 @@ check_final_overrider (tree overrider, tree basefn) && !tx_safe_fn_type_p (base_type) && !tx_safe_fn_type_p (over_type)) { + if (!(complain & tf_error)) + return 0; auto_diagnostic_group d; error ("conflicting type attributes specified for %q+#D", overrider); inform (DECL_SOURCE_LOCATION (basefn), @@ -2128,6 +2136,8 @@ check_final_overrider (tree overrider, tree basefn) if (DECL_IMMEDIATE_FUNCTION_P (overrider) != DECL_IMMEDIATE_FUNCTION_P (basefn)) { + if (!(complain & tf_error)) + return 0; auto_diagnostic_group d; if (DECL_IMMEDIATE_FUNCTION_P (overrider)) error ("% function %q+D overriding non-% " @@ -2148,7 +2158,8 @@ check_final_overrider (tree overrider, tree basefn) && lookup_attribute ("transaction_safe_dynamic", DECL_ATTRIBUTES (overrider)) && !lookup_attribute ("transaction_safe_dynamic", - DECL_ATTRIBUTES (basefn))) + DECL_ATTRIBUTES (basefn)) + && (complain & tf_error)) { auto_diagnostic_group d; error_at (DECL_SOURCE_LOCATION (overrider), @@ -2159,6 +2170,8 @@ check_final_overrider (tree overrider, tree basefn) if (DECL_DELETED_FN (basefn) != DECL_DELETED_FN (overrider)) { + if (!(complain & tf_error)) + return 0; if (DECL_DELETED_FN (overrider)) { auto_diagnostic_group d; @@ -2181,6 +2194,8 @@ check_final_overrider (tree overrider, tree basefn) if (!DECL_HAS_CONTRACTS_P (basefn) && DECL_HAS_CONTRACTS_P (overrider)) { + if (!(complain & tf_error)) + return 0; auto_diagnostic_group d; error ("function with contracts %q+D overriding contractless function", overrider); @@ -2207,6 +2222,8 @@ check_final_overrider (tree overrider, tree basefn) if (DECL_FINAL_P (basefn)) { + if (!(complain & tf_error)) + return 0; auto_diagnostic_group d; error ("virtual function %q+D overriding final function", overrider); inform (DECL_SOURCE_LOCATION (basefn), @@ -2216,6 +2233,15 @@ check_final_overrider (tree overrider, tree basefn) return 1; } +/* Check whether FN is a valid overrider for base function BASEFN. Note that + no diagnostic is emitted if FN is not a valid overrider. */ + +bool +overrides_p (tree fn, tree basefn) +{ + return check_final_overrider (fn, basefn, /*complain=*/tf_none); +} + /* Given a class TYPE, and a function decl FNDECL, look for virtual functions in TYPE's hierarchy which FNDECL overrides. We do not look in TYPE itself, only its bases. diff --git a/gcc/testsuite/g++.dg/warn/Woverloaded-virt1.C b/gcc/testsuite/g++.dg/warn/Woverloaded-virt1.C index 92f8327b9d0..9091bfabc96 100644 --- a/gcc/testsuite/g++.dg/warn/Woverloaded-virt1.C +++ b/gcc/testsuite/g++.dg/warn/Woverloaded-virt1.C @@ -5,10 +5,12 @@ class Foo { public: virtual void f(int); // { dg-warning "hidden" } + void g(int); // Not virtual, so no warning }; class Bar : public Foo { public: virtual void f(short); // { dg-message "by" } + virtual void g(short); }; diff --git a/gcc/testsuite/g++.dg/warn/Woverloaded-virt10.C b/gcc/testsuite/g++.dg/warn/Woverloaded-virt10.C new file mode 100644 index 00000000000..42b8b0f9788 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Woverloaded-virt10.C @@ -0,0 +1,11 @@ +// PR c++/117114 - Test case from PR c++/117114 +// { dg-do compile { target c++11 } } +// { dg-additional-options -Woverloaded-virtual } + +struct Troops { virtual ~Troops(); }; +struct Control { virtual int GetControl() const = 0; }; +struct Army : Troops, Control { int GetControl() const override; }; + +struct VirtualControl : virtual Control { + int GetControl() const override; +}; diff --git a/gcc/testsuite/g++.dg/warn/Woverloaded-virt11.C b/gcc/testsuite/g++.dg/warn/Woverloaded-virt11.C new file mode 100644 index 00000000000..bd82ce90ea8 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Woverloaded-virt11.C @@ -0,0 +1,25 @@ +// PR c++/109918 - More tests with multiple inheritance +// { dg-do compile { target c++11 } } +// { dg-additional-options -Woverloaded-virtual } + +struct Troops { virtual ~Troops(); }; +struct Control { + virtual int GetControl() const { return 42; } // { dg-warning "was hidden" } +}; +struct Army : Troops, Control { + template void GetControl() const; // { dg-message "by" } +}; + + +struct A { + virtual void get() const; +}; +struct B { + virtual void get() const; + virtual void get(char) const; // { dg-warning "was hidden" } +}; + +struct C : A, B { + virtual void get() const; // { dg-message "by" } + virtual void get(int) const; // { dg-message "by" } +}; diff --git a/gcc/testsuite/g++.dg/warn/Woverloaded-virt12.C b/gcc/testsuite/g++.dg/warn/Woverloaded-virt12.C new file mode 100644 index 00000000000..3cfe22c03ec --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Woverloaded-virt12.C @@ -0,0 +1,23 @@ +// PR c++/109918 - Test covariant return types +// { dg-do compile { target c++11 } } +// { dg-additional-options -Woverloaded-virtual } + +struct Big { virtual ~Big () {} }; +struct Smaller : Big {}; + +// Single inheritance case +struct Foo { + virtual Big* getMe() const; +}; +struct Bar : Foo { + virtual Smaller* getMe() const; +}; + +// Multiple inheritance case +struct Troops { virtual ~Troops(); }; +struct Control { + virtual Big* GetControl() const; +}; +struct Army : Troops, Control { + virtual Smaller* GetControl() const; +}; diff --git a/gcc/testsuite/g++.dg/warn/Woverloaded-virt13.C b/gcc/testsuite/g++.dg/warn/Woverloaded-virt13.C new file mode 100644 index 00000000000..fb421e17dc3 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Woverloaded-virt13.C @@ -0,0 +1,28 @@ +// PR c++/117114 - Reduced version of another bootstrap error +// Unrelated methods can have the same DECL_VINDEX when the class hierarchy +// depth is 2 or more. +// { dg-do compile { target c++11 } } +// { dg-additional-options -Woverloaded-virtual } + +class HIRFullVisitor; +class HIRTypeVisitor; + +struct FullVisitable { + virtual void accept_vis (HIRFullVisitor &vis) = 0; +}; + +struct Node { + virtual ~Node() {} +}; + +struct Type : Node, FullVisitable +{ + using FullVisitable::accept_vis; + virtual void accept_vis (HIRTypeVisitor &vis) = 0; +}; + +struct TypePath : Type +{ + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRTypeVisitor &vis) override; +}; diff --git a/gcc/testsuite/g++.dg/warn/Woverloaded-virt5.C b/gcc/testsuite/g++.dg/warn/Woverloaded-virt5.C new file mode 100644 index 00000000000..01cd562609a --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Woverloaded-virt5.C @@ -0,0 +1,12 @@ +// PR c++/109918 - Exact PR testcase +// { dg-do compile } +// { dg-additional-options -Wall } + +struct A { + virtual operator int() { return 42; } + virtual operator char() = 0; +}; + +struct B : public A { + operator char() { return 'A'; } +}; diff --git a/gcc/testsuite/g++.dg/warn/Woverloaded-virt6.C b/gcc/testsuite/g++.dg/warn/Woverloaded-virt6.C new file mode 100644 index 00000000000..c18049e3a92 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Woverloaded-virt6.C @@ -0,0 +1,12 @@ +// PR c++/109918 - PR testcase with -Woverloaded-virtual=2 +// { dg-do compile } +// { dg-additional-options -Woverloaded-virtual=2 } + +struct A { + virtual operator int() { return 42; } + virtual operator char() = 0; +}; + +struct B : public A { + operator char() { return 'A'; } +}; diff --git a/gcc/testsuite/g++.dg/warn/Woverloaded-virt7.C b/gcc/testsuite/g++.dg/warn/Woverloaded-virt7.C new file mode 100644 index 00000000000..5e8227f2793 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Woverloaded-virt7.C @@ -0,0 +1,31 @@ +// PR c++/109918 - Test different CV-quals and usage of typedefs +// { dg-do compile } +// { dg-additional-options -Woverloaded-virtual } + +struct A { + virtual operator char() { return 'a'; } + virtual operator char() const { return 'b'; } // { dg-warning "was hidden" } + virtual operator int() { return 42; } +}; + +struct B : public A { + operator char() { return 'A'; } // { dg-note "by" } + operator int() { return 43; } +}; + +typedef char MyChar; +struct C : public A { + operator MyChar() { return 'A'; } // { dg-note "by" } + operator int() { return 43; } +}; + +struct AA { + virtual char func(char) { return 'a'; } + virtual char func(char) const { return 'b'; } // { dg-warning "was hidden" } + virtual int func(int) { return 42; } +}; + +struct BB : public AA { + char func(char) { return 'A'; } // { dg-note "by" } + int func(int) { return 43; } // { dg-note "by" } +}; diff --git a/gcc/testsuite/g++.dg/warn/Woverloaded-virt8.C b/gcc/testsuite/g++.dg/warn/Woverloaded-virt8.C new file mode 100644 index 00000000000..51af2dae77c --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Woverloaded-virt8.C @@ -0,0 +1,15 @@ +// Identified when investigating PR c++/109918: no warning was emitted due to +// an incorrect early return in warn_hidden. +// { dg-additional-options -Wall } + +struct Foo +{ + virtual void f(int); // { dg-warning "hidden" } + virtual void g() {} +}; + +struct Bar : Foo +{ + virtual void f(short); // { dg-message "by" } + virtual void g() {} +}; diff --git a/gcc/testsuite/g++.dg/warn/Woverloaded-virt9.C b/gcc/testsuite/g++.dg/warn/Woverloaded-virt9.C new file mode 100644 index 00000000000..6d315c63a08 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Woverloaded-virt9.C @@ -0,0 +1,14 @@ +// PR c++/109918: Non virtual overloads in derived classes that don't override +// anything shouldn't cause warnings, even at -Woverloaded-virtual=2 +// { dg-additional-options -Woverloaded-virtual=2 } + +struct Foo +{ + virtual void g() {} +}; + +struct Bar : Foo +{ + virtual void g() {} + void g(int) {} +};