1 // RUN: %clang_cc1 -std=c++17 %s -verify
2 // RUN: %clang_cc1 -std=c++20 %s -verify
3 // RUN: %clang_cc1 -std=c++20 %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++20 %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
13 void operator<=>(A, A);
14 #ifdef COMPAT
15 // expected-warning@-2 {{'<=>' operator is incompatible with C++ standards before C++20}}
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++20; add a space to avoid a change in behavior}}
23 #else
24   >
25 #endif
26 #ifdef COMPAT
27 // expected-warning@-7 {{'<=>' operator is incompatible with C++ standards before C++20}}
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 )]];
74