[clang] dc7ebd2 - [C++2b] Support size_t literals

Anton Bikineev via cfe-commits cfe-commits at lists.llvm.org
Wed Mar 31 06:39:23 PDT 2021


Author: Anton Bikineev
Date: 2021-03-31T13:36:23Z
New Revision: dc7ebd2cb0cf4a83bb6cd1bfc8853b0a30054777

URL: https://github.com/llvm/llvm-project/commit/dc7ebd2cb0cf4a83bb6cd1bfc8853b0a30054777
DIFF: https://github.com/llvm/llvm-project/commit/dc7ebd2cb0cf4a83bb6cd1bfc8853b0a30054777.diff

LOG: [C++2b] Support size_t literals

This adds support for C++2b's z/uz suffixes for size_t literals (P0330).

Added: 
    clang/test/Lexer/size_t-literal.cpp
    clang/test/SemaCXX/size_t-literal.cpp

Modified: 
    clang/include/clang/Basic/DiagnosticCommonKinds.td
    clang/include/clang/Lex/LiteralSupport.h
    clang/lib/Frontend/InitPreprocessor.cpp
    clang/lib/Lex/LiteralSupport.cpp
    clang/lib/Lex/PPExpressions.cpp
    clang/lib/Sema/SemaExpr.cpp
    clang/test/Lexer/cxx-features.cpp
    clang/test/SemaCXX/cxx1y-user-defined-literals.cpp
    clang/www/cxx_status.html

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td
index a237d492de201..eab8206b104dc 100644
--- a/clang/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td
@@ -187,6 +187,17 @@ def ext_cxx11_longlong : Extension<
 def warn_cxx98_compat_longlong : Warning<
   "'long long' is incompatible with C++98">,
   InGroup<CXX98CompatPedantic>, DefaultIgnore;
+def ext_cxx2b_size_t_suffix : ExtWarn<
+  "'size_t' suffix for literals is a C++2b extension">,
+  InGroup<CXX2b>;
+def warn_cxx20_compat_size_t_suffix : Warning<
+  "'size_t' suffix for literals is incompatible with C++ standards before "
+  "C++2b">, InGroup<CXXPre2bCompat>, DefaultIgnore;
+def err_cxx2b_size_t_suffix: Error<
+  "'size_t' suffix for literals is a C++2b feature">;
+def err_size_t_literal_too_large: Error<
+  "%select{signed |}0'size_t' literal is out of range of possible "
+  "%select{signed |}0'size_t' values">;
 def err_integer_literal_too_large : Error<
   "integer literal is too large to be represented in any %select{signed |}0"
   "integer type">;

diff  --git a/clang/include/clang/Lex/LiteralSupport.h b/clang/include/clang/Lex/LiteralSupport.h
index 0c4f0fe277b7c..f131f045a73ea 100644
--- a/clang/include/clang/Lex/LiteralSupport.h
+++ b/clang/include/clang/Lex/LiteralSupport.h
@@ -63,6 +63,7 @@ class NumericLiteralParser {
   bool isUnsigned : 1;
   bool isLong : 1;          // This is *not* set for long long.
   bool isLongLong : 1;
+  bool isSizeT : 1;         // 1z, 1uz (C++2b)
   bool isHalf : 1;          // 1.0h
   bool isFloat : 1;         // 1.0f
   bool isImaginary : 1;     // 1.0i

diff  --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp
index 15f254515822b..3d69c59d166d0 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -589,6 +589,9 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts,
     //Builder.defineMacro("__cpp_modules", "201907L");
     //Builder.defineMacro("__cpp_using_enum", "201907L");
   }
+  // C++2b features.
+  if (LangOpts.CPlusPlus2b)
+    Builder.defineMacro("__cpp_size_t_suffix", "202011L");
   if (LangOpts.Char8)
     Builder.defineMacro("__cpp_char8_t", "201811L");
   Builder.defineMacro("__cpp_impl_destroying_delete", "201806L");

diff  --git a/clang/lib/Lex/LiteralSupport.cpp b/clang/lib/Lex/LiteralSupport.cpp
index df98516ee61d1..bfcb3c478b62d 100644
--- a/clang/lib/Lex/LiteralSupport.cpp
+++ b/clang/lib/Lex/LiteralSupport.cpp
@@ -546,6 +546,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
   isLong = false;
   isUnsigned = false;
   isLongLong = false;
+  isSizeT = false;
   isHalf = false;
   isFloat = false;
   isImaginary = false;
@@ -589,6 +590,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
   // integer constant.
   bool isFixedPointConstant = isFixedPointLiteral();
   bool isFPConstant = isFloatingLiteral();
+  bool HasSize = false;
 
   // Loop over all of the characters of the suffix.  If we see something bad,
   // we break out of the loop.
@@ -616,14 +618,17 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
       if (!(LangOpts.Half || LangOpts.FixedPoint))
         break;
       if (isIntegerLiteral()) break;  // Error for integer constant.
-      if (isHalf || isFloat || isLong) break; // HH, FH, LH invalid.
+      if (HasSize)
+        break;
+      HasSize = true;
       isHalf = true;
       continue;  // Success.
     case 'f':      // FP Suffix for "float"
     case 'F':
       if (!isFPConstant) break;  // Error for integer constant.
-      if (isHalf || isFloat || isLong || isFloat128)
-        break; // HF, FF, LF, QF invalid.
+      if (HasSize)
+        break;
+      HasSize = true;
 
       // CUDA host and device may have 
diff erent _Float16 support, therefore
       // allows f16 literals to avoid false alarm.
@@ -640,8 +645,9 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
     case 'q':    // FP Suffix for "__float128"
     case 'Q':
       if (!isFPConstant) break;  // Error for integer constant.
-      if (isHalf || isFloat || isLong || isFloat128)
-        break; // HQ, FQ, LQ, QQ invalid.
+      if (HasSize)
+        break;
+      HasSize = true;
       isFloat128 = true;
       continue;  // Success.
     case 'u':
@@ -652,8 +658,9 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
       continue;  // Success.
     case 'l':
     case 'L':
-      if (isLong || isLongLong) break;  // Cannot be repeated.
-      if (isHalf || isFloat || isFloat128) break;     // LH, LF, LQ invalid.
+      if (HasSize)
+        break;
+      HasSize = true;
 
       // Check for long long.  The L's need to be adjacent and the same case.
       if (s[1] == s[0]) {
@@ -665,42 +672,54 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
         isLong = true;
       }
       continue; // Success.
+    case 'z':
+    case 'Z':
+      if (isFPConstant)
+        break; // Invalid for floats.
+      if (HasSize)
+        break;
+      HasSize = true;
+      isSizeT = true;
+      continue;
     case 'i':
     case 'I':
-      if (LangOpts.MicrosoftExt) {
-        if (isLong || isLongLong || MicrosoftInteger)
+      if (LangOpts.MicrosoftExt && !isFPConstant) {
+        // Allow i8, i16, i32, and i64. First, look ahead and check if
+        // suffixes are Microsoft integers and not the imaginary unit.
+        uint8_t Bits = 0;
+        size_t ToSkip = 0;
+        switch (s[1]) {
+        case '8': // i8 suffix
+          Bits = 8;
+          ToSkip = 2;
           break;
-
-        if (!isFPConstant) {
-          // Allow i8, i16, i32, and i64.
-          switch (s[1]) {
-          case '8':
-            s += 2; // i8 suffix
-            MicrosoftInteger = 8;
-            break;
-          case '1':
-            if (s[2] == '6') {
-              s += 3; // i16 suffix
-              MicrosoftInteger = 16;
-            }
-            break;
-          case '3':
-            if (s[2] == '2') {
-              s += 3; // i32 suffix
-              MicrosoftInteger = 32;
-            }
-            break;
-          case '6':
-            if (s[2] == '4') {
-              s += 3; // i64 suffix
-              MicrosoftInteger = 64;
-            }
-            break;
-          default:
-            break;
+        case '1':
+          if (s[2] == '6') { // i16 suffix
+            Bits = 16;
+            ToSkip = 3;
           }
+          break;
+        case '3':
+          if (s[2] == '2') { // i32 suffix
+            Bits = 32;
+            ToSkip = 3;
+          }
+          break;
+        case '6':
+          if (s[2] == '4') { // i64 suffix
+            Bits = 64;
+            ToSkip = 3;
+          }
+          break;
+        default:
+          break;
         }
-        if (MicrosoftInteger) {
+        if (Bits) {
+          if (HasSize)
+            break;
+          HasSize = true;
+          MicrosoftInteger = Bits;
+          s += ToSkip;
           assert(s <= ThisTokEnd && "didn't maximally munch?");
           break;
         }
@@ -727,6 +746,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
         isLong = false;
         isUnsigned = false;
         isLongLong = false;
+        isSizeT = false;
         isFloat = false;
         isFloat16 = false;
         isHalf = false;

diff  --git a/clang/lib/Lex/PPExpressions.cpp b/clang/lib/Lex/PPExpressions.cpp
index 8c120c13d7d26..8537b31b9dc95 100644
--- a/clang/lib/Lex/PPExpressions.cpp
+++ b/clang/lib/Lex/PPExpressions.cpp
@@ -321,6 +321,14 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
         PP.Diag(PeekTok, diag::ext_c99_longlong);
     }
 
+    // 'z/uz' literals are a C++2b feature.
+    if (Literal.isSizeT)
+      PP.Diag(PeekTok, PP.getLangOpts().CPlusPlus
+                           ? PP.getLangOpts().CPlusPlus2b
+                                 ? diag::warn_cxx20_compat_size_t_suffix
+                                 : diag::ext_cxx2b_size_t_suffix
+                           : diag::err_cxx2b_size_t_suffix);
+
     // Parse the integer literal into Result.
     if (Literal.GetIntegerValue(Result.Val)) {
       // Overflow parsing integer literal.

diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 6b3da7ca5a4dc..1aff2a9edf0f9 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -3867,6 +3867,14 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
         Diag(Tok.getLocation(), diag::ext_c99_longlong);
     }
 
+    // 'z/uz' literals are a C++2b feature.
+    if (Literal.isSizeT)
+      Diag(Tok.getLocation(), getLangOpts().CPlusPlus
+                                  ? getLangOpts().CPlusPlus2b
+                                        ? diag::warn_cxx20_compat_size_t_suffix
+                                        : diag::ext_cxx2b_size_t_suffix
+                                  : diag::err_cxx2b_size_t_suffix);
+
     // Get the value in the widest-possible width.
     unsigned MaxWidth = Context.getTargetInfo().getIntMaxTWidth();
     llvm::APInt ResultVal(MaxWidth, 0);
@@ -3901,7 +3909,26 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
         }
       }
 
-      if (Ty.isNull() && !Literal.isLong && !Literal.isLongLong) {
+      // Check C++2b size_t literals.
+      if (Literal.isSizeT) {
+        assert(!Literal.MicrosoftInteger &&
+               "size_t literals can't be Microsoft literals");
+        unsigned SizeTSize = Context.getTargetInfo().getTypeWidth(
+            Context.getTargetInfo().getSizeType());
+
+        // Does it fit in size_t?
+        if (ResultVal.isIntN(SizeTSize)) {
+          // Does it fit in ssize_t?
+          if (!Literal.isUnsigned && ResultVal[SizeTSize - 1] == 0)
+            Ty = Context.getSignedSizeType();
+          else if (AllowUnsigned)
+            Ty = Context.getSizeType();
+          Width = SizeTSize;
+        }
+      }
+
+      if (Ty.isNull() && !Literal.isLong && !Literal.isLongLong &&
+          !Literal.isSizeT) {
         // Are int/unsigned possibilities?
         unsigned IntSize = Context.getTargetInfo().getIntWidth();
 
@@ -3917,7 +3944,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
       }
 
       // Are long/unsigned long possibilities?
-      if (Ty.isNull() && !Literal.isLongLong) {
+      if (Ty.isNull() && !Literal.isLongLong && !Literal.isSizeT) {
         unsigned LongSize = Context.getTargetInfo().getLongWidth();
 
         // Does it fit in a unsigned long?
@@ -3948,7 +3975,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
       }
 
       // Check long long if needed.
-      if (Ty.isNull()) {
+      if (Ty.isNull() && !Literal.isSizeT) {
         unsigned LongLongSize = Context.getTargetInfo().getLongLongWidth();
 
         // Does it fit in a unsigned long long?
@@ -3965,10 +3992,16 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
         }
       }
 
-      // If we still couldn't decide a type, we probably have something that
-      // does not fit in a signed long long, but has no U suffix.
+      // If we still couldn't decide a type, we either have 'size_t' literal
+      // that is out of range, or a decimal literal that does not fit in a
+      // signed long long and has no U suffix.
       if (Ty.isNull()) {
-        Diag(Tok.getLocation(), diag::ext_integer_literal_too_large_for_signed);
+        if (Literal.isSizeT)
+          Diag(Tok.getLocation(), diag::err_size_t_literal_too_large)
+              << Literal.isUnsigned;
+        else
+          Diag(Tok.getLocation(),
+               diag::ext_integer_literal_too_large_for_signed);
         Ty = Context.UnsignedLongLongTy;
         Width = Context.getTargetInfo().getLongLongWidth();
       }

diff  --git a/clang/test/Lexer/cxx-features.cpp b/clang/test/Lexer/cxx-features.cpp
index 2f46f354ee83f..22ac5567c1d86 100644
--- a/clang/test/Lexer/cxx-features.cpp
+++ b/clang/test/Lexer/cxx-features.cpp
@@ -29,6 +29,12 @@
 #define check(macro, cxx98, cxx11, cxx14, cxx17, cxx20, cxx23) (cxx23 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx23)
 #endif
 
+// --- C++2b features ---
+
+#if check(size_t_suffix, 0, 0, 0, 0, 0, 202011)
+#error "wrong value for __cpp_size_t_suffix"
+#endif
+
 // --- C++20 features ---
 
 #if check(aggregate_paren_init, 0, 0, 0, 0, 0, 0)

diff  --git a/clang/test/Lexer/size_t-literal.cpp b/clang/test/Lexer/size_t-literal.cpp
new file mode 100644
index 0000000000000..3e3e8094b070d
--- /dev/null
+++ b/clang/test/Lexer/size_t-literal.cpp
@@ -0,0 +1,167 @@
+// RUN: %clang_cc1 -std=c++2b -fsyntax-only -verify %s
+
+#if 1z != 1
+#error "z suffix must be recognized by preprocessor"
+#endif
+#if 1uz != 1
+#error "uz suffix must be recognized by preprocessor"
+#endif
+#if !(-1z < 0)
+#error "z suffix must be interpreted as signed"
+#endif
+#if !(-1uz > 0)
+#error "uz suffix must be interpreted as unsigned"
+#endif
+
+void ValidSuffix() {
+  // Decimal literals.
+  {
+    auto a1 = 1z;
+    auto a2 = 1Z;
+
+    auto a3 = 1uz;
+    auto a4 = 1uZ;
+    auto a5 = 1Uz;
+    auto a6 = 1UZ;
+
+    auto a7 = 1zu;
+    auto a8 = 1Zu;
+    auto a9 = 1zU;
+    auto a10 = 1ZU;
+
+    auto a11 = 1'2z;
+    auto a12 = 1'2Z;
+  }
+  // Hexadecimal literals.
+  {
+    auto a1 = 0x1z;
+    auto a2 = 0x1Z;
+
+    auto a3 = 0x1uz;
+    auto a4 = 0x1uZ;
+    auto a5 = 0x1Uz;
+    auto a6 = 0x1UZ;
+
+    auto a7 = 0x1zu;
+    auto a8 = 0x1Zu;
+    auto a9 = 0x1zU;
+    auto a10 = 0x1ZU;
+
+    auto a11 = 0x1'2z;
+    auto a12 = 0x1'2Z;
+  }
+  // Binary literals.
+  {
+    auto a1 = 0b1z;
+    auto a2 = 0b1Z;
+
+    auto a3 = 0b1uz;
+    auto a4 = 0b1uZ;
+    auto a5 = 0b1Uz;
+    auto a6 = 0b1UZ;
+
+    auto a7 = 0b1zu;
+    auto a8 = 0b1Zu;
+    auto a9 = 0b1zU;
+    auto a10 = 0b1ZU;
+
+    auto a11 = 0b1'1z;
+    auto a12 = 0b1'1Z;
+  }
+  // Octal literals.
+  {
+    auto a1 = 01z;
+    auto a2 = 01Z;
+
+    auto a3 = 01uz;
+    auto a4 = 01uZ;
+    auto a5 = 01Uz;
+    auto a6 = 01UZ;
+
+    auto a7 = 01zu;
+    auto a8 = 01Zu;
+    auto a9 = 01zU;
+    auto a10 = 01ZU;
+
+    auto a11 = 0'1z;
+    auto a12 = 0'1Z;
+  }
+}
+
+void InvalidSuffix() {
+  // Long.
+  {
+    auto a1 = 1lz; // expected-error {{invalid suffix}}
+    auto a2 = 1lZ; // expected-error {{invalid suffix}}
+    auto a3 = 1Lz; // expected-error {{invalid suffix}}
+    auto a4 = 1LZ; // expected-error {{invalid suffix}}
+
+    auto a5 = 1zl; // expected-error {{invalid suffix}}
+    auto a6 = 1Zl; // expected-error {{invalid suffix}}
+    auto a7 = 1zL; // expected-error {{invalid suffix}}
+    auto a8 = 1ZL; // expected-error {{invalid suffix}}
+
+    auto a9 = 1ulz;  // expected-error {{invalid suffix}}
+    auto a10 = 1ulZ; // expected-error {{invalid suffix}}
+    auto a11 = 1uLz; // expected-error {{invalid suffix}}
+    auto a12 = 1uLZ; // expected-error {{invalid suffix}}
+
+    auto a13 = 1uzl; // expected-error {{invalid suffix}}
+    auto a14 = 1uZl; // expected-error {{invalid suffix}}
+    auto a15 = 1uzL; // expected-error {{invalid suffix}}
+    auto a16 = 1uZL; // expected-error {{invalid suffix}}
+  }
+  // Long long.
+  {
+    auto a1 = 1llz; // expected-error {{invalid suffix}}
+    auto a2 = 1llZ; // expected-error {{invalid suffix}}
+    auto a3 = 1LLz; // expected-error {{invalid suffix}}
+    auto a4 = 1LLZ; // expected-error {{invalid suffix}}
+
+    auto a5 = 1zll; // expected-error {{invalid suffix}}
+    auto a6 = 1Zll; // expected-error {{invalid suffix}}
+    auto a7 = 1zLL; // expected-error {{invalid suffix}}
+    auto a8 = 1ZLL; // expected-error {{invalid suffix}}
+
+    auto a9 = 1ullz;  // expected-error {{invalid suffix}}
+    auto a10 = 1ullZ; // expected-error {{invalid suffix}}
+    auto a11 = 1uLLz; // expected-error {{invalid suffix}}
+    auto a12 = 1uLLZ; // expected-error {{invalid suffix}}
+
+    auto a13 = 1uzll; // expected-error {{invalid suffix}}
+    auto a14 = 1uZll; // expected-error {{invalid suffix}}
+    auto a15 = 1uzLL; // expected-error {{invalid suffix}}
+    auto a16 = 1uZLL; // expected-error {{invalid suffix}}
+  }
+  // Floating point.
+  {
+    auto a1 = 0.1z;   // expected-error {{invalid suffix}}
+    auto a2 = 0.1Z;   // expected-error {{invalid suffix}}
+    auto a3 = 0.1uz;  // expected-error {{invalid suffix}}
+    auto a4 = 0.1uZ;  // expected-error {{invalid suffix}}
+    auto a5 = 0.1Uz;  // expected-error {{invalid suffix}}
+    auto a6 = 0.1UZ;  // expected-error {{invalid suffix}}
+    auto a7 = 0.1zu;  // expected-error {{invalid suffix}}
+    auto a8 = 0.1Zu;  // expected-error {{invalid suffix}}
+    auto a9 = 0.1zU;  // expected-error {{invalid suffix}}
+    auto a10 = 0.1ZU; // expected-error {{invalid suffix}}
+
+    auto a11 = 0.1fz;   // expected-error {{invalid suffix}}
+    auto a12 = 0.1fZ;   // expected-error {{invalid suffix}}
+    auto a13 = 0.1fuz;  // expected-error {{invalid suffix}}
+    auto a14 = 0.1fuZ;  // expected-error {{invalid suffix}}
+    auto a15 = 0.1fUz;  // expected-error {{invalid suffix}}
+    auto a16 = 0.1fUZ;  // expected-error {{invalid suffix}}
+    auto a17 = 0.1fzu;  // expected-error {{invalid suffix}}
+    auto a18 = 0.1fZu;  // expected-error {{invalid suffix}}
+    auto a19 = 0.1fzU;  // expected-error {{invalid suffix}}
+    auto a110 = 0.1fZU; // expected-error {{invalid suffix}}
+  }
+  // Repetitive suffix.
+  {
+    auto a1 = 1zz; // expected-error {{invalid suffix}}
+    auto a2 = 1zZ; // expected-error {{invalid suffix}}
+    auto a3 = 1Zz; // expected-error {{invalid suffix}}
+    auto a4 = 1ZZ; // expected-error {{invalid suffix}}
+  }
+}

diff  --git a/clang/test/SemaCXX/cxx1y-user-defined-literals.cpp b/clang/test/SemaCXX/cxx1y-user-defined-literals.cpp
index fa4ff03fad7fd..d79924c8e2ed1 100644
--- a/clang/test/SemaCXX/cxx1y-user-defined-literals.cpp
+++ b/clang/test/SemaCXX/cxx1y-user-defined-literals.cpp
@@ -34,7 +34,7 @@ duration a = 1ns, b = 1us, c = 1ms, d = 1s, e = 1min, f = 1h;
 string s = "foo"s;
 char error = 'x's; // expected-error {{invalid suffix}} expected-error {{expected ';'}}
 
-int _1z = 1z; // expected-error {{invalid suffix}}
+int _1y = 1y; // expected-error {{invalid suffix}}
 int _1b = 1b; // expected-error {{invalid digit}}
 
 complex<float> cf1 = 1if, cf2 = 2.if, cf3 = 0x3if;

diff  --git a/clang/test/SemaCXX/size_t-literal.cpp b/clang/test/SemaCXX/size_t-literal.cpp
new file mode 100644
index 0000000000000..180f95979b39e
--- /dev/null
+++ b/clang/test/SemaCXX/size_t-literal.cpp
@@ -0,0 +1,99 @@
+// RUN: %clang_cc1 -std=c++2b -triple x86_64-linux -Wpre-c++2b-compat -fsyntax-only -verify=cxx2b %s
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-linux -fsyntax-only -verify=cxx20 %s
+// RUN: %clang_cc1 -std=c++2b -triple i686-linux -fsyntax-only -verify=cxx2b-32 %s
+// RUN: %clang_cc1 -x c -std=c11 -fsyntax-only -verify=c11 %s
+
+#ifdef __cplusplus
+
+typedef __SIZE_TYPE__ size_t;
+// Assume ptr
diff _t is the signed integer type corresponding to size_t.
+typedef __PTRDIFF_TYPE__ ssize_t;
+
+template <typename, typename>
+struct is_same { static constexpr bool value = false; };
+
+template <typename T>
+struct is_same<T, T> { static constexpr bool value = true; };
+
+void SSizeT() {
+  auto a1 = 1z;
+  // cxx2b-warning at -1 {{'size_t' suffix for literals is incompatible with C++ standards before C++2b}}
+  // cxx20-warning at -2 {{'size_t' suffix for literals is a C++2b extension}}
+  static_assert(is_same<decltype(a1), ssize_t>::value);
+
+  auto a2 = 1Z;
+  // cxx2b-warning at -1 {{'size_t' suffix for literals is incompatible with C++ standards before C++2b}}
+  // cxx20-warning at -2 {{'size_t' suffix for literals is a C++2b extension}}
+  static_assert(is_same<decltype(a2), ssize_t>::value);
+}
+
+void SizeT() {
+  auto a1 = 1uz;
+  // cxx2b-warning at -1 {{'size_t' suffix for literals is incompatible with C++ standards before C++2b}}
+  // cxx20-warning at -2 {{'size_t' suffix for literals is a C++2b extension}}
+  static_assert(is_same<decltype(a1), size_t>::value);
+
+  auto a2 = 1uZ;
+  // cxx2b-warning at -1 {{'size_t' suffix for literals is incompatible with C++ standards before C++2b}}
+  // cxx20-warning at -2 {{'size_t' suffix for literals is a C++2b extension}}
+  static_assert(is_same<decltype(a2), size_t>::value);
+
+  auto a3 = 1Uz;
+  // cxx2b-warning at -1 {{'size_t' suffix for literals is incompatible with C++ standards before C++2b}}
+  // cxx20-warning at -2 {{'size_t' suffix for literals is a C++2b extension}}
+  static_assert(is_same<decltype(a3), size_t>::value);
+
+  auto a4 = 1UZ;
+  // cxx2b-warning at -1 {{'size_t' suffix for literals is incompatible with C++ standards before C++2b}}
+  // cxx20-warning at -2 {{'size_t' suffix for literals is a C++2b extension}}
+  static_assert(is_same<decltype(a4), size_t>::value);
+
+  auto a5 = 1zu;
+  // cxx2b-warning at -1 {{'size_t' suffix for literals is incompatible with C++ standards before C++2b}}
+  // cxx20-warning at -2 {{'size_t' suffix for literals is a C++2b extension}}
+  static_assert(is_same<decltype(a5), size_t>::value);
+
+  auto a6 = 1Zu;
+  // cxx2b-warning at -1 {{'size_t' suffix for literals is incompatible with C++ standards before C++2b}}
+  // cxx20-warning at -2 {{'size_t' suffix for literals is a C++2b extension}}
+  static_assert(is_same<decltype(a6), size_t>::value);
+
+  auto a7 = 1zU;
+  // cxx2b-warning at -1 {{'size_t' suffix for literals is incompatible with C++ standards before C++2b}}
+  // cxx20-warning at -2 {{'size_t' suffix for literals is a C++2b extension}}
+  static_assert(is_same<decltype(a7), size_t>::value);
+
+  auto a8 = 1ZU;
+  // cxx2b-warning at -1 {{'size_t' suffix for literals is incompatible with C++ standards before C++2b}}
+  // cxx20-warning at -2 {{'size_t' suffix for literals is a C++2b extension}}
+  static_assert(is_same<decltype(a8), size_t>::value);
+}
+
+void oor() {
+#if __i386__
+  (void)3'000'000'000z; // cxx2b-32-error {{signed 'size_t' literal is out of range of possible signed 'size_t' values}}
+  (void)3'000'000'000uz;
+  (void)5'000'000'000uz; // cxx2b-32-error {{'size_t' literal is out of range of possible 'size_t' values}}
+
+  (void)0x80000000z;
+  (void)0x80000000uz;
+  (void)0x180000000uz; //cxx2b-32-error {{'size_t' literal is out of range of possible 'size_t' values}}
+#endif
+}
+
+#else
+
+void f() {
+  (void)1z;  // c11-error {{'size_t' suffix for literals is a C++2b feature}}
+  (void)1Z;  // c11-error {{'size_t' suffix for literals is a C++2b feature}}
+  (void)1uz; // c11-error {{'size_t' suffix for literals is a C++2b feature}}
+  (void)1uZ; // c11-error {{'size_t' suffix for literals is a C++2b feature}}
+  (void)1Uz; // c11-error {{'size_t' suffix for literals is a C++2b feature}}
+  (void)1UZ; // c11-error {{'size_t' suffix for literals is a C++2b feature}}
+  (void)1zu; // c11-error {{'size_t' suffix for literals is a C++2b feature}}
+  (void)1Zu; // c11-error {{'size_t' suffix for literals is a C++2b feature}}
+  (void)1zU; // c11-error {{'size_t' suffix for literals is a C++2b feature}}
+  (void)1ZU; // c11-error {{'size_t' suffix for literals is a C++2b feature}}
+}
+
+#endif

diff  --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html
index de8a4908f42e0..0660816b83c18 100755
--- a/clang/www/cxx_status.html
+++ b/clang/www/cxx_status.html
@@ -1270,7 +1270,7 @@ <h2 id="cxx23">C++2b implementation status</h2>
     <tr>
       <td>Literal suffix <tt>uz</tt>, <tt>z</tt> for <tt>size_t</tt>, <tt>ssize_t</tt></td>
       <td><a href="https://wg21.link/p0330r8">P0330R8</a></td>
-      <td class="none" align="center">No</td>
+      <td class="unreleased" align="center">Clang 13</td>
     </tr>
     <!-- Spring 2021 papers -->
     <tr>


        


More information about the cfe-commits mailing list