|  | // RUN: %clang_cc1 -std=c++17 %s -verify | 
|  | // RUN: %clang_cc1 -std=c++20 %s -verify | 
|  | // RUN: %clang_cc1 -std=c++20 %s -verify -Wc++17-compat -DCOMPAT | 
|  | // | 
|  | // RUN: %clang_cc1 -std=c++17 %s -E -o - | FileCheck %s --check-prefix=CXX17 | 
|  | // RUN: %clang_cc1 -std=c++20 %s -E -o - | FileCheck %s --check-prefix=CXX20 | 
|  |  | 
|  | namespace N { | 
|  |  | 
|  | struct A {}; | 
|  | void operator<=(A, A); | 
|  | #if __cplusplus > 201703L | 
|  | void operator<=>(A, A); | 
|  | #ifdef COMPAT | 
|  | // expected-warning@-2 {{'<=>' operator is incompatible with C++ standards before C++20}} | 
|  | #endif | 
|  | #endif | 
|  |  | 
|  | template<auto> struct X {}; | 
|  | X<operator<=> | 
|  | #if __cplusplus <= 201703L | 
|  | // expected-warning@-2 {{'<=>' is a single token in C++20; add a space to avoid a change in behavior}} | 
|  | #else | 
|  | > | 
|  | #endif | 
|  | #ifdef COMPAT | 
|  | // expected-warning@-7 {{'<=>' operator is incompatible with C++ standards before C++20}} | 
|  | #endif | 
|  | x; | 
|  | } | 
|  |  | 
|  | // <=> can be formed by pasting other comparison operators. | 
|  | #if __cplusplus > 201703L | 
|  | #define STR(x) #x | 
|  | #define STR_EXPANDED(x) STR(x) | 
|  | #define PASTE(x, y) x ## y | 
|  | constexpr char a[] = STR_EXPANDED(PASTE(<, =>)); | 
|  | constexpr char b[] = STR_EXPANDED(PASTE(<=, >)); | 
|  | static_assert(__builtin_strcmp(a, "<=>") == 0); | 
|  | static_assert(__builtin_strcmp(b, "<=>") == 0); | 
|  | #endif | 
|  |  | 
|  | // -E must not accidentally form a <=> token. | 
|  |  | 
|  | // CXX17: preprocess1: < => | 
|  | // CXX17: preprocess2: <=> | 
|  | // CXX17: preprocess3: < => | 
|  | // CXX17: preprocess4: <=>= | 
|  | // CXX17: preprocess5: <=>> | 
|  | // CXX17: preprocess6: <=>>= | 
|  | // CXX17: preprocess7: <=> | 
|  | // CXX17: preprocess8: <=>= | 
|  | // | 
|  | // CXX20: preprocess1: < => | 
|  | // CXX20: preprocess2: <= > | 
|  | // CXX20: preprocess3: < => | 
|  | // CXX20: preprocess4: <= >= | 
|  | // CXX20: preprocess5: <= >> | 
|  | // CXX20: preprocess6: <= >>= | 
|  | // CXX20: preprocess7: <=> | 
|  | // CXX20: preprocess8: <=>= | 
|  |  | 
|  | #define ID(x) x | 
|  | [[some_vendor::some_attribute( // expected-warning {{unknown attribute}} | 
|  | preprocess1: ID(<)ID(=>), | 
|  | preprocess2: ID(<=)ID(>), | 
|  | preprocess3: ID(<)ID(=)ID(>), | 
|  | preprocess4: ID(<=)ID(>=), | 
|  | preprocess5: ID(<=)ID(>>), | 
|  | preprocess6: ID(<=)ID(>>=), | 
|  | preprocess7: ID(<=>) // expected-warning 0-1{{'<=>'}} | 
|  | preprocess8: ID(<=>=) // expected-warning 0-1{{'<=>'}} | 
|  | )]]; |