1 | // RUN: %clang_cc1 -std=c++11 -verify %s |
2 | |
3 | struct B1 { |
4 | B1(int); // expected-note {{candidate}} |
5 | }; |
6 | |
7 | struct B2 { |
8 | B2(int); // expected-note {{candidate}} |
9 | }; |
10 | |
11 | struct D1 : B1, B2 { // expected-note 2{{candidate}} |
12 | using B1::B1; // expected-note {{inherited here}} |
13 | using B2::B2; // expected-note {{inherited here}} |
14 | }; |
15 | D1 d1(0); // expected-error {{ambiguous}} |
16 | |
17 | struct D2 : B1, B2 { |
18 | using B1::B1; |
19 | using B2::B2; |
20 | D2(int); |
21 | }; |
22 | D2 d2(0); // ok |
23 | |
24 | |
25 | // The emergent behavior of implicit special members is a bit odd when |
26 | // inheriting from multiple base classes. |
27 | namespace default_ctor { |
28 | struct C; |
29 | struct D; |
30 | |
31 | struct convert_to_D1 { |
32 | operator D&&(); |
33 | }; |
34 | struct convert_to_D2 { |
35 | operator D&&(); |
36 | }; |
37 | |
38 | struct A { // expected-note 2{{candidate}} |
39 | A(); // expected-note {{candidate}} |
40 | |
41 | A(C &&); // expected-note {{candidate}} |
42 | C &operator=(C&&); // expected-note {{candidate}} |
43 | |
44 | A(D &&); |
45 | D &operator=(D&&); // expected-note {{candidate}} |
46 | |
47 | A(convert_to_D2); // expected-note {{candidate}} |
48 | }; |
49 | |
50 | struct B { // expected-note 2{{candidate}} |
51 | B(); // expected-note {{candidate}} |
52 | |
53 | B(C &&); // expected-note {{candidate}} |
54 | C &operator=(C&&); // expected-note {{candidate}} |
55 | |
56 | B(D &&); |
57 | D &operator=(D&&); // expected-note {{candidate}} |
58 | |
59 | B(convert_to_D2); // expected-note {{candidate}} |
60 | }; |
61 | |
62 | struct C : A, B { |
63 | using A::A; |
64 | using A::operator=; |
65 | using B::B; |
66 | using B::operator=; |
67 | }; |
68 | struct D : A, B { |
69 | using A::A; // expected-note 3{{inherited here}} |
70 | using A::operator=; |
71 | using B::B; // expected-note 3{{inherited here}} |
72 | using B::operator=; |
73 | |
74 | D(int); |
75 | D(const D&); // expected-note {{candidate}} |
76 | D &operator=(const D&); // expected-note {{candidate}} |
77 | }; |
78 | |
79 | C c; |
80 | void f(C c) { |
81 | C c2(static_cast<C&&>(c)); |
82 | c = static_cast<C&&>(c); |
83 | } |
84 | |
85 | // D does not declare D(), D(D&&), nor operator=(D&&), so the base class |
86 | // versions are inherited. |
87 | D d; // expected-error {{ambiguous}} |
88 | void f(D d) { |
89 | D d2(static_cast<D&&>(d)); // ok, ignores inherited constructors |
90 | D d3(convert_to_D1{}); // ok, ignores inherited constructors |
91 | D d4(convert_to_D2{}); // expected-error {{ambiguous}} |
92 | d = static_cast<D&&>(d); // expected-error {{ambiguous}} |
93 | } |
94 | |
95 | struct Y; |
96 | struct X { |
97 | X(); |
98 | X(volatile Y &); // expected-note 3{{inherited constructor cannot be used to copy object}} |
99 | } x; |
100 | struct Y : X { using X::X; } volatile y; |
101 | struct Z : Y { using Y::Y; } volatile z; // expected-note 4{{no known conversion}} expected-note 2{{would lose volatile}} expected-note 3{{requires 0}} expected-note 3{{inherited here}} |
102 | Z z1(x); // expected-error {{no match}} |
103 | Z z2(y); // expected-error {{no match}} |
104 | Z z3(z); // expected-error {{no match}} |
105 | } |
106 | |