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];
SS32   constexpr S(const char (&r)[N]) {
33     __builtin_memcpy(a, r, N);
34     if (a[0] == 'x') throw "no";
35   }
~SS36   constexpr ~S() {
37     if (a[0] == 'y') throw "also no";
38   }
39 };
40 
41 // Check the produced contents are correct.
operator ""_str()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();
no_fallback()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);
f()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);
g()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;
XX70   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 {
YY78   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 
test()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