r319509 - [c++2a] P0515R3: lexer support for new <=> token.
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Thu Nov 30 17:07:11 PST 2017
Author: rsmith
Date: Thu Nov 30 17:07:10 2017
New Revision: 319509
URL: http://llvm.org/viewvc/llvm-project?rev=319509&view=rev
Log:
[c++2a] P0515R3: lexer support for new <=> token.
Added:
cfe/trunk/test/Lexer/cxx2a-spaceship.cpp
Modified:
cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td
cfe/trunk/include/clang/Basic/TokenKinds.def
cfe/trunk/lib/Lex/Lexer.cpp
cfe/trunk/lib/Lex/TokenConcatenation.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td?rev=319509&r1=319508&r2=319509&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td Thu Nov 30 17:07:10 2017
@@ -31,6 +31,14 @@ def warn_cxx98_compat_less_colon_colon :
"'<::' is treated as digraph '<:' (aka '[') followed by ':' in C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
+def warn_cxx17_compat_spaceship : Warning<
+ "'<=>' operator is incompatible with C++ standards before C++2a">,
+ InGroup<CXXPre2aCompat>, DefaultIgnore;
+def warn_cxx2a_compat_spaceship : Warning<
+ "'<=>' is a single token in C++2a; "
+ "add a space to avoid a change in behavior">,
+ InGroup<CXX2aCompat>;
+
// Trigraphs.
def trigraph_ignored : Warning<"trigraph ignored">, InGroup<Trigraphs>;
def trigraph_ignored_block_comment : Warning<
Modified: cfe/trunk/include/clang/Basic/TokenKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TokenKinds.def?rev=319509&r1=319508&r2=319509&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TokenKinds.def (original)
+++ cfe/trunk/include/clang/Basic/TokenKinds.def Thu Nov 30 17:07:10 2017
@@ -194,6 +194,7 @@ PUNCTUATOR(less, "<")
PUNCTUATOR(lessless, "<<")
PUNCTUATOR(lessequal, "<=")
PUNCTUATOR(lesslessequal, "<<=")
+PUNCTUATOR(spaceship, "<=>")
PUNCTUATOR(greater, ">")
PUNCTUATOR(greatergreater, ">>")
PUNCTUATOR(greaterequal, ">=")
Modified: cfe/trunk/lib/Lex/Lexer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/Lexer.cpp?rev=319509&r1=319508&r2=319509&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/Lexer.cpp (original)
+++ cfe/trunk/lib/Lex/Lexer.cpp Thu Nov 30 17:07:10 2017
@@ -3522,6 +3522,24 @@ LexNextToken:
Kind = tok::lessless;
}
} else if (Char == '=') {
+ char After = getCharAndSize(CurPtr+SizeTmp, SizeTmp2);
+ if (After == '>') {
+ if (getLangOpts().CPlusPlus2a) {
+ if (!isLexingRawMode())
+ Diag(BufferPtr, diag::warn_cxx17_compat_spaceship);
+ CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp, Result),
+ SizeTmp2, Result);
+ Kind = tok::spaceship;
+ break;
+ }
+ // Suggest adding a space between the '<=' and the '>' to avoid a
+ // change in semantics if this turns up in C++ <=17 mode.
+ if (getLangOpts().CPlusPlus && !isLexingRawMode()) {
+ Diag(BufferPtr, diag::warn_cxx2a_compat_spaceship)
+ << FixItHint::CreateInsertion(
+ getSourceLocation(CurPtr + SizeTmp, SizeTmp2), " ");
+ }
+ }
CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
Kind = tok::lessequal;
} else if (LangOpts.Digraphs && Char == ':') { // '<:' -> '['
Modified: cfe/trunk/lib/Lex/TokenConcatenation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/TokenConcatenation.cpp?rev=319509&r1=319508&r2=319509&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/TokenConcatenation.cpp (original)
+++ cfe/trunk/lib/Lex/TokenConcatenation.cpp Thu Nov 30 17:07:10 2017
@@ -103,6 +103,10 @@ TokenConcatenation::TokenConcatenation(P
if (PP.getLangOpts().CPlusPlus1z)
TokenInfo[tok::utf8_char_constant] |= aci_custom;
+ // These tokens have custom code in C++2a mode.
+ if (PP.getLangOpts().CPlusPlus2a)
+ TokenInfo[tok::lessequal ] |= aci_custom_firstchar;
+
// These tokens change behavior if followed by an '='.
TokenInfo[tok::amp ] |= aci_avoid_equal; // &=
TokenInfo[tok::plus ] |= aci_avoid_equal; // +=
@@ -283,5 +287,7 @@ bool TokenConcatenation::AvoidConcat(con
return FirstChar == '#' || FirstChar == '@' || FirstChar == '%';
case tok::arrow: // ->*
return PP.getLangOpts().CPlusPlus && FirstChar == '*';
+ case tok::lessequal: // <=> (C++2a)
+ return PP.getLangOpts().CPlusPlus2a && FirstChar == '>';
}
}
Added: cfe/trunk/test/Lexer/cxx2a-spaceship.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Lexer/cxx2a-spaceship.cpp?rev=319509&view=auto
==============================================================================
--- cfe/trunk/test/Lexer/cxx2a-spaceship.cpp (added)
+++ cfe/trunk/test/Lexer/cxx2a-spaceship.cpp Thu Nov 30 17:07:10 2017
@@ -0,0 +1,73 @@
+// RUN: %clang_cc1 -std=c++17 %s -verify
+// RUN: %clang_cc1 -std=c++2a %s -verify
+// RUN: %clang_cc1 -std=c++2a %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++2a %s -E -o - | FileCheck %s --check-prefix=CXX20
+
+namespace N {
+
+struct A {};
+void operator<=(A, A);
+#if __cplusplus > 201703L
+void operator<=>(A, A); // expected-error {{}}
+#ifdef COMPAT
+// expected-warning at -2 {{'<=>' operator is incompatible with C++ standards before C++2a}}
+#endif
+#endif
+
+template<auto> struct X {};
+X<operator<=>
+#if __cplusplus <= 201703L
+ // expected-warning at -2 {{'<=>' is a single token in C++2a; add a space to avoid a change in behavior}}
+#else
+ > // expected-error at -4 {{}}
+#endif
+#ifdef COMPAT
+// expected-warning at -7 {{'<=>' operator is incompatible with C++ standards before C++2a}}
+#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{{'<=>'}}
+)]];
More information about the cfe-commits
mailing list