On Thu, Jan 11, 2018 at 02:06:06PM +0000, Joseph Myers wrote:
> On Thu, 11 Jan 2018, David Brown wrote:
> 
> > Maybe it is easier to say "gcc supports <=> in C++2a, and as an
> > extension also supports it in C and C++ of any standard" ?  I don't
> > believe there is any way for it to conflict with existing valid code, so
> > it would do no harm as a gcc extension like that - and C users can then
> > use it too.
> 
> As per previous IRC discussion, changing the lexing to support this 
> pp-token can break valid code in previous standards, e.g. code 
> concatenating <=> and >, then stringizing the result (the C++ proposal for 
> adding this feature also notes some obscure cases where the character 
> sequence <=> can actually occur as tokens, not just pp-tokens - 
> "X<&Y::operator<=>" and "x+&operator<=>y" - so of course patches adding 
> this feature should add testcases using such cases with older -std= 
> options).
> 
> Changes to cpp_avoid_paste (so that preprocessed output does not put a 
> pp-token starting with > immediately after <=) do not need to be 
> conditional on the standard version, however.

Here is a patch that attempts to implement this (in libcpp + gcc/testsuite
only so far).
It needs to be parsed and handled in the C++ FE obviously, which is missing.

2018-08-30  Jakub Jelinek  <ja...@redhat.com>

        P0515R3 - Consistent comparison
        * include/cpplib.h (TTYPE_TABLE): Add CPP_SPACESHIP.
        (struct cpp_options): Add spaceship field.
        * init.c (struct lang_flags): Add spaceship field.
        (lang_defaults): Add spaceship column.
        (cpp_set_lang): Initialize CPP_OPTION (pfile, spaceship).
        * lex.c (_cpp_lex_direct): Lex CPP_SPACESHIP.
        (cpp_avoid_paste): Avoid pasting <= with >.

        * c-c++-common/cpp/spaceship-1.c: New test.
        * g++.dg/cpp/spaceship-1.C: New test.

--- libcpp/include/cpplib.h.jj  2018-08-26 22:43:12.510939169 +0200
+++ libcpp/include/cpplib.h     2018-08-30 18:55:55.483035882 +0200
@@ -91,6 +91,7 @@ struct _cpp_file;
   OP(XOR_EQ,           "^=")                                           \
   OP(RSHIFT_EQ,                ">>=")                                          
\
   OP(LSHIFT_EQ,                "<<=")                                          
\
+  OP(SPACESHIP,                "<=>")                                          
\
   /* Digraphs together, beginning with CPP_FIRST_DIGRAPH.  */          \
   OP(HASH,             "#")    /* digraphs */                          \
   OP(PASTE,            "##")                                           \
@@ -480,6 +481,9 @@ struct cpp_options
   /* Nonzero for C++2a __VA_OPT__ feature.  */
   unsigned char va_opt;
 
+  /* Nonzero for C++2a <=> operator.  */
+  unsigned char spaceship;
+
   /* Holds the name of the target (execution) character set.  */
   const char *narrow_charset;
 
--- libcpp/init.c.jj    2018-08-26 22:43:13.760918150 +0200
+++ libcpp/init.c       2018-08-30 18:57:41.479297007 +0200
@@ -92,30 +92,31 @@ struct lang_flags
   char trigraphs;
   char utf8_char_literals;
   char va_opt;
+  char spaceship;
 };
 
 static const struct lang_flags lang_defaults[] =
-{ /*              c99 c++ xnum xid c11 std digr ulit rlit udlit bincst digsep 
trig u8chlit vaopt */
-  /* GNUC89   */  { 0,  0,  1,  0,  0,  0,  1,   0,   0,   0,    0,     0,     
0,   0,      1 },
-  /* GNUC99   */  { 1,  0,  1,  1,  0,  0,  1,   1,   1,   0,    0,     0,     
0,   0,      1 },
-  /* GNUC11   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    0,     0,     
0,   0,      1 },
-  /* GNUC17   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    0,     0,     
0,   0,      1 },
-  /* STDC89   */  { 0,  0,  0,  0,  0,  1,  0,   0,   0,   0,    0,     0,     
1,   0,      0 },
-  /* STDC94   */  { 0,  0,  0,  0,  0,  1,  1,   0,   0,   0,    0,     0,     
1,   0,      0 },
-  /* STDC99   */  { 1,  0,  1,  1,  0,  1,  1,   0,   0,   0,    0,     0,     
1,   0,      0 },
-  /* STDC11   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    0,     0,     
1,   0,      0 },
-  /* STDC17   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    0,     0,     
1,   0,      0 },
-  /* GNUCXX   */  { 0,  1,  1,  1,  0,  0,  1,   0,   0,   0,    0,     0,     
0,   0,      1 },
-  /* CXX98    */  { 0,  1,  0,  1,  0,  1,  1,   0,   0,   0,    0,     0,     
1,   0,      0 },
-  /* GNUCXX11 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    0,     0,     
0,   0,      1 },
-  /* CXX11    */  { 1,  1,  0,  1,  1,  1,  1,   1,   1,   1,    0,     0,     
1,   0,      0 },
-  /* GNUCXX14 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     
0,   0,      1 },
-  /* CXX14    */  { 1,  1,  0,  1,  1,  1,  1,   1,   1,   1,    1,     1,     
1,   0,      0 },
-  /* GNUCXX17 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     
0,   1,      1 },
-  /* CXX17    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     
0,   1,      0 },
-  /* GNUCXX2A */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     
0,   1,      1 },
-  /* CXX2A    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     
0,   1,      1 },
-  /* ASM      */  { 0,  0,  1,  0,  0,  0,  0,   0,   0,   0,    0,     0,     
0,   0,      0 }
+{ /*              c99 c++ xnum xid c11 std digr ulit rlit udlit bincst digsep 
trig u8chlit vaopt spaceship */
+  /* GNUC89   */  { 0,  0,  1,  0,  0,  0,  1,   0,   0,   0,    0,     0,     
0,   0,      1,   0 },
+  /* GNUC99   */  { 1,  0,  1,  1,  0,  0,  1,   1,   1,   0,    0,     0,     
0,   0,      1,   0 },
+  /* GNUC11   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    0,     0,     
0,   0,      1,   0 },
+  /* GNUC17   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    0,     0,     
0,   0,      1,   0 },
+  /* STDC89   */  { 0,  0,  0,  0,  0,  1,  0,   0,   0,   0,    0,     0,     
1,   0,      0,   0 },
+  /* STDC94   */  { 0,  0,  0,  0,  0,  1,  1,   0,   0,   0,    0,     0,     
1,   0,      0,   0 },
+  /* STDC99   */  { 1,  0,  1,  1,  0,  1,  1,   0,   0,   0,    0,     0,     
1,   0,      0,   0 },
+  /* STDC11   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    0,     0,     
1,   0,      0,   0 },
+  /* STDC17   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    0,     0,     
1,   0,      0,   0 },
+  /* GNUCXX   */  { 0,  1,  1,  1,  0,  0,  1,   0,   0,   0,    0,     0,     
0,   0,      1,   0 },
+  /* CXX98    */  { 0,  1,  0,  1,  0,  1,  1,   0,   0,   0,    0,     0,     
1,   0,      0,   0 },
+  /* GNUCXX11 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    0,     0,     
0,   0,      1,   0 },
+  /* CXX11    */  { 1,  1,  0,  1,  1,  1,  1,   1,   1,   1,    0,     0,     
1,   0,      0,   0 },
+  /* GNUCXX14 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     
0,   0,      1,   0 },
+  /* CXX14    */  { 1,  1,  0,  1,  1,  1,  1,   1,   1,   1,    1,     1,     
1,   0,      0,   0 },
+  /* GNUCXX17 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     
0,   1,      1,   0 },
+  /* CXX17    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     
0,   1,      0,   0 },
+  /* GNUCXX2A */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     
0,   1,      1,   1 },
+  /* CXX2A    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     
0,   1,      1,   1 },
+  /* ASM      */  { 0,  0,  1,  0,  0,  0,  0,   0,   0,   0,    0,     0,     
0,   0,      0,   0 }
 };
 
 /* Sets internal flags correctly for a given language.  */
@@ -141,6 +142,7 @@ cpp_set_lang (cpp_reader *pfile, enum c_
   CPP_OPTION (pfile, trigraphs)                         = l->trigraphs;
   CPP_OPTION (pfile, utf8_char_literals)        = l->utf8_char_literals;
   CPP_OPTION (pfile, va_opt)                    = l->va_opt;
+  CPP_OPTION (pfile, spaceship)                         = l->spaceship;
 }
 
 /* Initialize library global state.  */
--- libcpp/lex.c.jj     2018-08-26 22:43:14.784900935 +0200
+++ libcpp/lex.c        2018-08-30 19:02:43.261340974 +0200
@@ -2963,7 +2963,11 @@ _cpp_lex_direct (cpp_reader *pfile)
 
       result->type = CPP_LESS;
       if (*buffer->cur == '=')
-       buffer->cur++, result->type = CPP_LESS_EQ;
+       {
+         buffer->cur++, result->type = CPP_LESS_EQ;
+         if (*buffer->cur == '>' && CPP_OPTION (pfile, spaceship))
+           buffer->cur++, result->type = CPP_SPACESHIP;
+       }
       else if (*buffer->cur == '<')
        {
          buffer->cur++;
@@ -3466,6 +3470,7 @@ cpp_avoid_paste (cpp_reader *pfile, cons
                                || (CPP_OPTION (pfile, objc)
                                    && token1->val.str.text[0] == '@'
                                    && (b == CPP_NAME || b == CPP_STRING)));
+    case CPP_LESS_EQ:  return c == '>';
     case CPP_STRING:
     case CPP_WSTRING:
     case CPP_UTF8STRING:
--- gcc/testsuite/c-c++-common/cpp/spaceship-1.c.jj     2018-08-30 
19:41:13.762257530 +0200
+++ gcc/testsuite/c-c++-common/cpp/spaceship-1.c        2018-08-30 
19:49:09.338386388 +0200
@@ -0,0 +1,6 @@
+/* { dg-do preprocess } */
+/* { dg-options "-std=c11" { target c } } */
+
+#define A(x, y) x##y
+A(<=, >)       /* { dg-error "does not give a valid preprocessing token" "" { 
target { ! c++2a } } } */
+A(<=>, >)      /* { dg-error "does not give a valid preprocessing token" "" { 
target c++2a } } */
--- gcc/testsuite/g++.dg/cpp/spaceship-1.C.jj   2018-08-30 19:58:56.152695104 
+0200
+++ gcc/testsuite/g++.dg/cpp/spaceship-1.C      2018-08-30 19:59:20.802288063 
+0200
@@ -0,0 +1,8 @@
+// { dg-do compile { target c++17_down } }
+// { dg-options "-Wno-pointer-arith" }
+
+struct X {};
+bool operator<= (X, X);
+template<bool (X, X)> struct Y {};
+Y<&operator<=> y;
+bool foo (bool (*fn) (X, X), int n) { return n+&operator<=> fn; }


        Jakub

Reply via email to