diff options
Diffstat (limited to 'test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp')
-rw-r--r-- | test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp index b45ed96d14456..085976b081332 100644 --- a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp @@ -1,4 +1,6 @@ // RUN: %clang_cc1 -fsyntax-only %s -verify +// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s -verify +// RUN: %clang_cc1 -std=c++17 -fsyntax-only %s -verify struct AnyT { template<typename T> @@ -62,3 +64,86 @@ void test_deduce_two_level_ptrmem_with_qual(TwoLevelPtrMem apm) { // deduce T = 'const double' const double X::* X::* pm1 = apm; // expected-note {{instantiation of}} } + +namespace non_ptr_ref_cv_qual { + template<typename Expected> + struct ConvToT { + template<typename T> operator T() { + using Check = T; + using Check = Expected; + } + }; + const int test_conv_to_t_1 = ConvToT<int>(); + // We intentionally deviate from [temp.deduct.conv]p4 here, and also remove + // the top-level cv-quaifiers from A *after* removing the reference type, if + // P is not also a reference type. This matches what other compilers are + // doing, and is necessary to support real-world code. + const int &test_conv_to_t_2 = ConvToT<int>(); + + // Example code that would be broken by the standard's rule. + struct Dest {}; + Dest d1a((ConvToT<Dest>())); + Dest d1b = ConvToT<Dest>(); + Dest &d2 = (d1a = ConvToT<Dest>()); + + template<typename Expected> + struct ConvToTRef { + template<typename T> operator T&() { + using Check = T; + using Check = Expected; + } + }; + const int test_conv_to_t_ref_1 = ConvToTRef<int>(); + const int &test_conv_to_t_ref_2 = ConvToTRef<const int>(); + + Dest d3a((ConvToTRef<const Dest>())); // initialize the copy ctor parameter with 'const Dest&' + Dest d3b = ConvToTRef<Dest>(); // convert to non-const T via [over.match.copy]/1.2 + Dest &d4 = (d3a = ConvToTRef<const Dest>()); + + template<typename Expected> + struct ConvToConstT { + template<typename T> operator const T() { + using Check = T; + using Check = Expected; + } + }; + const int test_conv_to_const_t_1 = ConvToConstT<int>(); + const int &test_conv_to_const_t_2 = ConvToConstT<int>(); + + template<typename Expected> + struct ConvToConstTRef { + template<typename T> operator const T&() { + using Check = T; + using Check = Expected; + } + }; + const int test_conv_to_const_t_ref_1 = ConvToConstTRef<int>(); + const int &test_conv_to_const_t_ref_2 = ConvToConstTRef<int>(); + + template <typename T, int N> using Arr = T[N]; + struct ConvToArr { + template <int N> + operator Arr<int, N> &() { + static_assert(N == 3, ""); + } + }; + int (&test_conv_to_arr_1)[3] = ConvToArr(); // ok + const int (&test_conv_to_arr_2)[3] = ConvToArr(); // ok, with qualification conversion + +#if __cplusplus >= 201702L + template<bool Noexcept, typename T, typename ...U> using Function = T(U...) noexcept(Noexcept); + template<bool Noexcept> struct ConvToFunction { + template <typename T, typename ...U> operator Function<Noexcept, T, U...>&(); // expected-note {{candidate}} + }; + void (&fn1)(int) noexcept(false) = ConvToFunction<false>(); + void (&fn2)(int) noexcept(true) = ConvToFunction<false>(); // expected-error {{no viable}} + void (&fn3)(int) noexcept(false) = ConvToFunction<true>(); + void (&fn4)(int) noexcept(true) = ConvToFunction<true>(); + + struct ConvToFunctionDeducingNoexcept { + template <bool Noexcept, typename T, typename ...U> operator Function<Noexcept, T, U...>&(); + }; + void (&fn5)(int) noexcept(false) = ConvToFunctionDeducingNoexcept(); + void (&fn6)(int) noexcept(true) = ConvToFunctionDeducingNoexcept(); +#endif +} |