All,

This patch implements C++2a proposal P0330R2 Literal Suffixes for ptrdiff_t and size_t*.  It's not official yet but looks very likely to pass.  It is incomplete because I'm looking for some opinions. 9We also might wait 'till it actually passes).

This paper takes the direction of a language change rather than a library change through C++11 literal operators.  This was after feedback on that paper after a few iterations.

As coded in this patch, integer suffixes involving 'z' are errors in C and warnings for C++ <= 17 (in addition to the usual warning about implementation suffixes shadowing user-defined ones).

OTOH, the 'z' suffix is not currently legal - it can't break currently-correct code in any C/C++ dialect.  furthermore, I suspect the language direction was chosen to accommodate a similar addition to C20.

I'm thinking of making this feature available as an extension to all of C/C++ perhaps with appropriate pedwarn.

Opinions?

Ed Smith-Rowland

[*] http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2018/p0330r2.html


Index: gcc/c-family/c-cppbuiltin.c
===================================================================
--- gcc/c-family/c-cppbuiltin.c (revision 265343)
+++ gcc/c-family/c-cppbuiltin.c (working copy)
@@ -975,6 +975,11 @@
          cpp_define (pfile, "__cpp_structured_bindings=201606");
          cpp_define (pfile, "__cpp_variadic_using=201611");
        }
+      if (cxx_dialect > cxx17)
+       {
+         /* Set feature test macros for C++2a.  */
+         cpp_define (pfile, "__cpp_ptrdiff_t_suffix=201811");
+       }
       if (flag_concepts)
        cpp_define (pfile, "__cpp_concepts=201507");
       if (flag_tm)
Index: gcc/c-family/c-lex.c
===================================================================
--- gcc/c-family/c-lex.c        (revision 265343)
+++ gcc/c-family/c-lex.c        (working copy)
@@ -766,6 +766,14 @@
     type = ((flags & CPP_N_UNSIGNED)
            ? widest_unsigned_literal_type_node
            : widest_integer_literal_type_node);
+  else if (flags & CPP_N_PTRDIFF_T)
+    {
+      /* itk refers to fundamental types not aliased size types.  */
+      if (flags & CPP_N_UNSIGNED)
+       type = size_type_node;
+      else
+       type = ptrdiff_type_node;
+    }
   else
     {
       type = integer_types[itk];
Index: gcc/c-family/c.opt
===================================================================
--- gcc/c-family/c.opt  (revision 265343)
+++ gcc/c-family/c.opt  (working copy)
@@ -699,6 +699,10 @@
 C ObjC C++ ObjC++ CPP(cpp_warn_long_long) CppReason(CPP_W_LONG_LONG) 
Var(warn_long_long) Init(-1) Warning LangEnabledBy(C ObjC,Wc90-c99-compat)
 Do not warn about using \"long long\" when -pedantic.
 
+Wptrdiff_t-literals
+C ObjC C++ ObjC++ CPP(ptrdiff_t_literals) CppReason(CPP_W_PTRDIFF_T_LITERALS) 
Var(warn_ptrdiff_t_literals) Init(1) Warning LangEnabledBy(C ObjC C++ ObjC++)
+Warn when \"z\" or \"Z\" is used as a numeric literal suffix for C or C++yy, 
yy <= 17.
+
 Wmain
 C ObjC C++ ObjC++ Var(warn_main) Init(-1) Warning LangEnabledBy(C ObjC,Wall, 
2, 0)
 Warn about suspicious declarations of \"main\".
Index: gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C
===================================================================
--- gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C       (revision 265343)
+++ gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C       (working copy)
@@ -17,6 +17,30 @@
 operator"" ull(unsigned long long int k)  // { dg-warning "integer 
suffix|shadowed by implementation" }
 { return k; }
 
+unsigned long long int
+operator"" z(unsigned long long int k)  // { dg-warning "integer 
suffix|shadowed by implementation" }
+{ return k; }
+
+unsigned long long int
+operator"" uz(unsigned long long int k)  // { dg-warning "integer 
suffix|shadowed by implementation" }
+{ return k; }
+
+unsigned long long int
+operator"" zu(unsigned long long int k)  // { dg-warning "integer 
suffix|shadowed by implementation" }
+{ return k; }
+
+unsigned long long int
+operator"" Z(unsigned long long int k)  // { dg-warning "integer 
suffix|shadowed by implementation" }
+{ return k; }
+
+unsigned long long int
+operator"" UZ(unsigned long long int k)  // { dg-warning "integer 
suffix|shadowed by implementation" }
+{ return k; }
+
+unsigned long long int
+operator"" ZU(unsigned long long int k)  // { dg-warning "integer 
suffix|shadowed by implementation" }
+{ return k; }
+
 //  Namespaces are no hiding place.
 namespace Long
 {
@@ -37,6 +61,30 @@
 operator"" ull(unsigned long long int k)  // { dg-warning "integer 
suffix|shadowed by implementation" }
 { return k; }
 
+unsigned long long int
+operator"" z(unsigned long long int k)  // { dg-warning "integer 
suffix|shadowed by implementation" }
+{ return k; }
+
+unsigned long long int
+operator"" uz(unsigned long long int k)  // { dg-warning "integer 
suffix|shadowed by implementation" }
+{ return k; }
+
+unsigned long long int
+operator"" zu(unsigned long long int k)  // { dg-warning "integer 
suffix|shadowed by implementation" }
+{ return k; }
+
+unsigned long long int
+operator"" Z(unsigned long long int k)  // { dg-warning "integer 
suffix|shadowed by implementation" }
+{ return k; }
+
+unsigned long long int
+operator"" UZ(unsigned long long int k)  // { dg-warning "integer 
suffix|shadowed by implementation" }
+{ return k; }
+
+unsigned long long int
+operator"" ZU(unsigned long long int k)  // { dg-warning "integer 
suffix|shadowed by implementation" }
+{ return k; }
+
 }
 
 // { dg-warning "literal operator suffixes not preceded by|are reserved for 
future standardization" "reserved" { target *-*-* } 5 }
@@ -43,7 +91,20 @@
 // { dg-warning "literal operator suffixes not preceded by|are reserved for 
future standardization" "reserved" { target *-*-* } 9 }
 // { dg-warning "literal operator suffixes not preceded by|are reserved for 
future standardization" "reserved" { target *-*-* } 13 }
 // { dg-warning "literal operator suffixes not preceded by|are reserved for 
future standardization" "reserved" { target *-*-* } 17 }
+// { dg-warning "literal operator suffixes not preceded by|are reserved for 
future standardization" "reserved" { target *-*-* } 21 }
 // { dg-warning "literal operator suffixes not preceded by|are reserved for 
future standardization" "reserved" { target *-*-* } 25 }
 // { dg-warning "literal operator suffixes not preceded by|are reserved for 
future standardization" "reserved" { target *-*-* } 29 }
 // { dg-warning "literal operator suffixes not preceded by|are reserved for 
future standardization" "reserved" { target *-*-* } 33 }
 // { dg-warning "literal operator suffixes not preceded by|are reserved for 
future standardization" "reserved" { target *-*-* } 37 }
+// { dg-warning "literal operator suffixes not preceded by|are reserved for 
future standardization" "reserved" { target *-*-* } 41 }
+
+// { dg-warning "literal operator suffixes not preceded by|are reserved for 
future standardization" "reserved" { target *-*-* } 49 }
+// { dg-warning "literal operator suffixes not preceded by|are reserved for 
future standardization" "reserved" { target *-*-* } 53 }
+// { dg-warning "literal operator suffixes not preceded by|are reserved for 
future standardization" "reserved" { target *-*-* } 57 }
+// { dg-warning "literal operator suffixes not preceded by|are reserved for 
future standardization" "reserved" { target *-*-* } 61 }
+// { dg-warning "literal operator suffixes not preceded by|are reserved for 
future standardization" "reserved" { target *-*-* } 65 }
+// { dg-warning "literal operator suffixes not preceded by|are reserved for 
future standardization" "reserved" { target *-*-* } 69 }
+// { dg-warning "literal operator suffixes not preceded by|are reserved for 
future standardization" "reserved" { target *-*-* } 73 }
+// { dg-warning "literal operator suffixes not preceded by|are reserved for 
future standardization" "reserved" { target *-*-* } 77 }
+// { dg-warning "literal operator suffixes not preceded by|are reserved for 
future standardization" "reserved" { target *-*-* } 81 }
+// { dg-warning "literal operator suffixes not preceded by|are reserved for 
future standardization" "reserved" { target *-*-* } 85 }
Index: gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C
===================================================================
--- gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C     (revision 265343)
+++ gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C     (working copy)
@@ -445,3 +445,11 @@
 #else
 #  error "__has_cpp_attribute"
 #endif
+
+// C++2a features:
+
+#ifndef __cpp_ptrdiff_t_suffix
+#  error "__cpp_ptrdiff_t_suffix"
+#elif __cpp_ptrdiff_t_suffix != 201811
+#  error "__cpp_ptrdiff_t_suffix != 201811"
+#endif
Index: libcpp/expr.c
===================================================================
--- libcpp/expr.c       (revision 265343)
+++ libcpp/expr.c       (working copy)
@@ -315,13 +315,18 @@
 interpret_int_suffix (cpp_reader *pfile, const uchar *s, size_t len)
 {
   size_t orig_len = len;
-  size_t u, l, i;
+  size_t u, l, i, z;
 
-  u = l = i = 0;
+  /* So far, "ull" is the longest suffix.  */
+  if (len > 3)
+    return 0;
 
+  u = l = i = z = 0;
+
   while (len--)
     switch (s[len])
       {
+      case 'z': case 'Z':      z++; break;
       case 'u': case 'U':      u++; break;
       case 'i': case 'I':
       case 'j': case 'J':      i++; break;
@@ -334,9 +339,17 @@
        return 0;
       }
 
-  if (l > 2 || u > 1 || i > 1)
+  if (l > 2 || u > 1 || i > 1 || z > 1)
     return 0;
 
+  if (z)
+    {
+      if (l > 0 || i > 0)
+       return 0;
+      if (!CPP_OPTION (pfile, cplusplus))
+       return 0;
+    }
+
   if (i)
     {
       if (!CPP_OPTION (pfile, ext_numeric_literals))
@@ -354,7 +367,8 @@
   return ((i ? CPP_N_IMAGINARY : 0)
          | (u ? CPP_N_UNSIGNED : 0)
          | ((l == 0) ? CPP_N_SMALL
-            : (l == 1) ? CPP_N_MEDIUM : CPP_N_LARGE));
+            : (l == 1) ? CPP_N_MEDIUM : CPP_N_LARGE)
+         | (z ? (CPP_N_PTRDIFF_T | CPP_N_LARGE) : 0));
 }
 
 /* Return the classification flags for an int suffix.  */
@@ -800,6 +814,16 @@
                                      virtual_location, 0, message);
         }
 
+      if ((result & CPP_N_PTRDIFF_T) == CPP_N_PTRDIFF_T
+         && !CPP_OPTION (pfile, ptrdiff_t_literals))
+       {
+          const char *message = (result & CPP_N_UNSIGNED) == CPP_N_UNSIGNED
+                               ? N_("use of C++2a size_t integer constant")
+                               : N_("use of C++2a ptrdiff_t integer constant");
+            cpp_warning_with_line (pfile, CPP_W_PTRDIFF_T_LITERALS,
+                                  virtual_location, 0, message);
+       }
+
       result |= CPP_N_INTEGER;
     }
 
Index: libcpp/include/cpplib.h
===================================================================
--- libcpp/include/cpplib.h     (revision 265343)
+++ libcpp/include/cpplib.h     (working copy)
@@ -481,6 +481,9 @@
   /* Nonzero for C++2a __VA_OPT__ feature.  */
   unsigned char va_opt;
 
+  /* Nonzero for C++2a ptrdiff_t and size_t literals.  */
+  unsigned char ptrdiff_t_literals;
+
   /* Holds the name of the target (execution) character set.  */
   const char *narrow_charset;
 
@@ -596,6 +599,7 @@
   CPP_W_INVALID_PCH,
   CPP_W_WARNING_DIRECTIVE,
   CPP_W_LITERAL_SUFFIX,
+  CPP_W_PTRDIFF_T_LITERALS,
   CPP_W_DATE_TIME,
   CPP_W_PEDANTIC,
   CPP_W_C90_C99_COMPAT,
@@ -1115,6 +1119,8 @@
 
 #define CPP_N_USERDEF  0x1000000 /* C++0x user-defined literal.  */
 
+#define CPP_N_PTRDIFF_T        0x2000000 /* C++2a size_t or ptrdiff_t  */
+
 #define CPP_N_WIDTH_FLOATN_NX  0xF0000000 /* _FloatN / _FloatNx value
                                              of N, divided by 16.  */
 #define CPP_FLOATN_SHIFT       24
Index: libcpp/init.c
===================================================================
--- libcpp/init.c       (revision 265343)
+++ libcpp/init.c       (working copy)
@@ -92,32 +92,33 @@
   char trigraphs;
   char utf8_char_literals;
   char va_opt;
+  char ptrdiff_t_literals;
 };
 
 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 },
-  /* GNUC2X   */  { 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 },
-  /* STDC2X   */  { 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 pdtlit */
+  /* 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 },
+  /* GNUC2X   */  { 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 },
+  /* STDC2X   */  { 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.  */
@@ -143,6 +144,7 @@
   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, ptrdiff_t_literals)        = l->ptrdiff_t_literals;
 }
 
 /* Initialize library global state.  */
Index: libstdc++-v3/include/bits/parse_numbers.h
===================================================================
--- libstdc++-v3/include/bits/parse_numbers.h   (revision 265343)
+++ libstdc++-v3/include/bits/parse_numbers.h   (working copy)
@@ -193,7 +193,8 @@
                                  __valid_digit::value ? _Pow / _Base : _Pow,
                                  _Digs...>;
       using type = __ull_constant<_Pow * __digit::value + __next::type::value>;
-      static_assert((type::value / _Pow) == __digit::value,
+      static_assert(!__valid_digit::value
+                   || (type::value / _Pow) == __digit::value,
                    "integer literal does not fit in unsigned long long");
     };
 
Index: libstdc++-v3/testsuite/20_util/duration/literals/69905.cc
===================================================================
--- libstdc++-v3/testsuite/20_util/duration/literals/69905.cc   (nonexistent)
+++ libstdc++-v3/testsuite/20_util/duration/literals/69905.cc   (working copy)
@@ -0,0 +1,25 @@
+// Copyright (C) 2016 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do compile { target c++14 } }
+
+// PR libstdc++/69905
+
+#include <chrono>
+
+using namespace std::chrono_literals;
+auto time = 01'23s;

Reply via email to