Quuxplusone / LLVMBugzillaTest

0 stars 0 forks source link

Copy initialization using conversion operator does not find correct candidates for initialization of final result #16772

Open Quuxplusone opened 11 years ago

Quuxplusone commented 11 years ago
Bugzilla Link PR16773
Status NEW
Importance P normal
Reported by hstong@ca.ibm.com
Reported on 2013-08-02 00:11:04 -0700
Last modified on 2013-10-07 16:30:11 -0700
Version 3.2
Hardware PC other
CC dgregor@apple.com, fang@csl.cornell.edu, llvm-bugs@lists.llvm.org, rafael@espindo.la, richard-llvm@metafoo.co.uk
Fixed by commit(s)
Attachments
Blocks
Blocked by
See also
I have a reduced test case.
MSVC seems to work fine (online compiler test: http://rise4fun.com/Vcpp/2sQ).

The copy initialization of an object of type A from a class object of type
C is expected to find C::operator B &() as the function selected by overload
resolution.

The result of the call, an lvalue of type B, is then used to direct-initialize
the object that is the destination of the copy-initialization.
See C++11 subclause 8.5 [dcl.init] paragraph 16.

Note that the result of the call is specified to be used, not the result of the
user-defined conversion sequence which was considered for overload resolution.

The direct initialization from the lvalue of type B has for its candidates all
of the constructors for A (13.3.1.3 [over.match.ctor]).

Note that A(B &) has a standard conversion sequence from the lvalue of type B to
its sole argument (the identity conversion).

clang++ seems to be fixated with the copy constructors for A instead of using
overload resolution for the direct initialization.

## Self-contained test case (main.cpp):
struct B;
struct A {
   A();
   A(const A &, bool = 0);
   A(const A &, short = 0);
   A(B &);
};

struct B : A { };

struct C {
   operator B &();
};

int main() {
   C c;
   A a = c;
}

## Compiler invocation:
clang++ '-std=c++11' -c main.cpp

## Compiler output:
main.cpp:17:6: error: ambiguous constructor call when copying variable of type
'B'
   A a = c;
     ^   ~
main.cpp:4:4: note: candidate constructor
   A(const A &, bool = 0);
   ^
main.cpp:5:4: note: candidate constructor
   A(const A &, short = 0);
   ^
1 error generated.

## Expected behaviour:
Clean compile.

## clang++ -v:
clang version 3.2 (trunk 158227)
Target: i386-pc-cygwin
Thread model: posix
Quuxplusone commented 11 years ago

None of EDG, g++, and Clang behave as you describe here, but I agree that the wording does imply that this example should be valid, and ICC accepts this code. I'm not sure whether this is a bug in Clang or a bug in the standard's wording.

Quuxplusone commented 11 years ago
The following case is along the same lines. This time around GCC, EDG and MSVC
all compile fine but Clang does not.

The root cause could still be a defect in the wording I guess.

struct A { A(...); };
struct B : A { template <typename T> B(volatile T &); };
struct C { operator volatile B &(); };

void foo(A);
int main()
{ C c;
  sizeof (foo(c), 0); }

## Expected:
Clean compile.

## Clang output (-std=c++11):
main.cpp:8:15: error: no viable constructor copying parameter of type 'volatile
B'
  sizeof (foo(c), 0); }
              ^
main.cpp:1:8: note: candidate constructor (the implicit copy constructor) not
viable: no known conversion from 'volatile B' to 'const A &' for 1st argument
struct A { A(...); };
       ^
main.cpp:1:8: note: candidate constructor (the implicit move constructor) not
viable: no known conversion from 'volatile B' to 'A &&' for 1st argument
struct A { A(...); };
       ^
1 error generated.