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
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
11 void operator<=(A
, A
);
12 #if __cplusplus > 201703L
13 void operator<=>(A
, A
);
15 // expected-warning@-2 {{'<=>' operator is incompatible with C++ standards before C++20}}
19 template<auto> struct X
{};
21 #if __cplusplus <= 201703L
22 // expected-warning@-2 {{'<=>' is a single token in C++20; add a space to avoid a change in behavior}}
27 // expected-warning@-7 {{'<=>' operator is incompatible with C++ standards before C++20}}
32 // <=> can be formed by pasting other comparison operators.
33 #if __cplusplus > 201703L
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);
43 // -E must not accidentally form a <=> token.
45 // CXX17: preprocess1: < =>
46 // CXX17: preprocess2: <=>
47 // CXX17: preprocess3: < =>
48 // CXX17: preprocess4: <=>=
49 // CXX17: preprocess5: <=>>
50 // CXX17: preprocess6: <=>>=
51 // CXX17: preprocess7: <=>
52 // CXX17: preprocess8: <=>=
54 // CXX20: preprocess1: < =>
55 // CXX20: preprocess2: <= >
56 // CXX20: preprocess3: < =>
57 // CXX20: preprocess4: <= >=
58 // CXX20: preprocess5: <= >>
59 // CXX20: preprocess6: <= >>=
60 // CXX20: preprocess7: <=>
61 // CXX20: preprocess8: <=>=
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{{'<=>'}}