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