Clang Project

clang_source_code/test/Lexer/cxx2a-spaceship.cpp
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
8namespace N {
9
10struct A {};
11void operator<=(A, A);
12#if __cplusplus > 201703L
13void operator<=>(A, A);
14#ifdef COMPAT
15// expected-warning@-2 {{'<=>' operator is incompatible with C++ standards before C++2a}}
16#endif
17#endif
18
19template<auto> struct X {};
20X<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
24  >
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
37constexpr char a[] = STR_EXPANDED(PASTE(<, =>));
38constexpr char b[] = STR_EXPANDED(PASTE(<=, >));
39static_assert(__builtin_strcmp(a, "<=>") == 0);
40static_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}}
65preprocess1: ID(<)ID(=>),
66preprocess2: ID(<=)ID(>),
67preprocess3: ID(<)ID(=)ID(>),
68preprocess4: ID(<=)ID(>=),
69preprocess5: ID(<=)ID(>>),
70preprocess6: ID(<=)ID(>>=),
71preprocess7: ID(<=>) // expected-warning 0-1{{'<=>'}}
72preprocess8: ID(<=>=) // expected-warning 0-1{{'<=>'}}
73)]];
74