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.129.124]) by sourceware.org (Postfix) with ESMTPS id 8FE47385C6C4 for ; Fri, 27 Oct 2023 20:01:16 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 8FE47385C6C4 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 8FE47385C6C4 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698436878; cv=none; b=DwDnpr0zv/x+mSdjfIBnpUm9YrdxYPtM/FCmAQ6jwLZyFUu2myzmpTKjTOP1D0rhvTjYAeUUtUYq41dFFQXd+UQAi/fCPney49VOdYRqz6R3x6n45t8MfyeFpD/gcQDXhif357JI82wO11kKG+b78LN6JEpjZYbsPlfDqFEj+a8= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698436878; c=relaxed/simple; bh=PssYKsTuqPoREWhDIhtd//kEO462mDlMON+ST0mtJGo=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=meWvv37hzwlNZ3ve0eP1o8yEY5i1LOTTK/OPH7HJoUHnSWkSBml88FRf+RlAH3GtWUubAroPiFfO2/0wkaastj5S7QQZBLwUjnFbucV3T+Jw6bYRfxvlBJwPknNr7AEl1ieOogk0TjJ0Eta86DSBt+3sbiR10QJK1/1QbX2CtJM= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1698436876; 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=GAcZooTvCmWdzoOVdyTNYJB8zSbKcMY24Kg43s//kgU=; b=aB3T7l3y+h1GniboeglhLAN98f2x8m+t5ZLbZEcJo9u/iR+nmzbv7AwiH9o+8FAOeiDc5l BrKAJjXgRtn0I/9unhVHsEWoxQvynlKRkHgQfY8SdC7xF4c7nCNop+AK4GwT/KBmLCBSyf 6eFoDKQta96Y3VlQsny3n4t3rBTEKCU= 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.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-647-ySViq0o0PG6nM38-hZ7b4A-1; Fri, 27 Oct 2023 16:01:14 -0400 X-MC-Unique: ySViq0o0PG6nM38-hZ7b4A-1 Received: by mail-qv1-f71.google.com with SMTP id 6a1803df08f44-66d062708b0so34345256d6.1 for ; Fri, 27 Oct 2023 13:01:14 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698436873; x=1699041673; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=GAcZooTvCmWdzoOVdyTNYJB8zSbKcMY24Kg43s//kgU=; b=ZMWpgrWAbXtxIe+0fOL+GWVgmUzxlhpEZZSKqWgQ74un9ycXrfoeuWLTmEP99d9AdL j7oWcOf90uxtCuPNe8tWqhycKc818fhWUmAHpzVNNVMnF08Fwi3UZ7nQ6M4zKxvOMHv+ IqburPe95X1ds9W90F0fE2YjXCS/EjIJnWnglTUUH9d8SpSGdSTBAEbiJAx9z+qCyvyJ NoeoZwnrOMh7V0K0H7l8mr8EDc8I80s7/3jlluFaF77wn1yLeVekmMwbG+DRH9Gn7Sx9 6hPGjj2hvVdhzJg483IXsYtUMYvTBwrS65l4wjYqdeBcjtGB4keemiyG/HTAeoI5aAMH bJ0g== X-Gm-Message-State: AOJu0YxFJ2c7olRyG7GsXPwwm4BEqcU2YobZkrYt0ZOZ7CEarWp0XL/r H58L1tOEUWk4NhGz9wcK9EEUqnzxxF9UvQMNvVZD7GU2+kQYk91RX6GQJ73Wq3B1XdVV6VpgJt2 ZdNKiCo5swYwt4CQL7REywwqG0vJxvjHF/YRLWlMWfwcAytPuQZoQMigE3gF1iuox4QrWxKFJuS w= X-Received: by 2002:a05:6214:252a:b0:66d:603b:9a0e with SMTP id gg10-20020a056214252a00b0066d603b9a0emr4226619qvb.16.1698436873393; Fri, 27 Oct 2023 13:01:13 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFyjjZtrTKH+UPHoXGPzkXYFqabCGw4z391Se1f6EmvKAwmZ3JevLNmwkWfZ6WnwfdrMMRh9Q== X-Received: by 2002:a05:6214:252a:b0:66d:603b:9a0e with SMTP id gg10-20020a056214252a00b0066d603b9a0emr4226596qvb.16.1698436872950; Fri, 27 Oct 2023 13:01:12 -0700 (PDT) Received: from localhost.localdomain (ool-457670bb.dyn.optonline.net. [69.118.112.187]) by smtp.gmail.com with ESMTPSA id l20-20020a0ce514000000b0065b17b925d0sm910777qvm.38.2023.10.27.13.01.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 27 Oct 2023 13:01:12 -0700 (PDT) From: Patrick Palka To: gcc-patches@gcc.gnu.org Cc: jason@redhat.com, Patrick Palka Subject: [PATCH v3 2/3] c++: remember candidates that we ignored Date: Fri, 27 Oct 2023 15:55:30 -0400 Message-ID: <20231027195532.2566822-2-ppalka@redhat.com> X-Mailer: git-send-email 2.42.0.482.g2e8e77cbac In-Reply-To: <20231027195532.2566822-1-ppalka@redhat.com> References: <20231027195532.2566822-1-ppalka@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset="US-ASCII"; x-default=true X-Spam-Status: No, score=-13.6 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,RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,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: During overload resolution, we sometimes outright ignore a function in the overload set and leave no trace of it in the candidates list, for example when we find a perfect non-template candidate we discard all function templates, or when the callee is a template-id we discard all non-template functions. We should still however make note of these non-viable functions when diagnosing overload resolution failure, but that's not possible if they're not present in the returned candidates list. To that end, this patch reworks add_candidates to add such ignored functions to the list. The new rr_ignored rejection reason is somewhat of a catch-all; we could perhaps split it up into more specific rejection reasons, but I leave that as future work. gcc/cp/ChangeLog: * call.cc (enum rejection_reason_code): Add rr_ignored. (add_ignored_candidate): Define. (ignored_candidate_p): Define. (add_template_candidate_real): Do add_ignored_candidate instead of returning NULL. (splice_viable): Put ignored (non-viable) candidates last. (print_z_candidate): Handle ignored candidates. (build_new_function_call): Refine shortcut that calls cp_build_function_call_vec now that non-templates can appear in the candidate list for a template-id call. (add_candidates): Replace 'bad_fns' overload with 'bad_cands' candidate list. When not considering a candidate, add it to the list as an ignored candidate. Add all 'bad_cands' to the overload set as well. gcc/testsuite/ChangeLog: * g++.dg/diagnostic/param-type-mismatch-2.C: Rename template function test_7 that accidentally (perhaps) shares the same name as its non-template callee. * g++.dg/overload/error6.C: New test. --- gcc/cp/call.cc | 150 +++++++++++++----- .../g++.dg/diagnostic/param-type-mismatch-2.C | 20 +-- gcc/testsuite/g++.dg/overload/error6.C | 9 ++ 3 files changed, 133 insertions(+), 46 deletions(-) create mode 100644 gcc/testsuite/g++.dg/overload/error6.C diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index 5d175b93a47..81cc029dddb 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -441,7 +441,8 @@ enum rejection_reason_code { rr_template_unification, rr_invalid_copy, rr_inherited_ctor, - rr_constraint_failure + rr_constraint_failure, + rr_ignored, }; struct conversion_info { @@ -2224,6 +2225,35 @@ add_candidate (struct z_candidate **candidates, return cand; } +/* FN is a function from the overload set that we outright didn't even + consider (for some reason); add it to the list as an non-viable "ignored" + candidate. */ + +static z_candidate * +add_ignored_candidate (z_candidate **candidates, tree fn) +{ + /* No need to dynamically allocate these. */ + static const rejection_reason reason_ignored = { rr_ignored, {} }; + + struct z_candidate *cand = (struct z_candidate *) + conversion_obstack_alloc (sizeof (struct z_candidate)); + + cand->fn = fn; + cand->reason = const_cast (&reason_ignored); + cand->next = *candidates; + *candidates = cand; + + return cand; +} + +/* True iff CAND is a candidate added by add_ignored_candidate. */ + +static bool +ignored_candidate_p (const z_candidate *cand) +{ + return cand->reason && cand->reason->code == rr_ignored; +} + /* Return the number of remaining arguments in the parameter list beginning with ARG. */ @@ -3471,7 +3501,7 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl, } if (len < skip_without_in_chrg) - return NULL; + return add_ignored_candidate (candidates, tmpl); if (DECL_CONSTRUCTOR_P (tmpl) && nargs == 2 && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (first_arg), @@ -3609,7 +3639,7 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl, if (((flags & (LOOKUP_ONLYCONVERTING|LOOKUP_LIST_INIT_CTOR)) == LOOKUP_ONLYCONVERTING) && DECL_NONCONVERTING_P (fn)) - return NULL; + return add_ignored_candidate (candidates, fn); if (DECL_CONSTRUCTOR_P (fn) && nargs == 2) { @@ -3724,6 +3754,9 @@ splice_viable (struct z_candidate *cands, z_candidate *non_viable = nullptr; z_candidate **non_viable_tail = &non_viable; + z_candidate *non_viable_ignored = nullptr; + z_candidate **non_viable_ignored_tail = &non_viable_ignored; + /* Be strict inside templates, since build_over_call won't actually do the conversions to get pedwarns. */ if (processing_template_decl) @@ -3742,6 +3775,7 @@ splice_viable (struct z_candidate *cands, its viability. */ auto& tail = (cand->viable == 1 ? strictly_viable_tail : cand->viable == -1 ? non_strictly_viable_tail + : ignored_candidate_p (cand) ? non_viable_ignored_tail : non_viable_tail); *tail = cand; tail = &cand->next; @@ -3751,7 +3785,8 @@ splice_viable (struct z_candidate *cands, || (!strict_p && non_strictly_viable != nullptr)); /* Combine the lists. */ - *non_viable_tail = nullptr; + *non_viable_ignored_tail = nullptr; + *non_viable_tail = non_viable_ignored; *non_strictly_viable_tail = non_viable; *strictly_viable_tail = non_strictly_viable; @@ -3901,6 +3936,8 @@ print_z_candidate (location_t loc, const char *msgstr, inform (cloc, "%s%qT (conversion)", msg, fn); else if (candidate->viable == -1) inform (cloc, "%s%#qD (near match)", msg, fn); + else if (ignored_candidate_p (candidate)) + inform (cloc, "%s%#qD (ignored)", msg, fn); else if (DECL_DELETED_FN (fn)) inform (cloc, "%s%#qD (deleted)", msg, fn); else if (candidate->reversed ()) @@ -3980,6 +4017,8 @@ print_z_candidate (location_t loc, const char *msgstr, "initialization from an expression of the same or derived " "type"); break; + case rr_ignored: + break; case rr_none: default: /* This candidate didn't have any issues or we failed to @@ -5023,7 +5062,12 @@ build_new_function_call (tree fn, vec **args, // If there is a single (non-viable) function candidate, // let the error be diagnosed by cp_build_function_call_vec. if (!any_viable_p && candidates && ! candidates->next - && (TREE_CODE (candidates->fn) == FUNCTION_DECL)) + && TREE_CODE (candidates->fn) == FUNCTION_DECL + /* A template-id callee consisting of a single (ignored) + non-template candidate needs to be diagnosed the + ordinary way. */ + && (TREE_CODE (fn) != TEMPLATE_ID_EXPR + || candidates->template_decl)) return cp_build_function_call_vec (candidates->fn, args, complain); // Otherwise, emit notes for non-viable candidates. @@ -6509,6 +6553,10 @@ add_candidates (tree fns, tree first_arg, const vec *args, else /*if (flags & LOOKUP_DEFAULTED)*/ which = non_templates; + /* Template candidates that we'll potentially ignore if the + perfect candidate optimization succeeds. */ + z_candidate *ignored_template_cands = nullptr; + /* During overload resolution, we first consider each function under the assumption that we'll eventually find a strictly viable candidate. This allows us to circumvent our defacto behavior when checking @@ -6519,20 +6567,29 @@ add_candidates (tree fns, tree first_arg, const vec *args, This trick is important for pruning member function overloads according to their const/ref-qualifiers (since all 'this' conversions are at worst bad) without breaking -fpermissive. */ - tree bad_fns = NULL_TREE; + z_candidate *bad_cands = nullptr; bool shortcut_bad_convs = true; again: for (tree fn : lkp_range (fns)) { - if (check_converting && DECL_NONCONVERTING_P (fn)) - continue; - if (check_list_ctor && !is_list_ctor (fn)) - continue; if (which == templates && TREE_CODE (fn) != TEMPLATE_DECL) - continue; + { + if (template_only) + add_ignored_candidate (candidates, fn); + continue; + } if (which == non_templates && TREE_CODE (fn) == TEMPLATE_DECL) - continue; + { + add_ignored_candidate (&ignored_template_cands, fn); + continue; + } + if ((check_converting && DECL_NONCONVERTING_P (fn)) + || (check_list_ctor && !is_list_ctor (fn))) + { + add_ignored_candidate (candidates, fn); + continue; + } tree fn_first_arg = NULL_TREE; const vec *fn_args = args; @@ -6589,22 +6646,19 @@ add_candidates (tree fns, tree first_arg, const vec *args, } if (TREE_CODE (fn) == TEMPLATE_DECL) - { - if (!add_template_candidate (candidates, - fn, - ctype, - explicit_targs, - fn_first_arg, - fn_args, - return_type, - access_path, - conversion_path, - flags, - strict, - shortcut_bad_convs, - complain)) - continue; - } + add_template_candidate (candidates, + fn, + ctype, + explicit_targs, + fn_first_arg, + fn_args, + return_type, + access_path, + conversion_path, + flags, + strict, + shortcut_bad_convs, + complain); else { add_function_candidate (candidates, @@ -6632,13 +6686,14 @@ add_candidates (tree fns, tree first_arg, const vec *args, { /* This candidate has been tentatively marked non-strictly viable, and we didn't compute all argument conversions for it (having - stopped at the first bad conversion). Add the function to BAD_FNS - to fully reconsider later if we don't find any strictly viable - candidates. */ + stopped at the first bad conversion). Move the candidate to + BAD_CANDS to fully reconsider later if we don't find any strictly + viable candidates. */ if (complain & (tf_error | tf_conv)) { - bad_fns = lookup_add (fn, bad_fns); - *candidates = (*candidates)->next; + *candidates = cand->next; + cand->next = bad_cands; + bad_cands = cand; } else /* But if we're in a SFINAE context, just mark this candidate as @@ -6652,21 +6707,44 @@ add_candidates (tree fns, tree first_arg, const vec *args, if (which == non_templates && !seen_perfect) { which = templates; + ignored_template_cands = nullptr; goto again; } else if (which == templates && !seen_strictly_viable && shortcut_bad_convs - && bad_fns) + && bad_cands) { /* None of the candidates are strictly viable, so consider again those - functions in BAD_FNS, this time without shortcutting bad conversions + functions in BAD_CANDS, this time without shortcutting bad conversions so that all their argument conversions are computed. */ which = either; - fns = bad_fns; + fns = NULL_TREE; + for (z_candidate *cand = bad_cands; cand; cand = cand->next) + { + tree fn = cand->fn; + if (tree ti = cand->template_decl) + fn = TI_TEMPLATE (ti); + fns = ovl_make (fn, fns); + } shortcut_bad_convs = false; + bad_cands = nullptr; goto again; } + + if (complain & tf_error) + { + /* Remember any omitted candidates if we need to print candidates + as part of overload resolution failure diagnostics. */ + for (z_candidate *omitted_cands : { ignored_template_cands, bad_cands }) + { + z_candidate **omitted_cands_tail = &omitted_cands; + while (*omitted_cands_tail) + omitted_cands_tail = &(*omitted_cands_tail)->next; + *omitted_cands_tail = *candidates; + *candidates = omitted_cands; + } + } } /* Returns 1 if P0145R2 says that the LHS of operator CODE is evaluated first, diff --git a/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C index de7570a6efa..50c25cd49b7 100644 --- a/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C +++ b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C @@ -129,22 +129,22 @@ int test_6 (int first, const char *second, float third, s6 *ptr) /* Template function. */ template -int test_7 (int one, T two, float three); // { dg-line test_7_decl } +int callee_7 (int one, T two, float three); // { dg-line callee_7_decl } int test_7 (int first, const char *second, float third) { - return test_7 (first, second, third); // { dg-line test_7_usage } - // { dg-message "cannot convert 'const char\\*' to 'const char\\*\\*'" "" { target *-*-* } test_7_usage } + return callee_7 (first, second, third); // { dg-line callee_7_usage } + // { dg-message "cannot convert 'const char\\*' to 'const char\\*\\*'" "" { target *-*-* } callee_7_usage } /* { dg-begin-multiline-output "" } - return test_7 (first, second, third); - ^~~~~~ - | - const char* + return callee_7 (first, second, third); + ^~~~~~ + | + const char* { dg-end-multiline-output "" } */ - // { dg-message "initializing argument 2 of 'int test_7\\(int, T, float\\) .with T = const char\\*\\*.'" "" { target *-*-* } test_7_decl } + // { dg-message "initializing argument 2 of 'int callee_7\\(int, T, float\\) .with T = const char\\*\\*.'" "" { target *-*-* } callee_7_decl } /* { dg-begin-multiline-output "" } - int test_7 (int one, T two, float three); - ~~^~~ + int callee_7 (int one, T two, float three); + ~~^~~ { dg-end-multiline-output "" } */ } diff --git a/gcc/testsuite/g++.dg/overload/error6.C b/gcc/testsuite/g++.dg/overload/error6.C new file mode 100644 index 00000000000..86a12eaa8de --- /dev/null +++ b/gcc/testsuite/g++.dg/overload/error6.C @@ -0,0 +1,9 @@ +// Verify we note even non-template candidates when diagnosing +// overload resolution failure for a template-id. + +template void f(T); // { dg-message "candidate" } +void f(int); // { dg-message {candidate: 'void f\(int\)' \(ignored\)} } + +int main() { + f(0, 0); // { dg-error "no match" } +} -- 2.42.0.482.g2e8e77cbac