1 // RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s -fcxx-exceptions -triple=x86_64-linux-gnu 2 // RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s -fcxx-exceptions -triple=x86_64-linux-gnu 3 4 using size_t = decltype(sizeof(int)); 5 6 int &operator ""_x1 (const char *); 7 double &operator ""_x1 (const char *, size_t); 8 double &i1 = "foo"_x1; 9 #if __cplusplus >= 202002L 10 using char8 = float; 11 float &operator ""_x1 (const char8_t *, size_t); 12 #else 13 using char8 = double; 14 #endif 15 char8 &i2 = u8"foo"_x1; 16 double &i3 = L"foo"_x1; // expected-error {{no matching literal operator for call to 'operator""_x1' with arguments of types 'const wchar_t *' and 'unsigned long'}} 17 18 char &operator ""_x1(const wchar_t *, size_t); 19 char &i4 = L"foo"_x1; // ok 20 double &i5 = R"(foo)"_x1; // ok 21 char8 &i6 = u\ 22 8\ 23 R\ 24 "(foo)"\ 25 _\ 26 x\ 27 1; // ok 28 29 #if __cplusplus >= 202002L 30 template<int N> struct S { 31 char a[N]; 32 constexpr S(const char (&r)[N]) { 33 __builtin_memcpy(a, r, N); 34 if (a[0] == 'x') throw "no"; 35 } 36 constexpr ~S() { 37 if (a[0] == 'y') throw "also no"; 38 } 39 }; 40 41 // Check the produced contents are correct. 42 template<S s> constexpr const decltype(s) &operator""_str() { return s; } 43 static_assert(__builtin_strcmp("hello world"_str.a, "hello world") == 0); 44 45 template<S> float &operator""_s(); 46 void no_fallback() { 47 "hello"_s; 48 // FIXME: It'd be useful to explain what candidates were found and why they didn't work. 49 "xyzzy"_s; // expected-error {{no matching literal operator for call to 'operator""_s' with arguments of types 'const char *' and 'unsigned long', and no matching literal operator template}} 50 "yello"_s; // expected-error {{no matching literal operator for call to 'operator""_s' with arguments of types 'const char *' and 'unsigned long', and no matching literal operator template}} 51 } 52 53 double &operator""_s(const char*, size_t); 54 void f() { 55 float &a = "foo"_s; 56 double &b = "xar"_s; 57 double &c = "yar"_s; 58 } 59 60 template<S<4>> float &operator""_t(); 61 double &operator""_t(const char*, size_t); 62 void g() { 63 double &a = "fo"_t; 64 float &b = "foo"_t; 65 double &c = "fooo"_t; 66 } 67 68 template<int N> struct X { 69 static constexpr int size = N; 70 constexpr X(const char (&r)[N]) {} 71 }; 72 template<X x> requires (x.size == 4) // expected-note {{because 'X<5>{}.size == 4' (5 == 4) evaluated to false}} 73 void operator""_x(); // expected-note {{constraints not satisfied}} 74 void operator""_x(const char*, size_t) = delete; 75 76 template<int N> requires (N == 4) 77 struct Y { 78 constexpr Y(const char (&r)[N]) {} 79 }; 80 template<Y> float &operator""_y(); 81 void operator""_y(const char*, size_t) = delete; // expected-note {{deleted here}} 82 83 void test() { 84 "foo"_x; 85 "foo"_y; 86 87 // We only check the template argument itself for validity, not the whole 88 // call, when deciding whether to use the template or non-template form. 89 "fooo"_x; // expected-error {{no matching function}} 90 "fooo"_y; // expected-error {{deleted function}} 91 } 92 #endif 93