159 lines · cpp
1// RUN: %clang_cc1 -fsyntax-only %s -verify2// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s -verify3// RUN: %clang_cc1 -std=c++17 -fsyntax-only %s -verify4 5struct AnyT {6 template<typename T>7 operator T();8};9 10void test_cvqual_ref(AnyT any) {11 const int &cir = any; 12}13 14struct AnyThreeLevelPtr {15 template<typename T>16 operator T***() const {17 T x = 0; // expected-note 2{{declared const here}}18 x = 0; // expected-error 2{{const-qualified type}}19 T ***p;20 return p;21 }22};23 24struct X { };25 26void test_deduce_with_qual(AnyThreeLevelPtr a3) {27 int * const * const * const ip1 = a3;28 // FIXME: This is wrong; we are supposed to deduce 'T = int' here.29 const int * const * const * const ip2 = a3; // expected-note {{instantiation of}}30 // This one is correct, though.31 const double * * * ip3 = a3; // expected-note {{instantiation of}}32}33 34struct AnyPtrMem {35 template<typename Class, typename T>36 operator T Class::*() const37 {38 // This is correct: we don't need a qualification conversion here, so we39 // deduce 'T = const float'.40 T x = 0; // expected-note {{declared const here}}41 x = 0; // expected-error {{const-qualified type}}42 return 0;43 }44};45 46void test_deduce_ptrmem_with_qual(AnyPtrMem apm) {47 const float X::* pm = apm; // expected-note {{instantiation of}}48}49 50struct TwoLevelPtrMem {51 template<typename Class1, typename Class2, typename T>52 operator T Class1::*Class2::*() const53 {54 T x = 0; // expected-note 2{{declared const here}}55 x = 0; // expected-error 2{{const-qualified type}}56 return 0;57 }58};59 60void test_deduce_two_level_ptrmem_with_qual(TwoLevelPtrMem apm) {61 // FIXME: This is wrong: we should deduce T = 'float'62 const float X::* const X::* pm2 = apm; // expected-note {{instantiation of}}63 // This is correct: we don't need a qualification conversion, so we directly64 // deduce T = 'const double'65 const double X::* X::* pm1 = apm; // expected-note {{instantiation of}}66}67 68namespace non_ptr_ref_cv_qual {69 template<typename Expected>70 struct ConvToT {71 template<typename T> operator T() {72 using Check = T;73 using Check = Expected;74 }75 };76 const int test_conv_to_t_1 = ConvToT<int>();77 // We intentionally deviate from [temp.deduct.conv]p4 here, and also remove78 // the top-level cv-quaifiers from A *after* removing the reference type, if79 // P is not also a reference type. This matches what other compilers are80 // doing, and is necessary to support real-world code.81 const int &test_conv_to_t_2 = ConvToT<int>();82 83 // Example code that would be broken by the standard's rule.84 struct Dest {};85 Dest d1a((ConvToT<Dest>()));86 Dest d1b = ConvToT<Dest>();87 Dest &d2 = (d1a = ConvToT<Dest>());88 89 template<typename Expected>90 struct ConvToTRef {91 template<typename T> operator T&() {92 using Check = T;93 using Check = Expected;94 }95 };96 const int test_conv_to_t_ref_1 = ConvToTRef<int>();97 const int &test_conv_to_t_ref_2 = ConvToTRef<const int>();98 99 Dest d3a((ConvToTRef<const Dest>())); // initialize the copy ctor parameter with 'const Dest&'100 Dest d3b = ConvToTRef<Dest>(); // convert to non-const T via [over.match.copy]/1.2101 Dest &d4 = (d3a = ConvToTRef<const Dest>());102 103 template<typename Expected>104 struct ConvToConstT {105 template<typename T> operator const T() {106 using Check = T;107 using Check = Expected;108 }109 };110 const int test_conv_to_const_t_1 = ConvToConstT<int>();111 const int &test_conv_to_const_t_2 = ConvToConstT<int>();112 113 template<typename Expected>114 struct ConvToConstTRef {115 template<typename T> operator const T&() {116 using Check = T;117 using Check = Expected;118 }119 };120 const int test_conv_to_const_t_ref_1 = ConvToConstTRef<int>();121 const int &test_conv_to_const_t_ref_2 = ConvToConstTRef<int>();122 123 template <typename T, int N> using Arr = T[N];124 struct ConvToArr {125 template <int N>126 operator Arr<int, N> &() {127 static_assert(N == 3, "");128 }129 };130 int (&test_conv_to_arr_1)[3] = ConvToArr(); // ok131 const int (&test_conv_to_arr_2)[3] = ConvToArr(); // ok, with qualification conversion132 133 struct ConvToConstArr {134 template <int N>135 operator const Arr<int, N> &() { // expected-note {{candidate}}136 static_assert(N == 3, "");137 }138 };139 Arr<int, 3> &test_conv_to_const_arr_1 = ConvToConstArr(); // expected-error {{no viable}}140 const Arr<int, 3> &test_conv_to_const_arr_2 = ConvToConstArr(); // ok141 142#if __cplusplus >= 201702L143 template<bool Noexcept, typename T, typename ...U> using Function = T(U...) noexcept(Noexcept);144 template<bool Noexcept> struct ConvToFunction {145 template <typename T, typename ...U> operator Function<Noexcept, T, U...>&(); // expected-note {{candidate}}146 };147 void (&fn1)(int) noexcept(false) = ConvToFunction<false>();148 void (&fn2)(int) noexcept(true) = ConvToFunction<false>(); // expected-error {{no viable}}149 void (&fn3)(int) noexcept(false) = ConvToFunction<true>();150 void (&fn4)(int) noexcept(true) = ConvToFunction<true>();151 152 struct ConvToFunctionDeducingNoexcept {153 template <bool Noexcept, typename T, typename ...U> operator Function<Noexcept, T, U...>&();154 };155 void (&fn5)(int) noexcept(false) = ConvToFunctionDeducingNoexcept();156 void (&fn6)(int) noexcept(true) = ConvToFunctionDeducingNoexcept();157#endif158}159