Bug 109159 - [10/11/12 Regression] explicit constructor is used in copy-initialization
Summary: [10/11/12 Regression] explicit constructor is used in copy-initialization
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 12.2.1
: P2 normal
Target Milestone: 10.5
Assignee: Marek Polacek
URL:
Keywords: accepts-invalid
Depends on:
Blocks:
 
Reported: 2023-03-16 19:51 UTC by Fedor Chelnokov
Modified: 2023-04-28 14:53 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work: 4.4.7, 5.1.0, 7.1.0, 8.1.0, 8.5.0
Known to fail: 10.1.0, 9.1.0
Last reconfirmed: 2023-03-16 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Fedor Chelnokov 2023-03-16 19:51:48 UTC
The following code must be accepted (as it does in Clang and MSVC):

struct A {
    A( float ) {}
    template<class U>
    explicit A( U ) {}
};

template<class T>
concept CopyFromIntList = requires( T t ) { t = { 1 }; };

static_assert( !CopyFromIntList<A> );

because 't = {1}' is invalid: chosen constructor is explicit in copy-initialization.

But in GCC static_assert fails. Online demo: https://gcc.godbolt.org/z/Pf47E6dno
Comment 1 Andrew Pinski 2023-03-16 21:35:03 UTC
Reduced testcase without the constraint that GCC accepts:
struct A {
    A( float ) {}
    template<class U>
    explicit A( U ) {}
};

void f(A t)
{
  t = {1};
}
Comment 2 Marek Polacek 2023-03-16 21:46:02 UTC
Oy, started with r9-3735-gb5ff4f5c0d61e5:

commit b5ff4f5c0d61e52e27a0727ae9e011aab525ccfd
Author: Marek Polacek <polacek@redhat.com>
Date:   Tue Oct 30 19:59:41 2018 +0000

    Implement P0892R2, explicit(bool).
Comment 3 Marek Polacek 2023-03-17 21:16:49 UTC
This hunk broke it:

@@ -3251,6 +3251,12 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
       goto fail;
     }
 
+  /* 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;


It doesn't check for BRACE_ENCLOSED_INITIALIZER_P (or some similar flag meaning we're initializing from an initializer_list) and that's the bug.
Comment 4 GCC Commits 2023-03-20 20:54:30 UTC
The trunk branch has been updated by Marek Polacek <mpolacek@gcc.gnu.org>:

https://gcc.gnu.org/g:a226590fefb35ed66adf73d85cefe49048a78ab8

commit r13-6765-ga226590fefb35ed66adf73d85cefe49048a78ab8
Author: Marek Polacek <polacek@redhat.com>
Date:   Fri Mar 17 18:25:13 2023 -0400

    c++: explicit ctor and list-initialization [PR109159]
    
    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.
    
            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.
Comment 5 Marek Polacek 2023-03-20 20:56:17 UTC
Fixed on trunk so far.
Comment 6 Marek Polacek 2023-03-27 14:06:12 UTC
The patch caused non-bug bug 109247, so I don't think it's appropriate to backport this (?).