Richard Smith | b453ad3 | 2012-03-08 08:45:32 +0000 | [diff] [blame] | 1 | // RUN: %clang_cc1 -std=c++11 -verify %s -fms-extensions -triple x86_64-apple-darwin9.0.0 |
| 2 | |
| 3 | using size_t = decltype(sizeof(int)); |
| 4 | enum class LitKind { |
| 5 | Char, WideChar, Char16, Char32, |
| 6 | CharStr, WideStr, Char16Str, Char32Str, |
Richard Smith | 36f5cfe | 2012-03-09 08:00:36 +0000 | [diff] [blame] | 7 | Integer, Floating, Raw, Template |
Richard Smith | b453ad3 | 2012-03-08 08:45:32 +0000 | [diff] [blame] | 8 | }; |
| 9 | constexpr LitKind operator"" _kind(char p) { return LitKind::Char; } |
| 10 | constexpr LitKind operator"" _kind(wchar_t p) { return LitKind::WideChar; } |
| 11 | constexpr LitKind operator"" _kind(char16_t p) { return LitKind::Char16; } |
| 12 | constexpr LitKind operator"" _kind(char32_t p) { return LitKind::Char32; } |
| 13 | constexpr LitKind operator"" _kind(const char *p, size_t n) { return LitKind::CharStr; } |
| 14 | constexpr LitKind operator"" _kind(const wchar_t *p, size_t n) { return LitKind::WideStr; } |
| 15 | constexpr LitKind operator"" _kind(const char16_t *p, size_t n) { return LitKind::Char16Str; } |
| 16 | constexpr LitKind operator"" _kind(const char32_t *p, size_t n) { return LitKind::Char32Str; } |
| 17 | constexpr LitKind operator"" _kind(unsigned long long n) { return LitKind::Integer; } |
| 18 | constexpr LitKind operator"" _kind(long double n) { return LitKind::Floating; } |
Richard Smith | 36f5cfe | 2012-03-09 08:00:36 +0000 | [diff] [blame] | 19 | constexpr LitKind operator"" _kind2(const char *p) { return LitKind::Raw; } |
| 20 | template<char ...Cs> constexpr LitKind operator"" _kind3() { return LitKind::Template; } |
Richard Smith | b453ad3 | 2012-03-08 08:45:32 +0000 | [diff] [blame] | 21 | |
| 22 | static_assert('x'_kind == LitKind::Char, ""); |
| 23 | static_assert(L'x'_kind == LitKind::WideChar, ""); |
| 24 | static_assert(u'x'_kind == LitKind::Char16, ""); |
| 25 | static_assert(U'x'_kind == LitKind::Char32, ""); |
| 26 | static_assert("foo"_kind == LitKind::CharStr, ""); |
| 27 | static_assert(u8"foo"_kind == LitKind::CharStr, ""); |
| 28 | static_assert(L"foo"_kind == LitKind::WideStr, ""); |
| 29 | static_assert(u"foo"_kind == LitKind::Char16Str, ""); |
| 30 | static_assert(U"foo"_kind == LitKind::Char32Str, ""); |
| 31 | static_assert(194_kind == LitKind::Integer, ""); |
| 32 | static_assert(0377_kind == LitKind::Integer, ""); |
| 33 | static_assert(0x5ffc_kind == LitKind::Integer, ""); |
| 34 | static_assert(.5954_kind == LitKind::Floating, ""); |
| 35 | static_assert(1._kind == LitKind::Floating, ""); |
| 36 | static_assert(1.e-2_kind == LitKind::Floating, ""); |
| 37 | static_assert(4e6_kind == LitKind::Floating, ""); |
Richard Smith | 36f5cfe | 2012-03-09 08:00:36 +0000 | [diff] [blame] | 38 | static_assert(4e6_kind2 == LitKind::Raw, ""); |
| 39 | static_assert(4e6_kind3 == LitKind::Template, ""); |
| 40 | |
| 41 | constexpr const char *fractional_digits_impl(const char *p) { |
| 42 | return *p == '.' ? p + 1 : *p ? fractional_digits_impl(p + 1) : 0; |
| 43 | } |
| 44 | constexpr const char *operator"" _fractional_digits(const char *p) { |
| 45 | return fractional_digits_impl(p) ?: p; |
| 46 | } |
| 47 | constexpr bool streq(const char *p, const char *q) { |
| 48 | return *p == *q && (!*p || streq(p+1, q+1)); |
| 49 | } |
| 50 | |
| 51 | static_assert(streq(143.97_fractional_digits, "97"), ""); |
| 52 | static_assert(streq(0x786_fractional_digits, "0x786"), ""); |
| 53 | static_assert(streq(.4_fractional_digits, "4"), ""); |
| 54 | static_assert(streq(4._fractional_digits, ""), ""); |
| 55 | static_assert(streq(1e+97_fractional_digits, "1e+97"), ""); |
| 56 | static_assert(streq(0377_fractional_digits, "0377"), ""); |
| 57 | static_assert(streq(0377.5_fractional_digits, "5"), ""); |
| 58 | |
| 59 | int operator"" _ambiguous(char); // expected-note {{candidate}} |
| 60 | namespace N { |
| 61 | void *operator"" _ambiguous(char); // expected-note {{candidate}} |
| 62 | } |
| 63 | using namespace N; |
| 64 | int k = 'x'_ambiguous; // expected-error {{ambiguous}} |
| 65 | |
| 66 | int operator"" _deleted(unsigned long long) = delete; // expected-note {{here}} |
| 67 | int m = 42_deleted; // expected-error {{attempt to use a deleted}} |
| 68 | |
| 69 | namespace Using { |
| 70 | namespace M { |
| 71 | int operator"" _using(char); |
| 72 | } |
| 73 | int k1 = 'x'_using; // expected-error {{no matching literal operator for call to 'operator "" _using'}} |
| 74 | |
| 75 | using M::operator "" _using; |
| 76 | int k2 = 'x'_using; |
| 77 | } |
| 78 | |
| 79 | namespace AmbiguousRawTemplate { |
| 80 | int operator"" _ambig1(const char *); // expected-note {{candidate}} |
| 81 | template<char...> int operator"" _ambig1(); // expected-note {{candidate}} |
| 82 | |
| 83 | int k1 = 123_ambig1; // expected-error {{call to 'operator "" _ambig1' is ambiguous}} |
| 84 | |
| 85 | namespace Inner { |
| 86 | template<char...> int operator"" _ambig2(); // expected-note 3{{candidate}} |
| 87 | } |
| 88 | int operator"" _ambig2(const char *); // expected-note 3{{candidate}} |
| 89 | using Inner::operator"" _ambig2; |
| 90 | |
| 91 | int k2 = 123_ambig2; // expected-error {{call to 'operator "" _ambig2' is ambiguous}} |
| 92 | |
| 93 | namespace N { |
| 94 | using Inner::operator"" _ambig2; |
| 95 | |
| 96 | int k3 = 123_ambig2; // ok |
| 97 | |
| 98 | using AmbiguousRawTemplate::operator"" _ambig2; |
| 99 | |
| 100 | int k4 = 123_ambig2; // expected-error {{ambiguous}} |
| 101 | |
| 102 | namespace M { |
| 103 | |
| 104 | template<char...> int operator"" _ambig2(); |
| 105 | |
| 106 | int k5 = 123_ambig2; // ok |
| 107 | } |
| 108 | |
| 109 | int operator"" _ambig2(unsigned long long); |
| 110 | |
| 111 | int k6 = 123_ambig2; // ok |
| 112 | int k7 = 123._ambig2; // expected-error {{ambiguous}} |
| 113 | } |
| 114 | } |
| 115 | |
| 116 | constexpr unsigned mash(unsigned a) { |
| 117 | return 0x93ae27b5 * ((a >> 13) | a << 19); |
| 118 | } |
| 119 | template<typename=void> constexpr unsigned hash(unsigned a) { return a; } |
| 120 | template<char C, char...Cs> constexpr unsigned hash(unsigned a) { |
| 121 | return hash<Cs...>(mash(a ^ mash(C))); |
| 122 | } |
| 123 | template<typename T, T v> struct constant { constexpr static T value = v; }; |
| 124 | template<char...Cs> constexpr unsigned operator"" _hash() { |
| 125 | return constant<unsigned, hash<Cs...>(0)>::value; |
| 126 | } |
| 127 | static_assert(0x1234_hash == 0x103eff5e, ""); |
| 128 | static_assert(hash<'0', 'x', '1', '2', '3', '4'>(0) == 0x103eff5e, ""); |
Richard Smith | 3a5032b | 2012-03-09 08:37:16 +0000 | [diff] [blame] | 129 | |
| 130 | // Functions and literal suffixes go in separate namespaces. |
| 131 | namespace Namespace { |
| 132 | template<char...> int operator"" _x(); |
| 133 | int k = _x(); // expected-error {{undeclared identifier '_x'}} |
| 134 | |
| 135 | int _y(unsigned long long); |
| 136 | int k2 = 123_y; // expected-error {{no matching literal operator for call to 'operator "" _y'}} |
| 137 | } |
Richard Smith | a121eb3 | 2013-01-15 07:12:59 +0000 | [diff] [blame] | 138 | |
| 139 | namespace PR14950 { |
| 140 | template<...> // expected-error {{expected template parameter}} |
| 141 | int operator"" _b(); // expected-error {{no function template matches function template specialization}} |
| 142 | int main() { return 0_b; } // expected-error {{no matching literal operator for call to 'operator "" _b'}} |
| 143 | } |