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.  */

Reply via email to