From patchwork Thu Feb 17 21:22:17 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 51194 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 97DB43857412 for ; Thu, 17 Feb 2022 21:23:00 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 97DB43857412 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1645132980; bh=TrqmKTOvbEP4B8354tSN8Cxm26DX+S+saFQ3uknqaDY=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=Vf+50X8GxuWOymLXxifEZOoAtqkTYpkYd6Px9lD2v/FR4nKDgNzCQW6uUwnJYjT3v B5A9TQfmmS9huP3cy27bNa5liKazex7H3vWeZqaRsM1OQBw9o3hzRp77EX2ijeIhpZ 7DVk80/Dn+JfcQ/gpqbXRR3Tg4O+N/76eG2W4dBU= 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 D965A3858D20 for ; Thu, 17 Feb 2022 21:22:29 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org D965A3858D20 Received: from mail-qv1-f71.google.com (mail-qv1-f71.google.com [209.85.219.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-44-ZVwtaLCcMiunXDCviyX9hQ-1; Thu, 17 Feb 2022 16:22:22 -0500 X-MC-Unique: ZVwtaLCcMiunXDCviyX9hQ-1 Received: by mail-qv1-f71.google.com with SMTP id kd18-20020a056214401200b0042de5c14702so6742269qvb.12 for ; Thu, 17 Feb 2022 13:22:22 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=TrqmKTOvbEP4B8354tSN8Cxm26DX+S+saFQ3uknqaDY=; b=hzUnTioRNK5JeORo3hN7y681A2VR4QcpRBRf/roCpJwRHvL69uTKPvRtmiDazxQxsf DNV6+T9K/0YgFapmcEc0IJLpBRwnaEBpasKEJgMlUDoYgBn3C9nIwQ0Q5HVuHZxivAzz KP0+cSL8Pz4zp5ao2fL3SaP8Zt+Ix4/Plx79NMZCBT+h/5ctaCboPQrQvh8GR0/fyH2f wNhhPMFmXIDYddUvpWBdZ7leYlTJ4C93o9xvCQCv71FEkUiBilQyhBuhm3ztF06U9wCM GPagBKrGNVr+91I7/kwhw8ZuuuSsnny1PugGBXJ1y7mBN2tsrWI9wm5isxg2J3KDskAY moEg== X-Gm-Message-State: AOAM531/RVqZ0CNKeRwNVdLGfZQRXHo0Z3CZkrqopmobkmsMnCiOzujy t1Q8Wg+tZs4f7oVisKUwevm8n2ByVW4AypxyMaNTpHffwttatD8w0pHOpp0H9k5v+YU2SvVlJMW Nxp/VKiRkJZUR4nD1TvEYInuVEL30MHRipXOv3GyrQ7PA36yhvfbYnVu8yf6YqiX8uQ== X-Received: by 2002:a05:622a:8e:b0:2d4:b31a:df51 with SMTP id o14-20020a05622a008e00b002d4b31adf51mr4229125qtw.108.1645132941444; Thu, 17 Feb 2022 13:22:21 -0800 (PST) X-Google-Smtp-Source: ABdhPJy5jEYIci+MM4vEAjURVykMwKanoULLi+phXSx5/dQlCPdWWlLMRnejc1lxx7Cm1R8vs7GgLA== X-Received: by 2002:a05:622a:8e:b0:2d4:b31a:df51 with SMTP id o14-20020a05622a008e00b002d4b31adf51mr4229096qtw.108.1645132940766; Thu, 17 Feb 2022 13:22:20 -0800 (PST) Received: from barrymore.redhat.com (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 z19sm4045886qts.18.2022.02.17.13.22.19 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 17 Feb 2022 13:22:19 -0800 (PST) To: gcc-patches@gcc.gnu.org Subject: [pushed] c++: avoid duplicate deprecated warning [PR90451] Date: Thu, 17 Feb 2022 16:22:17 -0500 Message-Id: <20220217212217.2118040-1-jason@redhat.com> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-13.1 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) 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: Jason Merrill via Gcc-patches From: Jason Merrill Reply-To: Jason Merrill Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" We were getting the deprecated warning twice for the same call because we called mark_used first in finish_qualified_id_expr and then again in build_over_call. Let's not call it the first time; C++17 clarified that a function is used only when it is selected from an overload set, which happens later. Then I had to add a few more uses in places that don't do anything further with the expression (convert_to_void, finish_decltype_type), and places that use the expression more unusually (cp_build_addr_expr_1, convert_nontype_argument). The new mark_single_function is mostly so that I only have to put the comment in one place. Tested x86_64-pc-linux-gnu, applying to trunk. PR c++/90451 gcc/cp/ChangeLog: * decl2.cc (mark_single_function): New. * cp-tree.h: Declare it. * typeck.cc (cp_build_addr_expr_1): mark_used when making a PMF. * semantics.cc (finish_qualified_id_expr): Not here. (finish_id_expression_1): Or here. (finish_decltype_type): Call mark_single_function. * cvt.cc (convert_to_void): And here. * pt.cc (convert_nontype_argument): And here. * init.cc (build_offset_ref): Adjust assert. gcc/testsuite/ChangeLog: * g++.dg/warn/deprecated-14.C: New test. * g++.dg/warn/deprecated-15.C: New test. --- gcc/cp/cp-tree.h | 1 + gcc/cp/cvt.cc | 3 + gcc/cp/decl2.cc | 23 ++++++++ gcc/cp/init.cc | 5 +- gcc/cp/pt.cc | 4 ++ gcc/cp/semantics.cc | 22 ++----- gcc/cp/typeck.cc | 6 ++ gcc/testsuite/g++.dg/warn/deprecated-14.C | 72 +++++++++++++++++++++++ gcc/testsuite/g++.dg/warn/deprecated-15.C | 14 +++++ 9 files changed, 132 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/g++.dg/warn/deprecated-14.C create mode 100644 gcc/testsuite/g++.dg/warn/deprecated-15.C base-commit: 1c2b44b52364cb5661095b346de794bc7ff02866 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index f253b32c3f2..37d462fca6e 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6930,6 +6930,7 @@ extern void no_linkage_error (tree); extern void check_default_args (tree); extern bool mark_used (tree); extern bool mark_used (tree, tsubst_flags_t); +extern bool mark_single_function (tree, tsubst_flags_t); extern void finish_static_data_member_decl (tree, tree, bool, tree, int); extern tree cp_build_parm_decl (tree, tree, tree); extern void copy_linkage (tree, tree); diff --git a/gcc/cp/cvt.cc b/gcc/cp/cvt.cc index e9803c1be31..53aa41368fe 100644 --- a/gcc/cp/cvt.cc +++ b/gcc/cp/cvt.cc @@ -1482,6 +1482,9 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain) default:; } expr = resolve_nondeduced_context (expr, complain); + if (!mark_single_function (expr, complain)) + return error_mark_node; + { tree probe = expr; diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc index c6bfcfe631a..2e58419ea51 100644 --- a/gcc/cp/decl2.cc +++ b/gcc/cp/decl2.cc @@ -5718,6 +5718,29 @@ decl_dependent_p (tree decl) return false; } +/* [basic.def.odr] A function is named [and therefore odr-used] by an + expression or conversion if it is the selected member of an overload set in + an overload resolution performed as part of forming that expression or + conversion, unless it is a pure virtual function and either the expression + is not an id-expression naming the function with an explicitly qualified + name or the expression forms a pointer to member. + + Mostly, we call mark_used in places that actually do something with a + function, like build_over_call. But in a few places we end up with a + non-overloaded FUNCTION_DECL that we aren't going to do any more with, like + convert_to_void. resolve_nondeduced_context is called in those places, + but it's also called in too many other places. */ + +bool +mark_single_function (tree expr, tsubst_flags_t complain) +{ + if (is_overloaded_fn (expr) == 1 + && !mark_used (expr, complain) + && (complain & tf_error)) + return false; + return true; +} + /* Mark DECL (either a _DECL or a BASELINK) as "used" in the program. If DECL is a specialization or implicitly declared class member, generate the actual definition. Return false if something goes diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc index fcb255f1ac7..545d904c0f9 100644 --- a/gcc/cp/init.cc +++ b/gcc/cp/init.cc @@ -2362,8 +2362,9 @@ build_offset_ref (tree type, tree member, bool address_p, return error_mark_node; gcc_assert (DECL_P (member) || BASELINK_P (member)); - /* Callers should call mark_used before this point. */ - gcc_assert (!DECL_P (member) || TREE_USED (member)); + /* Callers should call mark_used before this point, except for functions. */ + gcc_assert (!DECL_P (member) || TREE_USED (member) + || TREE_CODE (member) == FUNCTION_DECL); type = TYPE_MAIN_VARIANT (type); if (!COMPLETE_OR_OPEN_TYPE_P (complete_type (type))) diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 6dda66081bd..d4a40d517d1 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -7382,6 +7382,10 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain) for examples. */ if (TYPE_REF_OBJ_P (type) || TYPE_REFFN_P (type)) { + /* Check this before we strip *& to avoid redundancy. */ + if (!mark_single_function (expr, complain)) + return error_mark_node; + tree probe_type, probe = expr; if (REFERENCE_REF_P (probe)) probe = TREE_OPERAND (probe, 0); diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index 0cb17a6a8ab..94c0f183fb1 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -2319,7 +2319,10 @@ finish_qualified_id_expr (tree qualifying_class, if (error_operand_p (expr)) return error_mark_node; - if ((DECL_P (expr) || BASELINK_P (expr)) + if (DECL_P (expr) + /* Functions are marked after overload resolution; avoid redundant + warnings. */ + && TREE_CODE (expr) != FUNCTION_DECL && !mark_used (expr, complain)) return error_mark_node; @@ -4202,9 +4205,6 @@ finish_id_expression_1 (tree id_expression, decl = (adjust_result_of_qualified_name_lookup (decl, scope, current_nonlambda_class_type())); - if (TREE_CODE (decl) == FUNCTION_DECL) - mark_used (decl); - cp_warn_deprecated_use_scopes (scope); if (TYPE_P (scope)) @@ -4236,18 +4236,6 @@ finish_id_expression_1 (tree id_expression, tree first_fn = get_first_fn (decl); first_fn = STRIP_TEMPLATE (first_fn); - /* [basic.def.odr]: "A function whose name appears as a - potentially-evaluated expression is odr-used if it is the unique - lookup result". - - But only mark it if it's a complete postfix-expression; in a call, - ADL might select a different function, and we'll call mark_used in - build_over_call. */ - if (done - && !really_overloaded_fn (decl) - && !mark_used (first_fn)) - return error_mark_node; - if (!template_arg_p && (TREE_CODE (first_fn) == USING_DECL || (TREE_CODE (first_fn) == FUNCTION_DECL @@ -11256,6 +11244,8 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p, /* The type denoted by decltype(e) is defined as follows: */ expr = resolve_nondeduced_context (expr, complain); + if (!mark_single_function (expr, complain)) + return error_mark_node; if (invalid_nonstatic_memfn_p (input_location, expr, complain)) return error_mark_node; diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc index 50d04c1b84e..f796337f73c 100644 --- a/gcc/cp/typeck.cc +++ b/gcc/cp/typeck.cc @@ -6854,6 +6854,12 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain) return error_mark_node; } + /* Forming a pointer-to-member is a use of non-pure-virtual fns. */ + if (TREE_CODE (t) == FUNCTION_DECL + && !DECL_PURE_VIRTUAL_P (t) + && !mark_used (t, complain) && !(complain & tf_error)) + return error_mark_node; + type = build_ptrmem_type (context_for_name_lookup (t), TREE_TYPE (t)); t = make_ptrmem_cst (type, t); diff --git a/gcc/testsuite/g++.dg/warn/deprecated-14.C b/gcc/testsuite/g++.dg/warn/deprecated-14.C new file mode 100644 index 00000000000..7ad7ec49c7f --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/deprecated-14.C @@ -0,0 +1,72 @@ +// PR c++/90451 +// { dg-do compile { target c++11 } } + +struct myclass{ + [[deprecated("deprecated-static1")]] static void stat1() { } + [[deprecated("deprecated-static2")]] static void stat2() { } + [[deprecated("deprecated-static3")]] static void stat3() { } + [[deprecated("deprecated-static4")]] static void stat4() { } + + [[deprecated("deprecated-non1")]] void non1() { } + [[deprecated("deprecated-non2")]] void non2() { } +}; + +[[deprecated("deprecated-global1")]] void fn1(); +[[deprecated("deprecated-global2")]] void fn2(); +[[deprecated("deprecated-global3")]] void fn3(); + +[[deprecated("deprecated-global4")]] void fn4(); +[[deprecated("deprecated-global5")]] void fn5(); +[[deprecated("deprecated-global6")]] void fn6(); +[[deprecated("deprecated-global7")]] void fn7(); +[[deprecated("deprecated-global8")]] void fn8(); + +namespace N +{ + [[deprecated("deprecated-ns1")]] void fn1(); + [[deprecated("deprecated-ns2")]] void fn2(); + [[deprecated("deprecated-ns3")]] void fn3(); +} + +int main() +{ + myclass::stat1(); // { dg-bogus "deprecated-static1.*deprecated-static1" } + // { dg-warning "deprecated-static1" "" { target *-*-* } .-1 } + &myclass::stat2; // { dg-bogus "deprecated-static2.*deprecated-static2" } + // { dg-warning "deprecated-static2" "" { target *-*-* } .-1 } + auto x = myclass::stat3; // { dg-bogus "deprecated-static3.*deprecated-static3" } + // { dg-warning "deprecated-static3" "" { target *-*-* } .-1 } + (void) myclass::stat4; // { dg-bogus "deprecated-static4.*deprecated-static4" } + // { dg-warning "deprecated-static4" "" { target *-*-* } .-1 } + + myclass m; + m.myclass::non1(); // { dg-bogus "deprecated-non1.*deprecated-non1" } + // { dg-warning "deprecated-non1" "" { target *-*-* } .-1 } + &myclass::non2; // { dg-bogus "deprecated-non2.*deprecated-non2" } + // { dg-warning "deprecated-non2" "" { target *-*-* } .-1 } + + fn1(); // { dg-bogus "deprecated-global1.*deprecated-global1" } + // { dg-warning "deprecated-global1" "" { target *-*-* } .-1 } + &fn2; // { dg-bogus "deprecated-global2.*deprecated-global2" } + // { dg-warning "deprecated-global2" "" { target *-*-* } .-1 } + auto xg = fn3; // { dg-bogus "deprecated-global2.*deprecated-global3" } + // { dg-warning "deprecated-global3" "" { target *-*-* } .-1 } + (void) fn7; // { dg-bogus "deprecated-global7.*deprecated-global7" } + // { dg-warning "deprecated-global7" "" { target *-*-* } .-1 } + + ::fn4(); // { dg-bogus "deprecated-global4.*deprecated-global4" } + // { dg-warning "deprecated-global4" "" { target *-*-* } .-1 } + &::fn5; // { dg-bogus "deprecated-global5.*deprecated-global5" } + // { dg-warning "deprecated-global5" "" { target *-*-* } .-1 } + auto xgs = ::fn6; // { dg-bogus "deprecated-global2.*deprecated-global6" } + // { dg-warning "deprecated-global6" "" { target *-*-* } .-1 } + (void) ::fn8; // { dg-bogus "deprecated-global8.*deprecated-global8" } + // { dg-warning "deprecated-global8" "" { target *-*-* } .-1 } + + N::fn1(); // { dg-bogus "deprecated-ns1.*deprecated-ns1" } + // { dg-warning "deprecated-ns1" "" { target *-*-* } .-1 } + &N::fn2; // { dg-bogus "deprecated-ns2.*deprecated-ns2" } + // { dg-warning "deprecated-ns2" "" { target *-*-* } .-1 } + auto xgn = N::fn3; // { dg-bogus "deprecated-ns2.*deprecated-ns3" } + // { dg-warning "deprecated-ns3" "" { target *-*-* } .-1 } +} diff --git a/gcc/testsuite/g++.dg/warn/deprecated-15.C b/gcc/testsuite/g++.dg/warn/deprecated-15.C new file mode 100644 index 00000000000..7f25c46a9d7 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/deprecated-15.C @@ -0,0 +1,14 @@ +// { dg-do compile { target c++11 } } + +using vfn_t = void(); + +template struct A { }; +template struct B { }; + +[[deprecated("deprecated-global1")]] void fn1(); +[[deprecated("deprecated-global2")]] void fn2(); + +A a; // { dg-bogus "deprecated-global1.*deprecated-global1" } +// { dg-warning "deprecated-global1" "" { target *-*-* } .-1 } +B b; // { dg-bogus "deprecated-global2.*deprecated-global2" } +// { dg-warning "deprecated-global2" "" { target *-*-* } .-1 }