diff mbox series

[[C++] ] Implement C++2a P0330R2 - Literal Suffixes for ptrdiff_t and size_t

Message ID 7fe5ef20-0fd5-605a-408f-8894d2fa7a73@verizon.net
State New
Headers show
Series [[C++] ] Implement C++2a P0330R2 - Literal Suffixes for ptrdiff_t and size_t | expand

Commit Message

Ed Smith-Rowland Oct. 21, 2018, 8:39 p.m. UTC
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

Comments

Jason Merrill Oct. 22, 2018, 10:15 p.m. UTC | #1
On 10/21/18 4:39 PM, Ed Smith-Rowland wrote:
> 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. (We also 
> might wait 'till it actually passes).

I don't mind putting it in before it passes so long as you keep track of 
the proposal's progress -- I just discovered that the string UDL 
template proposal we implemented for C++14 wasn't actually accepted, so 
we need to pedwarn about it.

> 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?

That seems reasonable to me, but Joseph will need to weigh in about C.

Jason
Joseph Myers Oct. 22, 2018, 11:23 p.m. UTC | #2
On Mon, 22 Oct 2018, Jason Merrill wrote:

> > I'm thinking of making this feature available as an extension to all of
> > C/C++ perhaps with appropriate pedwarn.
> > 
> > Opinions?
> 
> That seems reasonable to me, but Joseph will need to weigh in about C.

A C extension would seem reasonable, if documented as such in the manual 
(and with pedwarns tested in the testsuite, etc.).  (The patch is also 
missing invoke.texi updates for the new command-line option, in any case.)
Florian Weimer Oct. 23, 2018, 9:22 a.m. UTC | #3
* Ed Smith-Rowland:

> 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).

So a plain z would denote ptrdiff_t, and size_t would be zu?  That is
very confusing.

Why is this not consistent with %td, %zd and %zu?  I would have expected
t for ptrdiff_t, zu for size_t, and z for ssize_t.

Thanks,
Florian
Jakub Jelinek Jan. 27, 2021, 8:32 p.m. UTC | #4
On Sun, Oct 21, 2018 at 04:39:30PM -0400, Ed Smith-Rowland wrote:
> 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.

GCC now supports -std=c++2b and -std=gnu++2b, are you going to update your
patch against it (and change for z/Z standing for ssize_t rather than
ptrdiff_t), plus incorporate the feedback from Joseph and Jason?

	Jakub
Ed Smith-Rowland Jan. 27, 2021, 11:23 p.m. UTC | #5
On 1/27/21 3:32 PM, Jakub Jelinek wrote:
> On Sun, Oct 21, 2018 at 04:39:30PM -0400, Ed Smith-Rowland wrote:
>> 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.
> GCC now supports -std=c++2b and -std=gnu++2b, are you going to update your
> patch against it (and change for z/Z standing for ssize_t rather than
> ptrdiff_t), plus incorporate the feedback from Joseph and Jason?
>
> 	Jakub
>
I'm actually working on it now!
Ed Smith-Rowland Jan. 30, 2021, 11:22 p.m. UTC | #6
On 1/27/21 3:32 PM, Jakub Jelinek wrote:
> On Sun, Oct 21, 2018 at 04:39:30PM -0400, Ed Smith-Rowland wrote:
>> 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.
> GCC now supports -std=c++2b and -std=gnu++2b, are you going to update your
> patch against it (and change for z/Z standing for ssize_t rather than
> ptrdiff_t), plus incorporate the feedback from Joseph and Jason?
>
> 	Jakub
>
Here is a rebased patch that is a bit leaner than the original.

Since I chose to be conservative in applying this just to C++23 I'm not 
adding this to C or t earlier versions of C++ as extensions. We can add 
that if people really want, maybe in stage 1.

The compat warning for C++ < 23 is not optional. since the suffixes are 
not preceded by '-' I don't hav much sympathy if people tried to make a 
literal 'z' operator. Which is the only reason I can see for a warning 
suppression.

Built and tested on x86_64.

Ok?
diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
index dca6815a876..48dec21d4b4 100644
--- a/gcc/c-family/c-cppbuiltin.c
+++ b/gcc/c-family/c-cppbuiltin.c
@@ -1025,6 +1025,11 @@ c_cpp_builtins (cpp_reader *pfile)
 	  cpp_define (pfile, "__cpp_aggregate_paren_init=201902L");
 	  cpp_define (pfile, "__cpp_using_enum=201907L");
 	}
+      if (cxx_dialect > cxx20)
+	{
+	  /* Set feature test macros for C++23.  */
+	  cpp_define (pfile, "__cpp_size_t_suffix=202006L");
+	}
       if (flag_concepts)
         {
 	  if (cxx_dialect >= cxx20)
diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c
index fe40a0f728b..02e397bb0c0 100644
--- a/gcc/c-family/c-lex.c
+++ b/gcc/c-family/c-lex.c
@@ -834,6 +834,14 @@ interpret_integer (const cpp_token *token, unsigned int flags,
     type = ((flags & CPP_N_UNSIGNED)
 	    ? widest_unsigned_literal_type_node
 	    : widest_integer_literal_type_node);
+  else if (flags & CPP_N_SIZE_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];
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C
index fdddd8d84ed..a30ec0f4f7e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C
@@ -17,6 +17,30 @@ unsigned long long int
 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,13 +61,50 @@ unsigned long long int
 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 }
 // { 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 }
diff --git a/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C b/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C
new file mode 100644
index 00000000000..94e08a4896c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C
@@ -0,0 +1,549 @@
+// { dg-options "-std=c++2b -I${srcdir}/g++.dg/cpp1y -I${srcdir}/g++.dg/cpp1y/testinc" }
+
+//  C++98 features:
+
+#ifndef __cpp_rtti
+#  error "__cpp_rtti"
+#elif  __cpp_rtti != 199711
+#  error "__cpp_rtti != 199711"
+#endif
+
+#ifndef __cpp_exceptions
+#  error "__cpp_exceptions"
+#elif  __cpp_exceptions != 199711
+#  error "__cpp_exceptions != 199711"
+#endif
+
+//  C++11 features:
+
+#ifndef __cpp_raw_strings
+#  error "__cpp_raw_strings"
+#elif __cpp_raw_strings != 200710
+#  error "__cpp_raw_strings != 200710"
+#endif
+
+#ifndef __cpp_unicode_literals
+#  error "__cpp_unicode_literals"
+#elif __cpp_unicode_literals != 200710
+#  error "__cpp_unicode_literals != 200710"
+#endif
+
+#ifndef __cpp_user_defined_literals
+#  error "__cpp_user_defined_literals"
+#elif __cpp_user_defined_literals != 200809
+#  error "__cpp_user_defined_literals != 200809"
+#endif
+
+#ifndef __cpp_lambdas
+#  error "__cpp_lambdas"
+#elif __cpp_lambdas != 200907
+#  error "__cpp_lambdas != 200907"
+#endif
+
+#ifndef __cpp_range_based_for
+#  error "__cpp_range_based_for"
+#elif __cpp_range_based_for != 201603
+#  error "__cpp_range_based_for != 201603"
+#endif
+
+#ifndef __cpp_decltype
+#  error "__cpp_decltype"
+#elif __cpp_decltype != 200707
+#  error "__cpp_decltype != 200707"
+#endif
+
+#ifndef __cpp_attributes
+#  error "__cpp_attributes"
+#elif __cpp_attributes != 200809
+#  error "__cpp_attributes != 200809"
+#endif
+
+#ifndef __cpp_rvalue_references
+#  error "__cpp_rvalue_references"
+#elif __cpp_rvalue_references != 200610
+#  error "__cpp_rvalue_references != 200610"
+#endif
+
+#ifndef __cpp_variadic_templates
+#  error "__cpp_variadic_templates"
+#elif __cpp_variadic_templates != 200704
+#  error "__cpp_variadic_templates != 200704"
+#endif
+
+#ifndef __cpp_initializer_lists
+#  error "__cpp_initializer_lists"
+#elif __cpp_initializer_lists != 200806
+#  error "__cpp_initializer_lists != 200806"
+#endif
+
+#ifndef __cpp_delegating_constructors
+#  error "__cpp_delegating_constructors"
+#elif __cpp_delegating_constructors != 200604
+#  error "__cpp_delegating_constructors != 200604"
+#endif
+
+#ifndef __cpp_nsdmi
+#  error "__cpp_nsdmi"
+#elif __cpp_nsdmi != 200809
+#  error "__cpp_nsdmi != 200809"
+#endif
+
+#ifndef __cpp_inheriting_constructors
+#  error "__cpp_inheriting_constructors"
+#elif  __cpp_inheriting_constructors!= 201511
+#  error "__cpp_inheriting_constructors != 201511"
+#endif
+
+#ifndef __cpp_ref_qualifiers
+#  error "__cpp_ref_qualifiers"
+#elif __cpp_ref_qualifiers != 200710
+#  error "__cpp_ref_qualifiers != 200710"
+#endif
+
+#ifndef __cpp_alias_templates
+#  error "__cpp_alias_templates"
+#elif __cpp_alias_templates != 200704
+#  error "__cpp_alias_templates != 200704"
+#endif
+
+#ifndef __cpp_threadsafe_static_init
+#  error "__cpp_threadsafe_static_init"
+#elif __cpp_threadsafe_static_init != 200806
+#  error "__cpp_threadsafe_static_init != 200806"
+#endif
+
+//  C++14 features:
+
+#ifndef __cpp_binary_literals
+#  error "__cpp_binary_literals"
+#elif __cpp_binary_literals != 201304
+#  error "__cpp_binary_literals != 201304"
+#endif
+
+#ifndef __cpp_init_captures
+#  error "__cpp_init_captures"
+#elif __cpp_init_captures != 201803
+#  error "__cpp_init_captures != 201803"
+#endif
+
+#ifndef __cpp_generic_lambdas
+#  error "__cpp_generic_lambdas"
+#elif __cpp_generic_lambdas != 201707
+#  error "__cpp_generic_lambdas != 201707"
+#endif
+
+#ifndef __cpp_constexpr
+#  error "__cpp_constexpr"
+#elif __cpp_constexpr != 201907
+#  error "__cpp_constexpr != 201907"
+#endif
+
+#ifndef __cpp_decltype_auto
+#  error "__cpp_decltype_auto"
+#elif __cpp_decltype_auto != 201304
+#  error "__cpp_decltype_auto != 201304"
+#endif
+
+#ifndef __cpp_return_type_deduction
+#  error "__cpp_return_type_deduction"
+#elif __cpp_return_type_deduction != 201304
+#  error "__cpp_return_type_deduction != 201304"
+#endif
+
+#ifndef __cpp_aggregate_nsdmi
+#  error "__cpp_aggregate_nsdmi"
+#elif __cpp_aggregate_nsdmi != 201304
+#  error "__cpp_aggregate_nsdmi != 201304"
+#endif
+
+#ifndef __cpp_variable_templates
+#  error "__cpp_variable_templates"
+#elif __cpp_variable_templates != 201304
+#  error "__cpp_variable_templates != 201304"
+#endif
+
+#ifndef __cpp_digit_separators
+#  error "__cpp_digit_separators"
+#elif __cpp_digit_separators != 201309
+#  error "__cpp_digit_separators != 201309"
+#endif
+
+#ifndef __cpp_sized_deallocation
+#  error "__cpp_sized_deallocation"
+#elif __cpp_sized_deallocation != 201309
+#  error "__cpp_sized_deallocation != 201309"
+#endif
+
+//  GNU VLA support:
+
+#ifndef __cpp_runtime_arrays
+#  error "__cpp_runtime_arrays"
+#elif __cpp_runtime_arrays != 198712
+#  error "__cpp_runtime_arrays != 198712"
+#endif
+
+//  C++11 attributes:
+
+#ifdef __has_cpp_attribute
+#  if ! __has_cpp_attribute(noreturn)
+#    error "__has_cpp_attribute(noreturn)"
+#  elif __has_cpp_attribute(noreturn) != 200809
+#    error "__has_cpp_attribute(noreturn) != 200809"
+#  endif
+#else
+#  error "__has_cpp_attribute"
+#endif
+
+//  Attribute carries_dependency not in yet.
+//#ifdef __has_cpp_attribute
+//#  if ! __has_cpp_attribute(carries_dependency)
+//#    error "__has_cpp_attribute(carries_dependency)"
+//#  elif __has_cpp_attribute(carries_dependency) != 200809
+//#    error "__has_cpp_attribute(carries_dependency) != 200809"
+//#  endif
+//#else
+//#  error "__has_cpp_attribute"
+//#endif
+
+//  C++14 attributes:
+
+#ifdef __has_cpp_attribute
+#  if ! __has_cpp_attribute(deprecated)
+#    error "__has_cpp_attribute(deprecated)"
+#  elif __has_cpp_attribute(deprecated) != 201309
+#    error "__has_cpp_attribute(deprecated) != 201309"
+#  endif
+#else
+#  error "__has_cpp_attribute"
+#endif
+
+//  Include checks:
+
+//  Check for __has_include macro.
+#ifndef __has_include
+#  error "__has_include"
+#endif
+
+//  Try known bracket header (use operator).
+#if __has_include (<complex>)
+#else
+#  error "<complex>"
+#endif
+
+//  Define and use a macro to invoke the operator.
+#define sluggo(TXT) __has_include(TXT)
+
+#if sluggo(<complex>)
+#else
+#  error "<complex>"
+#endif
+
+#if ! sluggo(<complex>)
+#  error "<complex>"
+#else
+#endif
+
+//  Quoted complex.h should find at least the bracket version.
+#if __has_include("complex.h")
+#else
+#  error "complex.h"
+#endif
+
+//  Try known local quote header.
+#if __has_include("complex_literals.h")
+#else
+#  error "\"complex_literals.h\""
+#endif
+
+//  Try nonexistent bracket header.
+#if __has_include(<stuff>)
+#  error "<stuff>"
+#else
+#endif
+
+//  Try nonexistent quote header.
+#if __has_include("phlegm")
+#  error "\"phlegm\""
+#else
+#endif
+
+//  Test __has_include_next.
+#if __has_include("phoobhar.h")
+#  include "phoobhar.h"
+#else
+#  error "__has_include(\"phoobhar.h\")"
+#endif
+
+//  Try a macro.
+#define COMPLEX_INC "complex.h"
+#if __has_include(COMPLEX_INC)
+#else
+#  error COMPLEX_INC
+#endif
+
+//  Realistic use of __has_include.
+#if __has_include(<array>)
+#  define STD_ARRAY 1
+#  include <array>
+  template<typename _Tp, std::size_t _Num>
+    using array = std::array<_Tp, _Num>;
+#elif __has_include(<tr1/array>)
+#  define TR1_ARRAY 1
+#  include <tr1/array>
+  template<typename _Tp, std::size_t _Num>
+    typedef std::tr1::array<_Tp, _Num> array;
+#endif
+
+// C++17 features:
+
+#ifndef __cpp_unicode_characters
+#  error "__cpp_unicode_characters"
+#elif __cpp_unicode_characters != 201411
+#  error "__cpp_unicode_characters != 201411"
+#endif
+
+#ifndef __cpp_static_assert
+#  error "__cpp_static_assert"
+#elif __cpp_static_assert != 201411
+#  error "__cpp_static_assert != 201411"
+#endif
+
+#ifndef __cpp_namespace_attributes
+#  error "__cpp_namespace_attributes"
+#elif __cpp_namespace_attributes != 201411
+#  error "__cpp_namespace_attributes != 201411"
+#endif
+
+#ifndef __cpp_enumerator_attributes
+#  error "__cpp_enumerator_attributes"
+#elif __cpp_enumerator_attributes != 201411
+#  error "__cpp_enumerator_attributes != 201411"
+#endif
+
+#ifndef __cpp_nested_namespace_definitions
+#  error "__cpp_nested_namespace_definitions"
+#elif __cpp_nested_namespace_definitions != 201411
+#  error "__cpp_nested_namespace_definitions != 201411"
+#endif
+
+#ifndef __cpp_fold_expressions
+#  error "__cpp_fold_expressions"
+#elif __cpp_fold_expressions != 201603
+#  error "__cpp_fold_expressions != 201603"
+#endif
+
+#ifndef __cpp_nontype_template_args
+#  error "__cpp_nontype_template_args"
+#elif __cpp_nontype_template_args != 201911
+#  error "__cpp_nontype_template_args != 201911"
+#endif
+
+#ifndef __cpp_hex_float
+#  error "__cpp_hex_float"
+#elif __cpp_hex_float != 201603
+#  error "__cpp_hex_float != 201603"
+#endif
+
+#ifndef __cpp_aggregate_bases
+#  error "__cpp_aggregate_bases"
+#elif __cpp_aggregate_bases != 201603
+#  error "__cpp_aggregate_bases != 201603"
+#endif
+
+#ifndef __cpp_deduction_guides
+#  error "__cpp_deduction_guides"
+#elif __cpp_deduction_guides != 201907
+#  error "__cpp_deduction_guides != 201907"
+#endif
+
+#ifndef __cpp_if_constexpr
+#  error "__cpp_if_constexpr"
+#elif __cpp_if_constexpr != 201606
+#  error "__cpp_if_constexpr != 201606"
+#endif
+
+#ifndef __cpp_aligned_new
+#  error "__cpp_aligned_new"
+#elif __cpp_aligned_new != 201606
+#  error "__cpp_aligned_new != 201606"
+#endif
+
+#ifndef __cpp_template_auto
+#  error "__cpp_template_auto"
+#elif __cpp_template_auto != 201606
+#  error "__cpp_template_auto != 201606"
+#endif
+
+#ifndef __cpp_inline_variables
+#  error "__cpp_inline_variables"
+#elif __cpp_inline_variables != 201606
+#  error "__cpp_inline_variables != 201606"
+#endif
+
+#ifndef __cpp_capture_star_this
+#  error "__cpp_capture_star_this"
+#elif __cpp_capture_star_this != 201603
+#  error "__cpp_capture_star_this != 201603"
+#endif
+
+#ifndef __cpp_noexcept_function_type
+#  error "__cpp_noexcept_function_type"
+#elif __cpp_noexcept_function_type != 201510
+#  error "__cpp_noexcept_function_type != 201510"
+#endif
+
+#ifndef __cpp_structured_bindings
+#  error "__cpp_structured_bindings"
+#elif __cpp_structured_bindings != 201606
+#  error "__cpp_structured_bindings != 201606"
+#endif
+
+#ifndef __cpp_template_template_args
+#  error "__cpp_template_template_args"
+#elif __cpp_template_template_args != 201611
+#  error "__cpp_template_template_args != 201611"
+#endif
+
+#ifndef __cpp_variadic_using
+#  error "__cpp_variadic_using"
+#elif __cpp_variadic_using != 201611
+#  error "__cpp_variadic_using != 201611"
+#endif
+
+#ifndef __cpp_guaranteed_copy_elision
+#  error "__cpp_guaranteed_copy_elision"
+#elif __cpp_guaranteed_copy_elision != 201606
+#  error "__cpp_guaranteed_copy_elision != 201606"
+#endif
+
+#ifndef __cpp_nontype_template_parameter_auto
+#  error "__cpp_nontype_template_parameter_auto"
+#elif __cpp_nontype_template_parameter_auto != 201606
+#  error "__cpp_nontype_template_parameter_auto != 201606"
+#endif
+
+// C++20 features
+
+#ifndef __cpp_conditional_explicit
+#  error "__cpp_conditional_explicit"
+#elif __cpp_conditional_explicit != 201806
+#  error "__cpp_conditional_explicit != 201806"
+#endif
+
+#ifndef __cpp_nontype_template_parameter_class
+#  error "__cpp_nontype_template_parameter_class"
+#elif __cpp_nontype_template_parameter_class != 201806
+#  error "__cpp_nontype_template_parameter_class != 201806"
+#endif
+
+#ifndef __cpp_impl_destroying_delete
+#  error "__cpp_impl_destroying_delete"
+#elif __cpp_impl_destroying_delete != 201806
+#  error "__cpp_impl_destroying_delete != 201806"
+#endif
+
+#ifndef __cpp_constinit
+#  error "__cpp_constinit"
+#elif __cpp_constinit != 201907
+#  error "__cpp_constinit != 201907"
+#endif
+
+#ifndef __cpp_constexpr_dynamic_alloc
+#  error "__cpp_constexpr_dynamic_alloc"
+#elif __cpp_constexpr_dynamic_alloc != 201907
+#  error "__cpp_constexpr_dynamic_alloc != 201907"
+#endif
+
+#ifndef __cpp_aggregate_paren_init
+#  error "__cpp_aggregate_paren_init"
+#elif __cpp_aggregate_paren_init != 201902
+#  error "__cpp_aggregate_paren_init != 201902"
+#endif
+
+#ifdef __has_cpp_attribute
+
+#  if ! __has_cpp_attribute(maybe_unused)
+#    error "__has_cpp_attribute(maybe_unused)"
+#  elif __has_cpp_attribute(maybe_unused) != 201603
+#    error "__has_cpp_attribute(maybe_unused) != 201603"
+#  endif
+
+#  if ! __has_cpp_attribute(nodiscard)
+#    error "__has_cpp_attribute(nodiscard)"
+#  elif __has_cpp_attribute(nodiscard) != 201907
+#    error "__has_cpp_attribute(nodiscard) != 201907"
+#  endif
+
+#  if ! __has_cpp_attribute(fallthrough)
+#    error "__has_cpp_attribute(fallthrough)"
+#  elif __has_cpp_attribute(fallthrough) != 201603
+#    error "__has_cpp_attribute(fallthrough) != 201603"
+#  endif
+
+#  if ! __has_cpp_attribute(no_unique_address)
+#    error "__has_cpp_attribute(no_unique_address)"
+#  elif __has_cpp_attribute(no_unique_address) != 201803
+#    error "__has_cpp_attribute(no_unique_address) != 201803"
+#  endif
+
+#  if ! __has_cpp_attribute(likely)
+#    error "__has_cpp_attribute(likely)"
+#  elif __has_cpp_attribute(likely) != 201803
+#    error "__has_cpp_attribute(likely) != 201803"
+#  endif
+
+#  if ! __has_cpp_attribute(unlikely)
+#    error "__has_cpp_attribute(unlikely)"
+#  elif __has_cpp_attribute(unlikely) != 201803
+#    error "__has_cpp_attribute(unlikely) != 201803"
+#  endif
+
+#else
+#  error "__has_cpp_attribute"
+#endif
+
+#ifndef __cpp_char8_t
+#  error "__cpp_char8_t"
+#elif __cpp_char8_t != 201811
+#  error "__cpp_char8_t != 201811"
+#endif
+
+#ifndef __cpp_designated_initializers
+#  error "__cpp_designated_initializers"
+#elif __cpp_designated_initializers != 201707
+#  error "__cpp_designated_initializers != 201707"
+#endif
+
+#ifndef __cpp_constexpr_in_decltype
+#  error "__cpp_constexpr_in_decltype"
+#elif __cpp_constexpr_in_decltype != 201711
+#  error "__cpp_constexpr_in_decltype != 201711"
+#endif
+
+/* Not supported fully yet:
+#ifndef __cpp_consteval
+#  error "__cpp_consteval"
+#elif __cpp_consteval != 201811
+#  error "__cpp_consteval != 201811"
+#endif
+*/
+
+#ifndef __cpp_concepts
+#  error "__cpp_concepts"
+#elif __cpp_concepts != 201907
+#  error "__cpp_concepts != 201907"
+#endif
+
+#ifndef __cpp_using_enum
+#  error "__cpp_using_enum"
+#elif __cpp_using_enum != 201907
+#  error "__cpp_using_enum != 201907"
+#endif
+
+// C++23 features:
+
+#ifndef __cpp_size_t_suffix
+#  error "__cpp_size_t_suffix"
+#elif __cpp_size_t_suffix != 202006
+#  error "__cpp_size_t_suffix != 202006"
+#endif
diff --git a/gcc/testsuite/g++.dg/cpp23/size_t-literals.C b/gcc/testsuite/g++.dg/cpp23/size_t-literals.C
new file mode 100644
index 00000000000..8c5b0b99287
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/size_t-literals.C
@@ -0,0 +1,8 @@
+// { dg-do compile { target c++23 } }
+
+#include <cstddef>
+#include <type_traits>
+
+static_assert(std::is_same_v<decltype(123zu), std::size_t>);
+static_assert(std::is_same_v<decltype(456z), std::ptrdiff_t>);
+
diff --git a/gcc/testsuite/g++.dg/warn/Wsize_t-literals.C b/gcc/testsuite/g++.dg/warn/Wsize_t-literals.C
new file mode 100644
index 00000000000..1f2f719af39
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wsize_t-literals.C
@@ -0,0 +1,11 @@
+// { dg-do compile { target c++20_down } }
+
+#include <cstddef>
+
+std::size_t s1 = 1234zu; // { dg-warning "use of C\+\+23 size_t integer constant" "" { target c++20_down } }
+std::size_t S1 = 5678ZU; // { dg-warning "use of C\+\+23 size_t integer constant" "" { target c++20_down } }
+std::size_t s2 = 1234uz; // { dg-warning "use of C\+\+23 size_t integer constant" "" { target c++20_down } }
+std::size_t S2 = 5678UZ; // { dg-warning "use of C\+\+23 size_t integer constant" "" { target c++20_down } }
+
+std::ptrdiff_t pd1 = 1234z; // { dg-warning "use of C\+\+23 ptrdiff_t integer constant" "" { target c++20_down } }
+std::ptrdiff_t PD1 = 5678Z; // { dg-warning "use of C\+\+23 ptrdiff_t integer constant" "" { target c++20_down } }
diff --git a/libcpp/expr.c b/libcpp/expr.c
index 474ea4d6b6f..42cd68a3380 100644
--- a/libcpp/expr.c
+++ b/libcpp/expr.c
@@ -313,13 +313,14 @@ static unsigned int
 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;
+  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;
@@ -332,9 +333,17 @@ interpret_int_suffix (cpp_reader *pfile, const uchar *s, size_t len)
 	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))
@@ -352,7 +361,8 @@ interpret_int_suffix (cpp_reader *pfile, const uchar *s, size_t len)
   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_SIZE_T | CPP_N_LARGE) : 0));
 }
 
 /* Return the classification flags for an int suffix.  */
@@ -805,6 +815,16 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
 				      virtual_location, 0, message);
         }
 
+      if ((result & CPP_N_SIZE_T) == CPP_N_SIZE_T
+	  && !CPP_OPTION (pfile, size_t_literals))
+       {
+	  const char *message = (result & CPP_N_UNSIGNED) == CPP_N_UNSIGNED
+				? N_("use of C++23 size_t integer constant")
+				: N_("use of C++23 ptrdiff_t integer constant");
+	  cpp_warning_with_line (pfile, CPP_W_SIZE_T_LITERALS,
+				 virtual_location, 0, message);
+       }
+
       result |= CPP_N_INTEGER;
     }
 
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
index 4467c73284d..f3e7213ede5 100644
--- a/libcpp/include/cpplib.h
+++ b/libcpp/include/cpplib.h
@@ -500,6 +500,9 @@ struct cpp_options
   /* Nonzero means tokenize C++20 module directives.  */
   unsigned char module_directives;
 
+  /* Nonzero for C++23 ptrdiff_t and size_t literals.  */
+  unsigned char size_t_literals;
+
   /* Holds the name of the target (execution) character set.  */
   const char *narrow_charset;
 
@@ -626,6 +629,7 @@ enum cpp_warning_reason {
   CPP_W_INVALID_PCH,
   CPP_W_WARNING_DIRECTIVE,
   CPP_W_LITERAL_SUFFIX,
+  CPP_W_SIZE_T_LITERALS,
   CPP_W_DATE_TIME,
   CPP_W_PEDANTIC,
   CPP_W_C90_C99_COMPAT,
@@ -1211,7 +1215,9 @@ struct cpp_num
 #define CPP_N_FLOATN	0x400000 /* _FloatN types.  */
 #define CPP_N_FLOATNX	0x800000 /* _FloatNx types.  */
 
-#define CPP_N_USERDEF	0x1000000 /* C++0x user-defined literal.  */
+#define CPP_N_USERDEF	0x1000000 /* C++11 user-defined literal.  */
+
+#define CPP_N_SIZE_T	0x2000000 /* C++23 size_t or ptrdiff_t literal  */
 
 #define CPP_N_WIDTH_FLOATN_NX	0xF0000000 /* _FloatN / _FloatNx value
 					      of N, divided by 16.  */
diff --git a/libcpp/init.c b/libcpp/init.c
index ecd3d5be7fd..17b0d251cda 100644
--- a/libcpp/init.c
+++ b/libcpp/init.c
@@ -94,34 +94,35 @@ struct lang_flags
   char va_opt;
   char scope;
   char dfp_constants;
+  char size_t_literals;
 };
 
 static const struct lang_flags lang_defaults[] =
-{ /*              c99 c++ xnum xid c11 std digr ulit rlit udlit bincst digsep trig u8chlit vaopt scope dfp */
-  /* GNUC89   */  { 0,  0,  1,  0,  0,  0,  1,   0,   0,   0,    0,     0,     0,   0,      1,   1,     0 },
-  /* GNUC99   */  { 1,  0,  1,  1,  0,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0 },
-  /* GNUC11   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0 },
-  /* GNUC17   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0 },
-  /* GNUC2X   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    1,     0,     0,   1,      1,   1,     1 },
-  /* STDC89   */  { 0,  0,  0,  0,  0,  1,  0,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0 },
-  /* STDC94   */  { 0,  0,  0,  0,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0 },
-  /* STDC99   */  { 1,  0,  1,  1,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0 },
-  /* STDC11   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    0,     0,     1,   0,      0,   0,     0 },
-  /* STDC17   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    0,     0,     1,   0,      0,   0,     0 },
-  /* STDC2X   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    1,     0,     1,   1,      0,   1,     1 },
-  /* GNUCXX   */  { 0,  1,  1,  1,  0,  0,  1,   0,   0,   0,    0,     0,     0,   0,      1,   1,     0 },
-  /* CXX98    */  { 0,  1,  0,  1,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   1,     0 },
-  /* GNUCXX11 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    0,     0,     0,   0,      1,   1,     0 },
-  /* CXX11    */  { 1,  1,  0,  1,  1,  1,  1,   1,   1,   1,    0,     0,     1,   0,      0,   1,     0 },
-  /* GNUCXX14 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   0,      1,   1,     0 },
-  /* CXX14    */  { 1,  1,  0,  1,  1,  1,  1,   1,   1,   1,    1,     1,     1,   0,      0,   1,     0 },
-  /* GNUCXX17 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0 },
-  /* CXX17    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      0,   1,     0 },
-  /* GNUCXX20 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0 },
-  /* CXX20    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0 },
-  /* GNUCXX23 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0 },
-  /* CXX23    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0 },
-  /* ASM      */  { 0,  0,  1,  0,  0,  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 scope dfp szlit */
+  /* GNUC89   */  { 0,  0,  1,  0,  0,  0,  1,   0,   0,   0,    0,     0,     0,   0,      1,   1,     0,   0 },
+  /* GNUC99   */  { 1,  0,  1,  1,  0,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0,   0 },
+  /* GNUC11   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0,   0 },
+  /* GNUC17   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0,   0 },
+  /* GNUC2X   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    1,     0,     0,   1,      1,   1,     1,   0 },
+  /* STDC89   */  { 0,  0,  0,  0,  0,  1,  0,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0 },
+  /* STDC94   */  { 0,  0,  0,  0,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0 },
+  /* STDC99   */  { 1,  0,  1,  1,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0 },
+  /* STDC11   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0 },
+  /* STDC17   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0 },
+  /* STDC2X   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    1,     0,     1,   1,      0,   1,     1,   0 },
+  /* GNUCXX   */  { 0,  1,  1,  1,  0,  0,  1,   0,   0,   0,    0,     0,     0,   0,      1,   1,     0,   0 },
+  /* CXX98    */  { 0,  1,  0,  1,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   1,     0,   0 },
+  /* GNUCXX11 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    0,     0,     0,   0,      1,   1,     0,   0 },
+  /* CXX11    */  { 1,  1,  0,  1,  1,  1,  1,   1,   1,   1,    0,     0,     1,   0,      0,   1,     0,   0 },
+  /* GNUCXX14 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   0,      1,   1,     0,   0 },
+  /* CXX14    */  { 1,  1,  0,  1,  1,  1,  1,   1,   1,   1,    1,     1,     1,   0,      0,   1,     0,   0 },
+  /* GNUCXX17 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   0 },
+  /* CXX17    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      0,   1,     0,   0 },
+  /* GNUCXX20 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   0 },
+  /* CXX20    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   0 },
+  /* GNUCXX23 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   1 },
+  /* CXX23    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   1 },
+  /* ASM      */  { 0,  0,  1,  0,  0,  0,  0,   0,   0,   0,    0,     0,     0,   0,      0,   0,     0,   0 }
 };
 
 /* Sets internal flags correctly for a given language.  */
@@ -149,6 +150,7 @@ cpp_set_lang (cpp_reader *pfile, enum c_lang lang)
   CPP_OPTION (pfile, va_opt)			 = l->va_opt;
   CPP_OPTION (pfile, scope)			 = l->scope;
   CPP_OPTION (pfile, dfp_constants)		 = l->dfp_constants;
+  CPP_OPTION (pfile, size_t_literals)		 = l->size_t_literals;
 }
 
 /* Initialize library global state.  */
Jason Merrill Feb. 1, 2021, 3:33 p.m. UTC | #7
On 1/30/21 6:22 PM, Ed Smith-Rowland wrote:
> On 1/27/21 3:32 PM, Jakub Jelinek wrote:
>> On Sun, Oct 21, 2018 at 04:39:30PM -0400, Ed Smith-Rowland wrote:
>>> 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.
>> GCC now supports -std=c++2b and -std=gnu++2b, are you going to update 
>> your
>> patch against it (and change for z/Z standing for ssize_t rather than
>> ptrdiff_t), plus incorporate the feedback from Joseph and Jason?
>>
>>     Jakub
>>
> Here is a rebased patch that is a bit leaner than the original.
> 
> Since I chose to be conservative in applying this just to C++23 I'm not 
> adding this to C or t earlier versions of C++ as extensions. We can add 
> that if people really want, maybe in stage 1.
> 
> The compat warning for C++ < 23 is not optional. since the suffixes are 
> not preceded by '-' I don't hav much sympathy if people tried to make a 
> literal 'z' operator. Which is the only reason I can see for a warning 
> suppression.

> +      /* itk refers to fundamental types not aliased size types.  */
> +      if (flags & CPP_N_UNSIGNED)
> +	type = size_type_node;
> +      else
> +	type = ptrdiff_type_node;

This is wrong if ptrdiff_t is a different size from size_t; it should be 
c_common_signed_type (size_type_node).

> +	  | (z ? (CPP_N_SIZE_T | CPP_N_LARGE) : 0));

Why CPP_N_LARGE here?  That would seem to suggest that size_t is always 
the same size as unsigned long long.

Jason
Ed Smith-Rowland Feb. 1, 2021, 6:46 p.m. UTC | #8
On 2/1/21 10:33 AM, Jason Merrill wrote:
> On 1/30/21 6:22 PM, Ed Smith-Rowland wrote:
>> On 1/27/21 3:32 PM, Jakub Jelinek wrote:
>>> On Sun, Oct 21, 2018 at 04:39:30PM -0400, Ed Smith-Rowland wrote:
>>>> 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.
>>> GCC now supports -std=c++2b and -std=gnu++2b, are you going to 
>>> update your
>>> patch against it (and change for z/Z standing for ssize_t rather than
>>> ptrdiff_t), plus incorporate the feedback from Joseph and Jason?
>>>
>>>     Jakub
>>>
>> Here is a rebased patch that is a bit leaner than the original.
>>
>> Since I chose to be conservative in applying this just to C++23 I'm 
>> not adding this to C or t earlier versions of C++ as extensions. We 
>> can add that if people really want, maybe in stage 1.
>>
>> The compat warning for C++ < 23 is not optional. since the suffixes 
>> are not preceded by '-' I don't hav much sympathy if people tried to 
>> make a literal 'z' operator. Which is the only reason I can see for a 
>> warning suppression.
>
>> +      /* itk refers to fundamental types not aliased size types.  */
>> +      if (flags & CPP_N_UNSIGNED)
>> +    type = size_type_node;
>> +      else
>> +    type = ptrdiff_type_node;
>
I thought size_type_node and ptrdiff_type_node were sort of fundamental 
the the others derived:

ssize_t:
   signed_size_type_node = c_common_signed_type (size_type_node);
???:
   unsigned_ptrdiff_type_node = c_common_unsigned_type (ptrdiff_type_node);

But I see in tree.c that things can be... interesting.

Fixed...

> This is wrong if ptrdiff_t is a different size from size_t; it should 
> be c_common_signed_type (size_type_node).
>
>> +      | (z ? (CPP_N_SIZE_T | CPP_N_LARGE) : 0));
>
> Why CPP_N_LARGE here?  That would seem to suggest that size_t is 
> always the same size as unsigned long long.
>
This doesn't need to be there. I don't use it anywhere.
> Jason
>
Is this Ok if it passes testing on x86_64-linux?

Ed
diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
index dca6815a876..48dec21d4b4 100644
--- a/gcc/c-family/c-cppbuiltin.c
+++ b/gcc/c-family/c-cppbuiltin.c
@@ -1025,6 +1025,11 @@ c_cpp_builtins (cpp_reader *pfile)
 	  cpp_define (pfile, "__cpp_aggregate_paren_init=201902L");
 	  cpp_define (pfile, "__cpp_using_enum=201907L");
 	}
+      if (cxx_dialect > cxx20)
+	{
+	  /* Set feature test macros for C++23.  */
+	  cpp_define (pfile, "__cpp_size_t_suffix=202006L");
+	}
       if (flag_concepts)
         {
 	  if (cxx_dialect >= cxx20)
diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c
index fe40a0f728b..bc4f6f9dfa7 100644
--- a/gcc/c-family/c-lex.c
+++ b/gcc/c-family/c-lex.c
@@ -834,6 +834,14 @@ interpret_integer (const cpp_token *token, unsigned int flags,
     type = ((flags & CPP_N_UNSIGNED)
 	    ? widest_unsigned_literal_type_node
 	    : widest_integer_literal_type_node);
+  else if (flags & CPP_N_SIZE_T)
+    {
+      /* itk refers to fundamental types not aliased size types.  */
+      if (flags & CPP_N_UNSIGNED)
+	type = size_type_node;
+      else
+	type = c_common_signed_type (size_type_node);
+    }
   else
     {
       type = integer_types[itk];
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C
index fdddd8d84ed..a30ec0f4f7e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C
@@ -17,6 +17,30 @@ unsigned long long int
 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,13 +61,50 @@ unsigned long long int
 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 }
 // { 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 }
diff --git a/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C b/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C
new file mode 100644
index 00000000000..94e08a4896c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C
@@ -0,0 +1,549 @@
+// { dg-options "-std=c++2b -I${srcdir}/g++.dg/cpp1y -I${srcdir}/g++.dg/cpp1y/testinc" }
+
+//  C++98 features:
+
+#ifndef __cpp_rtti
+#  error "__cpp_rtti"
+#elif  __cpp_rtti != 199711
+#  error "__cpp_rtti != 199711"
+#endif
+
+#ifndef __cpp_exceptions
+#  error "__cpp_exceptions"
+#elif  __cpp_exceptions != 199711
+#  error "__cpp_exceptions != 199711"
+#endif
+
+//  C++11 features:
+
+#ifndef __cpp_raw_strings
+#  error "__cpp_raw_strings"
+#elif __cpp_raw_strings != 200710
+#  error "__cpp_raw_strings != 200710"
+#endif
+
+#ifndef __cpp_unicode_literals
+#  error "__cpp_unicode_literals"
+#elif __cpp_unicode_literals != 200710
+#  error "__cpp_unicode_literals != 200710"
+#endif
+
+#ifndef __cpp_user_defined_literals
+#  error "__cpp_user_defined_literals"
+#elif __cpp_user_defined_literals != 200809
+#  error "__cpp_user_defined_literals != 200809"
+#endif
+
+#ifndef __cpp_lambdas
+#  error "__cpp_lambdas"
+#elif __cpp_lambdas != 200907
+#  error "__cpp_lambdas != 200907"
+#endif
+
+#ifndef __cpp_range_based_for
+#  error "__cpp_range_based_for"
+#elif __cpp_range_based_for != 201603
+#  error "__cpp_range_based_for != 201603"
+#endif
+
+#ifndef __cpp_decltype
+#  error "__cpp_decltype"
+#elif __cpp_decltype != 200707
+#  error "__cpp_decltype != 200707"
+#endif
+
+#ifndef __cpp_attributes
+#  error "__cpp_attributes"
+#elif __cpp_attributes != 200809
+#  error "__cpp_attributes != 200809"
+#endif
+
+#ifndef __cpp_rvalue_references
+#  error "__cpp_rvalue_references"
+#elif __cpp_rvalue_references != 200610
+#  error "__cpp_rvalue_references != 200610"
+#endif
+
+#ifndef __cpp_variadic_templates
+#  error "__cpp_variadic_templates"
+#elif __cpp_variadic_templates != 200704
+#  error "__cpp_variadic_templates != 200704"
+#endif
+
+#ifndef __cpp_initializer_lists
+#  error "__cpp_initializer_lists"
+#elif __cpp_initializer_lists != 200806
+#  error "__cpp_initializer_lists != 200806"
+#endif
+
+#ifndef __cpp_delegating_constructors
+#  error "__cpp_delegating_constructors"
+#elif __cpp_delegating_constructors != 200604
+#  error "__cpp_delegating_constructors != 200604"
+#endif
+
+#ifndef __cpp_nsdmi
+#  error "__cpp_nsdmi"
+#elif __cpp_nsdmi != 200809
+#  error "__cpp_nsdmi != 200809"
+#endif
+
+#ifndef __cpp_inheriting_constructors
+#  error "__cpp_inheriting_constructors"
+#elif  __cpp_inheriting_constructors!= 201511
+#  error "__cpp_inheriting_constructors != 201511"
+#endif
+
+#ifndef __cpp_ref_qualifiers
+#  error "__cpp_ref_qualifiers"
+#elif __cpp_ref_qualifiers != 200710
+#  error "__cpp_ref_qualifiers != 200710"
+#endif
+
+#ifndef __cpp_alias_templates
+#  error "__cpp_alias_templates"
+#elif __cpp_alias_templates != 200704
+#  error "__cpp_alias_templates != 200704"
+#endif
+
+#ifndef __cpp_threadsafe_static_init
+#  error "__cpp_threadsafe_static_init"
+#elif __cpp_threadsafe_static_init != 200806
+#  error "__cpp_threadsafe_static_init != 200806"
+#endif
+
+//  C++14 features:
+
+#ifndef __cpp_binary_literals
+#  error "__cpp_binary_literals"
+#elif __cpp_binary_literals != 201304
+#  error "__cpp_binary_literals != 201304"
+#endif
+
+#ifndef __cpp_init_captures
+#  error "__cpp_init_captures"
+#elif __cpp_init_captures != 201803
+#  error "__cpp_init_captures != 201803"
+#endif
+
+#ifndef __cpp_generic_lambdas
+#  error "__cpp_generic_lambdas"
+#elif __cpp_generic_lambdas != 201707
+#  error "__cpp_generic_lambdas != 201707"
+#endif
+
+#ifndef __cpp_constexpr
+#  error "__cpp_constexpr"
+#elif __cpp_constexpr != 201907
+#  error "__cpp_constexpr != 201907"
+#endif
+
+#ifndef __cpp_decltype_auto
+#  error "__cpp_decltype_auto"
+#elif __cpp_decltype_auto != 201304
+#  error "__cpp_decltype_auto != 201304"
+#endif
+
+#ifndef __cpp_return_type_deduction
+#  error "__cpp_return_type_deduction"
+#elif __cpp_return_type_deduction != 201304
+#  error "__cpp_return_type_deduction != 201304"
+#endif
+
+#ifndef __cpp_aggregate_nsdmi
+#  error "__cpp_aggregate_nsdmi"
+#elif __cpp_aggregate_nsdmi != 201304
+#  error "__cpp_aggregate_nsdmi != 201304"
+#endif
+
+#ifndef __cpp_variable_templates
+#  error "__cpp_variable_templates"
+#elif __cpp_variable_templates != 201304
+#  error "__cpp_variable_templates != 201304"
+#endif
+
+#ifndef __cpp_digit_separators
+#  error "__cpp_digit_separators"
+#elif __cpp_digit_separators != 201309
+#  error "__cpp_digit_separators != 201309"
+#endif
+
+#ifndef __cpp_sized_deallocation
+#  error "__cpp_sized_deallocation"
+#elif __cpp_sized_deallocation != 201309
+#  error "__cpp_sized_deallocation != 201309"
+#endif
+
+//  GNU VLA support:
+
+#ifndef __cpp_runtime_arrays
+#  error "__cpp_runtime_arrays"
+#elif __cpp_runtime_arrays != 198712
+#  error "__cpp_runtime_arrays != 198712"
+#endif
+
+//  C++11 attributes:
+
+#ifdef __has_cpp_attribute
+#  if ! __has_cpp_attribute(noreturn)
+#    error "__has_cpp_attribute(noreturn)"
+#  elif __has_cpp_attribute(noreturn) != 200809
+#    error "__has_cpp_attribute(noreturn) != 200809"
+#  endif
+#else
+#  error "__has_cpp_attribute"
+#endif
+
+//  Attribute carries_dependency not in yet.
+//#ifdef __has_cpp_attribute
+//#  if ! __has_cpp_attribute(carries_dependency)
+//#    error "__has_cpp_attribute(carries_dependency)"
+//#  elif __has_cpp_attribute(carries_dependency) != 200809
+//#    error "__has_cpp_attribute(carries_dependency) != 200809"
+//#  endif
+//#else
+//#  error "__has_cpp_attribute"
+//#endif
+
+//  C++14 attributes:
+
+#ifdef __has_cpp_attribute
+#  if ! __has_cpp_attribute(deprecated)
+#    error "__has_cpp_attribute(deprecated)"
+#  elif __has_cpp_attribute(deprecated) != 201309
+#    error "__has_cpp_attribute(deprecated) != 201309"
+#  endif
+#else
+#  error "__has_cpp_attribute"
+#endif
+
+//  Include checks:
+
+//  Check for __has_include macro.
+#ifndef __has_include
+#  error "__has_include"
+#endif
+
+//  Try known bracket header (use operator).
+#if __has_include (<complex>)
+#else
+#  error "<complex>"
+#endif
+
+//  Define and use a macro to invoke the operator.
+#define sluggo(TXT) __has_include(TXT)
+
+#if sluggo(<complex>)
+#else
+#  error "<complex>"
+#endif
+
+#if ! sluggo(<complex>)
+#  error "<complex>"
+#else
+#endif
+
+//  Quoted complex.h should find at least the bracket version.
+#if __has_include("complex.h")
+#else
+#  error "complex.h"
+#endif
+
+//  Try known local quote header.
+#if __has_include("complex_literals.h")
+#else
+#  error "\"complex_literals.h\""
+#endif
+
+//  Try nonexistent bracket header.
+#if __has_include(<stuff>)
+#  error "<stuff>"
+#else
+#endif
+
+//  Try nonexistent quote header.
+#if __has_include("phlegm")
+#  error "\"phlegm\""
+#else
+#endif
+
+//  Test __has_include_next.
+#if __has_include("phoobhar.h")
+#  include "phoobhar.h"
+#else
+#  error "__has_include(\"phoobhar.h\")"
+#endif
+
+//  Try a macro.
+#define COMPLEX_INC "complex.h"
+#if __has_include(COMPLEX_INC)
+#else
+#  error COMPLEX_INC
+#endif
+
+//  Realistic use of __has_include.
+#if __has_include(<array>)
+#  define STD_ARRAY 1
+#  include <array>
+  template<typename _Tp, std::size_t _Num>
+    using array = std::array<_Tp, _Num>;
+#elif __has_include(<tr1/array>)
+#  define TR1_ARRAY 1
+#  include <tr1/array>
+  template<typename _Tp, std::size_t _Num>
+    typedef std::tr1::array<_Tp, _Num> array;
+#endif
+
+// C++17 features:
+
+#ifndef __cpp_unicode_characters
+#  error "__cpp_unicode_characters"
+#elif __cpp_unicode_characters != 201411
+#  error "__cpp_unicode_characters != 201411"
+#endif
+
+#ifndef __cpp_static_assert
+#  error "__cpp_static_assert"
+#elif __cpp_static_assert != 201411
+#  error "__cpp_static_assert != 201411"
+#endif
+
+#ifndef __cpp_namespace_attributes
+#  error "__cpp_namespace_attributes"
+#elif __cpp_namespace_attributes != 201411
+#  error "__cpp_namespace_attributes != 201411"
+#endif
+
+#ifndef __cpp_enumerator_attributes
+#  error "__cpp_enumerator_attributes"
+#elif __cpp_enumerator_attributes != 201411
+#  error "__cpp_enumerator_attributes != 201411"
+#endif
+
+#ifndef __cpp_nested_namespace_definitions
+#  error "__cpp_nested_namespace_definitions"
+#elif __cpp_nested_namespace_definitions != 201411
+#  error "__cpp_nested_namespace_definitions != 201411"
+#endif
+
+#ifndef __cpp_fold_expressions
+#  error "__cpp_fold_expressions"
+#elif __cpp_fold_expressions != 201603
+#  error "__cpp_fold_expressions != 201603"
+#endif
+
+#ifndef __cpp_nontype_template_args
+#  error "__cpp_nontype_template_args"
+#elif __cpp_nontype_template_args != 201911
+#  error "__cpp_nontype_template_args != 201911"
+#endif
+
+#ifndef __cpp_hex_float
+#  error "__cpp_hex_float"
+#elif __cpp_hex_float != 201603
+#  error "__cpp_hex_float != 201603"
+#endif
+
+#ifndef __cpp_aggregate_bases
+#  error "__cpp_aggregate_bases"
+#elif __cpp_aggregate_bases != 201603
+#  error "__cpp_aggregate_bases != 201603"
+#endif
+
+#ifndef __cpp_deduction_guides
+#  error "__cpp_deduction_guides"
+#elif __cpp_deduction_guides != 201907
+#  error "__cpp_deduction_guides != 201907"
+#endif
+
+#ifndef __cpp_if_constexpr
+#  error "__cpp_if_constexpr"
+#elif __cpp_if_constexpr != 201606
+#  error "__cpp_if_constexpr != 201606"
+#endif
+
+#ifndef __cpp_aligned_new
+#  error "__cpp_aligned_new"
+#elif __cpp_aligned_new != 201606
+#  error "__cpp_aligned_new != 201606"
+#endif
+
+#ifndef __cpp_template_auto
+#  error "__cpp_template_auto"
+#elif __cpp_template_auto != 201606
+#  error "__cpp_template_auto != 201606"
+#endif
+
+#ifndef __cpp_inline_variables
+#  error "__cpp_inline_variables"
+#elif __cpp_inline_variables != 201606
+#  error "__cpp_inline_variables != 201606"
+#endif
+
+#ifndef __cpp_capture_star_this
+#  error "__cpp_capture_star_this"
+#elif __cpp_capture_star_this != 201603
+#  error "__cpp_capture_star_this != 201603"
+#endif
+
+#ifndef __cpp_noexcept_function_type
+#  error "__cpp_noexcept_function_type"
+#elif __cpp_noexcept_function_type != 201510
+#  error "__cpp_noexcept_function_type != 201510"
+#endif
+
+#ifndef __cpp_structured_bindings
+#  error "__cpp_structured_bindings"
+#elif __cpp_structured_bindings != 201606
+#  error "__cpp_structured_bindings != 201606"
+#endif
+
+#ifndef __cpp_template_template_args
+#  error "__cpp_template_template_args"
+#elif __cpp_template_template_args != 201611
+#  error "__cpp_template_template_args != 201611"
+#endif
+
+#ifndef __cpp_variadic_using
+#  error "__cpp_variadic_using"
+#elif __cpp_variadic_using != 201611
+#  error "__cpp_variadic_using != 201611"
+#endif
+
+#ifndef __cpp_guaranteed_copy_elision
+#  error "__cpp_guaranteed_copy_elision"
+#elif __cpp_guaranteed_copy_elision != 201606
+#  error "__cpp_guaranteed_copy_elision != 201606"
+#endif
+
+#ifndef __cpp_nontype_template_parameter_auto
+#  error "__cpp_nontype_template_parameter_auto"
+#elif __cpp_nontype_template_parameter_auto != 201606
+#  error "__cpp_nontype_template_parameter_auto != 201606"
+#endif
+
+// C++20 features
+
+#ifndef __cpp_conditional_explicit
+#  error "__cpp_conditional_explicit"
+#elif __cpp_conditional_explicit != 201806
+#  error "__cpp_conditional_explicit != 201806"
+#endif
+
+#ifndef __cpp_nontype_template_parameter_class
+#  error "__cpp_nontype_template_parameter_class"
+#elif __cpp_nontype_template_parameter_class != 201806
+#  error "__cpp_nontype_template_parameter_class != 201806"
+#endif
+
+#ifndef __cpp_impl_destroying_delete
+#  error "__cpp_impl_destroying_delete"
+#elif __cpp_impl_destroying_delete != 201806
+#  error "__cpp_impl_destroying_delete != 201806"
+#endif
+
+#ifndef __cpp_constinit
+#  error "__cpp_constinit"
+#elif __cpp_constinit != 201907
+#  error "__cpp_constinit != 201907"
+#endif
+
+#ifndef __cpp_constexpr_dynamic_alloc
+#  error "__cpp_constexpr_dynamic_alloc"
+#elif __cpp_constexpr_dynamic_alloc != 201907
+#  error "__cpp_constexpr_dynamic_alloc != 201907"
+#endif
+
+#ifndef __cpp_aggregate_paren_init
+#  error "__cpp_aggregate_paren_init"
+#elif __cpp_aggregate_paren_init != 201902
+#  error "__cpp_aggregate_paren_init != 201902"
+#endif
+
+#ifdef __has_cpp_attribute
+
+#  if ! __has_cpp_attribute(maybe_unused)
+#    error "__has_cpp_attribute(maybe_unused)"
+#  elif __has_cpp_attribute(maybe_unused) != 201603
+#    error "__has_cpp_attribute(maybe_unused) != 201603"
+#  endif
+
+#  if ! __has_cpp_attribute(nodiscard)
+#    error "__has_cpp_attribute(nodiscard)"
+#  elif __has_cpp_attribute(nodiscard) != 201907
+#    error "__has_cpp_attribute(nodiscard) != 201907"
+#  endif
+
+#  if ! __has_cpp_attribute(fallthrough)
+#    error "__has_cpp_attribute(fallthrough)"
+#  elif __has_cpp_attribute(fallthrough) != 201603
+#    error "__has_cpp_attribute(fallthrough) != 201603"
+#  endif
+
+#  if ! __has_cpp_attribute(no_unique_address)
+#    error "__has_cpp_attribute(no_unique_address)"
+#  elif __has_cpp_attribute(no_unique_address) != 201803
+#    error "__has_cpp_attribute(no_unique_address) != 201803"
+#  endif
+
+#  if ! __has_cpp_attribute(likely)
+#    error "__has_cpp_attribute(likely)"
+#  elif __has_cpp_attribute(likely) != 201803
+#    error "__has_cpp_attribute(likely) != 201803"
+#  endif
+
+#  if ! __has_cpp_attribute(unlikely)
+#    error "__has_cpp_attribute(unlikely)"
+#  elif __has_cpp_attribute(unlikely) != 201803
+#    error "__has_cpp_attribute(unlikely) != 201803"
+#  endif
+
+#else
+#  error "__has_cpp_attribute"
+#endif
+
+#ifndef __cpp_char8_t
+#  error "__cpp_char8_t"
+#elif __cpp_char8_t != 201811
+#  error "__cpp_char8_t != 201811"
+#endif
+
+#ifndef __cpp_designated_initializers
+#  error "__cpp_designated_initializers"
+#elif __cpp_designated_initializers != 201707
+#  error "__cpp_designated_initializers != 201707"
+#endif
+
+#ifndef __cpp_constexpr_in_decltype
+#  error "__cpp_constexpr_in_decltype"
+#elif __cpp_constexpr_in_decltype != 201711
+#  error "__cpp_constexpr_in_decltype != 201711"
+#endif
+
+/* Not supported fully yet:
+#ifndef __cpp_consteval
+#  error "__cpp_consteval"
+#elif __cpp_consteval != 201811
+#  error "__cpp_consteval != 201811"
+#endif
+*/
+
+#ifndef __cpp_concepts
+#  error "__cpp_concepts"
+#elif __cpp_concepts != 201907
+#  error "__cpp_concepts != 201907"
+#endif
+
+#ifndef __cpp_using_enum
+#  error "__cpp_using_enum"
+#elif __cpp_using_enum != 201907
+#  error "__cpp_using_enum != 201907"
+#endif
+
+// C++23 features:
+
+#ifndef __cpp_size_t_suffix
+#  error "__cpp_size_t_suffix"
+#elif __cpp_size_t_suffix != 202006
+#  error "__cpp_size_t_suffix != 202006"
+#endif
diff --git a/gcc/testsuite/g++.dg/cpp23/size_t-literals.C b/gcc/testsuite/g++.dg/cpp23/size_t-literals.C
new file mode 100644
index 00000000000..8c5b0b99287
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/size_t-literals.C
@@ -0,0 +1,8 @@
+// { dg-do compile { target c++23 } }
+
+#include <cstddef>
+#include <type_traits>
+
+static_assert(std::is_same_v<decltype(123zu), std::size_t>);
+static_assert(std::is_same_v<decltype(456z), std::ptrdiff_t>);
+
diff --git a/gcc/testsuite/g++.dg/warn/Wsize_t-literals.C b/gcc/testsuite/g++.dg/warn/Wsize_t-literals.C
new file mode 100644
index 00000000000..1f2f719af39
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wsize_t-literals.C
@@ -0,0 +1,11 @@
+// { dg-do compile { target c++20_down } }
+
+#include <cstddef>
+
+std::size_t s1 = 1234zu; // { dg-warning "use of C\+\+23 size_t integer constant" "" { target c++20_down } }
+std::size_t S1 = 5678ZU; // { dg-warning "use of C\+\+23 size_t integer constant" "" { target c++20_down } }
+std::size_t s2 = 1234uz; // { dg-warning "use of C\+\+23 size_t integer constant" "" { target c++20_down } }
+std::size_t S2 = 5678UZ; // { dg-warning "use of C\+\+23 size_t integer constant" "" { target c++20_down } }
+
+std::ptrdiff_t pd1 = 1234z; // { dg-warning "use of C\+\+23 ptrdiff_t integer constant" "" { target c++20_down } }
+std::ptrdiff_t PD1 = 5678Z; // { dg-warning "use of C\+\+23 ptrdiff_t integer constant" "" { target c++20_down } }
diff --git a/libcpp/expr.c b/libcpp/expr.c
index 474ea4d6b6f..46937c33ebf 100644
--- a/libcpp/expr.c
+++ b/libcpp/expr.c
@@ -313,13 +313,14 @@ static unsigned int
 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;
+  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;
@@ -332,9 +333,17 @@ interpret_int_suffix (cpp_reader *pfile, const uchar *s, size_t len)
 	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))
@@ -352,7 +361,8 @@ interpret_int_suffix (cpp_reader *pfile, const uchar *s, size_t len)
   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_SIZE_T : 0));
 }
 
 /* Return the classification flags for an int suffix.  */
@@ -805,6 +815,16 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
 				      virtual_location, 0, message);
         }
 
+      if ((result & CPP_N_SIZE_T) == CPP_N_SIZE_T
+	  && !CPP_OPTION (pfile, size_t_literals))
+       {
+	  const char *message = (result & CPP_N_UNSIGNED) == CPP_N_UNSIGNED
+				? N_("use of C++23 size_t integer constant")
+				: N_("use of C++23 ptrdiff_t integer constant");
+	  cpp_warning_with_line (pfile, CPP_W_SIZE_T_LITERALS,
+				 virtual_location, 0, message);
+       }
+
       result |= CPP_N_INTEGER;
     }
 
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
index 4467c73284d..f3e7213ede5 100644
--- a/libcpp/include/cpplib.h
+++ b/libcpp/include/cpplib.h
@@ -500,6 +500,9 @@ struct cpp_options
   /* Nonzero means tokenize C++20 module directives.  */
   unsigned char module_directives;
 
+  /* Nonzero for C++23 ptrdiff_t and size_t literals.  */
+  unsigned char size_t_literals;
+
   /* Holds the name of the target (execution) character set.  */
   const char *narrow_charset;
 
@@ -626,6 +629,7 @@ enum cpp_warning_reason {
   CPP_W_INVALID_PCH,
   CPP_W_WARNING_DIRECTIVE,
   CPP_W_LITERAL_SUFFIX,
+  CPP_W_SIZE_T_LITERALS,
   CPP_W_DATE_TIME,
   CPP_W_PEDANTIC,
   CPP_W_C90_C99_COMPAT,
@@ -1211,7 +1215,9 @@ struct cpp_num
 #define CPP_N_FLOATN	0x400000 /* _FloatN types.  */
 #define CPP_N_FLOATNX	0x800000 /* _FloatNx types.  */
 
-#define CPP_N_USERDEF	0x1000000 /* C++0x user-defined literal.  */
+#define CPP_N_USERDEF	0x1000000 /* C++11 user-defined literal.  */
+
+#define CPP_N_SIZE_T	0x2000000 /* C++23 size_t or ptrdiff_t literal  */
 
 #define CPP_N_WIDTH_FLOATN_NX	0xF0000000 /* _FloatN / _FloatNx value
 					      of N, divided by 16.  */
diff --git a/libcpp/init.c b/libcpp/init.c
index ecd3d5be7fd..17b0d251cda 100644
--- a/libcpp/init.c
+++ b/libcpp/init.c
@@ -94,34 +94,35 @@ struct lang_flags
   char va_opt;
   char scope;
   char dfp_constants;
+  char size_t_literals;
 };
 
 static const struct lang_flags lang_defaults[] =
-{ /*              c99 c++ xnum xid c11 std digr ulit rlit udlit bincst digsep trig u8chlit vaopt scope dfp */
-  /* GNUC89   */  { 0,  0,  1,  0,  0,  0,  1,   0,   0,   0,    0,     0,     0,   0,      1,   1,     0 },
-  /* GNUC99   */  { 1,  0,  1,  1,  0,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0 },
-  /* GNUC11   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0 },
-  /* GNUC17   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0 },
-  /* GNUC2X   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    1,     0,     0,   1,      1,   1,     1 },
-  /* STDC89   */  { 0,  0,  0,  0,  0,  1,  0,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0 },
-  /* STDC94   */  { 0,  0,  0,  0,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0 },
-  /* STDC99   */  { 1,  0,  1,  1,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0 },
-  /* STDC11   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    0,     0,     1,   0,      0,   0,     0 },
-  /* STDC17   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    0,     0,     1,   0,      0,   0,     0 },
-  /* STDC2X   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    1,     0,     1,   1,      0,   1,     1 },
-  /* GNUCXX   */  { 0,  1,  1,  1,  0,  0,  1,   0,   0,   0,    0,     0,     0,   0,      1,   1,     0 },
-  /* CXX98    */  { 0,  1,  0,  1,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   1,     0 },
-  /* GNUCXX11 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    0,     0,     0,   0,      1,   1,     0 },
-  /* CXX11    */  { 1,  1,  0,  1,  1,  1,  1,   1,   1,   1,    0,     0,     1,   0,      0,   1,     0 },
-  /* GNUCXX14 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   0,      1,   1,     0 },
-  /* CXX14    */  { 1,  1,  0,  1,  1,  1,  1,   1,   1,   1,    1,     1,     1,   0,      0,   1,     0 },
-  /* GNUCXX17 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0 },
-  /* CXX17    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      0,   1,     0 },
-  /* GNUCXX20 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0 },
-  /* CXX20    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0 },
-  /* GNUCXX23 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0 },
-  /* CXX23    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0 },
-  /* ASM      */  { 0,  0,  1,  0,  0,  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 scope dfp szlit */
+  /* GNUC89   */  { 0,  0,  1,  0,  0,  0,  1,   0,   0,   0,    0,     0,     0,   0,      1,   1,     0,   0 },
+  /* GNUC99   */  { 1,  0,  1,  1,  0,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0,   0 },
+  /* GNUC11   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0,   0 },
+  /* GNUC17   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0,   0 },
+  /* GNUC2X   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    1,     0,     0,   1,      1,   1,     1,   0 },
+  /* STDC89   */  { 0,  0,  0,  0,  0,  1,  0,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0 },
+  /* STDC94   */  { 0,  0,  0,  0,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0 },
+  /* STDC99   */  { 1,  0,  1,  1,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0 },
+  /* STDC11   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0 },
+  /* STDC17   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0 },
+  /* STDC2X   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    1,     0,     1,   1,      0,   1,     1,   0 },
+  /* GNUCXX   */  { 0,  1,  1,  1,  0,  0,  1,   0,   0,   0,    0,     0,     0,   0,      1,   1,     0,   0 },
+  /* CXX98    */  { 0,  1,  0,  1,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   1,     0,   0 },
+  /* GNUCXX11 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    0,     0,     0,   0,      1,   1,     0,   0 },
+  /* CXX11    */  { 1,  1,  0,  1,  1,  1,  1,   1,   1,   1,    0,     0,     1,   0,      0,   1,     0,   0 },
+  /* GNUCXX14 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   0,      1,   1,     0,   0 },
+  /* CXX14    */  { 1,  1,  0,  1,  1,  1,  1,   1,   1,   1,    1,     1,     1,   0,      0,   1,     0,   0 },
+  /* GNUCXX17 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   0 },
+  /* CXX17    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      0,   1,     0,   0 },
+  /* GNUCXX20 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   0 },
+  /* CXX20    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   0 },
+  /* GNUCXX23 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   1 },
+  /* CXX23    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   1 },
+  /* ASM      */  { 0,  0,  1,  0,  0,  0,  0,   0,   0,   0,    0,     0,     0,   0,      0,   0,     0,   0 }
 };
 
 /* Sets internal flags correctly for a given language.  */
@@ -149,6 +150,7 @@ cpp_set_lang (cpp_reader *pfile, enum c_lang lang)
   CPP_OPTION (pfile, va_opt)			 = l->va_opt;
   CPP_OPTION (pfile, scope)			 = l->scope;
   CPP_OPTION (pfile, dfp_constants)		 = l->dfp_constants;
+  CPP_OPTION (pfile, size_t_literals)		 = l->size_t_literals;
 }
 
 /* Initialize library global state.  */
Jakub Jelinek Feb. 1, 2021, 7:23 p.m. UTC | #9
On Mon, Feb 01, 2021 at 01:46:13PM -0500, Ed Smith-Rowland wrote:
> @@ -0,0 +1,8 @@
> +// { dg-do compile { target c++23 } }
> +
> +#include <cstddef>
> +#include <type_traits>
> +
> +static_assert(std::is_same_v<decltype(123zu), std::size_t>);
> +static_assert(std::is_same_v<decltype(456z), std::ptrdiff_t>);

Shouldn't this be std::make_signed<std::size_t>::type instead of std::ptrdiff_t

> +std::ptrdiff_t pd1 = 1234z; // { dg-warning "use of C\+\+23 ptrdiff_t integer constant" "" { target c++20_down } }
> +std::ptrdiff_t PD1 = 5678Z; // { dg-warning "use of C\+\+23 ptrdiff_t integer constant" "" { target c++20_down } }

Ditto here.

> +	  const char *message = (result & CPP_N_UNSIGNED) == CPP_N_UNSIGNED
> +				? N_("use of C++23 size_t integer constant")
> +				: N_("use of C++23 ptrdiff_t integer constant");

And here too (perhaps %<make_signed<size_t>::type%> )?
And maybe %<size_t%> too.

> --- a/libcpp/include/cpplib.h
> +++ b/libcpp/include/cpplib.h
> @@ -500,6 +500,9 @@ struct cpp_options
>    /* Nonzero means tokenize C++20 module directives.  */
>    unsigned char module_directives;
>  
> +  /* Nonzero for C++23 ptrdiff_t and size_t literals.  */

And drop "ptrdiff_t and " here?

> +#define CPP_N_SIZE_T	0x2000000 /* C++23 size_t or ptrdiff_t literal  */

And " or ptrdiff_t" here?

While ptrdiff_t will usually be the same type, seems there is e.g.:
config/darwin.h:#define SIZE_TYPE "long unsigned int"
config/darwin.h:#define PTRDIFF_TYPE "int"
config/i386/djgpp.h:#define SIZE_TYPE "long unsigned int"
config/i386/djgpp.h:#define PTRDIFF_TYPE "int"
config/m32c/m32c.h:#define PTRDIFF_TYPE (TARGET_A16 ? "int" : "long int")
config/m32c/m32c.h:#define SIZE_TYPE "unsigned int"
config/rs6000/rs6000.h:#define PTRDIFF_TYPE "int"
config/rs6000/rs6000.h:#define SIZE_TYPE "long unsigned int"
config/s390/linux.h:#define SIZE_TYPE "long unsigned int"
config/s390/linux.h:#define PTRDIFF_TYPE (TARGET_64BIT ? "long int" : "int")
config/visium/visium.h:#define SIZE_TYPE "unsigned int"
config/visium/visium.h:#define PTRDIFF_TYPE "long int"
config/vms/vms.h:#define SIZE_TYPE  "unsigned int"
config/vms/vms.h:#define PTRDIFF_TYPE (flag_vms_pointer_size == VMS_POINTER_SIZE_NONE ? \
config/vms/vms.h-                      "int" : "long long int")
so quite a few differences.

	Jakub
Jason Merrill Feb. 1, 2021, 7:42 p.m. UTC | #10
On 2/1/21 1:46 PM, Ed Smith-Rowland wrote:
> On 2/1/21 10:33 AM, Jason Merrill wrote:
>> On 1/30/21 6:22 PM, Ed Smith-Rowland wrote:
>>> On 1/27/21 3:32 PM, Jakub Jelinek wrote:
>>>> On Sun, Oct 21, 2018 at 04:39:30PM -0400, Ed Smith-Rowland wrote:
>>>>> 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.
>>>> GCC now supports -std=c++2b and -std=gnu++2b, are you going to 
>>>> update your
>>>> patch against it (and change for z/Z standing for ssize_t rather than
>>>> ptrdiff_t), plus incorporate the feedback from Joseph and Jason?
>>>>
>>>>     Jakub
>>>>
>>> Here is a rebased patch that is a bit leaner than the original.
>>>
>>> Since I chose to be conservative in applying this just to C++23 I'm 
>>> not adding this to C or t earlier versions of C++ as extensions. We 
>>> can add that if people really want, maybe in stage 1.
>>>
>>> The compat warning for C++ < 23 is not optional. since the suffixes 
>>> are not preceded by '-' I don't hav much sympathy if people tried to 
>>> make a literal 'z' operator. Which is the only reason I can see for a 
>>> warning suppression.
>>
>>> +      /* itk refers to fundamental types not aliased size types.  */
>>> +      if (flags & CPP_N_UNSIGNED)
>>> +    type = size_type_node;
>>> +      else
>>> +    type = ptrdiff_type_node;
>>
> I thought size_type_node and ptrdiff_type_node were sort of fundamental 
> the the others derived:

Yes, but the final proposal specifies a suffix for signed size_t, not 
ptrdiff_t.

> ssize_t:
>    signed_size_type_node = c_common_signed_type (size_type_node);

Ah, I wasn't aware of signed_size_type_node, that's better than my 
suggestion of calling c_common_signed_type again.

Jason
Jakub Jelinek Feb. 1, 2021, 7:46 p.m. UTC | #11
On Mon, Feb 01, 2021 at 08:23:18PM +0100, Jakub Jelinek via Gcc-patches wrote:
> On Mon, Feb 01, 2021 at 01:46:13PM -0500, Ed Smith-Rowland wrote:
> > @@ -0,0 +1,8 @@
> > +// { dg-do compile { target c++23 } }
> > +
> > +#include <cstddef>
> > +#include <type_traits>
> > +
> > +static_assert(std::is_same_v<decltype(123zu), std::size_t>);
> > +static_assert(std::is_same_v<decltype(456z), std::ptrdiff_t>);
> 
> Shouldn't this be std::make_signed<std::size_t>::type instead of std::ptrdiff_t

Or better std::make_signed_t<std::size_t> etc.

	Jakub
Ed Smith-Rowland Feb. 2, 2021, 2:15 a.m. UTC | #12
On 2/1/21 2:23 PM, Jakub Jelinek wrote:
> On Mon, Feb 01, 2021 at 01:46:13PM -0500, Ed Smith-Rowland wrote:
>> @@ -0,0 +1,8 @@
>> +// { dg-do compile { target c++23 } }
>> +
>> +#include <cstddef>
>> +#include <type_traits>
>> +
>> +static_assert(std::is_same_v<decltype(123zu), std::size_t>);
>> +static_assert(std::is_same_v<decltype(456z), std::ptrdiff_t>);
> Shouldn't this be std::make_signed<std::size_t>::type instead of std::ptrdiff_t
Yes it should. The paper goes on about ptrdiff_t but at the very end 
they punt on that in favor of what you have.
>
>> +std::ptrdiff_t pd1 = 1234z; // { dg-warning "use of C\+\+23 ptrdiff_t integer constant" "" { target c++20_down } }
>> +std::ptrdiff_t PD1 = 5678Z; // { dg-warning "use of C\+\+23 ptrdiff_t integer constant" "" { target c++20_down } }
> Ditto here.
Agree.
>
>> +	  const char *message = (result & CPP_N_UNSIGNED) == CPP_N_UNSIGNED
>> +				? N_("use of C++23 size_t integer constant")
>> +				: N_("use of C++23 ptrdiff_t integer constant");
> And here too (perhaps %<make_signed<size_t>::type%> )?
> And maybe %<size_t%> too.
Agree.
>
>> --- a/libcpp/include/cpplib.h
>> +++ b/libcpp/include/cpplib.h
>> @@ -500,6 +500,9 @@ struct cpp_options
>>     /* Nonzero means tokenize C++20 module directives.  */
>>     unsigned char module_directives;
>>   
>> +  /* Nonzero for C++23 ptrdiff_t and size_t literals.  */
> And drop "ptrdiff_t and " here?
>
>> +#define CPP_N_SIZE_T	0x2000000 /* C++23 size_t or ptrdiff_t literal  */
> And " or ptrdiff_t" here?
>
> While ptrdiff_t will usually be the same type, seems there is e.g.:
> config/darwin.h:#define SIZE_TYPE "long unsigned int"
> config/darwin.h:#define PTRDIFF_TYPE "int"
> config/i386/djgpp.h:#define SIZE_TYPE "long unsigned int"
> config/i386/djgpp.h:#define PTRDIFF_TYPE "int"
> config/m32c/m32c.h:#define PTRDIFF_TYPE (TARGET_A16 ? "int" : "long int")
> config/m32c/m32c.h:#define SIZE_TYPE "unsigned int"
> config/rs6000/rs6000.h:#define PTRDIFF_TYPE "int"
> config/rs6000/rs6000.h:#define SIZE_TYPE "long unsigned int"
> config/s390/linux.h:#define SIZE_TYPE "long unsigned int"
> config/s390/linux.h:#define PTRDIFF_TYPE (TARGET_64BIT ? "long int" : "int")
> config/visium/visium.h:#define SIZE_TYPE "unsigned int"
> config/visium/visium.h:#define PTRDIFF_TYPE "long int"
> config/vms/vms.h:#define SIZE_TYPE  "unsigned int"
> config/vms/vms.h:#define PTRDIFF_TYPE (flag_vms_pointer_size == VMS_POINTER_SIZE_NONE ? \
> config/vms/vms.h-                      "int" : "long long int")
> so quite a few differences.
>
> 	Jakub

Here is my last patch with all the concerns addressed.

I am not smart enough to get the dg-warning regex in Wsize_t-literals.C 
to work. If someone could carry this over the finish line that would be 
great. Or give me pointers. I can't any more.

Ed
diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
index dca6815a876..48dec21d4b4 100644
--- a/gcc/c-family/c-cppbuiltin.c
+++ b/gcc/c-family/c-cppbuiltin.c
@@ -1025,6 +1025,11 @@ c_cpp_builtins (cpp_reader *pfile)
 	  cpp_define (pfile, "__cpp_aggregate_paren_init=201902L");
 	  cpp_define (pfile, "__cpp_using_enum=201907L");
 	}
+      if (cxx_dialect > cxx20)
+	{
+	  /* Set feature test macros for C++23.  */
+	  cpp_define (pfile, "__cpp_size_t_suffix=202006L");
+	}
       if (flag_concepts)
         {
 	  if (cxx_dialect >= cxx20)
diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c
index fe40a0f728b..6374b72ed2d 100644
--- a/gcc/c-family/c-lex.c
+++ b/gcc/c-family/c-lex.c
@@ -834,6 +834,14 @@ interpret_integer (const cpp_token *token, unsigned int flags,
     type = ((flags & CPP_N_UNSIGNED)
 	    ? widest_unsigned_literal_type_node
 	    : widest_integer_literal_type_node);
+  else if (flags & CPP_N_SIZE_T)
+    {
+      /* itk refers to fundamental types not aliased size types.  */
+      if (flags & CPP_N_UNSIGNED)
+	type = size_type_node;
+      else
+	type = signed_size_type_node;
+    }
   else
     {
       type = integer_types[itk];
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C
index fdddd8d84ed..a30ec0f4f7e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C
@@ -17,6 +17,30 @@ unsigned long long int
 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,13 +61,50 @@ unsigned long long int
 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 }
 // { 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 }
diff --git a/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C b/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C
new file mode 100644
index 00000000000..94e08a4896c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C
@@ -0,0 +1,549 @@
+// { dg-options "-std=c++2b -I${srcdir}/g++.dg/cpp1y -I${srcdir}/g++.dg/cpp1y/testinc" }
+
+//  C++98 features:
+
+#ifndef __cpp_rtti
+#  error "__cpp_rtti"
+#elif  __cpp_rtti != 199711
+#  error "__cpp_rtti != 199711"
+#endif
+
+#ifndef __cpp_exceptions
+#  error "__cpp_exceptions"
+#elif  __cpp_exceptions != 199711
+#  error "__cpp_exceptions != 199711"
+#endif
+
+//  C++11 features:
+
+#ifndef __cpp_raw_strings
+#  error "__cpp_raw_strings"
+#elif __cpp_raw_strings != 200710
+#  error "__cpp_raw_strings != 200710"
+#endif
+
+#ifndef __cpp_unicode_literals
+#  error "__cpp_unicode_literals"
+#elif __cpp_unicode_literals != 200710
+#  error "__cpp_unicode_literals != 200710"
+#endif
+
+#ifndef __cpp_user_defined_literals
+#  error "__cpp_user_defined_literals"
+#elif __cpp_user_defined_literals != 200809
+#  error "__cpp_user_defined_literals != 200809"
+#endif
+
+#ifndef __cpp_lambdas
+#  error "__cpp_lambdas"
+#elif __cpp_lambdas != 200907
+#  error "__cpp_lambdas != 200907"
+#endif
+
+#ifndef __cpp_range_based_for
+#  error "__cpp_range_based_for"
+#elif __cpp_range_based_for != 201603
+#  error "__cpp_range_based_for != 201603"
+#endif
+
+#ifndef __cpp_decltype
+#  error "__cpp_decltype"
+#elif __cpp_decltype != 200707
+#  error "__cpp_decltype != 200707"
+#endif
+
+#ifndef __cpp_attributes
+#  error "__cpp_attributes"
+#elif __cpp_attributes != 200809
+#  error "__cpp_attributes != 200809"
+#endif
+
+#ifndef __cpp_rvalue_references
+#  error "__cpp_rvalue_references"
+#elif __cpp_rvalue_references != 200610
+#  error "__cpp_rvalue_references != 200610"
+#endif
+
+#ifndef __cpp_variadic_templates
+#  error "__cpp_variadic_templates"
+#elif __cpp_variadic_templates != 200704
+#  error "__cpp_variadic_templates != 200704"
+#endif
+
+#ifndef __cpp_initializer_lists
+#  error "__cpp_initializer_lists"
+#elif __cpp_initializer_lists != 200806
+#  error "__cpp_initializer_lists != 200806"
+#endif
+
+#ifndef __cpp_delegating_constructors
+#  error "__cpp_delegating_constructors"
+#elif __cpp_delegating_constructors != 200604
+#  error "__cpp_delegating_constructors != 200604"
+#endif
+
+#ifndef __cpp_nsdmi
+#  error "__cpp_nsdmi"
+#elif __cpp_nsdmi != 200809
+#  error "__cpp_nsdmi != 200809"
+#endif
+
+#ifndef __cpp_inheriting_constructors
+#  error "__cpp_inheriting_constructors"
+#elif  __cpp_inheriting_constructors!= 201511
+#  error "__cpp_inheriting_constructors != 201511"
+#endif
+
+#ifndef __cpp_ref_qualifiers
+#  error "__cpp_ref_qualifiers"
+#elif __cpp_ref_qualifiers != 200710
+#  error "__cpp_ref_qualifiers != 200710"
+#endif
+
+#ifndef __cpp_alias_templates
+#  error "__cpp_alias_templates"
+#elif __cpp_alias_templates != 200704
+#  error "__cpp_alias_templates != 200704"
+#endif
+
+#ifndef __cpp_threadsafe_static_init
+#  error "__cpp_threadsafe_static_init"
+#elif __cpp_threadsafe_static_init != 200806
+#  error "__cpp_threadsafe_static_init != 200806"
+#endif
+
+//  C++14 features:
+
+#ifndef __cpp_binary_literals
+#  error "__cpp_binary_literals"
+#elif __cpp_binary_literals != 201304
+#  error "__cpp_binary_literals != 201304"
+#endif
+
+#ifndef __cpp_init_captures
+#  error "__cpp_init_captures"
+#elif __cpp_init_captures != 201803
+#  error "__cpp_init_captures != 201803"
+#endif
+
+#ifndef __cpp_generic_lambdas
+#  error "__cpp_generic_lambdas"
+#elif __cpp_generic_lambdas != 201707
+#  error "__cpp_generic_lambdas != 201707"
+#endif
+
+#ifndef __cpp_constexpr
+#  error "__cpp_constexpr"
+#elif __cpp_constexpr != 201907
+#  error "__cpp_constexpr != 201907"
+#endif
+
+#ifndef __cpp_decltype_auto
+#  error "__cpp_decltype_auto"
+#elif __cpp_decltype_auto != 201304
+#  error "__cpp_decltype_auto != 201304"
+#endif
+
+#ifndef __cpp_return_type_deduction
+#  error "__cpp_return_type_deduction"
+#elif __cpp_return_type_deduction != 201304
+#  error "__cpp_return_type_deduction != 201304"
+#endif
+
+#ifndef __cpp_aggregate_nsdmi
+#  error "__cpp_aggregate_nsdmi"
+#elif __cpp_aggregate_nsdmi != 201304
+#  error "__cpp_aggregate_nsdmi != 201304"
+#endif
+
+#ifndef __cpp_variable_templates
+#  error "__cpp_variable_templates"
+#elif __cpp_variable_templates != 201304
+#  error "__cpp_variable_templates != 201304"
+#endif
+
+#ifndef __cpp_digit_separators
+#  error "__cpp_digit_separators"
+#elif __cpp_digit_separators != 201309
+#  error "__cpp_digit_separators != 201309"
+#endif
+
+#ifndef __cpp_sized_deallocation
+#  error "__cpp_sized_deallocation"
+#elif __cpp_sized_deallocation != 201309
+#  error "__cpp_sized_deallocation != 201309"
+#endif
+
+//  GNU VLA support:
+
+#ifndef __cpp_runtime_arrays
+#  error "__cpp_runtime_arrays"
+#elif __cpp_runtime_arrays != 198712
+#  error "__cpp_runtime_arrays != 198712"
+#endif
+
+//  C++11 attributes:
+
+#ifdef __has_cpp_attribute
+#  if ! __has_cpp_attribute(noreturn)
+#    error "__has_cpp_attribute(noreturn)"
+#  elif __has_cpp_attribute(noreturn) != 200809
+#    error "__has_cpp_attribute(noreturn) != 200809"
+#  endif
+#else
+#  error "__has_cpp_attribute"
+#endif
+
+//  Attribute carries_dependency not in yet.
+//#ifdef __has_cpp_attribute
+//#  if ! __has_cpp_attribute(carries_dependency)
+//#    error "__has_cpp_attribute(carries_dependency)"
+//#  elif __has_cpp_attribute(carries_dependency) != 200809
+//#    error "__has_cpp_attribute(carries_dependency) != 200809"
+//#  endif
+//#else
+//#  error "__has_cpp_attribute"
+//#endif
+
+//  C++14 attributes:
+
+#ifdef __has_cpp_attribute
+#  if ! __has_cpp_attribute(deprecated)
+#    error "__has_cpp_attribute(deprecated)"
+#  elif __has_cpp_attribute(deprecated) != 201309
+#    error "__has_cpp_attribute(deprecated) != 201309"
+#  endif
+#else
+#  error "__has_cpp_attribute"
+#endif
+
+//  Include checks:
+
+//  Check for __has_include macro.
+#ifndef __has_include
+#  error "__has_include"
+#endif
+
+//  Try known bracket header (use operator).
+#if __has_include (<complex>)
+#else
+#  error "<complex>"
+#endif
+
+//  Define and use a macro to invoke the operator.
+#define sluggo(TXT) __has_include(TXT)
+
+#if sluggo(<complex>)
+#else
+#  error "<complex>"
+#endif
+
+#if ! sluggo(<complex>)
+#  error "<complex>"
+#else
+#endif
+
+//  Quoted complex.h should find at least the bracket version.
+#if __has_include("complex.h")
+#else
+#  error "complex.h"
+#endif
+
+//  Try known local quote header.
+#if __has_include("complex_literals.h")
+#else
+#  error "\"complex_literals.h\""
+#endif
+
+//  Try nonexistent bracket header.
+#if __has_include(<stuff>)
+#  error "<stuff>"
+#else
+#endif
+
+//  Try nonexistent quote header.
+#if __has_include("phlegm")
+#  error "\"phlegm\""
+#else
+#endif
+
+//  Test __has_include_next.
+#if __has_include("phoobhar.h")
+#  include "phoobhar.h"
+#else
+#  error "__has_include(\"phoobhar.h\")"
+#endif
+
+//  Try a macro.
+#define COMPLEX_INC "complex.h"
+#if __has_include(COMPLEX_INC)
+#else
+#  error COMPLEX_INC
+#endif
+
+//  Realistic use of __has_include.
+#if __has_include(<array>)
+#  define STD_ARRAY 1
+#  include <array>
+  template<typename _Tp, std::size_t _Num>
+    using array = std::array<_Tp, _Num>;
+#elif __has_include(<tr1/array>)
+#  define TR1_ARRAY 1
+#  include <tr1/array>
+  template<typename _Tp, std::size_t _Num>
+    typedef std::tr1::array<_Tp, _Num> array;
+#endif
+
+// C++17 features:
+
+#ifndef __cpp_unicode_characters
+#  error "__cpp_unicode_characters"
+#elif __cpp_unicode_characters != 201411
+#  error "__cpp_unicode_characters != 201411"
+#endif
+
+#ifndef __cpp_static_assert
+#  error "__cpp_static_assert"
+#elif __cpp_static_assert != 201411
+#  error "__cpp_static_assert != 201411"
+#endif
+
+#ifndef __cpp_namespace_attributes
+#  error "__cpp_namespace_attributes"
+#elif __cpp_namespace_attributes != 201411
+#  error "__cpp_namespace_attributes != 201411"
+#endif
+
+#ifndef __cpp_enumerator_attributes
+#  error "__cpp_enumerator_attributes"
+#elif __cpp_enumerator_attributes != 201411
+#  error "__cpp_enumerator_attributes != 201411"
+#endif
+
+#ifndef __cpp_nested_namespace_definitions
+#  error "__cpp_nested_namespace_definitions"
+#elif __cpp_nested_namespace_definitions != 201411
+#  error "__cpp_nested_namespace_definitions != 201411"
+#endif
+
+#ifndef __cpp_fold_expressions
+#  error "__cpp_fold_expressions"
+#elif __cpp_fold_expressions != 201603
+#  error "__cpp_fold_expressions != 201603"
+#endif
+
+#ifndef __cpp_nontype_template_args
+#  error "__cpp_nontype_template_args"
+#elif __cpp_nontype_template_args != 201911
+#  error "__cpp_nontype_template_args != 201911"
+#endif
+
+#ifndef __cpp_hex_float
+#  error "__cpp_hex_float"
+#elif __cpp_hex_float != 201603
+#  error "__cpp_hex_float != 201603"
+#endif
+
+#ifndef __cpp_aggregate_bases
+#  error "__cpp_aggregate_bases"
+#elif __cpp_aggregate_bases != 201603
+#  error "__cpp_aggregate_bases != 201603"
+#endif
+
+#ifndef __cpp_deduction_guides
+#  error "__cpp_deduction_guides"
+#elif __cpp_deduction_guides != 201907
+#  error "__cpp_deduction_guides != 201907"
+#endif
+
+#ifndef __cpp_if_constexpr
+#  error "__cpp_if_constexpr"
+#elif __cpp_if_constexpr != 201606
+#  error "__cpp_if_constexpr != 201606"
+#endif
+
+#ifndef __cpp_aligned_new
+#  error "__cpp_aligned_new"
+#elif __cpp_aligned_new != 201606
+#  error "__cpp_aligned_new != 201606"
+#endif
+
+#ifndef __cpp_template_auto
+#  error "__cpp_template_auto"
+#elif __cpp_template_auto != 201606
+#  error "__cpp_template_auto != 201606"
+#endif
+
+#ifndef __cpp_inline_variables
+#  error "__cpp_inline_variables"
+#elif __cpp_inline_variables != 201606
+#  error "__cpp_inline_variables != 201606"
+#endif
+
+#ifndef __cpp_capture_star_this
+#  error "__cpp_capture_star_this"
+#elif __cpp_capture_star_this != 201603
+#  error "__cpp_capture_star_this != 201603"
+#endif
+
+#ifndef __cpp_noexcept_function_type
+#  error "__cpp_noexcept_function_type"
+#elif __cpp_noexcept_function_type != 201510
+#  error "__cpp_noexcept_function_type != 201510"
+#endif
+
+#ifndef __cpp_structured_bindings
+#  error "__cpp_structured_bindings"
+#elif __cpp_structured_bindings != 201606
+#  error "__cpp_structured_bindings != 201606"
+#endif
+
+#ifndef __cpp_template_template_args
+#  error "__cpp_template_template_args"
+#elif __cpp_template_template_args != 201611
+#  error "__cpp_template_template_args != 201611"
+#endif
+
+#ifndef __cpp_variadic_using
+#  error "__cpp_variadic_using"
+#elif __cpp_variadic_using != 201611
+#  error "__cpp_variadic_using != 201611"
+#endif
+
+#ifndef __cpp_guaranteed_copy_elision
+#  error "__cpp_guaranteed_copy_elision"
+#elif __cpp_guaranteed_copy_elision != 201606
+#  error "__cpp_guaranteed_copy_elision != 201606"
+#endif
+
+#ifndef __cpp_nontype_template_parameter_auto
+#  error "__cpp_nontype_template_parameter_auto"
+#elif __cpp_nontype_template_parameter_auto != 201606
+#  error "__cpp_nontype_template_parameter_auto != 201606"
+#endif
+
+// C++20 features
+
+#ifndef __cpp_conditional_explicit
+#  error "__cpp_conditional_explicit"
+#elif __cpp_conditional_explicit != 201806
+#  error "__cpp_conditional_explicit != 201806"
+#endif
+
+#ifndef __cpp_nontype_template_parameter_class
+#  error "__cpp_nontype_template_parameter_class"
+#elif __cpp_nontype_template_parameter_class != 201806
+#  error "__cpp_nontype_template_parameter_class != 201806"
+#endif
+
+#ifndef __cpp_impl_destroying_delete
+#  error "__cpp_impl_destroying_delete"
+#elif __cpp_impl_destroying_delete != 201806
+#  error "__cpp_impl_destroying_delete != 201806"
+#endif
+
+#ifndef __cpp_constinit
+#  error "__cpp_constinit"
+#elif __cpp_constinit != 201907
+#  error "__cpp_constinit != 201907"
+#endif
+
+#ifndef __cpp_constexpr_dynamic_alloc
+#  error "__cpp_constexpr_dynamic_alloc"
+#elif __cpp_constexpr_dynamic_alloc != 201907
+#  error "__cpp_constexpr_dynamic_alloc != 201907"
+#endif
+
+#ifndef __cpp_aggregate_paren_init
+#  error "__cpp_aggregate_paren_init"
+#elif __cpp_aggregate_paren_init != 201902
+#  error "__cpp_aggregate_paren_init != 201902"
+#endif
+
+#ifdef __has_cpp_attribute
+
+#  if ! __has_cpp_attribute(maybe_unused)
+#    error "__has_cpp_attribute(maybe_unused)"
+#  elif __has_cpp_attribute(maybe_unused) != 201603
+#    error "__has_cpp_attribute(maybe_unused) != 201603"
+#  endif
+
+#  if ! __has_cpp_attribute(nodiscard)
+#    error "__has_cpp_attribute(nodiscard)"
+#  elif __has_cpp_attribute(nodiscard) != 201907
+#    error "__has_cpp_attribute(nodiscard) != 201907"
+#  endif
+
+#  if ! __has_cpp_attribute(fallthrough)
+#    error "__has_cpp_attribute(fallthrough)"
+#  elif __has_cpp_attribute(fallthrough) != 201603
+#    error "__has_cpp_attribute(fallthrough) != 201603"
+#  endif
+
+#  if ! __has_cpp_attribute(no_unique_address)
+#    error "__has_cpp_attribute(no_unique_address)"
+#  elif __has_cpp_attribute(no_unique_address) != 201803
+#    error "__has_cpp_attribute(no_unique_address) != 201803"
+#  endif
+
+#  if ! __has_cpp_attribute(likely)
+#    error "__has_cpp_attribute(likely)"
+#  elif __has_cpp_attribute(likely) != 201803
+#    error "__has_cpp_attribute(likely) != 201803"
+#  endif
+
+#  if ! __has_cpp_attribute(unlikely)
+#    error "__has_cpp_attribute(unlikely)"
+#  elif __has_cpp_attribute(unlikely) != 201803
+#    error "__has_cpp_attribute(unlikely) != 201803"
+#  endif
+
+#else
+#  error "__has_cpp_attribute"
+#endif
+
+#ifndef __cpp_char8_t
+#  error "__cpp_char8_t"
+#elif __cpp_char8_t != 201811
+#  error "__cpp_char8_t != 201811"
+#endif
+
+#ifndef __cpp_designated_initializers
+#  error "__cpp_designated_initializers"
+#elif __cpp_designated_initializers != 201707
+#  error "__cpp_designated_initializers != 201707"
+#endif
+
+#ifndef __cpp_constexpr_in_decltype
+#  error "__cpp_constexpr_in_decltype"
+#elif __cpp_constexpr_in_decltype != 201711
+#  error "__cpp_constexpr_in_decltype != 201711"
+#endif
+
+/* Not supported fully yet:
+#ifndef __cpp_consteval
+#  error "__cpp_consteval"
+#elif __cpp_consteval != 201811
+#  error "__cpp_consteval != 201811"
+#endif
+*/
+
+#ifndef __cpp_concepts
+#  error "__cpp_concepts"
+#elif __cpp_concepts != 201907
+#  error "__cpp_concepts != 201907"
+#endif
+
+#ifndef __cpp_using_enum
+#  error "__cpp_using_enum"
+#elif __cpp_using_enum != 201907
+#  error "__cpp_using_enum != 201907"
+#endif
+
+// C++23 features:
+
+#ifndef __cpp_size_t_suffix
+#  error "__cpp_size_t_suffix"
+#elif __cpp_size_t_suffix != 202006
+#  error "__cpp_size_t_suffix != 202006"
+#endif
diff --git a/gcc/testsuite/g++.dg/cpp23/size_t-literals.C b/gcc/testsuite/g++.dg/cpp23/size_t-literals.C
new file mode 100644
index 00000000000..3488032de3f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/size_t-literals.C
@@ -0,0 +1,8 @@
+// { dg-do compile { target c++23 } }
+
+#include <cstddef>
+#include <type_traits>
+
+static_assert(std::is_same_v<decltype(123zu), std::size_t>);
+static_assert(std::is_same_v<decltype(456z), std::make_signed_t<std::size_t>>);
+
diff --git a/gcc/testsuite/g++.dg/warn/Wsize_t-literals.C b/gcc/testsuite/g++.dg/warn/Wsize_t-literals.C
new file mode 100644
index 00000000000..8e077965bb1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wsize_t-literals.C
@@ -0,0 +1,16 @@
+// { dg-do compile { target c++20_down } }
+
+#if __cplusplus >= 201103L
+
+#include <cstddef>
+#include <type_traits>
+
+std::size_t s1 = 1234zu; // { dg-warning "use of C\+\+23 .size_t. integer constant" "" { target c++20_down } }
+std::size_t S1 = 5678ZU; // { dg-warning "use of C\+\+23 .size_t. integer constant" "" { target c++20_down } }
+std::size_t s2 = 1234uz; // { dg-warning "use of C\+\+23 .size_t. integer constant" "" { target c++20_down } }
+std::size_t S2 = 5678UZ; // { dg-warning "use of C\+\+23 .size_t. integer constant" "" { target c++20_down } }
+
+std::make_signed<std::size_t>::type pd1 = 1234z; // { dg-warning "use of C\+\+23 .make_signed<size_t>::type. integer constant" "" { target c++20_down } }
+std::make_signed<std::size_t>::type PD1 = 5678Z; // { dg-warning "use of C\+\+23 .make_signed<size_t>::type. integer constant" "" { target c++20_down } }
+
+#endif
diff --git a/libcpp/expr.c b/libcpp/expr.c
index 474ea4d6b6f..42007f98b93 100644
--- a/libcpp/expr.c
+++ b/libcpp/expr.c
@@ -313,13 +313,14 @@ static unsigned int
 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;
+  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;
@@ -332,9 +333,17 @@ interpret_int_suffix (cpp_reader *pfile, const uchar *s, size_t len)
 	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))
@@ -352,7 +361,8 @@ interpret_int_suffix (cpp_reader *pfile, const uchar *s, size_t len)
   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_SIZE_T : 0));
 }
 
 /* Return the classification flags for an int suffix.  */
@@ -805,6 +815,16 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
 				      virtual_location, 0, message);
         }
 
+      if ((result & CPP_N_SIZE_T) == CPP_N_SIZE_T
+	  && !CPP_OPTION (pfile, size_t_literals))
+       {
+	  const char *message = (result & CPP_N_UNSIGNED) == CPP_N_UNSIGNED
+				? N_("use of C++23 %<size_t%> integer constant")
+				: N_("use of C++23 %<make_signed<size_t>::type%> integer constant");
+	  cpp_warning_with_line (pfile, CPP_W_SIZE_T_LITERALS,
+				 virtual_location, 0, message);
+       }
+
       result |= CPP_N_INTEGER;
     }
 
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
index 4467c73284d..17feb648ebe 100644
--- a/libcpp/include/cpplib.h
+++ b/libcpp/include/cpplib.h
@@ -500,6 +500,9 @@ struct cpp_options
   /* Nonzero means tokenize C++20 module directives.  */
   unsigned char module_directives;
 
+  /* Nonzero for C++23 size_t literals.  */
+  unsigned char size_t_literals;
+
   /* Holds the name of the target (execution) character set.  */
   const char *narrow_charset;
 
@@ -626,6 +629,7 @@ enum cpp_warning_reason {
   CPP_W_INVALID_PCH,
   CPP_W_WARNING_DIRECTIVE,
   CPP_W_LITERAL_SUFFIX,
+  CPP_W_SIZE_T_LITERALS,
   CPP_W_DATE_TIME,
   CPP_W_PEDANTIC,
   CPP_W_C90_C99_COMPAT,
@@ -1211,7 +1215,9 @@ struct cpp_num
 #define CPP_N_FLOATN	0x400000 /* _FloatN types.  */
 #define CPP_N_FLOATNX	0x800000 /* _FloatNx types.  */
 
-#define CPP_N_USERDEF	0x1000000 /* C++0x user-defined literal.  */
+#define CPP_N_USERDEF	0x1000000 /* C++11 user-defined literal.  */
+
+#define CPP_N_SIZE_T	0x2000000 /* C++23 size_t literal.  */
 
 #define CPP_N_WIDTH_FLOATN_NX	0xF0000000 /* _FloatN / _FloatNx value
 					      of N, divided by 16.  */
diff --git a/libcpp/init.c b/libcpp/init.c
index ecd3d5be7fd..17b0d251cda 100644
--- a/libcpp/init.c
+++ b/libcpp/init.c
@@ -94,34 +94,35 @@ struct lang_flags
   char va_opt;
   char scope;
   char dfp_constants;
+  char size_t_literals;
 };
 
 static const struct lang_flags lang_defaults[] =
-{ /*              c99 c++ xnum xid c11 std digr ulit rlit udlit bincst digsep trig u8chlit vaopt scope dfp */
-  /* GNUC89   */  { 0,  0,  1,  0,  0,  0,  1,   0,   0,   0,    0,     0,     0,   0,      1,   1,     0 },
-  /* GNUC99   */  { 1,  0,  1,  1,  0,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0 },
-  /* GNUC11   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0 },
-  /* GNUC17   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0 },
-  /* GNUC2X   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    1,     0,     0,   1,      1,   1,     1 },
-  /* STDC89   */  { 0,  0,  0,  0,  0,  1,  0,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0 },
-  /* STDC94   */  { 0,  0,  0,  0,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0 },
-  /* STDC99   */  { 1,  0,  1,  1,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0 },
-  /* STDC11   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    0,     0,     1,   0,      0,   0,     0 },
-  /* STDC17   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    0,     0,     1,   0,      0,   0,     0 },
-  /* STDC2X   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    1,     0,     1,   1,      0,   1,     1 },
-  /* GNUCXX   */  { 0,  1,  1,  1,  0,  0,  1,   0,   0,   0,    0,     0,     0,   0,      1,   1,     0 },
-  /* CXX98    */  { 0,  1,  0,  1,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   1,     0 },
-  /* GNUCXX11 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    0,     0,     0,   0,      1,   1,     0 },
-  /* CXX11    */  { 1,  1,  0,  1,  1,  1,  1,   1,   1,   1,    0,     0,     1,   0,      0,   1,     0 },
-  /* GNUCXX14 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   0,      1,   1,     0 },
-  /* CXX14    */  { 1,  1,  0,  1,  1,  1,  1,   1,   1,   1,    1,     1,     1,   0,      0,   1,     0 },
-  /* GNUCXX17 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0 },
-  /* CXX17    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      0,   1,     0 },
-  /* GNUCXX20 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0 },
-  /* CXX20    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0 },
-  /* GNUCXX23 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0 },
-  /* CXX23    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0 },
-  /* ASM      */  { 0,  0,  1,  0,  0,  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 scope dfp szlit */
+  /* GNUC89   */  { 0,  0,  1,  0,  0,  0,  1,   0,   0,   0,    0,     0,     0,   0,      1,   1,     0,   0 },
+  /* GNUC99   */  { 1,  0,  1,  1,  0,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0,   0 },
+  /* GNUC11   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0,   0 },
+  /* GNUC17   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0,   0 },
+  /* GNUC2X   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    1,     0,     0,   1,      1,   1,     1,   0 },
+  /* STDC89   */  { 0,  0,  0,  0,  0,  1,  0,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0 },
+  /* STDC94   */  { 0,  0,  0,  0,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0 },
+  /* STDC99   */  { 1,  0,  1,  1,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0 },
+  /* STDC11   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0 },
+  /* STDC17   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0 },
+  /* STDC2X   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    1,     0,     1,   1,      0,   1,     1,   0 },
+  /* GNUCXX   */  { 0,  1,  1,  1,  0,  0,  1,   0,   0,   0,    0,     0,     0,   0,      1,   1,     0,   0 },
+  /* CXX98    */  { 0,  1,  0,  1,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   1,     0,   0 },
+  /* GNUCXX11 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    0,     0,     0,   0,      1,   1,     0,   0 },
+  /* CXX11    */  { 1,  1,  0,  1,  1,  1,  1,   1,   1,   1,    0,     0,     1,   0,      0,   1,     0,   0 },
+  /* GNUCXX14 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   0,      1,   1,     0,   0 },
+  /* CXX14    */  { 1,  1,  0,  1,  1,  1,  1,   1,   1,   1,    1,     1,     1,   0,      0,   1,     0,   0 },
+  /* GNUCXX17 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   0 },
+  /* CXX17    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      0,   1,     0,   0 },
+  /* GNUCXX20 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   0 },
+  /* CXX20    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   0 },
+  /* GNUCXX23 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   1 },
+  /* CXX23    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   1 },
+  /* ASM      */  { 0,  0,  1,  0,  0,  0,  0,   0,   0,   0,    0,     0,     0,   0,      0,   0,     0,   0 }
 };
 
 /* Sets internal flags correctly for a given language.  */
@@ -149,6 +150,7 @@ cpp_set_lang (cpp_reader *pfile, enum c_lang lang)
   CPP_OPTION (pfile, va_opt)			 = l->va_opt;
   CPP_OPTION (pfile, scope)			 = l->scope;
   CPP_OPTION (pfile, dfp_constants)		 = l->dfp_constants;
+  CPP_OPTION (pfile, size_t_literals)		 = l->size_t_literals;
 }
 
 /* Initialize library global state.  */
Jason Merrill Feb. 2, 2021, 5:12 a.m. UTC | #13
On 2/1/21 9:15 PM, Ed Smith-Rowland wrote:
> On 2/1/21 2:23 PM, Jakub Jelinek wrote:
>> On Mon, Feb 01, 2021 at 01:46:13PM -0500, Ed Smith-Rowland wrote:
>>> @@ -0,0 +1,8 @@
>>> +// { dg-do compile { target c++23 } }
>>> +
>>> +#include <cstddef>
>>> +#include <type_traits>
>>> +
>>> +static_assert(std::is_same_v<decltype(123zu), std::size_t>);
>>> +static_assert(std::is_same_v<decltype(456z), std::ptrdiff_t>);
>> Shouldn't this be std::make_signed<std::size_t>::type instead of 
>> std::ptrdiff_t
> Yes it should. The paper goes on about ptrdiff_t but at the very end 
> they punt on that in favor of what you have.
>>
>>> +std::ptrdiff_t pd1 = 1234z; // { dg-warning "use of C\+\+23 
>>> ptrdiff_t integer constant" "" { target c++20_down } }
>>> +std::ptrdiff_t PD1 = 5678Z; // { dg-warning "use of C\+\+23 
>>> ptrdiff_t integer constant" "" { target c++20_down } }
>> Ditto here.
> Agree.
>>
>>> +      const char *message = (result & CPP_N_UNSIGNED) == CPP_N_UNSIGNED
>>> +                ? N_("use of C++23 size_t integer constant")
>>> +                : N_("use of C++23 ptrdiff_t integer constant");
>> And here too (perhaps %<make_signed<size_t>::type%> )?
>> And maybe %<size_t%> too.
> Agree.
>>
>>> --- a/libcpp/include/cpplib.h
>>> +++ b/libcpp/include/cpplib.h
>>> @@ -500,6 +500,9 @@ struct cpp_options
>>>     /* Nonzero means tokenize C++20 module directives.  */
>>>     unsigned char module_directives;
>>> +  /* Nonzero for C++23 ptrdiff_t and size_t literals.  */
>> And drop "ptrdiff_t and " here?
>>
>>> +#define CPP_N_SIZE_T    0x2000000 /* C++23 size_t or ptrdiff_t 
>>> literal  */
>> And " or ptrdiff_t" here?
>>
>> While ptrdiff_t will usually be the same type, seems there is e.g.:
>> config/darwin.h:#define SIZE_TYPE "long unsigned int"
>> config/darwin.h:#define PTRDIFF_TYPE "int"
>> config/i386/djgpp.h:#define SIZE_TYPE "long unsigned int"
>> config/i386/djgpp.h:#define PTRDIFF_TYPE "int"
>> config/m32c/m32c.h:#define PTRDIFF_TYPE (TARGET_A16 ? "int" : "long int")
>> config/m32c/m32c.h:#define SIZE_TYPE "unsigned int"
>> config/rs6000/rs6000.h:#define PTRDIFF_TYPE "int"
>> config/rs6000/rs6000.h:#define SIZE_TYPE "long unsigned int"
>> config/s390/linux.h:#define SIZE_TYPE "long unsigned int"
>> config/s390/linux.h:#define PTRDIFF_TYPE (TARGET_64BIT ? "long int" : 
>> "int")
>> config/visium/visium.h:#define SIZE_TYPE "unsigned int"
>> config/visium/visium.h:#define PTRDIFF_TYPE "long int"
>> config/vms/vms.h:#define SIZE_TYPE  "unsigned int"
>> config/vms/vms.h:#define PTRDIFF_TYPE (flag_vms_pointer_size == 
>> VMS_POINTER_SIZE_NONE ? \
>> config/vms/vms.h-                      "int" : "long long int")
>> so quite a few differences.
>>
>>     Jakub
> 
> Here is my last patch with all the concerns addressed.
> 
> I am not smart enough to get the dg-warning regex in Wsize_t-literals.C 
> to work. If someone could carry this over the finish line that would be 
> great. Or give me pointers. I can't any more.

Your regex will work fine if you wrap it in {} instead of "", e.g.

{ dg-warning {use of C\+\+23 .size_t. integer constant} }

Jason
Ed Smith-Rowland Feb. 2, 2021, 6:19 a.m. UTC | #14
On 2/2/21 12:12 AM, Jason Merrill wrote:
> On 2/1/21 9:15 PM, Ed Smith-Rowland wrote:
>> On 2/1/21 2:23 PM, Jakub Jelinek wrote:
>>> On Mon, Feb 01, 2021 at 01:46:13PM -0500, Ed Smith-Rowland wrote:
>>>> @@ -0,0 +1,8 @@
>>>> +// { dg-do compile { target c++23 } }
>>>> +
>>>> +#include <cstddef>
>>>> +#include <type_traits>
>>>> +
>>>> +static_assert(std::is_same_v<decltype(123zu), std::size_t>);
>>>> +static_assert(std::is_same_v<decltype(456z), std::ptrdiff_t>);
>>> Shouldn't this be std::make_signed<std::size_t>::type instead of 
>>> std::ptrdiff_t
>> Yes it should. The paper goes on about ptrdiff_t but at the very end 
>> they punt on that in favor of what you have.
>>>
>>>> +std::ptrdiff_t pd1 = 1234z; // { dg-warning "use of C\+\+23 
>>>> ptrdiff_t integer constant" "" { target c++20_down } }
>>>> +std::ptrdiff_t PD1 = 5678Z; // { dg-warning "use of C\+\+23 
>>>> ptrdiff_t integer constant" "" { target c++20_down } }
>>> Ditto here.
>> Agree.
>>>
>>>> +      const char *message = (result & CPP_N_UNSIGNED) == 
>>>> CPP_N_UNSIGNED
>>>> +                ? N_("use of C++23 size_t integer constant")
>>>> +                : N_("use of C++23 ptrdiff_t integer constant");
>>> And here too (perhaps %<make_signed<size_t>::type%> )?
>>> And maybe %<size_t%> too.
>> Agree.
>>>
>>>> --- a/libcpp/include/cpplib.h
>>>> +++ b/libcpp/include/cpplib.h
>>>> @@ -500,6 +500,9 @@ struct cpp_options
>>>>     /* Nonzero means tokenize C++20 module directives.  */
>>>>     unsigned char module_directives;
>>>> +  /* Nonzero for C++23 ptrdiff_t and size_t literals.  */
>>> And drop "ptrdiff_t and " here?
>>>
>>>> +#define CPP_N_SIZE_T    0x2000000 /* C++23 size_t or ptrdiff_t 
>>>> literal  */
>>> And " or ptrdiff_t" here?
>>>
>>> While ptrdiff_t will usually be the same type, seems there is e.g.:
>>> config/darwin.h:#define SIZE_TYPE "long unsigned int"
>>> config/darwin.h:#define PTRDIFF_TYPE "int"
>>> config/i386/djgpp.h:#define SIZE_TYPE "long unsigned int"
>>> config/i386/djgpp.h:#define PTRDIFF_TYPE "int"
>>> config/m32c/m32c.h:#define PTRDIFF_TYPE (TARGET_A16 ? "int" : "long 
>>> int")
>>> config/m32c/m32c.h:#define SIZE_TYPE "unsigned int"
>>> config/rs6000/rs6000.h:#define PTRDIFF_TYPE "int"
>>> config/rs6000/rs6000.h:#define SIZE_TYPE "long unsigned int"
>>> config/s390/linux.h:#define SIZE_TYPE "long unsigned int"
>>> config/s390/linux.h:#define PTRDIFF_TYPE (TARGET_64BIT ? "long int" 
>>> : "int")
>>> config/visium/visium.h:#define SIZE_TYPE "unsigned int"
>>> config/visium/visium.h:#define PTRDIFF_TYPE "long int"
>>> config/vms/vms.h:#define SIZE_TYPE  "unsigned int"
>>> config/vms/vms.h:#define PTRDIFF_TYPE (flag_vms_pointer_size == 
>>> VMS_POINTER_SIZE_NONE ? \
>>> config/vms/vms.h-                      "int" : "long long int")
>>> so quite a few differences.
>>>
>>>     Jakub
>>
>> Here is my last patch with all the concerns addressed.
>>
>> I am not smart enough to get the dg-warning regex in 
>> Wsize_t-literals.C to work. If someone could carry this over the 
>> finish line that would be great. Or give me pointers. I can't any more.
>
> Your regex will work fine if you wrap it in {} instead of "", e.g.
>
> { dg-warning {use of C\+\+23 .size_t. integer constant} }
>
> Jason
>
Thank you Jason,

So here is the latest in testing.

Ed
diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
index dca6815a876..48dec21d4b4 100644
--- a/gcc/c-family/c-cppbuiltin.c
+++ b/gcc/c-family/c-cppbuiltin.c
@@ -1025,6 +1025,11 @@ c_cpp_builtins (cpp_reader *pfile)
 	  cpp_define (pfile, "__cpp_aggregate_paren_init=201902L");
 	  cpp_define (pfile, "__cpp_using_enum=201907L");
 	}
+      if (cxx_dialect > cxx20)
+	{
+	  /* Set feature test macros for C++23.  */
+	  cpp_define (pfile, "__cpp_size_t_suffix=202006L");
+	}
       if (flag_concepts)
         {
 	  if (cxx_dialect >= cxx20)
diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c
index fe40a0f728b..6374b72ed2d 100644
--- a/gcc/c-family/c-lex.c
+++ b/gcc/c-family/c-lex.c
@@ -834,6 +834,14 @@ interpret_integer (const cpp_token *token, unsigned int flags,
     type = ((flags & CPP_N_UNSIGNED)
 	    ? widest_unsigned_literal_type_node
 	    : widest_integer_literal_type_node);
+  else if (flags & CPP_N_SIZE_T)
+    {
+      /* itk refers to fundamental types not aliased size types.  */
+      if (flags & CPP_N_UNSIGNED)
+	type = size_type_node;
+      else
+	type = signed_size_type_node;
+    }
   else
     {
       type = integer_types[itk];
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C
index fdddd8d84ed..a30ec0f4f7e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C
@@ -17,6 +17,30 @@ unsigned long long int
 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,13 +61,50 @@ unsigned long long int
 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 }
 // { 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 }
diff --git a/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C b/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C
new file mode 100644
index 00000000000..94e08a4896c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C
@@ -0,0 +1,549 @@
+// { dg-options "-std=c++2b -I${srcdir}/g++.dg/cpp1y -I${srcdir}/g++.dg/cpp1y/testinc" }
+
+//  C++98 features:
+
+#ifndef __cpp_rtti
+#  error "__cpp_rtti"
+#elif  __cpp_rtti != 199711
+#  error "__cpp_rtti != 199711"
+#endif
+
+#ifndef __cpp_exceptions
+#  error "__cpp_exceptions"
+#elif  __cpp_exceptions != 199711
+#  error "__cpp_exceptions != 199711"
+#endif
+
+//  C++11 features:
+
+#ifndef __cpp_raw_strings
+#  error "__cpp_raw_strings"
+#elif __cpp_raw_strings != 200710
+#  error "__cpp_raw_strings != 200710"
+#endif
+
+#ifndef __cpp_unicode_literals
+#  error "__cpp_unicode_literals"
+#elif __cpp_unicode_literals != 200710
+#  error "__cpp_unicode_literals != 200710"
+#endif
+
+#ifndef __cpp_user_defined_literals
+#  error "__cpp_user_defined_literals"
+#elif __cpp_user_defined_literals != 200809
+#  error "__cpp_user_defined_literals != 200809"
+#endif
+
+#ifndef __cpp_lambdas
+#  error "__cpp_lambdas"
+#elif __cpp_lambdas != 200907
+#  error "__cpp_lambdas != 200907"
+#endif
+
+#ifndef __cpp_range_based_for
+#  error "__cpp_range_based_for"
+#elif __cpp_range_based_for != 201603
+#  error "__cpp_range_based_for != 201603"
+#endif
+
+#ifndef __cpp_decltype
+#  error "__cpp_decltype"
+#elif __cpp_decltype != 200707
+#  error "__cpp_decltype != 200707"
+#endif
+
+#ifndef __cpp_attributes
+#  error "__cpp_attributes"
+#elif __cpp_attributes != 200809
+#  error "__cpp_attributes != 200809"
+#endif
+
+#ifndef __cpp_rvalue_references
+#  error "__cpp_rvalue_references"
+#elif __cpp_rvalue_references != 200610
+#  error "__cpp_rvalue_references != 200610"
+#endif
+
+#ifndef __cpp_variadic_templates
+#  error "__cpp_variadic_templates"
+#elif __cpp_variadic_templates != 200704
+#  error "__cpp_variadic_templates != 200704"
+#endif
+
+#ifndef __cpp_initializer_lists
+#  error "__cpp_initializer_lists"
+#elif __cpp_initializer_lists != 200806
+#  error "__cpp_initializer_lists != 200806"
+#endif
+
+#ifndef __cpp_delegating_constructors
+#  error "__cpp_delegating_constructors"
+#elif __cpp_delegating_constructors != 200604
+#  error "__cpp_delegating_constructors != 200604"
+#endif
+
+#ifndef __cpp_nsdmi
+#  error "__cpp_nsdmi"
+#elif __cpp_nsdmi != 200809
+#  error "__cpp_nsdmi != 200809"
+#endif
+
+#ifndef __cpp_inheriting_constructors
+#  error "__cpp_inheriting_constructors"
+#elif  __cpp_inheriting_constructors!= 201511
+#  error "__cpp_inheriting_constructors != 201511"
+#endif
+
+#ifndef __cpp_ref_qualifiers
+#  error "__cpp_ref_qualifiers"
+#elif __cpp_ref_qualifiers != 200710
+#  error "__cpp_ref_qualifiers != 200710"
+#endif
+
+#ifndef __cpp_alias_templates
+#  error "__cpp_alias_templates"
+#elif __cpp_alias_templates != 200704
+#  error "__cpp_alias_templates != 200704"
+#endif
+
+#ifndef __cpp_threadsafe_static_init
+#  error "__cpp_threadsafe_static_init"
+#elif __cpp_threadsafe_static_init != 200806
+#  error "__cpp_threadsafe_static_init != 200806"
+#endif
+
+//  C++14 features:
+
+#ifndef __cpp_binary_literals
+#  error "__cpp_binary_literals"
+#elif __cpp_binary_literals != 201304
+#  error "__cpp_binary_literals != 201304"
+#endif
+
+#ifndef __cpp_init_captures
+#  error "__cpp_init_captures"
+#elif __cpp_init_captures != 201803
+#  error "__cpp_init_captures != 201803"
+#endif
+
+#ifndef __cpp_generic_lambdas
+#  error "__cpp_generic_lambdas"
+#elif __cpp_generic_lambdas != 201707
+#  error "__cpp_generic_lambdas != 201707"
+#endif
+
+#ifndef __cpp_constexpr
+#  error "__cpp_constexpr"
+#elif __cpp_constexpr != 201907
+#  error "__cpp_constexpr != 201907"
+#endif
+
+#ifndef __cpp_decltype_auto
+#  error "__cpp_decltype_auto"
+#elif __cpp_decltype_auto != 201304
+#  error "__cpp_decltype_auto != 201304"
+#endif
+
+#ifndef __cpp_return_type_deduction
+#  error "__cpp_return_type_deduction"
+#elif __cpp_return_type_deduction != 201304
+#  error "__cpp_return_type_deduction != 201304"
+#endif
+
+#ifndef __cpp_aggregate_nsdmi
+#  error "__cpp_aggregate_nsdmi"
+#elif __cpp_aggregate_nsdmi != 201304
+#  error "__cpp_aggregate_nsdmi != 201304"
+#endif
+
+#ifndef __cpp_variable_templates
+#  error "__cpp_variable_templates"
+#elif __cpp_variable_templates != 201304
+#  error "__cpp_variable_templates != 201304"
+#endif
+
+#ifndef __cpp_digit_separators
+#  error "__cpp_digit_separators"
+#elif __cpp_digit_separators != 201309
+#  error "__cpp_digit_separators != 201309"
+#endif
+
+#ifndef __cpp_sized_deallocation
+#  error "__cpp_sized_deallocation"
+#elif __cpp_sized_deallocation != 201309
+#  error "__cpp_sized_deallocation != 201309"
+#endif
+
+//  GNU VLA support:
+
+#ifndef __cpp_runtime_arrays
+#  error "__cpp_runtime_arrays"
+#elif __cpp_runtime_arrays != 198712
+#  error "__cpp_runtime_arrays != 198712"
+#endif
+
+//  C++11 attributes:
+
+#ifdef __has_cpp_attribute
+#  if ! __has_cpp_attribute(noreturn)
+#    error "__has_cpp_attribute(noreturn)"
+#  elif __has_cpp_attribute(noreturn) != 200809
+#    error "__has_cpp_attribute(noreturn) != 200809"
+#  endif
+#else
+#  error "__has_cpp_attribute"
+#endif
+
+//  Attribute carries_dependency not in yet.
+//#ifdef __has_cpp_attribute
+//#  if ! __has_cpp_attribute(carries_dependency)
+//#    error "__has_cpp_attribute(carries_dependency)"
+//#  elif __has_cpp_attribute(carries_dependency) != 200809
+//#    error "__has_cpp_attribute(carries_dependency) != 200809"
+//#  endif
+//#else
+//#  error "__has_cpp_attribute"
+//#endif
+
+//  C++14 attributes:
+
+#ifdef __has_cpp_attribute
+#  if ! __has_cpp_attribute(deprecated)
+#    error "__has_cpp_attribute(deprecated)"
+#  elif __has_cpp_attribute(deprecated) != 201309
+#    error "__has_cpp_attribute(deprecated) != 201309"
+#  endif
+#else
+#  error "__has_cpp_attribute"
+#endif
+
+//  Include checks:
+
+//  Check for __has_include macro.
+#ifndef __has_include
+#  error "__has_include"
+#endif
+
+//  Try known bracket header (use operator).
+#if __has_include (<complex>)
+#else
+#  error "<complex>"
+#endif
+
+//  Define and use a macro to invoke the operator.
+#define sluggo(TXT) __has_include(TXT)
+
+#if sluggo(<complex>)
+#else
+#  error "<complex>"
+#endif
+
+#if ! sluggo(<complex>)
+#  error "<complex>"
+#else
+#endif
+
+//  Quoted complex.h should find at least the bracket version.
+#if __has_include("complex.h")
+#else
+#  error "complex.h"
+#endif
+
+//  Try known local quote header.
+#if __has_include("complex_literals.h")
+#else
+#  error "\"complex_literals.h\""
+#endif
+
+//  Try nonexistent bracket header.
+#if __has_include(<stuff>)
+#  error "<stuff>"
+#else
+#endif
+
+//  Try nonexistent quote header.
+#if __has_include("phlegm")
+#  error "\"phlegm\""
+#else
+#endif
+
+//  Test __has_include_next.
+#if __has_include("phoobhar.h")
+#  include "phoobhar.h"
+#else
+#  error "__has_include(\"phoobhar.h\")"
+#endif
+
+//  Try a macro.
+#define COMPLEX_INC "complex.h"
+#if __has_include(COMPLEX_INC)
+#else
+#  error COMPLEX_INC
+#endif
+
+//  Realistic use of __has_include.
+#if __has_include(<array>)
+#  define STD_ARRAY 1
+#  include <array>
+  template<typename _Tp, std::size_t _Num>
+    using array = std::array<_Tp, _Num>;
+#elif __has_include(<tr1/array>)
+#  define TR1_ARRAY 1
+#  include <tr1/array>
+  template<typename _Tp, std::size_t _Num>
+    typedef std::tr1::array<_Tp, _Num> array;
+#endif
+
+// C++17 features:
+
+#ifndef __cpp_unicode_characters
+#  error "__cpp_unicode_characters"
+#elif __cpp_unicode_characters != 201411
+#  error "__cpp_unicode_characters != 201411"
+#endif
+
+#ifndef __cpp_static_assert
+#  error "__cpp_static_assert"
+#elif __cpp_static_assert != 201411
+#  error "__cpp_static_assert != 201411"
+#endif
+
+#ifndef __cpp_namespace_attributes
+#  error "__cpp_namespace_attributes"
+#elif __cpp_namespace_attributes != 201411
+#  error "__cpp_namespace_attributes != 201411"
+#endif
+
+#ifndef __cpp_enumerator_attributes
+#  error "__cpp_enumerator_attributes"
+#elif __cpp_enumerator_attributes != 201411
+#  error "__cpp_enumerator_attributes != 201411"
+#endif
+
+#ifndef __cpp_nested_namespace_definitions
+#  error "__cpp_nested_namespace_definitions"
+#elif __cpp_nested_namespace_definitions != 201411
+#  error "__cpp_nested_namespace_definitions != 201411"
+#endif
+
+#ifndef __cpp_fold_expressions
+#  error "__cpp_fold_expressions"
+#elif __cpp_fold_expressions != 201603
+#  error "__cpp_fold_expressions != 201603"
+#endif
+
+#ifndef __cpp_nontype_template_args
+#  error "__cpp_nontype_template_args"
+#elif __cpp_nontype_template_args != 201911
+#  error "__cpp_nontype_template_args != 201911"
+#endif
+
+#ifndef __cpp_hex_float
+#  error "__cpp_hex_float"
+#elif __cpp_hex_float != 201603
+#  error "__cpp_hex_float != 201603"
+#endif
+
+#ifndef __cpp_aggregate_bases
+#  error "__cpp_aggregate_bases"
+#elif __cpp_aggregate_bases != 201603
+#  error "__cpp_aggregate_bases != 201603"
+#endif
+
+#ifndef __cpp_deduction_guides
+#  error "__cpp_deduction_guides"
+#elif __cpp_deduction_guides != 201907
+#  error "__cpp_deduction_guides != 201907"
+#endif
+
+#ifndef __cpp_if_constexpr
+#  error "__cpp_if_constexpr"
+#elif __cpp_if_constexpr != 201606
+#  error "__cpp_if_constexpr != 201606"
+#endif
+
+#ifndef __cpp_aligned_new
+#  error "__cpp_aligned_new"
+#elif __cpp_aligned_new != 201606
+#  error "__cpp_aligned_new != 201606"
+#endif
+
+#ifndef __cpp_template_auto
+#  error "__cpp_template_auto"
+#elif __cpp_template_auto != 201606
+#  error "__cpp_template_auto != 201606"
+#endif
+
+#ifndef __cpp_inline_variables
+#  error "__cpp_inline_variables"
+#elif __cpp_inline_variables != 201606
+#  error "__cpp_inline_variables != 201606"
+#endif
+
+#ifndef __cpp_capture_star_this
+#  error "__cpp_capture_star_this"
+#elif __cpp_capture_star_this != 201603
+#  error "__cpp_capture_star_this != 201603"
+#endif
+
+#ifndef __cpp_noexcept_function_type
+#  error "__cpp_noexcept_function_type"
+#elif __cpp_noexcept_function_type != 201510
+#  error "__cpp_noexcept_function_type != 201510"
+#endif
+
+#ifndef __cpp_structured_bindings
+#  error "__cpp_structured_bindings"
+#elif __cpp_structured_bindings != 201606
+#  error "__cpp_structured_bindings != 201606"
+#endif
+
+#ifndef __cpp_template_template_args
+#  error "__cpp_template_template_args"
+#elif __cpp_template_template_args != 201611
+#  error "__cpp_template_template_args != 201611"
+#endif
+
+#ifndef __cpp_variadic_using
+#  error "__cpp_variadic_using"
+#elif __cpp_variadic_using != 201611
+#  error "__cpp_variadic_using != 201611"
+#endif
+
+#ifndef __cpp_guaranteed_copy_elision
+#  error "__cpp_guaranteed_copy_elision"
+#elif __cpp_guaranteed_copy_elision != 201606
+#  error "__cpp_guaranteed_copy_elision != 201606"
+#endif
+
+#ifndef __cpp_nontype_template_parameter_auto
+#  error "__cpp_nontype_template_parameter_auto"
+#elif __cpp_nontype_template_parameter_auto != 201606
+#  error "__cpp_nontype_template_parameter_auto != 201606"
+#endif
+
+// C++20 features
+
+#ifndef __cpp_conditional_explicit
+#  error "__cpp_conditional_explicit"
+#elif __cpp_conditional_explicit != 201806
+#  error "__cpp_conditional_explicit != 201806"
+#endif
+
+#ifndef __cpp_nontype_template_parameter_class
+#  error "__cpp_nontype_template_parameter_class"
+#elif __cpp_nontype_template_parameter_class != 201806
+#  error "__cpp_nontype_template_parameter_class != 201806"
+#endif
+
+#ifndef __cpp_impl_destroying_delete
+#  error "__cpp_impl_destroying_delete"
+#elif __cpp_impl_destroying_delete != 201806
+#  error "__cpp_impl_destroying_delete != 201806"
+#endif
+
+#ifndef __cpp_constinit
+#  error "__cpp_constinit"
+#elif __cpp_constinit != 201907
+#  error "__cpp_constinit != 201907"
+#endif
+
+#ifndef __cpp_constexpr_dynamic_alloc
+#  error "__cpp_constexpr_dynamic_alloc"
+#elif __cpp_constexpr_dynamic_alloc != 201907
+#  error "__cpp_constexpr_dynamic_alloc != 201907"
+#endif
+
+#ifndef __cpp_aggregate_paren_init
+#  error "__cpp_aggregate_paren_init"
+#elif __cpp_aggregate_paren_init != 201902
+#  error "__cpp_aggregate_paren_init != 201902"
+#endif
+
+#ifdef __has_cpp_attribute
+
+#  if ! __has_cpp_attribute(maybe_unused)
+#    error "__has_cpp_attribute(maybe_unused)"
+#  elif __has_cpp_attribute(maybe_unused) != 201603
+#    error "__has_cpp_attribute(maybe_unused) != 201603"
+#  endif
+
+#  if ! __has_cpp_attribute(nodiscard)
+#    error "__has_cpp_attribute(nodiscard)"
+#  elif __has_cpp_attribute(nodiscard) != 201907
+#    error "__has_cpp_attribute(nodiscard) != 201907"
+#  endif
+
+#  if ! __has_cpp_attribute(fallthrough)
+#    error "__has_cpp_attribute(fallthrough)"
+#  elif __has_cpp_attribute(fallthrough) != 201603
+#    error "__has_cpp_attribute(fallthrough) != 201603"
+#  endif
+
+#  if ! __has_cpp_attribute(no_unique_address)
+#    error "__has_cpp_attribute(no_unique_address)"
+#  elif __has_cpp_attribute(no_unique_address) != 201803
+#    error "__has_cpp_attribute(no_unique_address) != 201803"
+#  endif
+
+#  if ! __has_cpp_attribute(likely)
+#    error "__has_cpp_attribute(likely)"
+#  elif __has_cpp_attribute(likely) != 201803
+#    error "__has_cpp_attribute(likely) != 201803"
+#  endif
+
+#  if ! __has_cpp_attribute(unlikely)
+#    error "__has_cpp_attribute(unlikely)"
+#  elif __has_cpp_attribute(unlikely) != 201803
+#    error "__has_cpp_attribute(unlikely) != 201803"
+#  endif
+
+#else
+#  error "__has_cpp_attribute"
+#endif
+
+#ifndef __cpp_char8_t
+#  error "__cpp_char8_t"
+#elif __cpp_char8_t != 201811
+#  error "__cpp_char8_t != 201811"
+#endif
+
+#ifndef __cpp_designated_initializers
+#  error "__cpp_designated_initializers"
+#elif __cpp_designated_initializers != 201707
+#  error "__cpp_designated_initializers != 201707"
+#endif
+
+#ifndef __cpp_constexpr_in_decltype
+#  error "__cpp_constexpr_in_decltype"
+#elif __cpp_constexpr_in_decltype != 201711
+#  error "__cpp_constexpr_in_decltype != 201711"
+#endif
+
+/* Not supported fully yet:
+#ifndef __cpp_consteval
+#  error "__cpp_consteval"
+#elif __cpp_consteval != 201811
+#  error "__cpp_consteval != 201811"
+#endif
+*/
+
+#ifndef __cpp_concepts
+#  error "__cpp_concepts"
+#elif __cpp_concepts != 201907
+#  error "__cpp_concepts != 201907"
+#endif
+
+#ifndef __cpp_using_enum
+#  error "__cpp_using_enum"
+#elif __cpp_using_enum != 201907
+#  error "__cpp_using_enum != 201907"
+#endif
+
+// C++23 features:
+
+#ifndef __cpp_size_t_suffix
+#  error "__cpp_size_t_suffix"
+#elif __cpp_size_t_suffix != 202006
+#  error "__cpp_size_t_suffix != 202006"
+#endif
diff --git a/gcc/testsuite/g++.dg/cpp23/size_t-literals.C b/gcc/testsuite/g++.dg/cpp23/size_t-literals.C
new file mode 100644
index 00000000000..3488032de3f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/size_t-literals.C
@@ -0,0 +1,8 @@
+// { dg-do compile { target c++23 } }
+
+#include <cstddef>
+#include <type_traits>
+
+static_assert(std::is_same_v<decltype(123zu), std::size_t>);
+static_assert(std::is_same_v<decltype(456z), std::make_signed_t<std::size_t>>);
+
diff --git a/gcc/testsuite/g++.dg/warn/Wsize_t-literals.C b/gcc/testsuite/g++.dg/warn/Wsize_t-literals.C
new file mode 100644
index 00000000000..1766d910454
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wsize_t-literals.C
@@ -0,0 +1,16 @@
+// { dg-do compile { target c++20_down } }
+
+#if __cplusplus >= 201103L
+
+#include <cstddef>
+#include <type_traits>
+
+std::size_t s1 = 1234zu; // { dg-warning {use of C\+\+23 .size_t. integer constant} "" { target { ! c++98_only } } }
+std::size_t S1 = 5678ZU; // { dg-warning {use of C\+\+23 .size_t. integer constant} "" { target { ! c++98_only } } }
+std::size_t s2 = 1234uz; // { dg-warning {use of C\+\+23 .size_t. integer constant} "" { target { ! c++98_only } } }
+std::size_t S2 = 5678UZ; // { dg-warning {use of C\+\+23 .size_t. integer constant} "" { target { ! c++98_only } } }
+
+std::make_signed<std::size_t>::type pd1 = 1234z; // { dg-warning {use of C\+\+23 .make_signed<size_t>::type. integer constant} "" { target { ! c++98_only } } }
+std::make_signed<std::size_t>::type PD1 = 5678Z; // { dg-warning {use of C\+\+23 .make_signed<size_t>::type. integer constant} "" { target { ! c++98_only } } }
+
+#endif
diff --git a/libcpp/expr.c b/libcpp/expr.c
index 474ea4d6b6f..42007f98b93 100644
--- a/libcpp/expr.c
+++ b/libcpp/expr.c
@@ -313,13 +313,14 @@ static unsigned int
 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;
+  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;
@@ -332,9 +333,17 @@ interpret_int_suffix (cpp_reader *pfile, const uchar *s, size_t len)
 	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))
@@ -352,7 +361,8 @@ interpret_int_suffix (cpp_reader *pfile, const uchar *s, size_t len)
   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_SIZE_T : 0));
 }
 
 /* Return the classification flags for an int suffix.  */
@@ -805,6 +815,16 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
 				      virtual_location, 0, message);
         }
 
+      if ((result & CPP_N_SIZE_T) == CPP_N_SIZE_T
+	  && !CPP_OPTION (pfile, size_t_literals))
+       {
+	  const char *message = (result & CPP_N_UNSIGNED) == CPP_N_UNSIGNED
+				? N_("use of C++23 %<size_t%> integer constant")
+				: N_("use of C++23 %<make_signed<size_t>::type%> integer constant");
+	  cpp_warning_with_line (pfile, CPP_W_SIZE_T_LITERALS,
+				 virtual_location, 0, message);
+       }
+
       result |= CPP_N_INTEGER;
     }
 
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
index 4467c73284d..17feb648ebe 100644
--- a/libcpp/include/cpplib.h
+++ b/libcpp/include/cpplib.h
@@ -500,6 +500,9 @@ struct cpp_options
   /* Nonzero means tokenize C++20 module directives.  */
   unsigned char module_directives;
 
+  /* Nonzero for C++23 size_t literals.  */
+  unsigned char size_t_literals;
+
   /* Holds the name of the target (execution) character set.  */
   const char *narrow_charset;
 
@@ -626,6 +629,7 @@ enum cpp_warning_reason {
   CPP_W_INVALID_PCH,
   CPP_W_WARNING_DIRECTIVE,
   CPP_W_LITERAL_SUFFIX,
+  CPP_W_SIZE_T_LITERALS,
   CPP_W_DATE_TIME,
   CPP_W_PEDANTIC,
   CPP_W_C90_C99_COMPAT,
@@ -1211,7 +1215,9 @@ struct cpp_num
 #define CPP_N_FLOATN	0x400000 /* _FloatN types.  */
 #define CPP_N_FLOATNX	0x800000 /* _FloatNx types.  */
 
-#define CPP_N_USERDEF	0x1000000 /* C++0x user-defined literal.  */
+#define CPP_N_USERDEF	0x1000000 /* C++11 user-defined literal.  */
+
+#define CPP_N_SIZE_T	0x2000000 /* C++23 size_t literal.  */
 
 #define CPP_N_WIDTH_FLOATN_NX	0xF0000000 /* _FloatN / _FloatNx value
 					      of N, divided by 16.  */
diff --git a/libcpp/init.c b/libcpp/init.c
index ecd3d5be7fd..17b0d251cda 100644
--- a/libcpp/init.c
+++ b/libcpp/init.c
@@ -94,34 +94,35 @@ struct lang_flags
   char va_opt;
   char scope;
   char dfp_constants;
+  char size_t_literals;
 };
 
 static const struct lang_flags lang_defaults[] =
-{ /*              c99 c++ xnum xid c11 std digr ulit rlit udlit bincst digsep trig u8chlit vaopt scope dfp */
-  /* GNUC89   */  { 0,  0,  1,  0,  0,  0,  1,   0,   0,   0,    0,     0,     0,   0,      1,   1,     0 },
-  /* GNUC99   */  { 1,  0,  1,  1,  0,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0 },
-  /* GNUC11   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0 },
-  /* GNUC17   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0 },
-  /* GNUC2X   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    1,     0,     0,   1,      1,   1,     1 },
-  /* STDC89   */  { 0,  0,  0,  0,  0,  1,  0,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0 },
-  /* STDC94   */  { 0,  0,  0,  0,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0 },
-  /* STDC99   */  { 1,  0,  1,  1,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0 },
-  /* STDC11   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    0,     0,     1,   0,      0,   0,     0 },
-  /* STDC17   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    0,     0,     1,   0,      0,   0,     0 },
-  /* STDC2X   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    1,     0,     1,   1,      0,   1,     1 },
-  /* GNUCXX   */  { 0,  1,  1,  1,  0,  0,  1,   0,   0,   0,    0,     0,     0,   0,      1,   1,     0 },
-  /* CXX98    */  { 0,  1,  0,  1,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   1,     0 },
-  /* GNUCXX11 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    0,     0,     0,   0,      1,   1,     0 },
-  /* CXX11    */  { 1,  1,  0,  1,  1,  1,  1,   1,   1,   1,    0,     0,     1,   0,      0,   1,     0 },
-  /* GNUCXX14 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   0,      1,   1,     0 },
-  /* CXX14    */  { 1,  1,  0,  1,  1,  1,  1,   1,   1,   1,    1,     1,     1,   0,      0,   1,     0 },
-  /* GNUCXX17 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0 },
-  /* CXX17    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      0,   1,     0 },
-  /* GNUCXX20 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0 },
-  /* CXX20    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0 },
-  /* GNUCXX23 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0 },
-  /* CXX23    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0 },
-  /* ASM      */  { 0,  0,  1,  0,  0,  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 scope dfp szlit */
+  /* GNUC89   */  { 0,  0,  1,  0,  0,  0,  1,   0,   0,   0,    0,     0,     0,   0,      1,   1,     0,   0 },
+  /* GNUC99   */  { 1,  0,  1,  1,  0,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0,   0 },
+  /* GNUC11   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0,   0 },
+  /* GNUC17   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0,   0 },
+  /* GNUC2X   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    1,     0,     0,   1,      1,   1,     1,   0 },
+  /* STDC89   */  { 0,  0,  0,  0,  0,  1,  0,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0 },
+  /* STDC94   */  { 0,  0,  0,  0,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0 },
+  /* STDC99   */  { 1,  0,  1,  1,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0 },
+  /* STDC11   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0 },
+  /* STDC17   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0 },
+  /* STDC2X   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    1,     0,     1,   1,      0,   1,     1,   0 },
+  /* GNUCXX   */  { 0,  1,  1,  1,  0,  0,  1,   0,   0,   0,    0,     0,     0,   0,      1,   1,     0,   0 },
+  /* CXX98    */  { 0,  1,  0,  1,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   1,     0,   0 },
+  /* GNUCXX11 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    0,     0,     0,   0,      1,   1,     0,   0 },
+  /* CXX11    */  { 1,  1,  0,  1,  1,  1,  1,   1,   1,   1,    0,     0,     1,   0,      0,   1,     0,   0 },
+  /* GNUCXX14 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   0,      1,   1,     0,   0 },
+  /* CXX14    */  { 1,  1,  0,  1,  1,  1,  1,   1,   1,   1,    1,     1,     1,   0,      0,   1,     0,   0 },
+  /* GNUCXX17 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   0 },
+  /* CXX17    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      0,   1,     0,   0 },
+  /* GNUCXX20 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   0 },
+  /* CXX20    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   0 },
+  /* GNUCXX23 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   1 },
+  /* CXX23    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   1 },
+  /* ASM      */  { 0,  0,  1,  0,  0,  0,  0,   0,   0,   0,    0,     0,     0,   0,      0,   0,     0,   0 }
 };
 
 /* Sets internal flags correctly for a given language.  */
@@ -149,6 +150,7 @@ cpp_set_lang (cpp_reader *pfile, enum c_lang lang)
   CPP_OPTION (pfile, va_opt)			 = l->va_opt;
   CPP_OPTION (pfile, scope)			 = l->scope;
   CPP_OPTION (pfile, dfp_constants)		 = l->dfp_constants;
+  CPP_OPTION (pfile, size_t_literals)		 = l->size_t_literals;
 }
 
 /* Initialize library global state.  */
Jason Merrill Feb. 2, 2021, 2:32 p.m. UTC | #15
On 2/2/21 1:19 AM, Ed Smith-Rowland wrote:
> On 2/2/21 12:12 AM, Jason Merrill wrote:
>> On 2/1/21 9:15 PM, Ed Smith-Rowland wrote:
>>> On 2/1/21 2:23 PM, Jakub Jelinek wrote:
>>>> On Mon, Feb 01, 2021 at 01:46:13PM -0500, Ed Smith-Rowland wrote:
>>>>> @@ -0,0 +1,8 @@
>>>>> +// { dg-do compile { target c++23 } }
>>>>> +
>>>>> +#include <cstddef>
>>>>> +#include <type_traits>
>>>>> +
>>>>> +static_assert(std::is_same_v<decltype(123zu), std::size_t>);
>>>>> +static_assert(std::is_same_v<decltype(456z), std::ptrdiff_t>);
>>>> Shouldn't this be std::make_signed<std::size_t>::type instead of 
>>>> std::ptrdiff_t
>>> Yes it should. The paper goes on about ptrdiff_t but at the very end 
>>> they punt on that in favor of what you have.
>>>>
>>>>> +std::ptrdiff_t pd1 = 1234z; // { dg-warning "use of C\+\+23 
>>>>> ptrdiff_t integer constant" "" { target c++20_down } }
>>>>> +std::ptrdiff_t PD1 = 5678Z; // { dg-warning "use of C\+\+23 
>>>>> ptrdiff_t integer constant" "" { target c++20_down } }
>>>> Ditto here.
>>> Agree.
>>>>
>>>>> +      const char *message = (result & CPP_N_UNSIGNED) == 
>>>>> CPP_N_UNSIGNED
>>>>> +                ? N_("use of C++23 size_t integer constant")
>>>>> +                : N_("use of C++23 ptrdiff_t integer constant");
>>>> And here too (perhaps %<make_signed<size_t>::type%> )?
>>>> And maybe %<size_t%> too.
>>> Agree.
>>>>
>>>>> --- a/libcpp/include/cpplib.h
>>>>> +++ b/libcpp/include/cpplib.h
>>>>> @@ -500,6 +500,9 @@ struct cpp_options
>>>>>     /* Nonzero means tokenize C++20 module directives.  */
>>>>>     unsigned char module_directives;
>>>>> +  /* Nonzero for C++23 ptrdiff_t and size_t literals.  */
>>>> And drop "ptrdiff_t and " here?
>>>>
>>>>> +#define CPP_N_SIZE_T    0x2000000 /* C++23 size_t or ptrdiff_t 
>>>>> literal  */
>>>> And " or ptrdiff_t" here?
>>>>
>>>> While ptrdiff_t will usually be the same type, seems there is e.g.:
>>>> config/darwin.h:#define SIZE_TYPE "long unsigned int"
>>>> config/darwin.h:#define PTRDIFF_TYPE "int"
>>>> config/i386/djgpp.h:#define SIZE_TYPE "long unsigned int"
>>>> config/i386/djgpp.h:#define PTRDIFF_TYPE "int"
>>>> config/m32c/m32c.h:#define PTRDIFF_TYPE (TARGET_A16 ? "int" : "long 
>>>> int")
>>>> config/m32c/m32c.h:#define SIZE_TYPE "unsigned int"
>>>> config/rs6000/rs6000.h:#define PTRDIFF_TYPE "int"
>>>> config/rs6000/rs6000.h:#define SIZE_TYPE "long unsigned int"
>>>> config/s390/linux.h:#define SIZE_TYPE "long unsigned int"
>>>> config/s390/linux.h:#define PTRDIFF_TYPE (TARGET_64BIT ? "long int" 
>>>> : "int")
>>>> config/visium/visium.h:#define SIZE_TYPE "unsigned int"
>>>> config/visium/visium.h:#define PTRDIFF_TYPE "long int"
>>>> config/vms/vms.h:#define SIZE_TYPE  "unsigned int"
>>>> config/vms/vms.h:#define PTRDIFF_TYPE (flag_vms_pointer_size == 
>>>> VMS_POINTER_SIZE_NONE ? \
>>>> config/vms/vms.h-                      "int" : "long long int")
>>>> so quite a few differences.
>>>>
>>>>     Jakub
>>>
>>> Here is my last patch with all the concerns addressed.
>>>
>>> I am not smart enough to get the dg-warning regex in 
>>> Wsize_t-literals.C to work. If someone could carry this over the 
>>> finish line that would be great. Or give me pointers. I can't any more.
>>
>> Your regex will work fine if you wrap it in {} instead of "", e.g.
>>
>> { dg-warning {use of C\+\+23 .size_t. integer constant} }
>>
>> Jason
>>
> Thank you Jason,
> 
> So here is the latest in testing.

> +++ b/gcc/testsuite/g++.dg/warn/Wsize_t-literals.C
> @@ -0,0 +1,16 @@
> +// { dg-do compile { target c++20_down } }
> +
> +#if __cplusplus >= 201103L
> +
> +#include <cstddef>
> +#include <type_traits>
> +
> +std::size_t s1 = 1234zu; // { dg-warning {use of C\+\+23 .size_t. integer constant} "" { target { ! c++98_only } } }
> +std::size_t S1 = 5678ZU; // { dg-warning {use of C\+\+23 .size_t. integer constant} "" { target { ! c++98_only } } }
> +std::size_t s2 = 1234uz; // { dg-warning {use of C\+\+23 .size_t. integer constant} "" { target { ! c++98_only } } }
> +std::size_t S2 = 5678UZ; // { dg-warning {use of C\+\+23 .size_t. integer constant} "" { target { ! c++98_only } } }
> +
> +std::make_signed<std::size_t>::type pd1 = 1234z; // { dg-warning {use of C\+\+23 .make_signed<size_t>::type. integer constant} "" { target { ! c++98_only } } }
> +std::make_signed<std::size_t>::type PD1 = 5678Z; // { dg-warning {use of C\+\+23 .make_signed<size_t>::type. integer constant} "" { target { ! c++98_only } } }
> +
> +#endif

I'd suggest switching the target constraints around: use target c++11 in 
the dg-do line, drop the #if, and use target c++20_down in the 
diagnostics.  OK with that change.

Jason
Tam S. B. Feb. 4, 2021, 11:31 a.m. UTC | #16
`__cpp_size_t_suffix` is defined as 202006L, but the draft standard says 202011L: http://eel.is/c++draft/cpp.predefined#tab:cpp.predefined.ft-row-48
Ed Smith-Rowland Feb. 4, 2021, 4:27 p.m. UTC | #17
On 2/4/21 6:31 AM, Tam S. B. wrote:
> `__cpp_size_t_suffix` is defined as 202006L, but the draft standard says 202011L: http://eel.is/c++draft/cpp.predefined#tab:cpp.predefined.ft-row-48

I looks like you're right. Both the latest draft and 
https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations 
agree. Not sure what's up with all the dates in the latest draft of P0330...

Jason, is this OK?

Ed
diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
index 48dec21d4b4..9f993c4aff2 100644
--- a/gcc/c-family/c-cppbuiltin.c
+++ b/gcc/c-family/c-cppbuiltin.c
@@ -1028,7 +1028,7 @@ c_cpp_builtins (cpp_reader *pfile)
       if (cxx_dialect > cxx20)
 	{
 	  /* Set feature test macros for C++23.  */
-	  cpp_define (pfile, "__cpp_size_t_suffix=202006L");
+	  cpp_define (pfile, "__cpp_size_t_suffix=202011L");
 	}
       if (flag_concepts)
         {
diff --git a/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C b/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C
index 94e08a4896c..4a342e967f8 100644
--- a/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C
+++ b/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C
@@ -544,6 +544,6 @@
 
 #ifndef __cpp_size_t_suffix
 #  error "__cpp_size_t_suffix"
-#elif __cpp_size_t_suffix != 202006
-#  error "__cpp_size_t_suffix != 202006"
+#elif __cpp_size_t_suffix != 202011
+#  error "__cpp_size_t_suffix != 202011"
 #endif
Jason Merrill Feb. 4, 2021, 4:37 p.m. UTC | #18
On 2/4/21 11:27 AM, Ed Smith-Rowland wrote:
> On 2/4/21 6:31 AM, Tam S. B. wrote:
>> `__cpp_size_t_suffix` is defined as 202006L, but the draft standard 
>> says 202011L: 
>> http://eel.is/c++draft/cpp.predefined#tab:cpp.predefined.ft-row-48
> 
> I looks like you're right. Both the latest draft and 
> https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations 
> agree. Not sure what's up with all the dates in the latest draft of 
> P0330...

It seems reasonable for the date in the standard to be later than the 
date in the proposal paper.

> Jason, is this OK?

OK.

Jason
diff mbox series

Patch

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;