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