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 6049E3857413 for ; Tue, 7 Jun 2022 19:18:23 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 6049E3857413 Received: from mail-qt1-f200.google.com (mail-qt1-f200.google.com [209.85.160.200]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-312--X3dzy-FPJC8ekssns0hew-1; Tue, 07 Jun 2022 15:18:22 -0400 X-MC-Unique: -X3dzy-FPJC8ekssns0hew-1 Received: by mail-qt1-f200.google.com with SMTP id m6-20020ac866c6000000b002f52f9fb4edso14643226qtp.19 for ; Tue, 07 Jun 2022 12:18:22 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:date:to:cc:subject:in-reply-to:message-id :references:mime-version; bh=bByKtp7B2p2+HzwcxuYH5807X869R3v6Wo+Ngyt9/m8=; b=7W4ggp3laNmn/wCxcauTdIoBTEmOjqMgWUoII4UxkV2JC5XwRU0qbd8yOwNztMA1ID aU3aAE6liKUgwGY6Dq9yCbUYKcYM8pypUDVhlrZ/grXwdH6+ij6c+giXjrtFn4RmG4rQ fH1wo+JGdAjV4MA/I/xZtyXCBeHlAc/EZMS4t4IyuDSb7NOOaKdzMmE8m2hFeeM1Yk8A v45cIlVO05Nc5AIMHYNT1YmBcQf2yF8yCaK7Xv0BH6d8XAgVb+07vHOT7EQEL9Mnzf53 raVkve3t6ZHcNibS8Hvp/z8Czv7dsqimzg9TOgevqqbYLDPJAMnPxwZEXvlfCR5axbUj LTSw== X-Gm-Message-State: AOAM53255/eBGygCkI7uy11Je77zAC/9mVk/KVdfqvVpwP+i6mwafjT5 auHNUHB12PzOeETTkb57OAN1v5Tt6FZQ7U22eolnyIsVvF5wg4Ig+a9k/YIAos9Qiqe6R5XVZC+ ies8D2qu+xtpvHr7e/w== X-Received: by 2002:ad4:5b89:0:b0:46b:9e62:ea06 with SMTP id 9-20020ad45b89000000b0046b9e62ea06mr9305620qvp.66.1654629501482; Tue, 07 Jun 2022 12:18:21 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxFgXvfVigZiPg4ql1wqn71Tfqo1sYJtGHmhATck90o7tIR+IN2MaYIfl11iv1ER/oStq6xpA== X-Received: by 2002:ad4:5b89:0:b0:46b:9e62:ea06 with SMTP id 9-20020ad45b89000000b0046b9e62ea06mr9305599qvp.66.1654629501007; Tue, 07 Jun 2022 12:18:21 -0700 (PDT) Received: from [192.168.1.130] (ool-457670bb.dyn.optonline.net. [69.118.112.187]) by smtp.gmail.com with ESMTPSA id bp13-20020a05620a458d00b006a6bfcd6df5sm5420421qkb.37.2022.06.07.12.18.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Jun 2022 12:18:20 -0700 (PDT) From: Patrick Palka X-Google-Original-From: Patrick Palka Date: Tue, 7 Jun 2022 15:18:19 -0400 (EDT) To: Jason Merrill cc: Patrick Palka , gcc-patches@gcc.gnu.org Subject: Re: [PATCH] c++: function NTTP argument considered unused [PR53164, PR105848] In-Reply-To: Message-ID: <20cd91d1-38a1-03f9-3565-682542344347@idea> References: <95c2097c-5466-fcae-fdcd-fafdf1ab9431@idea> <41cec505-46f4-5622-ab08-e693fa8b7d90@redhat.com> <50baf432-cc69-45b9-0325-fe1bb7418308@idea> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-14.7 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_NONE, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8BIT X-Content-Filtered-By: Mailman/MimeDel 2.1.29 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-List-Received-Date: Tue, 07 Jun 2022 19:18:26 -0000 On Tue, 7 Jun 2022, Jason Merrill wrote: > On 6/7/22 09:24, Patrick Palka wrote: > > On Mon, 6 Jun 2022, Jason Merrill wrote: > > > > > On 6/6/22 14:27, Patrick Palka wrote: > > > > On Thu, 7 Oct 2021, Jason Merrill wrote: > > > > > > > > > On 10/7/21 11:17, Patrick Palka wrote: > > > > > > On Wed, 6 Oct 2021, Jason Merrill wrote: > > > > > > > > > > > > > On 10/6/21 15:52, Patrick Palka wrote: > > > > > > > > On Wed, 6 Oct 2021, Patrick Palka wrote: > > > > > > > > > > > > > > > > > On Tue, 5 Oct 2021, Jason Merrill wrote: > > > > > > > > > > > > > > > > > > > On 10/5/21 15:17, Patrick Palka wrote: > > > > > > > > > > > On Mon, 4 Oct 2021, Patrick Palka wrote: > > > > > > > > > > > > > > > > > > > > > > > When passing a function template as the argument to a > > > > > > > > > > > > function > > > > > > > > > > > > NTTP > > > > > > > > > > > > inside a template, we resolve it to the right > > > > > > > > > > > > specialization > > > > > > > > > > > > ahead > > > > > > > > > > > > of > > > > > > > > > > > > time via resolve_address_of_overloaded_function, though > > > > > > > > > > > > the > > > > > > > > > > > > call > > > > > > > > > > > > to > > > > > > > > > > > > mark_used within defers odr-using it until instantiation > > > > > > > > > > > > time > > > > > > > > > > > > (as > > > > > > > > > > > > usual). > > > > > > > > > > > > But at instantiation time we end up never calling > > > > > > > > > > > > mark_used > > > > > > > > > > > > on > > > > > > > > > > > > the > > > > > > > > > > > > specialization. > > > > > > > > > > > > > > > > > > > > > > > > This patch fixes this by adding a call to mark_used in > > > > > > > > > > > > convert_nontype_argument_function. > > > > > > > > > > > > > > > > > > > > > > > > PR c++/53164 > > > > > > > > > > > > > > > > > > > > > > > > gcc/cp/ChangeLog: > > > > > > > > > > > > > > > > > > > > > > > > * pt.c (convert_nontype_argument_function): Call > > > > > > > > > > > > mark_used. > > > > > > > > > > > > > > > > > > > > > > > > gcc/testsuite/ChangeLog: > > > > > > > > > > > > > > > > > > > > > > > > * g++.dg/template/non-dependent16.C: New test. > > > > > > > > > > > > --- > > > > > > > > > > > > gcc/cp/pt.c | > > > > > > > > > > > > 3 > > > > > > > > > > > > +++ > > > > > > > > > > > > gcc/testsuite/g++.dg/template/non-dependent16.C | > > > > > > > > > > > > 16 > > > > > > > > > > > > ++++++++++++++++ > > > > > > > > > > > > 2 files changed, 19 insertions(+) > > > > > > > > > > > > create mode 100644 > > > > > > > > > > > > gcc/testsuite/g++.dg/template/non-dependent16.C > > > > > > > > > > > > > > > > > > > > > > > > diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c > > > > > > > > > > > > index f950f4a21b7..5e819c9598c 100644 > > > > > > > > > > > > --- a/gcc/cp/pt.c > > > > > > > > > > > > +++ b/gcc/cp/pt.c > > > > > > > > > > > > @@ -6668,6 +6668,9 @@ convert_nontype_argument_function > > > > > > > > > > > > (tree > > > > > > > > > > > > type, > > > > > > > > > > > > tree > > > > > > > > > > > > expr, > > > > > > > > > > > > return NULL_TREE; > > > > > > > > > > > > } > > > > > > > > > > > > + if (!mark_used (fn_no_ptr, complain) && > > > > > > > > > > > > !(complain & > > > > > > > > > > > > tf_error)) > > > > > > > > > > > > + return NULL_TREE; > > > > > > > > > > > > + > > > > > > > > > > > > linkage = decl_linkage (fn_no_ptr); > > > > > > > > > > > > if (cxx_dialect >= cxx11 ? linkage == lk_none : > > > > > > > > > > > > linkage != > > > > > > > > > > > > lk_external) > > > > > > > > > > > > { > > > > > > > > > > > > diff --git > > > > > > > > > > > > a/gcc/testsuite/g++.dg/template/non-dependent16.C > > > > > > > > > > > > b/gcc/testsuite/g++.dg/template/non-dependent16.C > > > > > > > > > > > > new file mode 100644 > > > > > > > > > > > > index 00000000000..b7dca8f6752 > > > > > > > > > > > > --- /dev/null > > > > > > > > > > > > +++ b/gcc/testsuite/g++.dg/template/non-dependent16.C > > > > > > > > > > > > @@ -0,0 +1,16 @@ > > > > > > > > > > > > +// PR c++/53164 > > > > > > > > > > > > + > > > > > > > > > > > > +template > > > > > > > > > > > > +void f(T) { > > > > > > > > > > > > + T::fail; // { dg-error "not a member" } > > > > > > > > > > > > +} > > > > > > > > > > > > + > > > > > > > > > > > > +template > > > > > > > > > > > > +struct A { }; > > > > > > > > > > > > + > > > > > > > > > > > > +template > > > > > > > > > > > > +void g() { > > > > > > > > > > > > + A a; > > > > > > > > > > > > +} > > > > > > > > > > > > > > > > > > > > > > I should mention that the original testcase in the PR was > > > > > > > > > > > slightly > > > > > > > > > > > different than this one in that it also performed a call > > > > > > > > > > > to > > > > > > > > > > > the > > > > > > > > > > > NTTP, > > > > > > > > > > > e.g. > > > > > > > > > > > > > > > > > > > > > > template > > > > > > > > > > > struct A { > > > > > > > > > > > static void h() { > > > > > > > > > > > p(0); > > > > > > > > > > > } > > > > > > > > > > > }; > > > > > > > > > > > > > > > > > > > > > > template > > > > > > > > > > > void g() { > > > > > > > > > > > A::h(); > > > > > > > > > > > } > > > > > > > > > > > > > > > > > > > > > > templated void g<0>(); > > > > > > > > > > > > > > > > > > > > > > and not even the call was enough to odr-use f, apparently > > > > > > > > > > > because > > > > > > > > > > > the > > > > > > > > > > > CALL_EXPR case of tsubst_expr calls mark_used on the > > > > > > > > > > > callee > > > > > > > > > > > only > > > > > > > > > > > when > > > > > > > > > > > it's a FUNCTION_DECL, but in this case after substitution > > > > > > > > > > > it's > > > > > > > > > > > an > > > > > > > > > > > ADDR_EXPR of a FUNCTION_DECL. Fixing this by looking > > > > > > > > > > > through > > > > > > > > > > > the > > > > > > > > > > > ADDR_EXPR > > > > > > > > > > > worked, but IIUC the call isn't necessary for f to be > > > > > > > > > > > odr-used, > > > > > > > > > > > simply > > > > > > > > > > > using f as a template argument should be sufficient, so it > > > > > > > > > > > seems > > > > > > > > > > > the > > > > > > > > > > > above is better fix. > > > > > > > > > > > > > > > > > > > > I agree that pedantically the use happens when substituting > > > > > > > > > > into > > > > > > > > > > the > > > > > > > > > > use > > > > > > > > > > of > > > > > > > > > > A, but convert_nontype_argument_function seems like a > > > > > > > > > > weird > > > > > > > > > > place > > > > > > > > > > to > > > > > > > > > > implement that; it's only called again during instantiation > > > > > > > > > > of > > > > > > > > > > A, > > > > > > > > > > when we > > > > > > > > > > instantiate the injected-class-name. If A isn't > > > > > > > > > > instantiated, > > > > > > > > > > e.g. > > > > > > > > > > if 'a' > > > > > > > > > > is a pointer to A, we again don't instantiate f. > > > > > > > > > > > > > > > > > > I see, makes sense.. I'm not sure where else we can mark the > > > > > > > > > use, > > > > > > > > > then. > > > > > > > > > Since we resolve the OVERLOAD f to the FUNCTION_DECL f > > > > > > > > > ahead > > > > > > > > > of > > > > > > > > > time (during which mark_used doesn't actually instantiate > > > > > > > > > f > > > > > > > > > because > > > > > > > > > we're inside a template), at instantiation time the type A > > > > > > > > > is > > > > > > > > > already > > > > > > > > > non-dependent so tsubst_aggr_type avoids doing the work that > > > > > > > > > would > > > > > > > > > end > > > > > > > > > up calling convert_nontype_argument_function. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > I see that clang doesn't reject your testcase, either, but > > > > > > > > > > MSVC > > > > > > > > > > and > > > > > > > > > > icc > > > > > > > > > > do > > > > > > > > > > (even with 'a' a pointer): https://godbolt.org/z/MGE6TcMch > > > > > > > > > > > > > > > > > > FWIW although Clang doesn't reject 'A a;', it does reject > > > > > > > > > 'using type = A;' weirdly enough: > > > > > > > > > https://godbolt.org/z/T9qEn6bWW > > > > > > > > > > > > > > > > > > > > > > > > > > > Shall we just go with the other more specific approach, that > > > > > > > > > makes > > > > > > > > > sure > > > > > > > > > the CALL_EXPR case of tsubst_expr calls mark_used when the > > > > > > > > > callee > > > > > > > > > is > > > > > > > > > an > > > > > > > > > ADDR_EXPR? Something like (bootstrapped and regtested): > > > > > > > > > > > > > > > > Err, this approach is wrong because by stripping the ADDR_EXPR > > > > > > > > here > > > > > > > > we > > > > > > > > end up checking access of the unwrapped FUNCTION_DECL again > > > > > > > > after > > > > > > > > substituting into the call. So we incorrectly reject e.g. > > > > > > > > > > > > > > > > template > > > > > > > > void g() { > > > > > > > > P(); // error: ‘static void A::h()’ is private within > > > > > > > > this > > > > > > > > context > > > > > > > > } > > > > > > > > > > > > > > > > struct A { > > > > > > > > void f() { > > > > > > > > g(); > > > > > > > > } > > > > > > > > private: > > > > > > > > static void h(); > > > > > > > > }; > > > > > > > > > > > > > > > > since A::h isn't accessible from g. > > > > > > > > > > > > > > I guess you could call mark_used directly instead of stripping the > > > > > > > ADDR_EXPR. > > > > > > > > > > > > That seems to work nicely, how does the below look? Bootstrapped > > > > > > and > > > > > > regtested on x86_64-pc-linux-gnu. > > > > > > > > > > > > > > > > > > > > Or for the general problem, perhaps we could mark the > > > > > > > TEMPLATE_INFO or > > > > > > > TI_ARGS > > > > > > > to indicate that we still need to mark_used the arguments when we > > > > > > > encounter > > > > > > > A again during instantiation? > > > > > > > > > > > > That sounds plausible, though I suppose it might not be worth it > > > > > > only to > > > > > > handle such a corner case.. > > > > > > > > > > Indeed. A lower-overhead possibility would be to remember, for a > > > > > template, > > > > > decls that we wanted to mark_used but didn't because we were in a > > > > > template. > > > > > But I wouldn't worry about it for now. > > > > > > > > > > > -- >8 -- > > > > > > > > > > > > Subject: [PATCH] c++: function NTTP argument considered unused > > > > > > [PR53164] > > > > > > > > > > > > Here at parse time the template argument f (an OVERLOAD) in A > > > > > > gets > > > > > > resolved ahead of time to the FUNCTION_DECL f, and we defer > > > > > > marking > > > > > > f as used until instantiation (of g) as usual. > > > > > > > > > > > > Later when instantiating g the type A (where f has already been > > > > > > resolved) > > > > > > is non-dependent, so tsubst_aggr_type avoids re-processing its > > > > > > template > > > > > > arguments, and we end up never actually marking f as used > > > > > > (which > > > > > > means > > > > > > we never instantiate it) even though A::h() calls it. > > > > > > > > > > > > This patch works around this problem by making us look through > > > > > > ADDR_EXPR > > > > > > when calling mark_used on the callee of a substituted CALL_EXPR. > > > > > > > > > > > > PR c++/53164 > > > > > > > > > > > > gcc/cp/ChangeLog: > > > > > > > > > > > > * pt.c (tsubst_copy_and_build) : Look through > > > > > > an > > > > > > ADDR_EXPR callee when calling mark_used. > > > > > > > > > > > > gcc/testsuite/ChangeLog: > > > > > > > > > > > > * g++.dg/template/fn-ptr3.C: New test. > > > > > > --- > > > > > > gcc/cp/pt.c | 12 ++++++++---- > > > > > > gcc/testsuite/g++.dg/template/fn-ptr3.C | 20 > > > > > > ++++++++++++++++++++ > > > > > > 2 files changed, 28 insertions(+), 4 deletions(-) > > > > > > create mode 100644 gcc/testsuite/g++.dg/template/fn-ptr3.C > > > > > > > > > > > > diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c > > > > > > index 1e52aa757e1..cd10340ce12 100644 > > > > > > --- a/gcc/cp/pt.c > > > > > > +++ b/gcc/cp/pt.c > > > > > > @@ -20508,10 +20508,14 @@ tsubst_copy_and_build (tree t, > > > > > > } > > > > > > /* Remember that there was a reference to this entity. > > > > > > */ > > > > > > - if (function != NULL_TREE > > > > > > - && DECL_P (function) > > > > > > - && !mark_used (function, complain) && !(complain & > > > > > > tf_error)) > > > > > > - RETURN (error_mark_node); > > > > > > + if (function) > > > > > > + { > > > > > > + tree sub = function; > > > > > > + if (TREE_CODE (sub) == ADDR_EXPR) > > > > > > + sub = TREE_OPERAND (sub, 0); > > > > > > > > > > Let's add a comment about why this is needed. OK with that change. > > > > > > > > Thanks. I ended up neglecting to commit this patch for GCC 12, and > > > > turns out it also fixes the recently reported regression PR105848 > > > > (which is essentially another manifestation of PR53164 exposed by the > > > > non-dependent overload set pruning patch r12-6075), so I'm going to > > > > commit this now. I suppose it's also OK to backport to 12? > > > > > > What if the use is not as a call, but say assigning the address to a > > > global > > > pointer? > > > > > > I wonder about calling mark_used when substituting the > > > TEMPLATE_PARM_INDEX, > > > probably with tf_none or tf_error to avoid redundant deprecated warnings. > > > > Ah, that seems to work very nicely -- it even handles the case where there > > the > > only use is as a template argument and there is no "use" inside the body > > of the function, because we always have to substitute the > > TEMPLATE_PARM_INDEX > > in the generic template arguments. > > > > Like so? Bootstrapped and tested on x86_64-pc-linux-gnu. I'm not sure > > if it's worth also checking !processing_template_decl && !DECL_ODR_USED > > before calling mark_used here, since otherwise the call ought to be > > certainly redundant. > > Wouldn't hurt to benchmark that, but I wouldn't expect it to make a measurable > difference. I suspect the same, but will benchmark to make sure. > > > -- >8 -- > > > > Subject: [PATCH] c++: improve "NTTP argument considered unused" fix > > [PR53164] > > > > PR c++/53164 > > PR c++/105848 > > > > gcc/cp/ChangeLog: > > > > * pt.cc (tsubst) : Call mark_used on > > an ADDR_EXPR argument. > > (tsubst_copy_and_build) : Revert r13-995 change. > > > > gcc/testsuite/ChangeLog: > > > > * g++.dg/template/fn-ptr3a.C: New test. > > > > Co-authored-by: Jason Merrill > > --- > > gcc/cp/pt.cc | 40 +++++++++++++----------- > > gcc/testsuite/g++.dg/template/fn-ptr3a.C | 25 +++++++++++++++ > > 2 files changed, 46 insertions(+), 19 deletions(-) > > create mode 100644 gcc/testsuite/g++.dg/template/fn-ptr3a.C > > > > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc > > index dcacba56a1c..5863d83b4fd 100644 > > --- a/gcc/cp/pt.cc > > +++ b/gcc/cp/pt.cc > > @@ -15858,9 +15858,23 @@ tsubst (tree t, tree args, tsubst_flags_t complain, > > tree in_decl) > > } > > else if (code == TEMPLATE_TEMPLATE_PARM) > > return arg; > > - else > > - /* TEMPLATE_PARM_INDEX. */ > > - return convert_from_reference (unshare_expr (arg)); > > + else /* if (code == TEMPLATE_PARM_INDEX) */ > > + { > > + if (TREE_CODE (arg) == ADDR_EXPR > > + && DECL_P (TREE_OPERAND (arg, 0))) > > If the parameter is a reference to function, rather than a pointer, do we need > to look through a NOP_EXPR? Ah yeah, NOP_EXPR as well as REFERENCE_REF_P it seems. (And I guess in light of C++20 class NTTPs we might need to walk the entire argument in search of decls to call mark_used on, but that seems overkill, Clang doesn't seem to handle that either.) I'm testing the following, which additionally handles/tests the reference-to-function case: -- >8 -- Subject: [PATCH] c++: improve "NTTP argument considered unused" fix [PR53164, PR105848] PR c++/53164 PR c++/105848 gcc/cp/ChangeLog: * pt.cc (tsubst) : Call mark_used on an ADDR_EXPR argument. (tsubst_copy_and_build) : Revert r13-995 change. gcc/testsuite/ChangeLog: * g++.dg/template/fn-ptr3a.C: New test. Co-authored-by: Jason Merrill --- gcc/cp/pt.cc | 43 +++++++++++++----------- gcc/testsuite/g++.dg/template/fn-ptr3a.C | 25 ++++++++++++++ 2 files changed, 49 insertions(+), 19 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/fn-ptr3a.C diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index dcacba56a1c..ac9b5a5bb04 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -15858,9 +15858,26 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) } else if (code == TEMPLATE_TEMPLATE_PARM) return arg; - else - /* TEMPLATE_PARM_INDEX. */ - return convert_from_reference (unshare_expr (arg)); + else /* if (code == TEMPLATE_PARM_INDEX) */ + { + tree sub = arg; + while (CONVERT_EXPR_P (sub) || REFERENCE_REF_P (sub)) + sub = TREE_OPERAND (sub, 0); + if (TREE_CODE (sub) == ADDR_EXPR + && DECL_P (TREE_OPERAND (sub, 0))) + /* Remember that there was a reference to this entity. + We should already have called mark_used when taking + the address of this entity, but do so again to make + sure: at worst it's redundant, but if we so far only + called mark_used in a template context then we might + not have yet marked it odr-used (53164). */ + /* Mask out tf_warning_or_error so that we don't issue + redundant diagnostics -- we just want to make sure + this entity is odr-used. */ + mark_used (TREE_OPERAND (sub, 0), + complain & ~tf_warning_or_error); + return convert_from_reference (unshare_expr (arg)); + } } if (level == 1) @@ -20884,22 +20901,10 @@ tsubst_copy_and_build (tree t, } /* Remember that there was a reference to this entity. */ - if (function != NULL_TREE) - { - tree inner = function; - if (TREE_CODE (inner) == ADDR_EXPR - && TREE_CODE (TREE_OPERAND (inner, 0)) == FUNCTION_DECL) - /* We should already have called mark_used when taking the - address of this function, but do so again anyway to make - sure it's odr-used: at worst this is a no-op, but if we - obtained this FUNCTION_DECL as part of ahead-of-time overload - resolution then that call to mark_used wouldn't have marked it - odr-used yet (53164). */ - inner = TREE_OPERAND (inner, 0); - if (DECL_P (inner) - && !mark_used (inner, complain) && !(complain & tf_error)) - RETURN (error_mark_node); - } + if (function != NULL_TREE + && DECL_P (function) + && !mark_used (function, complain) && !(complain & tf_error)) + RETURN (error_mark_node); if (!maybe_fold_fn_template_args (function, complain)) return error_mark_node; diff --git a/gcc/testsuite/g++.dg/template/fn-ptr3a.C b/gcc/testsuite/g++.dg/template/fn-ptr3a.C new file mode 100644 index 00000000000..7456be5d51f --- /dev/null +++ b/gcc/testsuite/g++.dg/template/fn-ptr3a.C @@ -0,0 +1,25 @@ +// PR c++/53164 +// PR c++/105848 +// A stricter version of fn-ptr3.C that verifies using f as a template +// argument alone constitutes an odr-use. + +template +void f(T) { T::fail; } // { dg-error "fail" } + +template +struct A { + static void wrap(); +}; + +template +void wrap(); + +template +void g() { + A::wrap(); // { dg-message "required from here" } + wrap(); // { dg-message "required from here" } +} + +int main() { + g<0>(); +} -- 2.36.1.299.gab336e8f1c I'm testing the folowing: