Richard Smith | edbf597 | 2017-12-01 01:07:10 +0000 | [diff] [blame] | 1 | // RUN: %clang_cc1 -std=c++17 %s -verify |
| 2 | // RUN: %clang_cc1 -std=c++2a %s -verify |
| 3 | // RUN: %clang_cc1 -std=c++2a %s -verify -Wc++17-compat -DCOMPAT |
| 4 | // |
| 5 | // RUN: %clang_cc1 -std=c++17 %s -E -o - | FileCheck %s --check-prefix=CXX17 |
| 6 | // RUN: %clang_cc1 -std=c++2a %s -E -o - | FileCheck %s --check-prefix=CXX20 |
| 7 | |
| 8 | namespace N { |
| 9 | |
| 10 | struct A {}; |
| 11 | void operator<=(A, A); |
| 12 | #if __cplusplus > 201703L |
Richard Smith | d30b23d | 2017-12-01 02:13:10 +0000 | [diff] [blame^] | 13 | void operator<=>(A, A); |
Richard Smith | edbf597 | 2017-12-01 01:07:10 +0000 | [diff] [blame] | 14 | #ifdef COMPAT |
| 15 | // expected-warning@-2 {{'<=>' operator is incompatible with C++ standards before C++2a}} |
| 16 | #endif |
| 17 | #endif |
| 18 | |
| 19 | template<auto> struct X {}; |
| 20 | X<operator<=> |
| 21 | #if __cplusplus <= 201703L |
| 22 | // expected-warning@-2 {{'<=>' is a single token in C++2a; add a space to avoid a change in behavior}} |
| 23 | #else |
Richard Smith | d30b23d | 2017-12-01 02:13:10 +0000 | [diff] [blame^] | 24 | > |
Richard Smith | edbf597 | 2017-12-01 01:07:10 +0000 | [diff] [blame] | 25 | #endif |
| 26 | #ifdef COMPAT |
| 27 | // expected-warning@-7 {{'<=>' operator is incompatible with C++ standards before C++2a}} |
| 28 | #endif |
| 29 | x; |
| 30 | } |
| 31 | |
| 32 | // <=> can be formed by pasting other comparison operators. |
| 33 | #if __cplusplus > 201703L |
| 34 | #define STR(x) #x |
| 35 | #define STR_EXPANDED(x) STR(x) |
| 36 | #define PASTE(x, y) x ## y |
| 37 | constexpr char a[] = STR_EXPANDED(PASTE(<, =>)); |
| 38 | constexpr char b[] = STR_EXPANDED(PASTE(<=, >)); |
| 39 | static_assert(__builtin_strcmp(a, "<=>") == 0); |
| 40 | static_assert(__builtin_strcmp(b, "<=>") == 0); |
| 41 | #endif |
| 42 | |
| 43 | // -E must not accidentally form a <=> token. |
| 44 | |
| 45 | // CXX17: preprocess1: < => |
| 46 | // CXX17: preprocess2: <=> |
| 47 | // CXX17: preprocess3: < => |
| 48 | // CXX17: preprocess4: <=>= |
| 49 | // CXX17: preprocess5: <=>> |
| 50 | // CXX17: preprocess6: <=>>= |
| 51 | // CXX17: preprocess7: <=> |
| 52 | // CXX17: preprocess8: <=>= |
| 53 | // |
| 54 | // CXX20: preprocess1: < => |
| 55 | // CXX20: preprocess2: <= > |
| 56 | // CXX20: preprocess3: < => |
| 57 | // CXX20: preprocess4: <= >= |
| 58 | // CXX20: preprocess5: <= >> |
| 59 | // CXX20: preprocess6: <= >>= |
| 60 | // CXX20: preprocess7: <=> |
| 61 | // CXX20: preprocess8: <=>= |
| 62 | |
| 63 | #define ID(x) x |
| 64 | [[some_vendor::some_attribute( // expected-warning {{unknown attribute}} |
| 65 | preprocess1: ID(<)ID(=>), |
| 66 | preprocess2: ID(<=)ID(>), |
| 67 | preprocess3: ID(<)ID(=)ID(>), |
| 68 | preprocess4: ID(<=)ID(>=), |
| 69 | preprocess5: ID(<=)ID(>>), |
| 70 | preprocess6: ID(<=)ID(>>=), |
| 71 | preprocess7: ID(<=>) // expected-warning 0-1{{'<=>'}} |
| 72 | preprocess8: ID(<=>=) // expected-warning 0-1{{'<=>'}} |
| 73 | )]]; |