From patchwork Mon Mar 20 15:55:08 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Polacek X-Patchwork-Id: 66643 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 457AA3854178 for ; Mon, 20 Mar 2023 15:55:44 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 457AA3854178 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1679327744; bh=+zvY4rMvI9LgO0DuAn6YnydJL16Td/F/08xXiQil2wY=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=O47ofE5O3TUybOT1NHTl8j8ffXbpRNky/cnXx5fvq+xs+TLUcUKKorWv+QZwGJrhQ Qfx8bp+yYEU8krwKW0Eqoepb8cVU0VvweJXUfVA6ngAAE34JMJaolAaJdchfkHh3e+ TO4djIjO2uWLQ2Pz/7w7vieagThJpCP9sABKrQTs= 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 BC3F83858436 for ; Mon, 20 Mar 2023 15:55:14 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org BC3F83858436 Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-616-ysxQ7YzZOg26_j6mrXqFbw-1; Mon, 20 Mar 2023 11:55:12 -0400 X-MC-Unique: ysxQ7YzZOg26_j6mrXqFbw-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id C8769100DEB4 for ; Mon, 20 Mar 2023 15:55:11 +0000 (UTC) Received: from pdp-11.redhat.com (unknown [10.22.17.50]) by smtp.corp.redhat.com (Postfix) with ESMTP id A36FC40C83B6; Mon, 20 Mar 2023 15:55:11 +0000 (UTC) To: Jason Merrill , GCC Patches Subject: [PATCH] c++: explicit ctor and list-initialization [PR109159] Date: Mon, 20 Mar 2023 11:55:08 -0400 Message-Id: <20230320155508.28497-1-polacek@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-12.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_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" When I implemented explicit(bool) in r9-3735, I added this code to add_template_candidate_real: + /* Now the explicit specifier might have been deduced; check if this + declaration is explicit. If it is and we're ignoring non-converting + constructors, don't add this function to the set of candidates. */ + if ((flags & LOOKUP_ONLYCONVERTING) && DECL_NONCONVERTING_P (fn)) + return NULL; but as this test demonstrates, that's incorrect when we're initializing from a {}: for list-initialization we consider explicit constructors and complain if one is chosen. Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/12? PR c++/109159 gcc/cp/ChangeLog: * call.cc (add_template_candidate_real): Add explicit decls to the set of candidates when the initializer is a braced-init-list. libstdc++-v3/ChangeLog: * testsuite/20_util/pair/cons/explicit_construct.cc: Adjust dg-error. * testsuite/20_util/tuple/cons/explicit_construct.cc: Likewise. * testsuite/23_containers/span/explicit.cc: Likewise. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/explicit16.C: New test. --- gcc/cp/call.cc | 4 +- gcc/testsuite/g++.dg/cpp0x/explicit16.C | 18 ++++++ .../20_util/pair/cons/explicit_construct.cc | 10 ++-- .../20_util/tuple/cons/explicit_construct.cc | 58 +++++++++---------- .../testsuite/23_containers/span/explicit.cc | 4 +- 5 files changed, 57 insertions(+), 37 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/explicit16.C base-commit: fbd50e867e6a782c7b56c9727bf7e1e74dae4b94 diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index c01e7b82457..c52a09b9be2 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -3612,7 +3612,9 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl, /* Now the explicit specifier might have been deduced; check if this declaration is explicit. If it is and we're ignoring non-converting constructors, don't add this function to the set of candidates. */ - if ((flags & LOOKUP_ONLYCONVERTING) && DECL_NONCONVERTING_P (fn)) + if (((flags & (LOOKUP_ONLYCONVERTING|LOOKUP_LIST_INIT_CTOR)) + == LOOKUP_ONLYCONVERTING) + && DECL_NONCONVERTING_P (fn)) return NULL; if (DECL_CONSTRUCTOR_P (fn) && nargs == 2) diff --git a/gcc/testsuite/g++.dg/cpp0x/explicit16.C b/gcc/testsuite/g++.dg/cpp0x/explicit16.C new file mode 100644 index 00000000000..bb5a823aee6 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/explicit16.C @@ -0,0 +1,18 @@ +// PR c++/109159 +// { dg-do compile { target c++11 } } + +struct A { + A(float) {} + template + explicit A(U) {} +}; + +void f(A t) +{ + t = {1}; // { dg-error "explicit constructor" } + t = 1; + A a1{1}; + A a2 = {1}; // { dg-error "explicit constructor" } + A a3 = 1; + A a4(1); +} diff --git a/libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc b/libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc index e875f0cbcd2..d550e9c604b 100644 --- a/libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc +++ b/libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc @@ -37,7 +37,7 @@ struct ExplicitDefaultDefault std::pair f1() {return {1,2};} -std::pair f2() {return {1,2};} // { dg-error "could not convert" } +std::pair f2() {return {1,2};} // { dg-error "explicit constructor" } std::pair f3() {return std::pair{1,2};} @@ -52,7 +52,7 @@ std::pair v0{1,2}; std::pair v1{1,2}; -std::pair v2 = {1,2}; // { dg-error "could not convert" } +std::pair v2 = {1,2}; // { dg-error "explicit constructor" } std::pair v3{std::pair{1,2}}; @@ -99,7 +99,7 @@ void test_arg_passing() { f6(v0); // { dg-error "could not convert" } f6(v1); - f6({1,2}); // { dg-error "could not convert" } + f6({1,2}); // { dg-error "explicit constructor" } f6(std::pair{}); f6(std::pair{}); // { dg-error "could not convert" } f7(v0); @@ -130,6 +130,6 @@ std::pair v14{nullptr, MoveOnly{}}; std::pair v15{MoveOnly{}, nullptr}; std::pair v16 = - {nullptr, MoveOnly{}}; // { dg-error "could not convert" } + {nullptr, MoveOnly{}}; // { dg-error "explicit constructor" } std::pair v17 = - {MoveOnly{}, nullptr}; // { dg-error "could not convert" } + {MoveOnly{}, nullptr}; // { dg-error "explicit constructor" } diff --git a/libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc b/libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc index 820ddef30b4..3352dd15f7d 100644 --- a/libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc +++ b/libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc @@ -45,11 +45,11 @@ std::tuple f1b() {return {1,2};} std::tuple f1c() {return {1,2,3};} std::tuple f2_a() -{return {1};} // { dg-error "could not convert" } +{return {1};} // { dg-error "explicit constructor" } std::tuple f2_b() -{return {1,2};} // { dg-error "could not convert" } +{return {1,2};} // { dg-error "explicit constructor" } std::tuple f2_c() -{return {1,2,3};} // { dg-error "could not convert" } +{return {1,2,3};} // { dg-error "explicit constructor" } std::tuple f3_a() {return std::tuple{1};} std::tuple f3_b() {return std::tuple{1,2};} @@ -73,22 +73,22 @@ std::tuple f5_b() {return {1,2};} std::tuple f5_c() {return {1,2,3};} std::tuple f6_a() -{return {};} // { dg-error "could not convert" } +{return {};} // { dg-error "explicit constructor" } std::tuple f6_b() -{return {};} // { dg-error "could not convert" } +{return {};} // { dg-error "explicit constructor" } std::tuple f6_c() -{return {};} // { dg-error "could not convert" } +{return {};} // { dg-error "explicit constructor" } std::tuple f6_d() -{return {};} // { dg-error "could not convert" } +{return {};} // { dg-error "explicit constructor" } std::tuple f7_a() -{return {};} // { dg-error "could not convert" } +{return {};} // { dg-error "explicit constructor" } std::tuple f7_b() -{return {};} // { dg-error "could not convert" } +{return {};} // { dg-error "explicit constructor" } std::tuple f7_c() -{return {};} // { dg-error "could not convert" } +{return {};} // { dg-error "explicit constructor" } std::tuple fp1() {return std::pair{1,2}; } std::tuple fp2() {return std::pair{1,2}; } @@ -103,9 +103,9 @@ std::tuple v1_a{1}; std::tuple v1_b{1,2}; std::tuple v1_c{1,2,3}; -std::tuple v2_a = {1}; // { dg-error "could not convert" } -std::tuple v2_b = {1,2}; // { dg-error "could not convert" } -std::tuple v2_c = {1,2,3}; // { dg-error "could not convert" } +std::tuple v2_a = {1}; // { dg-error "explicit constructor" } +std::tuple v2_b = {1,2}; // { dg-error "explicit constructor" } +std::tuple v2_c = {1,2,3}; // { dg-error "explicit constructor" } std::tuple v3_a{std::tuple{1}}; std::tuple v3_b{std::tuple{1,2}}; @@ -196,11 +196,11 @@ std::tuple v31_c{std::allocator_arg, std::allocator{}, 1,2,3}; std::tuple v32_a - = {std::allocator_arg, std::allocator{ }, 1}; // { dg-error "could not convert" } + = {std::allocator_arg, std::allocator{ }, 1}; // { dg-error "explicit constructor" } std::tuple v32_b - = {std::allocator_arg, std::allocator{}, 1, 2}; // { dg-error "could not convert" } + = {std::allocator_arg, std::allocator{}, 1, 2}; // { dg-error "explicit constructor" } std::tuple v32_c - = {std::allocator_arg, std::allocator{}, 1,2,3}; // { dg-error "could not convert" } + = {std::allocator_arg, std::allocator{}, 1,2,3}; // { dg-error "explicit constructor" } std::tuple v33{std::allocator_arg, std::allocator{}, std::pair{1, 2}}; @@ -218,7 +218,7 @@ std::tuple v37 = {std::allocator_arg, std::allocator{}, std::pair{1, 2}}; std::tuple v38 -= {std::allocator_arg, std::allocator{}, std::pair{1, 2}}; // { dg-error "could not convert" } += {std::allocator_arg, std::allocator{}, std::pair{1, 2}}; // { dg-error "explicit constructor" } std::tuple v39{std::allocator_arg, std::allocator{}, v20}; @@ -232,18 +232,18 @@ std::tuple v42 = {std::allocator_arg, std::allocator{}, v20}; std::tuple v43 = {std::allocator_arg, std::allocator{}, v20}; std::tuple v44 -= {std::allocator_arg, std::allocator{ }, v20}; // { dg-error "could not convert" } += {std::allocator_arg, std::allocator{ }, v20}; // { dg-error "explicit constructor" } std::tuple v45_a{}; std::tuple v45_b{}; -std::tuple v46_a = {}; // { dg-error "could not convert" } -std::tuple v46_b = {}; // { dg-error "could not convert" } +std::tuple v46_a = {}; // { dg-error "explicit constructor" } +std::tuple v46_b = {}; // { dg-error "explicit constructor" } std::tuple v47_a{}; std::tuple v47_b{}; -std::tuple v48_a = {}; // { dg-error "could not convert" } -std::tuple v48_b = { }; // { dg-error "could not convert" } +std::tuple v48_a = {}; // { dg-error "explicit constructor" } +std::tuple v48_b = { }; // { dg-error "explicit constructor" } struct DeletedCopy @@ -295,9 +295,9 @@ void test_arg_passing() f8_b(v1_b); f8_c(v1_c); - f8_a({1}); // { dg-error "could not convert" } - f8_b({1,2}); // { dg-error "could not convert" } - f8_c({1,2,3}); // { dg-error "could not convert" } + f8_a({1}); // { dg-error "explicit constructor" } + f8_b({1,2}); // { dg-error "explicit constructor" } + f8_c({1,2,3}); // { dg-error "explicit constructor" } f8_a(std::tuple{}); f8_b(std::tuple{}); @@ -330,10 +330,10 @@ void test_arg_passing() f9_b(std::tuple{}); f9_c(std::tuple{}); - f10_a({}); // { dg-error "could not convert" } - f10_b({}); // { dg-error "could not convert" } - f11_a({}); // { dg-error "could not convert" } - f11_b({}); // { dg-error "could not convert" } + f10_a({}); // { dg-error "explicit constructor" } + f10_b({}); // { dg-error "explicit constructor" } + f11_a({}); // { dg-error "explicit constructor" } + f11_b({}); // { dg-error "explicit constructor" } f10_a(std::tuple{}); f10_b(std::tuple{}); diff --git a/libstdc++-v3/testsuite/23_containers/span/explicit.cc b/libstdc++-v3/testsuite/23_containers/span/explicit.cc index 580d69e4f09..b0a1311f02c 100644 --- a/libstdc++-v3/testsuite/23_containers/span/explicit.cc +++ b/libstdc++-v3/testsuite/23_containers/span/explicit.cc @@ -31,11 +31,11 @@ auto first = std::begin(r), last = std::end(r); // span(It, size_type) std::span s1 = {first, 2}; -std::span s2 = {first, 2}; // { dg-error "could not convert" } +std::span s2 = {first, 2}; // { dg-error "explicit constructor" } // span(It, End) std::span s3 = {first, last}; -std::span s4 = {first, last}; // { dg-error "could not convert" } +std::span s4 = {first, last}; // { dg-error "explicit constructor" } // span(R&&) std::span s5 = r;