summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/CXX/temp/temp.deduct.guide/p1.cpp2
-rw-r--r--test/CXX/temp/temp.deduct.guide/p3.cpp8
-rw-r--r--test/PCH/cxx-explicit-specifier.cpp124
-rw-r--r--test/SemaCXX/builtin-is-constant-evaluated.cpp2
-rw-r--r--test/SemaCXX/cxx2a-compat.cpp20
-rw-r--r--test/SemaCXX/cxx2a-explicit-bool.cpp719
-rw-r--r--test/SemaCXX/explicit.cpp8
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 &copy5 = b;
+const bool &copy6 = n;// expected-error {{no viable conversion}}
+const bool &copyu6 = u;// expected-error {{no viable conversion}}
+const int &copy7 = b;// expected-error {{no viable conversion}}
+const int &copy8 = n;
+const int &copyu8 = 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 &copyList5 = {b};
+const bool &copyList6 = {n};// expected-error {{no viable conversion}}
+const bool &copyListu6 = {u};// expected-error {{no viable conversion}}
+const int &copyList7 = {b};// expected-error {{no viable conversion}}
+const int &copyList8 = {n};
+const int &copyListu8 = {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 &copyList7 = {b};
const int &copyList8 = {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: