// RUN: %clang_cc1 -std=c++17 -fsyntax-only %s -verify -Wno-c++2a-extensions // RUN: %clang_cc1 -std=c++2a -fsyntax-only %s -verify template struct enable_ifv {}; template struct enable_ifv { static constexpr auto value = val; }; template struct is_same { static constexpr bool value = false; }; template struct is_same { static constexpr bool value = true; }; namespace special_cases { template struct A { // expected-note@-1+ {{candidate constructor}} explicit(1 << a) // expected-note@-1 {{negative shift count -1}} // expected-error@-2 {{explicit specifier argument is not a constant expression}} A(int); }; A<-1> a(0); // expected-error@-1 {{no matching constructor}} // expected-note@-2 {{in instantiation of template class}} template struct B { explicit(b) // expected-error@-1 {{use of undeclared identifier}} B(int); }; template struct B1 { explicit(a +) // expected-error@-1 {{expected expression}} B1(int); }; struct B2 { explicit(false) explicit B2(int); // expected-error@-2 {{duplicate 'explicit' declaration specifier}} }; template struct C { // expected-note@-1 {{candidate constructor}} expected-note@-1 {{candidate constructor}} // expected-note@-2 {{candidate constructor}} expected-note@-2 {{candidate constructor}} explicit(a == 0) C(int), // expected-note 2{{not a candidate}} C(double); // expected-note 2{{not a candidate}} }; C<0> c0 = 0.0; // expected-error {{no viable conversion}} C<0> c1 = 0; // expected-error {{no viable conversion}} C<1> c2 = 0.0; C<1> c3 = 0; explicit(false) void f(int);// expected-error {{'explicit' can only be specified inside the class definition}} struct D { explicit(false) void f(int);// expected-error {{'explicit' can only be applied to a constructor or conversion function}} }; template struct E { // expected-note@-1+ {{candidate constructor}} explicit((T{}, false)) // expected-error@-1 {{illegal initializer type 'void'}} E(int); }; E e = 1; // expected-error@-1 {{no viable conversion}} // expected-note@-2 {{in instantiation of}} } namespace trailling_object { template struct B { explicit(b) B(int) {} }; template struct A : B { explicit(b) A(int) : B(0) {} }; A a(0); } namespace constructor1 { template struct A { // expected-note@-1+ {{candidate constructor}} // expected-note@-2+ {{candidate function}} explicit(b) A(int, int = 0); // expected-note {{not a candidate}} // expected-note@-1+ {{explicit constructor declared here}} }; template A::A(int, int) {} void f() { A a0 = 0; // expected-error {{no viable conversion}} A a1( 0); A && a2 = 0;// expected-error {{could not bind}} A && a3( 0);// expected-error {{could not bind}} A a4{ 0}; A && a5 = { 0};// expected-error {{chosen constructor is explicit}} A && a6{ 0}; A a7 = { 0}; // expected-error {{chosen constructor is explicit in copy-initialization}} a0 = 0; // expected-error {{no viable overloaded '='}} a1 = { 0}; // expected-error {{no viable overloaded '='}} a2 = A( 0); a3 = A{ 0}; A c0 = ((short)0); A c1( ((short)0)); A && c2 = ((short)0); A && c3( ((short)0)); A c4{ ((short)0)}; A && c5 = { ((short)0)}; A && c6{ ((short)0)}; A d1( 0, 0); A d2{ 0, 0}; A d3 = { 0, 0}; // expected-error {{chosen constructor is explicit in copy-initialization}} d1 = { 0, 0}; // expected-error {{no viable overloaded '='}} d2 = A( 0, 0); d3 = A{ 0, 0}; } } namespace constructor2 { template struct A { // expected-note@-1 {{candidate constructor}} expected-note@-1 {{candidate constructor}} // expected-note@-2 {{candidate constructor}} expected-note@-2 {{candidate constructor}} template explicit(a ^ is_same::value) A(T2) {} // expected-note@-1+ {{explicit constructor declared here}} // expected-note@-2+ {{not a candidate}} }; A a0 = 0.0; // expected-error {{no viable conversion}} A a1( 0.0); A && a2 = 0.0;// expected-error {{could not bind}} A && a3( 0.0);// expected-error {{could not bind}} A a4{ 0.0}; A && a5 = { 0.0};// expected-error {{chosen constructor is explicit}} A && a6{ 0.0}; A a7 = { 0.0}; // expected-error {{chosen constructor is explicit in copy-initialization}} A b0 = 0; A b1( 0); A && b2 = 0; A && b3( 0); A b4{ 0}; A && b5 = { 0}; A && b6{ 0}; A b7 = { 0}; A c0 = 0; // expected-error {{no viable conversion}} A c1( 0); A && c2 = 0;// expected-error {{could not bind}} A && c3( 0);// expected-error {{could not bind}} A c4{ 0}; A && c5 = { 0};// expected-error {{chosen constructor is explicit}} A && c6{ 0}; A c7 = { 0}; // expected-error {{chosen constructor is explicit in copy-initialization}} } namespace constructor_sfinae { template struct A { // expected-note@-1+ {{candidate constructor}} template explicit(enable_ifv::value, a>::value) A(T) {} // expected-note@-1+ {{substitution failure}} // expected-note@-2 {{not a candidate}} // expected-note@-3 {{explicit constructor declared here}} template explicit(enable_ifv::value, a>::value) A(T) {} // expected-note@-1+ {{substitution failure}} // expected-note@-2 {{not a candidate}} // expected-note@-3 {{explicit constructor declared here}} }; A a0 = 0.0; // expected-error {{no viable conversion}} A a1( 0.0); // expected-error {{no matching constructor}} A a4{ 0.0}; // expected-error {{no matching constructor}} A a7 = { 0.0}; // expected-error {{no matching constructor}} A b0 = 0; // expected-error {{no viable conversion}} A b1( 0); A b4{ 0}; A b7 = { 0}; // expected-error {{chosen constructor is explicit}} A c0 = 0; A c1( 0); A c4{ 0}; A c7 = { 0}; A d0 = true; // expected-error {{no viable conversion}} A d1( true); A d4{ true}; A d7 = { true}; // expected-error {{chosen constructor is explicit}} } namespace conversion { template struct A { explicit(a) operator int (); // expected-note+ {{not a candidate}} }; template A::operator int() { return 0; } A A_true; A A_false; int ai0 = A(); // expected-error {{no viable conversion}} const int& ai1 = A(); // expected-error {{no viable conversion}} int&& ai3 = A(); // expected-error {{no viable conversion}} int ai4 = A_true; // expected-error {{no viable conversion}} const int& ai5 = A_true; // expected-error {{no viable conversion}} int ai01 = {A()}; // expected-error {{no viable conversion}} const int& ai11 = {A()}; // expected-error {{no viable conversion}} int&& ai31 = {A()}; // expected-error {{no viable conversion}} int ai41 = {A_true}; // expected-error {{no viable conversion}} const int& ai51 = {A_true}; // expected-error {{no viable conversion}} int ae0(A()); const int& ae1(A()); int&& ae3(A()); int ae4(A_true); const int& ae5(A_true); int bi0 = A(); const int& bi1 = A(); int&& bi3 = A(); int bi4 = A_false; const int& bi5 = A_false; int bi01 = {A()}; const int& bi11 = {A()}; int&& bi31 = {A()}; int bi41 = {A_false}; const int& bi51 = {A_false}; int be0(A()); const int& be1(A()); int&& be3(A()); int be4(A_true); const int& be5(A_true); } namespace conversion2 { struct B {}; // expected-note@-1+ {{candidate constructor}} template struct A { template explicit(enable_ifv::value, a>::value) operator T2() { return T2(); }; // expected-note@-1+ {{substitution failure}} // expected-note@-2+ {{not a candidate}} }; A A_false; A A_true; int ai0 = A(); // expected-error {{no viable conversion}} const int& ai1 = A(); // expected-error {{no viable conversion}} int&& ai3 = A(); // expected-error {{no viable conversion}} int ai4 = A_false; // expected-error {{no viable conversion}} const int& ai5 = A_false; // expected-error {{no viable conversion}} int ae0{A()}; // expected-error {{no viable conversion}} const int& ae1{A()}; // expected-error {{no viable conversion}} int&& ae3{A()}; // expected-error {{no viable conversion}} int ae4{A_true}; // expected-error {{no viable conversion}} const int& ae5{A_true}; // expected-error {{no viable conversion}} int ap0((A())); // expected-error {{no viable conversion}} const int& ap1((A())); // expected-error {{no viable conversion}} int&& ap3((A())); // expected-error {{no viable conversion}} int ap4(A_true); // expected-error {{no viable conversion}} const int& ap5(A_true); // expected-error {{no viable conversion}} B b0 = A(); // expected-error {{no viable conversion}} const B & b1 = A(); // expected-error {{no viable conversion}} B && b3 = A(); // expected-error {{no viable conversion}} B b4 = A_true; // expected-error {{no viable conversion}} const B & b5 = A_true; // expected-error {{no viable conversion}} B be0(A()); const B& be1(A()); B&& be3(A()); B be4(A_true); const B& be5(A_true); B c0 = A(); const B & c1 = A(); B && c3 = A(); B c4 = A_false; const B & c5 = A_false; } namespace parameter_pack { template struct A { // expected-note@-1+ {{candidate constructor}} // expected-note@-2+ {{candidate function}} template explicit((is_same::value && ...)) A(Ts...); // expected-note@-1 {{not a candidate}} // expected-note@-2 {{explicit constructor}} }; template template A::A(Ts ...) {} void f() { A a0 = 0; // expected-error {{no viable conversion}} A a1( 0, 1); A a2{ 0, 1}; A a3 = { 0, 1}; // expected-error {{chosen constructor is explicit}} a1 = 0; // expected-error {{no viable overloaded '='}} a2 = { 0, 1}; // expected-error {{no viable overloaded '='}} A b0 = 0; A b1( 0, 1); A b2{ 0, 1}; A b3 = { 0, 1}; b1 = 0; b2 = { 0, 1}; } } namespace deduction_guide { template struct B {}; B b_true; B b_false; template struct nondeduced { using type = T; }; template struct A { // expected-note@-1+ {{candidate function}} explicit(false) A(typename nondeduced::type, typename nondeduced::type, typename nondeduced>::type) {} // expected-note@-1+ {{candidate template ignored}} }; template explicit(enable_ifv::value, b>::value) A(T1, T2, B) -> A; // expected-note@-1+ {{explicit deduction guide declared here}} // expected-note@-2+ {{candidate template ignored}} void f() { A a0( 0.0, 1, b_true); // expected-error {{no viable constructor or deduction guide}} A a1{ 0.0, 1, b_true}; // expected-error {{no viable constructor or deduction guide}} A a2 = { 0.0, 1, b_true}; // expected-error {{no viable constructor or deduction guide}} auto a4 = A( 0.0, 1, b_true); // expected-error {{no viable constructor or deduction guide}} auto a5 = A{ 0.0, 1, b_true}; // expected-error {{no viable constructor or deduction guide}} A b0( 0, 1, b_true); A b1{ 0, 1, b_true}; A b2 = { 0, 1, b_true}; // expected-error {{explicit deduction guide for copy-list-initialization}} auto b4 = A( 0, 1, b_true); auto b5 = A{ 0, 1, b_true}; b0 = { 0, 1, b_false}; // expected-error {{no viable overloaded '='}} A c0( 0, 1, b_false); A c1{ 0, 1, b_false}; A c2 = { 0, 1, b_false}; auto c4 = A( 0, 1, b_false); auto c5 = A{ 0, 1, b_false}; c2 = { 0, 1, b_false}; } } namespace test8 { template struct A { //expected-note@-1+ {{candidate function}} template explicit(b) A(T1, T2) {} //expected-note@-1 {{explicit constructor declared here}} }; template explicit(!is_same::value) A(T1, T2) -> A::value>; // expected-note@-1+ {{explicit deduction guide declared here}} template A v(); void f() { A a0( 0, 1); A a1{ 0, 1}; A a2 = { 0, 1}; auto a4 = A( 0, 1); auto a5 = A{ 0, 1}; auto a6(v()); a6 = { 0, 1}; A b0( 0.0, 1); A b1{ 0.0, 1}; A b2 = { 0.0, 1}; // expected-error {{explicit deduction guide for copy-list-initialization}} auto b4 = A( 0.0, 1); auto b5 = A{ 0.0, 1}; A c0( 0, 1.0); A c1{ 0, 1.0}; A c2 = { 0, 1.0}; // expected-error {{chosen constructor is explicit}} auto c4 = A( 0, 1.0); auto c5 = A{ 0, 1.0}; auto c6(v()); c0 = { 0, 1.0}; // expected-error {{no viable overloaded '='}} A d0( 0.0, 1.0); A d1{ 0.0, 1.0}; A d2 = { 0.0, 1.0}; // expected-error {{explicit deduction guide for copy-list-initialization}} auto d4 = A( 0.0, 1.0); auto d5 = A{ 0.0, 1.0}; } } namespace conversion3 { template struct A { explicit(!b) operator int(); explicit(b) operator bool(); }; template A::operator bool() { return false; } struct B { void f(int); void f(bool); }; void f(A a, B b) { b.f(a); } void f1(A a, B b) { b.f(a); } // Taken from 12.3.2p2 class X { X(); }; class Y { }; // expected-note+ {{candidate constructor (the implicit}} template struct Z { explicit(b) operator X() const; explicit(b) operator Y() const; // expected-note 2{{not a candidate}} explicit(b) operator int() const; // expected-note {{not a candidate}} }; void testExplicit() { Z z; // 13.3.1.4p1 & 8.5p16: Y y2 = z; // expected-error {{no viable conversion}} 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}} const int& y7 = z; // expected-error {{no viable conversion}} 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}} 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}; } struct tmp {}; template struct C { template explicit(!is_same::value) operator T(); // expected-note+ {{explicit conversion function is not a candidate}} }; using Bool = C; using Integral = C; using Unrelated = C; void testBool() { Bool b; Integral n; Unrelated u; (void) (1 + b); // expected-error {{invalid operands to binary expression}} (void) (1 + n); (void) (1 + u); // expected-error {{invalid operands to binary expression}} // 5.3.1p9: (void) (!b); (void) (!n); (void) (!u); // 5.14p1: (void) (b && true); (void) (n && true); (void) (u && true); // 5.15p1: (void) (b || true); (void) (n || true); (void) (u || true); // 5.16p1: (void) (b ? 0 : 1); (void) (n ? 0: 1); (void) (u ? 0: 1); // // 5.19p5: // // TODO: After constexpr has been implemented // 6.4p4: if (b) {} if (n) {} if (u) {} // 6.4.2p2: switch (b) {} // expected-error {{statement requires expression of integer type}} switch (n) {} // expected-error {{statement requires expression of integer type}} switch (u) {} // expected-error {{statement requires expression of integer type}} // 6.5.1: while (b) {} while (n) {} while (u) {} // 6.5.2p1: do {} while (b); do {} while (n); do {} while (u); // 6.5.3: for (;b;) {} for (;n;) {} for (;u;) {} // 13.3.1.5p1: bool db1(b); bool db2(n); bool db3(u); int di1(b); int di2(n); int di3(n); const bool &direct_cr1(b); const bool &direct_cr2(n); const bool &direct_cr3(n); const int &direct_cr4(b); const int &direct_cr5(n); const int &direct_cr6(n); bool directList1{b}; bool directList2{n}; bool directList3{n}; int directList4{b}; int directList5{n}; int directList6{n}; const bool &directList_cr1{b}; const bool &directList_cr2{n}; const bool &directList_cr3{n}; const int &directList_cr4{b}; const int &directList_cr5{n}; const int &directList_cr6{n}; bool copy1 = b; bool copy2 = n;// expected-error {{no viable conversion}} bool copyu2 = u;// expected-error {{no viable conversion}} int copy3 = b;// expected-error {{no viable conversion}} int copy4 = n; int copyu4 = u;// expected-error {{no viable conversion}} const bool ©5 = b; const bool ©6 = n;// expected-error {{no viable conversion}} const bool ©u6 = u;// expected-error {{no viable conversion}} const int ©7 = b;// expected-error {{no viable conversion}} const int ©8 = n; const int ©u8 = u;// expected-error {{no viable conversion}} bool copyList1 = {b}; bool copyList2 = {n};// expected-error {{no viable conversion}} bool copyListu2 = {u};// expected-error {{no viable conversion}} int copyList3 = {b};// expected-error {{no viable conversion}} int copyList4 = {n}; int copyListu4 = {u};// expected-error {{no viable conversion}} const bool ©List5 = {b}; const bool ©List6 = {n};// expected-error {{no viable conversion}} const bool ©Listu6 = {u};// expected-error {{no viable conversion}} const int ©List7 = {b};// expected-error {{no viable conversion}} const int ©List8 = {n}; const int ©Listu8 = {u};// expected-error {{no viable conversion}} } } namespace deduction_guide2 { template struct A { // expected-note@-1+ {{candidate template ignored}} explicit(!is_same::value) A(T1 = 0, T2 = 0) {} // expected-note@-1 {{explicit constructor declared here}} // expected-note@-2 2{{explicit constructor is not a candidate}} }; A a0 = 0; A a1(0, 0); A a2{0, 0}; A a3 = {0, 0}; A b0 = 0.0; // expected-error {{no viable constructor or deduction guide}} A b1(0.0, 0.0); A b2{0.0, 0.0}; A b3 = {0.0, 0.0}; A b4 = {0.0, 0}; // expected-error {{explicit constructor}} template explicit A(T1, T2) -> A; // expected-note@-1+ {{explicit deduction guide}} A c0 = 0; A c1(0, 0); A c2{0, 0}; A c3 = {0, 0};// expected-error {{explicit deduction guide}} A d0 = 0.0; // expected-error {{no viable constructor or deduction guide}} A d1(0, 0); A d2{0, 0}; A d3 = {0.0, 0.0};// expected-error {{explicit deduction guide}} } namespace PR42980 { using size_t = decltype(sizeof(0)); struct Str {// expected-note+ {{candidate constructor}} template explicit(N > 7) Str(char const (&str)[N]); // expected-note {{explicit constructor is not a candidate}} }; template Str::Str(char const(&str)[N]) { } Str a = "short"; Str b = "not so short";// expected-error {{no viable conversion}} }