https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82840

            Bug ID: 82840
           Summary: call to conversion operator instead of converting
                    constructor in c++17 during overload resolution
           Product: gcc
           Version: 8.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: bruno.bugs.contact at gmail dot com
  Target Milestone: ---

This code compiled by gcc trunk with std=c++17 returns 1 
instead of the expected 0 since D::operator C() is called instead of the
apparently better match C::C(const D&). Compiling the code with std=c++14
make this behaviour disappear and 0 is returned as expected.

gcc 7.2 also has this behaviour but 6.4 do not.
clang trunk also has this behaviour.

Rationale for why 0 should be returned instead of 1 :
(copied from the original post on stackoverflow)

Tentative reading of the standard (latest draft N4687) :

C c(d) is a direct-initialization which is not a copy elision
([dcl.init]/17.6.1). [dcl.init]/17.6.2 tells us that applicable constructors
are enumerated and that the best one is chosen by overload resolution.
[over.match.ctor] tells us that the applicable constructors are in this case
all the constructors.

In this case : C(), C(const C&) and C(const D&) (no move ctor). C() is clearly
not viable and thus is discarded from the overload set. ([over.match.viable])

Constructors have no implicit object parameter and so C(const C&) and C(const
D&) both take exactly one parameter. ([over.match.funcs]/2)

We now go to [over.match.best]. Here we find that we need to determine which of
these two implicit conversion sequences (ICS) is better. The ICS of C(const D&)
only involves a standard conversion sequence, but the ICS of C(const C&)
involves a user-defined conversion sequence.

Therefore C(const D&) should be selected instead of C(const C&).


See the discussion on stackoverflow:
https://stackoverflow.com/questions/47110853/call-to-conversion-operator-instead-of-converting-constructor-in-c17-during-ov


static int ret;
struct D;
struct C {
    C() {}
    C(const C&) {}
    C(const D&) {}
};
struct D {
    operator C() { ret = 1; return C();}
};

int main(){
    D d;
    C c(d);
    return ret;
}


g++ -v :

Using built-in specs.
COLLECT_GCC=/home/bruno/software/gcc-svn-install/bin/g++
COLLECT_LTO_WRAPPER=/home/bruno/software/gcc-svn-install/libexec/gcc/x86_64-pc-linux-gnu/8.0.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ../gcc-svn/configure
--prefix=/home/bruno/software/gcc-svn-install
Thread model: posix
gcc version 8.0.0 20171104 (experimental) (GCC) 
COLLECT_GCC_OPTIONS='-v' '-O0' '-g' '-std=c++17' '-Wall' '-Wextra' '-Wpedantic'
'-o' 'bug_DoperatorC_CconstDref_minimal' '-shared-libgcc' '-mtune=generic'
'-march=x86-64'

/home/bruno/software/gcc-svn-install/libexec/gcc/x86_64-pc-linux-gnu/8.0.0/cc1plus
-quiet -v -imultiarch x86_64-linux-gnu -D_GNU_SOURCE
bug_DoperatorC_CconstDref_minimal.cpp -quiet -dumpbase
bug_DoperatorC_CconstDref_minimal.cpp -mtune=generic -march=x86-64 -auxbase
bug_DoperatorC_CconstDref_minimal -g -O0 -Wall -Wextra -Wpedantic -std=c++17
-version -o /tmp/cc2hfg03.s
GNU C++17 (GCC) version 8.0.0 20171104 (experimental) (x86_64-pc-linux-gnu)
        compiled by GNU C version 8.0.0 20171104 (experimental), GMP version
6.1.2, MPFR version 3.1.6, MPC version 1.0.3, isl version none
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory
"/home/bruno/software/gcc-svn-install/lib/gcc/x86_64-pc-linux-gnu/8.0.0/../../../../x86_64-pc-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:

/home/bruno/software/gcc-svn-install/lib/gcc/x86_64-pc-linux-gnu/8.0.0/../../../../include/c++/8.0.0

/home/bruno/software/gcc-svn-install/lib/gcc/x86_64-pc-linux-gnu/8.0.0/../../../../include/c++/8.0.0/x86_64-pc-linux-gnu

/home/bruno/software/gcc-svn-install/lib/gcc/x86_64-pc-linux-gnu/8.0.0/../../../../include/c++/8.0.0/backward
 /home/bruno/software/gcc-svn-install/lib/gcc/x86_64-pc-linux-gnu/8.0.0/include
 /usr/local/include
 /home/bruno/software/gcc-svn-install/include

/home/bruno/software/gcc-svn-install/lib/gcc/x86_64-pc-linux-gnu/8.0.0/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
GNU C++17 (GCC) version 8.0.0 20171104 (experimental) (x86_64-pc-linux-gnu)
        compiled by GNU C version 8.0.0 20171104 (experimental), GMP version
6.1.2, MPFR version 3.1.6, MPC version 1.0.3, isl version none
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096
Compiler executable checksum: a6d84215658bcb7c80db361d04a47f0c
COLLECT_GCC_OPTIONS='-v' '-O0' '-g' '-std=c++17' '-Wall' '-Wextra' '-Wpedantic'
'-o' 'bug_DoperatorC_CconstDref_minimal' '-shared-libgcc' '-mtune=generic'
'-march=x86-64'
 as -v --64 -o /tmp/ccaD0Gbb.o /tmp/cc2hfg03.s
GNU assembler version 2.29.1 (x86_64-linux-gnu) using BFD version (GNU Binutils
for Ubuntu) 2.29.1
COMPILER_PATH=/home/bruno/software/gcc-svn-install/libexec/gcc/x86_64-pc-linux-gnu/8.0.0/:/home/bruno/software/gcc-svn-install/libexec/gcc/x86_64-pc-linux-gnu/8.0.0/:/home/bruno/software/gcc-svn-install/libexec/gcc/x86_64-pc-linux-gnu/:/home/bruno/software/gcc-svn-install/lib/gcc/x86_64-pc-linux-gnu/8.0.0/:/home/bruno/software/gcc-svn-install/lib/gcc/x86_64-pc-linux-gnu/
LIBRARY_PATH=/home/bruno/software/gcc-svn-install/lib/gcc/x86_64-pc-linux-gnu/8.0.0/:/home/bruno/software/gcc-svn-install/lib/gcc/x86_64-pc-linux-gnu/8.0.0/../../../../lib64/:/lib/x86_64-linux-gnu/:/lib/../lib64/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib64/:/home/bruno/software/gcc-svn-install/lib/gcc/x86_64-pc-linux-gnu/8.0.0/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-O0' '-g' '-std=c++17' '-Wall' '-Wextra' '-Wpedantic'
'-o' 'bug_DoperatorC_CconstDref_minimal' '-shared-libgcc' '-mtune=generic'
'-march=x86-64'

/home/bruno/software/gcc-svn-install/libexec/gcc/x86_64-pc-linux-gnu/8.0.0/collect2
-plugin
/home/bruno/software/gcc-svn-install/libexec/gcc/x86_64-pc-linux-gnu/8.0.0/liblto_plugin.so
-plugin-opt=/home/bruno/software/gcc-svn-install/libexec/gcc/x86_64-pc-linux-gnu/8.0.0/lto-wrapper
-plugin-opt=-fresolution=/tmp/ccu9eKoi.res -plugin-opt=-pass-through=-lgcc_s
-plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc
-plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc
--eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o
bug_DoperatorC_CconstDref_minimal /usr/lib/x86_64-linux-gnu/crt1.o
/usr/lib/x86_64-linux-gnu/crti.o
/home/bruno/software/gcc-svn-install/lib/gcc/x86_64-pc-linux-gnu/8.0.0/crtbegin.o
-L/home/bruno/software/gcc-svn-install/lib/gcc/x86_64-pc-linux-gnu/8.0.0
-L/home/bruno/software/gcc-svn-install/lib/gcc/x86_64-pc-linux-gnu/8.0.0/../../../../lib64
-L/lib/x86_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86_64-linux-gnu
-L/usr/lib/../lib64
-L/home/bruno/software/gcc-svn-install/lib/gcc/x86_64-pc-linux-gnu/8.0.0/../../..
/tmp/ccaD0Gbb.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc
/home/bruno/software/gcc-svn-install/lib/gcc/x86_64-pc-linux-gnu/8.0.0/crtend.o
/usr/lib/x86_64-linux-gnu/crtn.o
COLLECT_GCC_OPTIONS='-v' '-O0' '-g' '-std=c++17' '-Wall' '-Wextra' '-Wpedantic'
'-o' 'bug_DoperatorC_CconstDref_minimal' '-shared-libgcc' '-mtune=generic'
'-march=x86-64'

Reply via email to