diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/CXX/temp/temp.deduct.guide/p1.cpp | 2 | ||||
-rw-r--r-- | test/CXX/temp/temp.deduct.guide/p3.cpp | 8 | ||||
-rw-r--r-- | test/PCH/cxx-explicit-specifier.cpp | 124 | ||||
-rw-r--r-- | test/SemaCXX/builtin-is-constant-evaluated.cpp | 2 | ||||
-rw-r--r-- | test/SemaCXX/cxx2a-compat.cpp | 20 | ||||
-rw-r--r-- | test/SemaCXX/cxx2a-explicit-bool.cpp | 719 | ||||
-rw-r--r-- | test/SemaCXX/explicit.cpp | 8 |
7 files changed, 875 insertions, 8 deletions
diff --git a/test/CXX/temp/temp.deduct.guide/p1.cpp b/test/CXX/temp/temp.deduct.guide/p1.cpp index 8bb9da8a97..86aa29dc34 100644 --- a/test/CXX/temp/temp.deduct.guide/p1.cpp +++ b/test/CXX/temp/temp.deduct.guide/p1.cpp @@ -71,7 +71,7 @@ extern A(int(&)[26]) -> A<int>; #endif mutable A(int(&)[27]) -> A<int>; // expected-error-re {{{{'mutable' cannot be applied to|illegal storage class on}} function}} virtual A(int(&)[28]) -> A<int>; // expected-error {{'virtual' can only appear on non-static member functions}} -const A(int(&)[28]) -> A<int>; // expected-error {{deduction guide cannot be declared 'const'}} +const A(int(&)[31]) -> A<int>; // expected-error {{deduction guide cannot be declared 'const'}} const volatile static constexpr inline A(int(&)[29]) -> A<int>; // expected-error {{deduction guide cannot be declared 'static inline constexpr const volatile'}} diff --git a/test/CXX/temp/temp.deduct.guide/p3.cpp b/test/CXX/temp/temp.deduct.guide/p3.cpp index 07d1be0593..ec39c0c5ac 100644 --- a/test/CXX/temp/temp.deduct.guide/p3.cpp +++ b/test/CXX/temp/temp.deduct.guide/p3.cpp @@ -3,14 +3,14 @@ // The same restrictions apply to the parameter-declaration-clause of a // deduction guide as in a function declaration. template<typename T> struct A {}; -A(void) -> A<int>; // ok +A(void) -> A<int>; // expected-note {{previous}} A(void, int) -> A<int>; // expected-error {{'void' must be the first and only parameter if specified}} -// We interpret this as also extending to the validity of redeclarations. It's -// a bit of a stretch (OK, a lot of a stretch) but it gives desirable answers. -A() -> A<int>; // ok, redeclaration +A() -> A<int>; // expected-error {{redeclaration of deduction guide}} +// expected-note@-1 {{previous}} A() -> A<int>; // expected-note {{previous}} +// expected-error@-1 {{redeclaration of deduction guide}} A() -> A<float>; // FIXME: "functions" is a poor term. expected-error {{functions that differ only in their return type cannot be overloaded}} template<typename T> A(T) -> A<typename T::foo>; diff --git a/test/PCH/cxx-explicit-specifier.cpp b/test/PCH/cxx-explicit-specifier.cpp new file mode 100644 index 0000000000..a800cfc9d5 --- /dev/null +++ b/test/PCH/cxx-explicit-specifier.cpp @@ -0,0 +1,124 @@ +// RUN: %clang_cc1 -std=c++2a -emit-pch %s -o %t-cxx2a +// RUN: %clang_cc1 -std=c++2a -DUSE_PCH -include-pch %t-cxx2a %s -ast-print -verify | FileCheck %s + +#ifndef USE_PCH +namespace inheriting_constructor { + struct S {}; + + template<typename X, typename Y> struct T { + template<typename A> + explicit((Y{}, true)) T(A &&a) {} + }; + + template<typename X, typename Y> struct U : T<X, Y> { + using T<X, Y>::T; + }; + + U<S, char> foo(char ch) { + return U<S, char>(ch); + } +} +#else +namespace inheriting_constructor { +U<S, char> a = foo('0'); +} + +//CHECK: explicit((char{} , true)) + +#endif + +namespace basic { +#ifndef USE_PCH + +struct B {}; + +struct A { + explicit A(int); + explicit(false) operator bool(); + explicit(true) operator B(); +}; +#else +//expected-note@-6+ {{candidate constructor}} +//expected-note@-9+ {{candidate constructor}} +//expected-note@-6+ {{candidate function}} + +//CHECK: explicit{{ +}}A( +//CHECK-NEXT: explicit(false){{ +}}operator +//CHECK-NEXT: explicit(true){{ +}}operator +A a = 0; //expected-error {{no viable conversion}} +A a1(0); + +bool b = a1; +B b1 = a1; //expected-error {{no viable conversion}} + +#endif +} + + +namespace templ { +#ifndef USE_PCH + +template<bool b> +struct B { + static constexpr bool value = b; +}; + +template<bool b> +struct A { + explicit(b) A(B<b>) {} + template<typename T> + explicit(b ^ T::value) operator T(); +}; +B<true> b_true; +B<false> b_false; +#else +//expected-note@-8 {{candidate template ignored}} +//expected-note@-8+ {{explicit constructor}} +//expected-note@-15+ {{candidate constructor}} +//expected-note@-8+ {{candidate conversion operator ignored}} +//expected-note@-9+ {{explicit(bool) specifier resolved to true}} +//expected-note@-12 {{explicit(bool) specifier resolved to true}} +//expected-note@-13+ {{candidate deductiong guide ignored}} + +//CHECK: explicit(b){{ +}}A +//CHECK: explicit(b{{ +}}^{{ +}}T::value){{ +}}operator + +A a = { b_true }; //expected-error {{class template argument deduction}} +A a0 = b_true; //expected-error {{no viable constructor or deduction guide}} +A a_true(b_true); +A a_false = b_false; + +B<true> b = a_true; +B<true> b1 = a_false; //expected-error {{no viable conversion}} +B<false> b2(a_true); + +#endif + +} + +namespace guide { + +#ifndef USE_PCH + +template<typename T> +struct A { + A(T); +}; + +template<typename T> +explicit(true) A(T) -> A<T>; + +explicit(false) A(int) -> A<int>; + +#else +//expected-note@-5 {{explicit deduction guide}} + +//CHECK: explicit(true){{ +}}A( +//CHECK: explicit(false){{ +}}A( + +A a = { 0.0 }; //expected-error {{explicit deduction guide}} +A a1 = { 0 }; + +#endif + +} diff --git a/test/SemaCXX/builtin-is-constant-evaluated.cpp b/test/SemaCXX/builtin-is-constant-evaluated.cpp index 47b54d6ac3..b2ec5cb9fa 100644 --- a/test/SemaCXX/builtin-is-constant-evaluated.cpp +++ b/test/SemaCXX/builtin-is-constant-evaluated.cpp @@ -115,7 +115,7 @@ static_assert(&r == &x); #if defined(__cpp_conditional_explicit) struct TestConditionalExplicit { - explicit(__builtin_is_constant_evaluated()) TestConditionalExplicit(int) {} + explicit(!__builtin_is_constant_evaluated()) TestConditionalExplicit(int) {} }; TestConditionalExplicit e = 42; #endif diff --git a/test/SemaCXX/cxx2a-compat.cpp b/test/SemaCXX/cxx2a-compat.cpp index d51f1e6aab..49db0bc539 100644 --- a/test/SemaCXX/cxx2a-compat.cpp +++ b/test/SemaCXX/cxx2a-compat.cpp @@ -37,3 +37,23 @@ string u8str = u8"test" u8"test"; // expected-error@-8 {{cannot initialize a variable of type 'const char *' with an lvalue of type 'const char8_t [6]'}} // expected-error@-8 {{no viable conversion from 'const char8_t [9]' to 'string'}} #endif + +template<bool b> +struct C { + explicit(C)(int); +}; +#if __cplusplus <= 201703L +// expected-warning@-3 {{this expression will be parsed as explicit(bool) in C++2a}} +#if defined(__cpp_conditional_explicit) +#error "the feature test macro __cpp_conditional_explicit isn't correct" +#endif +#else +// expected-error@-8 {{does not refer to a value}} +// expected-error@-9 {{expected member name or ';'}} +// expected-error@-10 {{expected ')'}} +// expected-note@-12 {{declared here}} +// expected-note@-12 {{to match this '('}} +#if !defined(__cpp_conditional_explicit) || __cpp_conditional_explicit != 201806L +#error "the feature test macro __cpp_conditional_explicit isn't correct" +#endif +#endif
\ No newline at end of file diff --git a/test/SemaCXX/cxx2a-explicit-bool.cpp b/test/SemaCXX/cxx2a-explicit-bool.cpp new file mode 100644 index 0000000000..1c532cfb59 --- /dev/null +++ b/test/SemaCXX/cxx2a-explicit-bool.cpp @@ -0,0 +1,719 @@ +// RUN: %clang_cc1 -std=c++2a -fsyntax-only %s -verify + +template <bool b, auto val> struct enable_ifv {}; + +template <auto val> struct enable_ifv<true, val> { + static constexpr auto value = val; +}; + +template <typename T1, typename T2> struct is_same { + static constexpr bool value = false; +}; + +template <typename T> struct is_same<T, T> { + static constexpr bool value = true; +}; + +namespace special_cases +{ + +template<int a> +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<int a> +struct B { + explicit(b) + // expected-error@-1 {{use of undeclared identifier}} + B(int); +}; + +template<int a> +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<int a> + 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), +C(double); +}; + +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 <typename T> struct E { + // expected-note@-1+ {{candidate constructor}} + explicit((T{}, false)) + // expected-error@-1 {{illegal initializer type 'void'}} + E(int); +}; + +E<void> e = 1; +// expected-error@-1 {{no viable conversion}} +// expected-note@-2 {{in instantiation of}} + +} + +namespace trailling_object { + +template<bool b> +struct B { + explicit(b) B(int) {} +}; + +template<bool b> +struct A : B<b> { + explicit(b) A(int) : B<b>(0) {} +}; + +A<true> a(0); + +} + +namespace constructor1 { + +template<bool b> + struct A { + // expected-note@-1+ {{candidate constructor}} + // expected-note@-2+ {{candidate function}} + explicit(b) A(int, int = 0); + // expected-note@-1+ {{explicit constructor declared here}} +}; + +template<bool b> +A<b>::A(int, int) {} + +void f() +{ +A<true> a0 = 0; // expected-error {{no viable conversion}} +A<true> a1( 0); +A<true> && a2 = 0;// expected-error {{could not bind}} +A<true> && a3( 0);// expected-error {{could not bind}} +A<true> a4{ 0}; +A<true> && a5 = { 0};// expected-error {{chosen constructor is explicit}} +A<true> && a6{ 0}; +A<true> a7 = { 0}; // expected-error {{chosen constructor is explicit in copy-initialization}} + +a0 = 0; +a1 = { 0}; // expected-error {{no viable overloaded '='}} +a2 = A<true>( 0); +a3 = A<true>{ 0}; + +A<false> c0 = ((short)0); +A<false> c1( ((short)0)); +A<false> && c2 = ((short)0); +A<false> && c3( ((short)0)); +A<false> c4{ ((short)0)}; +A<false> && c5 = { ((short)0)}; +A<false> && c6{ ((short)0)}; + +A<true> d1( 0, 0); +A<true> d2{ 0, 0}; +A<true> d3 = { 0, 0}; // expected-error {{chosen constructor is explicit in copy-initialization}} + +d1 = { 0, 0}; // expected-error {{no viable overloaded '='}} +d2 = A<true>( 0, 0); +d3 = A<true>{ 0, 0}; +} +} + +namespace constructor2 { + +template<bool a, typename T1> +struct A { + // expected-note@-1 {{candidate constructor}} expected-note@-1 {{candidate constructor}} + // expected-note@-2 {{candidate constructor}} expected-note@-2 {{candidate constructor}} + template<typename T2> + explicit(a ^ is_same<T1, T2>::value) + // expected-note@-1+ {{explicit(bool) specifier resolved to true}} + A(T2) {} + // expected-note@-1+ {{explicit constructor declared here}} + // expected-note@-2+ {{candidate constructor ignored}} +}; + +A<true, int> a0 = 0.0; // expected-error {{no viable conversion}} +A<true, int> a1( 0.0); +A<true, int> && a2 = 0.0;// expected-error {{could not bind}} +A<true, int> && a3( 0.0);// expected-error {{could not bind}} +A<true, int> a4{ 0.0}; +A<true, int> && a5 = { 0.0};// expected-error {{chosen constructor is explicit}} +A<true, int> && a6{ 0.0}; +A<true, int> a7 = { 0.0}; // expected-error {{chosen constructor is explicit in copy-initialization}} + +A<true, int> b0 = 0; +A<true, int> b1( 0); +A<true, int> && b2 = 0; +A<true, int> && b3( 0); +A<true, int> b4{ 0}; +A<true, int> && b5 = { 0}; +A<true, int> && b6{ 0}; +A<true, int> b7 = { 0}; + +A<true, double> c0 = 0; // expected-error {{no viable conversion}} +A<true, double> c1( 0); +A<true, double> && c2 = 0;// expected-error {{could not bind}} +A<true, double> && c3( 0);// expected-error {{could not bind}} +A<true, double> c4{ 0}; +A<true, double> && c5 = { 0};// expected-error {{chosen constructor is explicit}} +A<true, double> && c6{ 0}; +A<true, double> c7 = { 0}; // expected-error {{chosen constructor is explicit in copy-initialization}} + +} + +namespace constructor_sfinae { + +template<bool a> +struct A { + // expected-note@-1+ {{candidate constructor}} + template<typename T> + explicit(enable_ifv<is_same<int, T>::value, a>::value) + //expected-note@-1 {{explicit(bool) specifier resolved to true}} + A(T) {} + // expected-note@-1+ {{substitution failure}} + // expected-note@-2 {{candidate constructor ignored}} + // expected-note@-3 {{explicit constructor declared here}} + template<typename T, bool c = true> + explicit(enable_ifv<is_same<bool, T>::value, a>::value) + //expected-note@-1 {{explicit(bool) specifier resolved to true}} + A(T) {} + // expected-note@-1+ {{substitution failure}} + // expected-note@-2 {{candidate constructor ignored}} + // expected-note@-3 {{explicit constructor declared here}} +}; + +A<true> a0 = 0.0; // expected-error {{no viable conversion}} +A<true> a1( 0.0); // expected-error {{no matching constructor}} +A<true> a4{ 0.0}; // expected-error {{no matching constructor}} +A<true> a7 = { 0.0}; // expected-error {{no matching constructor}} + +A<true> b0 = 0; // expected-error {{no viable conversion}} +A<true> b1( 0); +A<true> b4{ 0}; +A<true> b7 = { 0}; // expected-error {{chosen constructor is explicit}} + +A<false> c0 = 0; +A<false> c1( 0); +A<false> c4{ 0}; +A<false> c7 = { 0}; + +A<true> d0 = true; // expected-error {{no viable conversion}} +A<true> d1( true); +A<true> d4{ true}; +A<true> d7 = { true}; // expected-error {{chosen constructor is explicit}} + +} + +namespace conversion { + +template<bool a> +struct A { + explicit(a) operator int (); +}; + +template<bool a> +A<a>::operator int() { + return 0; +} + +A<true> A_true; +A<false> A_false; + +int ai0 = A<true>(); // expected-error {{no viable conversion}} +const int& ai1 = A<true>(); // expected-error {{no viable conversion}} +int&& ai3 = A<true>(); // 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<true>()}; // expected-error {{no viable conversion}} +const int& ai11 = {A<true>()}; // expected-error {{no viable conversion}} +int&& ai31 = {A<true>()}; // 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<true>()); +const int& ae1(A<true>()); +int&& ae3(A<true>()); +int ae4(A_true); +const int& ae5(A_true); + +int bi0 = A<false>(); +const int& bi1 = A<false>(); +int&& bi3 = A<false>(); +int bi4 = A_false; +const int& bi5 = A_false; + +int bi01 = {A<false>()}; +const int& bi11 = {A<false>()}; +int&& bi31 = {A<false>()}; +int bi41 = {A_false}; +const int& bi51 = {A_false}; + +int be0(A<true>()); +const int& be1(A<true>()); +int&& be3(A<true>()); +int be4(A_true); +const int& be5(A_true); + +} + +namespace conversion2 { + +struct B {}; +// expected-note@-1+ {{candidate constructor}} +template<bool a> +struct A { + template<typename T2> + explicit(enable_ifv<is_same<B, T2>::value, a>::value) + // expected-note@-1+ {{explicit(bool) specifier resolved to true}} + operator T2() { return T2(); }; + // expected-note@-1+ {{substitution failure}} + // expected-note@-2+ {{candidate conversion}} +}; + +A<false> A_false; +A<true> A_true; + +int ai0 = A<true>(); // expected-error {{no viable conversion}} +const int& ai1 = A<true>(); // expected-error {{no viable conversion}} +int&& ai3 = A<true>(); // 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<true>()}; // expected-error {{no viable conversion}} +const int& ae1{A<true>()}; // expected-error {{no viable conversion}} +int&& ae3{A<true>()}; // 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<true>())); // expected-error {{no viable conversion}} +const int& ap1((A<true>())); // expected-error {{no viable conversion}} +int&& ap3((A<true>())); // 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<true>(); // expected-error {{no viable conversion}} +const B & b1 = A<true>(); // expected-error {{no viable conversion}} +B && b3 = A<true>(); // 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<true>()); +const B& be1(A<true>()); +B&& be3(A<true>()); +B be4(A_true); +const B& be5(A_true); + +B c0 = A<false>(); +const B & c1 = A<false>(); +B && c3 = A<false>(); +B c4 = A_false; +const B & c5 = A_false; + +} + +namespace parameter_pack { + +template<typename T> +struct A { + // expected-note@-1+ {{candidate constructor}} + // expected-note@-2+ {{candidate function}} + template<typename ... Ts> + explicit((is_same<T, Ts>::value && ...)) + // expected-note@-1 {{explicit(bool) specifier resolved to true}} + A(Ts...); + // expected-note@-1 {{candidate constructor}} + // expected-note@-2 {{explicit constructor}} +}; + +template<typename T> +template<typename ... Ts> +A<T>::A(Ts ...) {} + +void f() { + +A<int> a0 = 0; // expected-error {{no viable conversion}} +A<int> a1( 0, 1); +A<int> a2{ 0, 1}; +A<int> 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<double> b0 = 0; +A<double> b1( 0, 1); +A<double> b2{ 0, 1}; +A<double> b3 = { 0, 1}; + +b1 = 0; +b2 = { 0, 1}; + +} + +} + +namespace deduction_guide { + +template<bool b> +struct B {}; + +B<true> b_true; +B<false> b_false; + +template<typename T> +struct nondeduced +{ +using type = T; +}; + +template<typename T1, typename T2, bool b> +struct A { + // expected-note@-1+ {{candidate function}} + explicit(false) + A(typename nondeduced<T1>::type, typename nondeduced<T2>::type, typename nondeduced<B<b>>::type) {} + // expected-note@-1+ {{candidate template ignored}} +}; + +template<typename T1, typename T2, bool b> +explicit(enable_ifv<is_same<T1, T2>::value, b>::value) +A(T1, T2, B<b>) -> A<T1, T2, b>; +// 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<bool b> +struct A { + //expected-note@-1+ {{candidate function}} + template<typename T1, typename T2> + explicit(b) + A(T1, T2) {} + //expected-note@-1 {{explicit constructor declared here}} +}; + +template<typename T1, typename T2> +explicit(!is_same<T1, int>::value) +A(T1, T2) -> A<!is_same<int, T2>::value>; +// expected-note@-1+ {{explicit deduction guide declared here}} + +template<bool b> +A<b> 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<false>()); +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<true>()); +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<bool b> +struct A { + explicit(!b) operator int(); + explicit(b) operator bool(); +}; + +template<bool b> +A<b>::operator bool() { return false; } + +struct B { + void f(int); + void f(bool); +}; + +void f(A<true> a, B b) { + b.f(a); +} + +void f1(A<false> a, B b) { + b.f(a); +} + +// Taken from 12.3.2p2 +class X { X(); }; +class Y { }; // expected-note+ {{candidate constructor (the implicit}} + +template<bool b> +struct Z { + explicit(b) operator X() const; + explicit(b) operator Y() const; + explicit(b) operator int() const; +}; + +void testExplicit() +{ +Z<true> 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<Y>(z); +// 13.3.1.5p1 & 8.5p16: +int i1 = (int)z; +int i2 = int(z); +int i3 = static_cast<int>(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<typename T1> +struct C { + template<typename T> + explicit(!is_same<T1, T>::value) + // expected-note@-1+ {{explicit(bool) specifier resolved to true}} + operator T(); + // expected-note@-1+ {{candidate conversion operator ignored}} +}; + +using Bool = C<bool>; +using Integral = C<int>; +using Unrelated = C<tmp>; + +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<typename T1 = int, typename T2 = int> +struct A { + // expected-note@-1+ {{candidate template ignored}} + explicit(!is_same<T1, T2>::value) + // expected-note@-1+ {{explicit(bool) specifier resolved to true}} + A(T1 = 0, T2 = 0) {} + // expected-note@-1 {{explicit constructor}} + // expected-note@-2+ {{candidate deductiong guide ignored}} +}; + +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<typename T1, typename T2> +explicit A(T1, T2) -> A<T1, T2>; +// 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}} + +} diff --git a/test/SemaCXX/explicit.cpp b/test/SemaCXX/explicit.cpp index a3902e5d10..bd1199f23c 100644 --- a/test/SemaCXX/explicit.cpp +++ b/test/SemaCXX/explicit.cpp @@ -1,4 +1,6 @@ // 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); @@ -183,7 +185,8 @@ namespace Conversion { const int ©List7 = {b}; const int ©List8 = {n}; // expected-error {{no viable conversion}} } - + +#if __cplusplus < 201707L void testNew() { // 5.3.4p6: @@ -200,7 +203,8 @@ namespace Conversion { 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: |