// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s // RUN: %clang_cc1 -fsyntax-only -verify -std=c++2a %s namespace Constructor { struct A { A(int); }; struct B { // expected-note+ {{candidate}} explicit B(int); }; B::B(int) { } // expected-note+ {{here}} struct C { void f(const A&); void f(const B&); }; void f(C c) { c.f(10); } A a0 = 0; A a1(0); A &&a2 = 0; A &&a3(0); A a4{0}; A &&a5 = {0}; A &&a6{0}; B b0 = 0; // expected-error {{no viable conversion}} B b1(0); B &&b2 = 0; // expected-error {{could not bind}} B &&b3(0); // expected-error {{could not bind}} B b4{0}; B &&b5 = {0}; // expected-error {{chosen constructor is explicit}} B &&b6{0}; struct S { template explicit S(); }; struct T : S { // T(); }; struct U : T { U(); }; U::U() {} } namespace Conversion { struct A { operator int(); explicit operator bool(); }; A::operator bool() { return false; } struct B { void f(int); void f(bool); }; void f(A a, B b) { b.f(a); } void testExplicit() { // Taken from 12.3.2p2 class X { X(); }; class Y { }; // expected-note+ {{candidate constructor (the implicit}} struct Z { explicit operator X() const; explicit operator Y() const; explicit operator int() const; }; Z z; // 13.3.1.4p1 & 8.5p16: Y y2 = z; // expected-error {{no viable conversion from 'Z' to 'Y'}} Y y2b(z); Y y3 = (Y)z; Y y4 = Y(z); Y y5 = static_cast(z); // 13.3.1.5p1 & 8.5p16: int i1 = (int)z; int i2 = int(z); int i3 = static_cast(z); int i4(z); // 13.3.1.6p1 & 8.5.3p5: const Y& y6 = z; // expected-error {{no viable conversion from 'Z' to 'const Y'}} const int& y7 = z; // expected-error {{no viable conversion from 'Z' to 'const int'}} const Y& y8(z); const int& y9(z); // Y is an aggregate, so aggregate-initialization is performed and the // conversion function is not considered. const Y y10{z}; // expected-error {{excess elements}} const Y& y11{z}; // expected-error {{excess elements}} expected-note {{in initialization of temporary of type 'const Y'}} const int& y12{z}; // X is not an aggregate, so constructors are considered, // per 13.3.3.1/4 & DR1467. const X x1{z}; const X& x2{z}; } void testBool() { struct Bool { operator bool(); }; struct NotBool { explicit operator bool(); // expected-note {{conversion to integral type 'bool'}} }; Bool b; NotBool n; (void) (1 + b); (void) (1 + n); // expected-error {{invalid operands to binary expression ('int' and 'NotBool')}} // 5.3.1p9: (void) (!b); (void) (!n); // 5.14p1: (void) (b && true); (void) (n && true); // 5.15p1: (void) (b || true); (void) (n || true); // 5.16p1: (void) (b ? 0 : 1); (void) (n ? 0: 1); // 5.19p5: // TODO: After constexpr has been implemented // 6.4p4: if (b) {} if (n) {} // 6.4.2p2: switch (b) {} // expected-warning {{switch condition has boolean value}} switch (n) {} // expected-error {{switch condition type 'NotBool' requires explicit conversion to 'bool'}} \ expected-warning {{switch condition has boolean value}} // 6.5.1: while (b) {} while (n) {} // 6.5.2p1: do {} while (b); do {} while (n); // 6.5.3: for (;b;) {} for (;n;) {} // 13.3.1.5p1: bool direct1(b); bool direct2(n); int direct3(b); int direct4(n); // expected-error {{no viable conversion}} const bool &direct5(b); const bool &direct6(n); const int &direct7(b); const int &direct8(n); // expected-error {{no viable conversion}} bool directList1{b}; bool directList2{n}; int directList3{b}; int directList4{n}; // expected-error {{no viable conversion}} const bool &directList5{b}; const bool &directList6{n}; const int &directList7{b}; const int &directList8{n}; // expected-error {{no viable conversion}} bool copy1 = b; bool copy2 = n; // expected-error {{no viable conversion}} int copy3 = b; int copy4 = n; // expected-error {{no viable conversion}} const bool ©5 = b; const bool ©6 = n; // expected-error {{no viable conversion}} const int ©7 = b; const int ©8 = n; // expected-error {{no viable conversion}} bool copyList1 = {b}; bool copyList2 = {n}; // expected-error {{no viable conversion}} int copyList3 = {b}; int copyList4 = {n}; // expected-error {{no viable conversion}} const bool ©List5 = {b}; const bool ©List6 = {n}; // expected-error {{no viable conversion}} const int ©List7 = {b}; const int ©List8 = {n}; // expected-error {{no viable conversion}} } #if __cplusplus < 201707L void testNew() { // 5.3.4p6: struct Int { operator int(); }; struct NotInt { explicit operator int(); // expected-note {{conversion to integral type 'int' declared here}} }; Int i; NotInt ni; new int[i]; new int[ni]; // expected-error {{array size expression of type 'NotInt' requires explicit conversion to type 'int'}} } #endif void testDelete() { // 5.3.5pp2: struct Ptr { operator int*(); }; struct NotPtr { explicit operator int*(); // expected-note {{conversion}} }; Ptr p; NotPtr np; delete p; delete np; // expected-error {{converting delete expression from type 'NotPtr' to type 'int *' invokes an explicit conversion function}} } void testFunctionPointer() { // 13.3.1.1.2p2: using Func = void(*)(int); struct FP { operator Func(); }; struct NotFP { explicit operator Func(); }; FP fp; NotFP nfp; fp(1); nfp(1); // expected-error {{type 'NotFP' does not provide a call operator}} } } namespace pr8264 { struct Test { explicit explicit Test(int x); // expected-warning{{duplicate 'explicit' declaration specifier}} }; } namespace PR18777 { struct S { explicit operator bool() const; } s; int *p = new int(s); // expected-error {{no viable conversion}} }