Skip to content

[clang-tidy] Teach readability-uppercase-literal-suffix about C++23 and C23 suffixes #148275

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

localspook
Copy link
Contributor

@localspook localspook commented Jul 11, 2025

C++23 integer literal suffixes:

Suffix Type
z std::make_signed_t<std::size_t>
uz std::size_t

C++23 floating-point literal suffixes:

Suffix Type
bf16 std::bfloat16_t
f16 std::float16_t
f32 std::float32_t
f64 std::float64_t
f128 std::float128_t

C23 integer literal suffixes:

Suffix Type
wb _BitInt(N)
uwb unsigned _BitInt(N)

C23 floating-point literal suffixes:

Suffix Type
df _Decimal32
dd _Decimal64
dl _Decimal128

Clang doesn't actually support any of the new floating point types yet (except for f16). I've decided to add disabled tests for them, so that when the support comes, we can flip the switch and support them with no delay.

@llvmbot
Copy link
Member

llvmbot commented Jul 11, 2025

@llvm/pr-subscribers-clang-tools-extra

Author: Victor Chernyakin (localspook)

Changes

C++23 integer literal suffixes:

Suffix Type
z std::make_signed_t&lt;std::size_t&gt;
uz std::size_t

C++23 floating-point literal suffixes:

Suffix Type
bf16 std::bfloat16_t
f16 std::float16_t
f32 std::float32_t
f64 std::float64_t
f128 std::float128_t

C23 integer literal suffixes:

Suffix Type
wb _BitInt(N)
uwb unsigned _BitInt(N)

C23 floating-point literal suffixes:

Suffix Type
df _Decimal32
dd _Decimal64
dl _Decimal128

Clang doesn't actually support any of the new floating point types yet (except for f16). I've decided to add disabled tests for them, so that when the support comes, we can flip the switch and support them with no delay.


Patch is 26.98 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/148275.diff

6 Files Affected:

  • (modified) clang-tools-extra/clang-tidy/readability/UppercaseLiteralSuffixCheck.cpp (+7-6)
  • (modified) clang-tools-extra/docs/ReleaseNotes.rst (+4)
  • (added) clang-tools-extra/test/clang-tidy/checkers/readability/uppercase-literal-suffix-c23.c (+162)
  • (added) clang-tools-extra/test/clang-tidy/checkers/readability/uppercase-literal-suffix-extended-floating-point.cpp (+248)
  • (removed) clang-tools-extra/test/clang-tidy/checkers/readability/uppercase-literal-suffix-float16.cpp (-51)
  • (modified) clang-tools-extra/test/clang-tidy/checkers/readability/uppercase-literal-suffix-integer.cpp (+85-1)
diff --git a/clang-tools-extra/clang-tidy/readability/UppercaseLiteralSuffixCheck.cpp b/clang-tools-extra/clang-tidy/readability/UppercaseLiteralSuffixCheck.cpp
index 678aa8dad48a7..dd43ee200f4c0 100644
--- a/clang-tools-extra/clang-tidy/readability/UppercaseLiteralSuffixCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UppercaseLiteralSuffixCheck.cpp
@@ -25,10 +25,11 @@ struct IntegerLiteralCheck {
   static constexpr llvm::StringLiteral Name = llvm::StringLiteral("integer");
   // What should be skipped before looking for the Suffixes? (Nothing here.)
   static constexpr llvm::StringLiteral SkipFirst = llvm::StringLiteral("");
-  // Suffix can only consist of 'u' and 'l' chars, and can be a complex number
-  // ('i', 'j'). In MS compatibility mode, suffixes like i32 are supported.
+  // Suffix can only consist of 'u', 'l', and 'z' chars, can be a bit-precise
+  // integer (wb), and can be a complex number ('i', 'j'). In MS compatibility
+  // mode, suffixes like i32 are supported.
   static constexpr llvm::StringLiteral Suffixes =
-      llvm::StringLiteral("uUlLiIjJ");
+      llvm::StringLiteral("uUlLzZwWbBiIjJ");
 };
 constexpr llvm::StringLiteral IntegerLiteralCheck::Name;
 constexpr llvm::StringLiteral IntegerLiteralCheck::SkipFirst;
@@ -45,10 +46,10 @@ struct FloatingLiteralCheck {
   // Since the exponent ('p'/'P') is mandatory for hexadecimal floating-point
   // literals, we first skip everything before the exponent.
   static constexpr llvm::StringLiteral SkipFirst = llvm::StringLiteral("pP");
-  // Suffix can only consist of 'f', 'l', "f16", 'h', 'q' chars,
-  // and can be a complex number ('i', 'j').
+  // Suffix can only consist of 'f', 'l', "f16", "bf16", "df", "dd", "dl",
+  // 'h', 'q' chars, and can be a complex number ('i', 'j').
   static constexpr llvm::StringLiteral Suffixes =
-      llvm::StringLiteral("fFlLhHqQiIjJ");
+      llvm::StringLiteral("fFlLbBdDhHqQiIjJ");
 };
 constexpr llvm::StringLiteral FloatingLiteralCheck::Name;
 constexpr llvm::StringLiteral FloatingLiteralCheck::SkipFirst;
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index ad869265a2db5..119c030b43852 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -354,6 +354,10 @@ Changes in existing checks
   <clang-tidy/checks/readability/redundant-smartptr-get>` check by fixing
   some false positives involving smart pointers to arrays.
 
+- Improved :doc:`readability-uppercase-literal-suffix
+  <clang-tidy/checks/readability/uppercase-literal-suffix>` check to recognize
+  literal suffixes added in C++23 and C23.
+
 Removed checks
 ^^^^^^^^^^^^^^
 
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/uppercase-literal-suffix-c23.c b/clang-tools-extra/test/clang-tidy/checkers/readability/uppercase-literal-suffix-c23.c
new file mode 100644
index 0000000000000..75727fc69e68c
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/uppercase-literal-suffix-c23.c
@@ -0,0 +1,162 @@
+// TODO: When Clang adds support for decimal floating point types, enable these tests by:
+//    1. Removing all the #if 0 + #endif guards.
+//    2. Removing all occurrences of the string "DISABLED-" in this file.
+//    3. Deleting this message.
+
+// RUN: %check_clang_tidy %s readability-uppercase-literal-suffix %t -- -- -std=c23
+// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.c
+// RUN: clang-tidy %t.c -checks='-*,readability-uppercase-literal-suffix' -fix -- -std=c23
+// RUN: clang-tidy %t.c -checks='-*,readability-uppercase-literal-suffix' -warnings-as-errors='-*,readability-uppercase-literal-suffix' -- -std=c23
+
+void bit_precise_literal_suffix() {
+  // _BitInt()
+
+  static constexpr auto v1 = 1wb;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: integer literal has suffix 'wb', which is not uppercase
+  // CHECK-MESSAGES-NEXT: static constexpr auto v1 = 1wb;
+  // CHECK-MESSAGES-NEXT: ^~~
+  // CHECK-MESSAGES-NEXT: WB{{$}}
+  // CHECK-FIXES: static constexpr auto v1 = 1WB;
+  static_assert(v1 == 1WB);
+
+  static constexpr auto v2 = 1WB; // OK.
+  static_assert(v2 == 1WB);
+
+  // _BitInt() Unsigned
+
+  static constexpr auto v3 = 1wbu;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: integer literal has suffix 'wbu', which is not uppercase
+  // CHECK-MESSAGES-NEXT: static constexpr auto v3 = 1wbu;
+  // CHECK-MESSAGES-NEXT: ^~~~
+  // CHECK-MESSAGES-NEXT: WBU{{$}}
+  // CHECK-FIXES: static constexpr auto v3 = 1WBU;
+  static_assert(v3 == 1WBU);
+
+  static constexpr auto v4 = 1WBu;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: integer literal has suffix 'WBu', which is not uppercase
+  // CHECK-MESSAGES-NEXT: static constexpr auto v4 = 1WBu;
+  // CHECK-MESSAGES-NEXT: ^~~~
+  // CHECK-MESSAGES-NEXT: WBU{{$}}
+  // CHECK-FIXES: static constexpr auto v4 = 1WBU;
+  static_assert(v4 == 1WBU);
+
+  static constexpr auto v5 = 1wbU;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: integer literal has suffix 'wbU', which is not uppercase
+  // CHECK-MESSAGES-NEXT: static constexpr auto v5 = 1wbU;
+  // CHECK-MESSAGES-NEXT: ^~~~
+  // CHECK-MESSAGES-NEXT: WBU{{$}}
+  // CHECK-FIXES: static constexpr auto v5 = 1WBU;
+  static_assert(v5 == 1WBU);
+
+  static constexpr auto v6 = 1WBU; // OK.
+  static_assert(v6 == 1WBU);
+
+  // Unsigned _BitInt()
+
+  static constexpr auto v7 = 1uwb;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: integer literal has suffix 'uwb', which is not uppercase
+  // CHECK-MESSAGES-NEXT: static constexpr auto v7 = 1uwb;
+  // CHECK-MESSAGES-NEXT: ^~~~
+  // CHECK-MESSAGES-NEXT: UWB{{$}}
+  // CHECK-FIXES: static constexpr auto v7 = 1UWB;
+  static_assert(v7 == 1UWB);
+
+  static constexpr auto v8 = 1uWB;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: integer literal has suffix 'uWB', which is not uppercase
+  // CHECK-MESSAGES-NEXT: static constexpr auto v8 = 1uWB;
+  // CHECK-MESSAGES-NEXT: ^~~~
+  // CHECK-MESSAGES-NEXT: UWB{{$}}
+  // CHECK-FIXES: static constexpr auto v8 = 1UWB;
+  static_assert(v8 == 1UWB);
+
+  static constexpr auto v9 = 1Uwb;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: integer literal has suffix 'Uwb', which is not uppercase
+  // CHECK-MESSAGES-NEXT: static constexpr auto v9 = 1Uwb;
+  // CHECK-MESSAGES-NEXT: ^~~~
+  // CHECK-MESSAGES-NEXT: UWB{{$}}
+  // CHECK-FIXES: static constexpr auto v9 = 1UWB;
+  static_assert(v9 == 1UWB);
+
+  static constexpr auto v10 = 1UWB; // OK.
+  static_assert(v10 == 1UWB);
+}
+
+void decimal_floating_point_suffix() {
+  // _Decimal32
+
+#if 0
+  static constexpr auto v1 = 1.df;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'df', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v1 = 1.df;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^ ~
+  // DISABLED-CHECK-MESSAGES-NEXT: DF{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v1 = 1.DF;
+  static_assert(v1 == 1.DF);
+
+  static constexpr auto v2 = 1.e0df;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'df', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v2 = 1.e0df;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^ ~
+  // DISABLED-CHECK-MESSAGES-NEXT: DF{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v2 = 1.e0DF;
+  static_assert(v2 == 1.DF);
+
+  static constexpr auto v3 = 1.DF; // OK.
+  static_assert(v3 == 1.DF);
+
+  static constexpr auto v4 = 1.e0DF; // OK.
+  static_assert(v4 == 1.DF);
+#endif
+
+  // _Decimal64
+
+#if 0
+  static constexpr auto v5 = 1.dd;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'dd', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v5 = 1.dd;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^ ~
+  // DISABLED-CHECK-MESSAGES-NEXT: DD{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v5 = 1.DD;
+  static_assert(v5 == 1.DD);
+
+  static constexpr auto v6 = 1.e0dd;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'dd', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v6 = 1.e0dd;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^ ~
+  // DISABLED-CHECK-MESSAGES-NEXT: DD{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v6 = 1.e0DD;
+  static_assert(v6 == 1.DD);
+
+  static constexpr auto v7 = 1.DD; // OK.
+  static_assert(v7 == 1.DD);
+
+  static constexpr auto v8 = 1.e0DD; // OK.
+  static_assert(v8 == 1.DD);
+#endif
+
+  // _Decimal128
+
+#if 0
+  static constexpr auto v9 = 1.dl;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'dl', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v9 = 1.dl;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^ ~
+  // DISABLED-CHECK-MESSAGES-NEXT: DL{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v9 = 1.DL;
+  static_assert(v9 == 1.DL);
+
+  static constexpr auto v10 = 1.e0dl;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'dl', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v10 = 1.e0dl;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^ ~
+  // DISABLED-CHECK-MESSAGES-NEXT: DL{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v10 = 1.e0DL;
+  static_assert(v10 == 1.DL);
+
+  static constexpr auto v11 = 1.DL; // OK.
+  static_assert(v11 == 1.DL);
+
+  static constexpr auto v12 = 1.e0DL; // OK.
+  static_assert(v12 == 1.DL);
+#endif
+}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/uppercase-literal-suffix-extended-floating-point.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/uppercase-literal-suffix-extended-floating-point.cpp
new file mode 100644
index 0000000000000..abe23e3363766
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/uppercase-literal-suffix-extended-floating-point.cpp
@@ -0,0 +1,248 @@
+// TODO: When Clang adds support for C++23 floating-point types, enable these tests by:
+//    1. Removing all the #if 0 + #endif guards.
+//    2. Removing all occurrences of the string "DISABLED-" in this file.
+//    3. Deleting this message.
+// These suffixes may be relevant to C too: https://github.com/llvm/llvm-project/issues/97335
+
+// RUN: %check_clang_tidy -std=c++23 %s readability-uppercase-literal-suffix %t -- -- -target aarch64-linux-gnu -I %clang_tidy_headers
+
+#include "integral_constant.h"
+#if 0
+#include <stdfloat>
+#endif
+
+void normal_literals() {
+  // std::bfloat16_t
+
+#if 0
+  static constexpr auto v1 = 1.bf16;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'bf16', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v1 = 1.bf16;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^ ~
+  // DISABLED-CHECK-MESSAGES-NEXT: BF16{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v1 = 1.BF16;
+  static_assert(is_same<decltype(v1), const std::bfloat16_t>::value, "");
+  static_assert(v1 == 1.BF16, "");
+
+  static constexpr auto v2 = 1.e0bf16;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'bf16', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v2 = 1.e0bf16;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^ ~
+  // DISABLED-CHECK-MESSAGES-NEXT: BF16{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v2 = 1.e0BF16;
+  static_assert(is_same<decltype(v2), const std::bfloat16_t>::value, "");
+  static_assert(v2 == 1.BF16, "");
+
+  static constexpr auto v3 = 1.BF16; // OK.
+  static_assert(is_same<decltype(v3), const std::bfloat16_t>::value, "");
+  static_assert(v3 == 1.BF16, "");
+
+  static constexpr auto v4 = 1.e0BF16; // OK.
+  static_assert(is_same<decltype(v4), const std::bfloat16_t>::value, "");
+  static_assert(v4 == 1.BF16, "");
+#endif
+
+  // _Float16/std::float16_t
+
+  static constexpr auto v5 = 1.f16;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'f16', which is not uppercase
+  // CHECK-MESSAGES-NEXT: static constexpr auto v5 = 1.f16;
+  // CHECK-MESSAGES-NEXT: ^ ~
+  // CHECK-MESSAGES-NEXT: F16{{$}}
+  // CHECK-FIXES: static constexpr auto v5 = 1.F16;
+  static_assert(is_same<decltype(v5), const _Float16>::value, "");
+  static_assert(v5 == 1.F16, "");
+
+  static constexpr auto v6 = 1.e0f16;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'f16', which is not uppercase
+  // CHECK-MESSAGES-NEXT: static constexpr auto v6 = 1.e0f16;
+  // CHECK-MESSAGES-NEXT: ^ ~
+  // CHECK-MESSAGES-NEXT: F16{{$}}
+  // CHECK-FIXES: static constexpr auto v6 = 1.e0F16;
+  static_assert(is_same<decltype(v6), const _Float16>::value, "");
+  static_assert(v6 == 1.F16, "");
+
+  static constexpr auto v7 = 1.F16; // OK.
+  static_assert(is_same<decltype(v7), const _Float16>::value, "");
+  static_assert(v7 == 1.F16, "");
+
+  static constexpr auto v8 = 1.e0F16; // OK.
+  static_assert(is_same<decltype(v8), const _Float16>::value, "");
+  static_assert(v8 == 1.F16, "");
+
+  // std::float32_t
+
+#if 0
+  static constexpr auto v9 = 1.f32;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'f32', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v9 = 1.f32;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^ ~
+  // DISABLED-CHECK-MESSAGES-NEXT: F32{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v9 = 1.F32;
+  static_assert(is_same<decltype(v9), const std::float32_t>::value, "");
+  static_assert(v9 == 1.F32, "");
+
+  static constexpr auto v10 = 1.e0f32;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'f32', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v10 = 1.e0f32;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^ ~
+  // DISABLED-CHECK-MESSAGES-NEXT: F32{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v10 = 1.e0F32;
+  static_assert(is_same<decltype(v10), const std::float32_t>::value, "");
+  static_assert(v10 == 1.F32, "");
+
+  static constexpr auto v11 = 1.F32; // OK.
+  static_assert(is_same<decltype(v11), const std::float32_t>::value, "");
+  static_assert(v11 == 1.F32, "");
+
+  static constexpr auto v12 = 1.e0F32; // OK.
+  static_assert(is_same<decltype(v12), const std::float32_t>::value, "");
+  static_assert(v12 == 1.F32, "");
+#endif
+
+  // std::float64_t
+
+#if 0
+  static constexpr auto v13 = 1.f64;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'f64', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v13 = 1.f64;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^ ~
+  // DISABLED-CHECK-MESSAGES-NEXT: F64{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v13 = 1.F64;
+  static_assert(is_same<decltype(v13), const std::float64_t>::value, "");
+  static_assert(v13 == 1.F64, "");
+
+  static constexpr auto v14 = 1.e0f64;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'f64', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v14 = 1.e0f64;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^ ~
+  // DISABLED-CHECK-MESSAGES-NEXT: F64{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v14 = 1.e0F64;
+  static_assert(is_same<decltype(v14), const std::float64_t>::value, "");
+  static_assert(v14 == 1.F64, "");
+
+  static constexpr auto v15 = 1.F64; // OK.
+  static_assert(is_same<decltype(v15), const std::float64_t>::value, "");
+  static_assert(v15 == 1.F64, "");
+
+  static constexpr auto v16 = 1.e0F64; // OK.
+  static_assert(is_same<decltype(v16), const std::float64_t>::value, "");
+  static_assert(v16 == 1.F64, "");
+#endif
+
+  // std::float128_t
+
+#if 0
+  static constexpr auto v17 = 1.f128;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'f128', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v17 = 1.f128;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^ ~
+  // DISABLED-CHECK-MESSAGES-NEXT: F128{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v17 = 1.F128;
+  static_assert(is_same<decltype(v17), const std::float128_t>::value, "");
+  static_assert(v17 == 1.F128, "");
+
+  static constexpr auto v18 = 1.e0f128;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'f128', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v18 = 1.e0f128;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^ ~
+  // DISABLED-CHECK-MESSAGES-NEXT: F128{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v18 = 1.e0F128;
+  static_assert(is_same<decltype(v18), const std::float128_t>::value, "");
+  static_assert(v18 == 1.F128, "");
+
+  static constexpr auto v19 = 1.F128; // OK.
+  static_assert(is_same<decltype(v19), const std::float128_t>::value, "");
+  static_assert(v19 == 1.F128, "");
+
+  static constexpr auto v20 = 1.e0F128; // OK.
+  static_assert(is_same<decltype(v20), const std::float128_t>::value, "");
+  static_assert(v20 == 1.F128, "");
+#endif
+}
+
+void hexadecimal_literals() {
+  // std::bfloat16_t
+
+#if 0
+  static constexpr auto v1 = 0xfp0bf16;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'bf16', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v1 = 0xfp0bf16;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^    ~
+  // DISABLED-CHECK-MESSAGES-NEXT: BF16{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v1 = 0xfp0BF16;
+  static_assert(is_same<decltype(v1), const std::bfloat16_t>::value, "");
+  static_assert(v1 == 0xfp0BF16, "");
+
+  static constexpr auto v2 = 0xfp0BF16; // OK.
+  static_assert(is_same<decltype(v2), const std::bfloat16_t>::value, "");
+  static_assert(v2 == 0xfp0BF16, "");
+#endif
+
+  // _Float16/std::float16_t
+
+  static constexpr auto v3 = 0xfp0f16;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'f16', which is not uppercase
+  // CHECK-MESSAGES-NEXT: static constexpr auto v3 = 0xfp0f16;
+  // CHECK-MESSAGES-NEXT: ^    ~
+  // CHECK-MESSAGES-NEXT: F16{{$}}
+  // CHECK-FIXES: static constexpr auto v3 = 0xfp0F16;
+  static_assert(is_same<decltype(v3), const _Float16>::value, "");
+  static_assert(v3 == 0xfp0F16, "");
+
+  static constexpr auto v4 = 0xfp0F16; // OK.
+  static_assert(is_same<decltype(v4), const _Float16>::value, "");
+  static_assert(v4 == 0xfp0F16, "");
+
+  // std::float32_t
+
+#if 0
+  static constexpr auto v5 = 0xfp0f32;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'f32', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v5 = 0xfp0f32;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^    ~
+  // DISABLED-CHECK-MESSAGES-NEXT: F32{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v5 = 0xfp0F32;
+  static_assert(is_same<decltype(v5), const std::float32_t>::value, "");
+  static_assert(v5 == 0xfp0F32, "");
+
+  static constexpr auto v6 = 0xfp0F32; // OK.
+  static_assert(is_same<decltype(v6), const std::float32_t>::value, "");
+  static_assert(v6 == 0xfp0F32, "");
+#endif
+
+  // std::float64_t
+
+#if 0
+  static constexpr auto v7 = 0xfp0f64;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'f64', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v7 = 0xfp0f64;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^    ~
+  // DISABLED-CHECK-MESSAGES-NEXT: F64{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v7 = 0xfp0F64;
+  static_assert(is_same<decltype(v7), const std::float64_t>::value, "");
+  static_assert(v7 == 0xfp0F64, "");
+
+  static constexpr auto v8 = 0xfp0F64; // OK.
+  static_assert(is_same<decltype(v8), const std::float64_t>::value, "");
+  static_assert(v8 == 0xfp0F64, "");
+#endif
+
+  // std::float128_t
+
+#if 0
+  static constexpr auto v9 = 0xfp0f128;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'f128', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v9 = 0xfp0f128;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^    ~
+  // DISABLED-CHECK-MESSAGES-NEXT: F128{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v9 = 0xfp0F128;
+  static_assert(is_same<decltype(v9), const std::float128_t>::value, "");
+  static_assert(v9 == 0xfp0F128, "");
+
+  static constexpr auto v10 ...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Jul 11, 2025

@llvm/pr-subscribers-clang-tidy

Author: Victor Chernyakin (localspook)

Changes

C++23 integer literal suffixes:

Suffix Type
z std::make_signed_t&lt;std::size_t&gt;
uz std::size_t

C++23 floating-point literal suffixes:

Suffix Type
bf16 std::bfloat16_t
f16 std::float16_t
f32 std::float32_t
f64 std::float64_t
f128 std::float128_t

C23 integer literal suffixes:

Suffix Type
wb _BitInt(N)
uwb unsigned _BitInt(N)

C23 floating-point literal suffixes:

Suffix Type
df _Decimal32
dd _Decimal64
dl _Decimal128

Clang doesn't actually support any of the new floating point types yet (except for f16). I've decided to add disabled tests for them, so that when the support comes, we can flip the switch and support them with no delay.


Patch is 26.98 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/148275.diff

6 Files Affected:

  • (modified) clang-tools-extra/clang-tidy/readability/UppercaseLiteralSuffixCheck.cpp (+7-6)
  • (modified) clang-tools-extra/docs/ReleaseNotes.rst (+4)
  • (added) clang-tools-extra/test/clang-tidy/checkers/readability/uppercase-literal-suffix-c23.c (+162)
  • (added) clang-tools-extra/test/clang-tidy/checkers/readability/uppercase-literal-suffix-extended-floating-point.cpp (+248)
  • (removed) clang-tools-extra/test/clang-tidy/checkers/readability/uppercase-literal-suffix-float16.cpp (-51)
  • (modified) clang-tools-extra/test/clang-tidy/checkers/readability/uppercase-literal-suffix-integer.cpp (+85-1)
diff --git a/clang-tools-extra/clang-tidy/readability/UppercaseLiteralSuffixCheck.cpp b/clang-tools-extra/clang-tidy/readability/UppercaseLiteralSuffixCheck.cpp
index 678aa8dad48a7..dd43ee200f4c0 100644
--- a/clang-tools-extra/clang-tidy/readability/UppercaseLiteralSuffixCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UppercaseLiteralSuffixCheck.cpp
@@ -25,10 +25,11 @@ struct IntegerLiteralCheck {
   static constexpr llvm::StringLiteral Name = llvm::StringLiteral("integer");
   // What should be skipped before looking for the Suffixes? (Nothing here.)
   static constexpr llvm::StringLiteral SkipFirst = llvm::StringLiteral("");
-  // Suffix can only consist of 'u' and 'l' chars, and can be a complex number
-  // ('i', 'j'). In MS compatibility mode, suffixes like i32 are supported.
+  // Suffix can only consist of 'u', 'l', and 'z' chars, can be a bit-precise
+  // integer (wb), and can be a complex number ('i', 'j'). In MS compatibility
+  // mode, suffixes like i32 are supported.
   static constexpr llvm::StringLiteral Suffixes =
-      llvm::StringLiteral("uUlLiIjJ");
+      llvm::StringLiteral("uUlLzZwWbBiIjJ");
 };
 constexpr llvm::StringLiteral IntegerLiteralCheck::Name;
 constexpr llvm::StringLiteral IntegerLiteralCheck::SkipFirst;
@@ -45,10 +46,10 @@ struct FloatingLiteralCheck {
   // Since the exponent ('p'/'P') is mandatory for hexadecimal floating-point
   // literals, we first skip everything before the exponent.
   static constexpr llvm::StringLiteral SkipFirst = llvm::StringLiteral("pP");
-  // Suffix can only consist of 'f', 'l', "f16", 'h', 'q' chars,
-  // and can be a complex number ('i', 'j').
+  // Suffix can only consist of 'f', 'l', "f16", "bf16", "df", "dd", "dl",
+  // 'h', 'q' chars, and can be a complex number ('i', 'j').
   static constexpr llvm::StringLiteral Suffixes =
-      llvm::StringLiteral("fFlLhHqQiIjJ");
+      llvm::StringLiteral("fFlLbBdDhHqQiIjJ");
 };
 constexpr llvm::StringLiteral FloatingLiteralCheck::Name;
 constexpr llvm::StringLiteral FloatingLiteralCheck::SkipFirst;
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index ad869265a2db5..119c030b43852 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -354,6 +354,10 @@ Changes in existing checks
   <clang-tidy/checks/readability/redundant-smartptr-get>` check by fixing
   some false positives involving smart pointers to arrays.
 
+- Improved :doc:`readability-uppercase-literal-suffix
+  <clang-tidy/checks/readability/uppercase-literal-suffix>` check to recognize
+  literal suffixes added in C++23 and C23.
+
 Removed checks
 ^^^^^^^^^^^^^^
 
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/uppercase-literal-suffix-c23.c b/clang-tools-extra/test/clang-tidy/checkers/readability/uppercase-literal-suffix-c23.c
new file mode 100644
index 0000000000000..75727fc69e68c
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/uppercase-literal-suffix-c23.c
@@ -0,0 +1,162 @@
+// TODO: When Clang adds support for decimal floating point types, enable these tests by:
+//    1. Removing all the #if 0 + #endif guards.
+//    2. Removing all occurrences of the string "DISABLED-" in this file.
+//    3. Deleting this message.
+
+// RUN: %check_clang_tidy %s readability-uppercase-literal-suffix %t -- -- -std=c23
+// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.c
+// RUN: clang-tidy %t.c -checks='-*,readability-uppercase-literal-suffix' -fix -- -std=c23
+// RUN: clang-tidy %t.c -checks='-*,readability-uppercase-literal-suffix' -warnings-as-errors='-*,readability-uppercase-literal-suffix' -- -std=c23
+
+void bit_precise_literal_suffix() {
+  // _BitInt()
+
+  static constexpr auto v1 = 1wb;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: integer literal has suffix 'wb', which is not uppercase
+  // CHECK-MESSAGES-NEXT: static constexpr auto v1 = 1wb;
+  // CHECK-MESSAGES-NEXT: ^~~
+  // CHECK-MESSAGES-NEXT: WB{{$}}
+  // CHECK-FIXES: static constexpr auto v1 = 1WB;
+  static_assert(v1 == 1WB);
+
+  static constexpr auto v2 = 1WB; // OK.
+  static_assert(v2 == 1WB);
+
+  // _BitInt() Unsigned
+
+  static constexpr auto v3 = 1wbu;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: integer literal has suffix 'wbu', which is not uppercase
+  // CHECK-MESSAGES-NEXT: static constexpr auto v3 = 1wbu;
+  // CHECK-MESSAGES-NEXT: ^~~~
+  // CHECK-MESSAGES-NEXT: WBU{{$}}
+  // CHECK-FIXES: static constexpr auto v3 = 1WBU;
+  static_assert(v3 == 1WBU);
+
+  static constexpr auto v4 = 1WBu;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: integer literal has suffix 'WBu', which is not uppercase
+  // CHECK-MESSAGES-NEXT: static constexpr auto v4 = 1WBu;
+  // CHECK-MESSAGES-NEXT: ^~~~
+  // CHECK-MESSAGES-NEXT: WBU{{$}}
+  // CHECK-FIXES: static constexpr auto v4 = 1WBU;
+  static_assert(v4 == 1WBU);
+
+  static constexpr auto v5 = 1wbU;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: integer literal has suffix 'wbU', which is not uppercase
+  // CHECK-MESSAGES-NEXT: static constexpr auto v5 = 1wbU;
+  // CHECK-MESSAGES-NEXT: ^~~~
+  // CHECK-MESSAGES-NEXT: WBU{{$}}
+  // CHECK-FIXES: static constexpr auto v5 = 1WBU;
+  static_assert(v5 == 1WBU);
+
+  static constexpr auto v6 = 1WBU; // OK.
+  static_assert(v6 == 1WBU);
+
+  // Unsigned _BitInt()
+
+  static constexpr auto v7 = 1uwb;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: integer literal has suffix 'uwb', which is not uppercase
+  // CHECK-MESSAGES-NEXT: static constexpr auto v7 = 1uwb;
+  // CHECK-MESSAGES-NEXT: ^~~~
+  // CHECK-MESSAGES-NEXT: UWB{{$}}
+  // CHECK-FIXES: static constexpr auto v7 = 1UWB;
+  static_assert(v7 == 1UWB);
+
+  static constexpr auto v8 = 1uWB;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: integer literal has suffix 'uWB', which is not uppercase
+  // CHECK-MESSAGES-NEXT: static constexpr auto v8 = 1uWB;
+  // CHECK-MESSAGES-NEXT: ^~~~
+  // CHECK-MESSAGES-NEXT: UWB{{$}}
+  // CHECK-FIXES: static constexpr auto v8 = 1UWB;
+  static_assert(v8 == 1UWB);
+
+  static constexpr auto v9 = 1Uwb;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: integer literal has suffix 'Uwb', which is not uppercase
+  // CHECK-MESSAGES-NEXT: static constexpr auto v9 = 1Uwb;
+  // CHECK-MESSAGES-NEXT: ^~~~
+  // CHECK-MESSAGES-NEXT: UWB{{$}}
+  // CHECK-FIXES: static constexpr auto v9 = 1UWB;
+  static_assert(v9 == 1UWB);
+
+  static constexpr auto v10 = 1UWB; // OK.
+  static_assert(v10 == 1UWB);
+}
+
+void decimal_floating_point_suffix() {
+  // _Decimal32
+
+#if 0
+  static constexpr auto v1 = 1.df;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'df', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v1 = 1.df;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^ ~
+  // DISABLED-CHECK-MESSAGES-NEXT: DF{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v1 = 1.DF;
+  static_assert(v1 == 1.DF);
+
+  static constexpr auto v2 = 1.e0df;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'df', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v2 = 1.e0df;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^ ~
+  // DISABLED-CHECK-MESSAGES-NEXT: DF{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v2 = 1.e0DF;
+  static_assert(v2 == 1.DF);
+
+  static constexpr auto v3 = 1.DF; // OK.
+  static_assert(v3 == 1.DF);
+
+  static constexpr auto v4 = 1.e0DF; // OK.
+  static_assert(v4 == 1.DF);
+#endif
+
+  // _Decimal64
+
+#if 0
+  static constexpr auto v5 = 1.dd;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'dd', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v5 = 1.dd;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^ ~
+  // DISABLED-CHECK-MESSAGES-NEXT: DD{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v5 = 1.DD;
+  static_assert(v5 == 1.DD);
+
+  static constexpr auto v6 = 1.e0dd;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'dd', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v6 = 1.e0dd;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^ ~
+  // DISABLED-CHECK-MESSAGES-NEXT: DD{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v6 = 1.e0DD;
+  static_assert(v6 == 1.DD);
+
+  static constexpr auto v7 = 1.DD; // OK.
+  static_assert(v7 == 1.DD);
+
+  static constexpr auto v8 = 1.e0DD; // OK.
+  static_assert(v8 == 1.DD);
+#endif
+
+  // _Decimal128
+
+#if 0
+  static constexpr auto v9 = 1.dl;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'dl', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v9 = 1.dl;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^ ~
+  // DISABLED-CHECK-MESSAGES-NEXT: DL{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v9 = 1.DL;
+  static_assert(v9 == 1.DL);
+
+  static constexpr auto v10 = 1.e0dl;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'dl', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v10 = 1.e0dl;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^ ~
+  // DISABLED-CHECK-MESSAGES-NEXT: DL{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v10 = 1.e0DL;
+  static_assert(v10 == 1.DL);
+
+  static constexpr auto v11 = 1.DL; // OK.
+  static_assert(v11 == 1.DL);
+
+  static constexpr auto v12 = 1.e0DL; // OK.
+  static_assert(v12 == 1.DL);
+#endif
+}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/uppercase-literal-suffix-extended-floating-point.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/uppercase-literal-suffix-extended-floating-point.cpp
new file mode 100644
index 0000000000000..abe23e3363766
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/uppercase-literal-suffix-extended-floating-point.cpp
@@ -0,0 +1,248 @@
+// TODO: When Clang adds support for C++23 floating-point types, enable these tests by:
+//    1. Removing all the #if 0 + #endif guards.
+//    2. Removing all occurrences of the string "DISABLED-" in this file.
+//    3. Deleting this message.
+// These suffixes may be relevant to C too: https://github.com/llvm/llvm-project/issues/97335
+
+// RUN: %check_clang_tidy -std=c++23 %s readability-uppercase-literal-suffix %t -- -- -target aarch64-linux-gnu -I %clang_tidy_headers
+
+#include "integral_constant.h"
+#if 0
+#include <stdfloat>
+#endif
+
+void normal_literals() {
+  // std::bfloat16_t
+
+#if 0
+  static constexpr auto v1 = 1.bf16;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'bf16', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v1 = 1.bf16;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^ ~
+  // DISABLED-CHECK-MESSAGES-NEXT: BF16{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v1 = 1.BF16;
+  static_assert(is_same<decltype(v1), const std::bfloat16_t>::value, "");
+  static_assert(v1 == 1.BF16, "");
+
+  static constexpr auto v2 = 1.e0bf16;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'bf16', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v2 = 1.e0bf16;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^ ~
+  // DISABLED-CHECK-MESSAGES-NEXT: BF16{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v2 = 1.e0BF16;
+  static_assert(is_same<decltype(v2), const std::bfloat16_t>::value, "");
+  static_assert(v2 == 1.BF16, "");
+
+  static constexpr auto v3 = 1.BF16; // OK.
+  static_assert(is_same<decltype(v3), const std::bfloat16_t>::value, "");
+  static_assert(v3 == 1.BF16, "");
+
+  static constexpr auto v4 = 1.e0BF16; // OK.
+  static_assert(is_same<decltype(v4), const std::bfloat16_t>::value, "");
+  static_assert(v4 == 1.BF16, "");
+#endif
+
+  // _Float16/std::float16_t
+
+  static constexpr auto v5 = 1.f16;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'f16', which is not uppercase
+  // CHECK-MESSAGES-NEXT: static constexpr auto v5 = 1.f16;
+  // CHECK-MESSAGES-NEXT: ^ ~
+  // CHECK-MESSAGES-NEXT: F16{{$}}
+  // CHECK-FIXES: static constexpr auto v5 = 1.F16;
+  static_assert(is_same<decltype(v5), const _Float16>::value, "");
+  static_assert(v5 == 1.F16, "");
+
+  static constexpr auto v6 = 1.e0f16;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'f16', which is not uppercase
+  // CHECK-MESSAGES-NEXT: static constexpr auto v6 = 1.e0f16;
+  // CHECK-MESSAGES-NEXT: ^ ~
+  // CHECK-MESSAGES-NEXT: F16{{$}}
+  // CHECK-FIXES: static constexpr auto v6 = 1.e0F16;
+  static_assert(is_same<decltype(v6), const _Float16>::value, "");
+  static_assert(v6 == 1.F16, "");
+
+  static constexpr auto v7 = 1.F16; // OK.
+  static_assert(is_same<decltype(v7), const _Float16>::value, "");
+  static_assert(v7 == 1.F16, "");
+
+  static constexpr auto v8 = 1.e0F16; // OK.
+  static_assert(is_same<decltype(v8), const _Float16>::value, "");
+  static_assert(v8 == 1.F16, "");
+
+  // std::float32_t
+
+#if 0
+  static constexpr auto v9 = 1.f32;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'f32', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v9 = 1.f32;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^ ~
+  // DISABLED-CHECK-MESSAGES-NEXT: F32{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v9 = 1.F32;
+  static_assert(is_same<decltype(v9), const std::float32_t>::value, "");
+  static_assert(v9 == 1.F32, "");
+
+  static constexpr auto v10 = 1.e0f32;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'f32', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v10 = 1.e0f32;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^ ~
+  // DISABLED-CHECK-MESSAGES-NEXT: F32{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v10 = 1.e0F32;
+  static_assert(is_same<decltype(v10), const std::float32_t>::value, "");
+  static_assert(v10 == 1.F32, "");
+
+  static constexpr auto v11 = 1.F32; // OK.
+  static_assert(is_same<decltype(v11), const std::float32_t>::value, "");
+  static_assert(v11 == 1.F32, "");
+
+  static constexpr auto v12 = 1.e0F32; // OK.
+  static_assert(is_same<decltype(v12), const std::float32_t>::value, "");
+  static_assert(v12 == 1.F32, "");
+#endif
+
+  // std::float64_t
+
+#if 0
+  static constexpr auto v13 = 1.f64;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'f64', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v13 = 1.f64;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^ ~
+  // DISABLED-CHECK-MESSAGES-NEXT: F64{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v13 = 1.F64;
+  static_assert(is_same<decltype(v13), const std::float64_t>::value, "");
+  static_assert(v13 == 1.F64, "");
+
+  static constexpr auto v14 = 1.e0f64;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'f64', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v14 = 1.e0f64;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^ ~
+  // DISABLED-CHECK-MESSAGES-NEXT: F64{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v14 = 1.e0F64;
+  static_assert(is_same<decltype(v14), const std::float64_t>::value, "");
+  static_assert(v14 == 1.F64, "");
+
+  static constexpr auto v15 = 1.F64; // OK.
+  static_assert(is_same<decltype(v15), const std::float64_t>::value, "");
+  static_assert(v15 == 1.F64, "");
+
+  static constexpr auto v16 = 1.e0F64; // OK.
+  static_assert(is_same<decltype(v16), const std::float64_t>::value, "");
+  static_assert(v16 == 1.F64, "");
+#endif
+
+  // std::float128_t
+
+#if 0
+  static constexpr auto v17 = 1.f128;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'f128', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v17 = 1.f128;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^ ~
+  // DISABLED-CHECK-MESSAGES-NEXT: F128{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v17 = 1.F128;
+  static_assert(is_same<decltype(v17), const std::float128_t>::value, "");
+  static_assert(v17 == 1.F128, "");
+
+  static constexpr auto v18 = 1.e0f128;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'f128', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v18 = 1.e0f128;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^ ~
+  // DISABLED-CHECK-MESSAGES-NEXT: F128{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v18 = 1.e0F128;
+  static_assert(is_same<decltype(v18), const std::float128_t>::value, "");
+  static_assert(v18 == 1.F128, "");
+
+  static constexpr auto v19 = 1.F128; // OK.
+  static_assert(is_same<decltype(v19), const std::float128_t>::value, "");
+  static_assert(v19 == 1.F128, "");
+
+  static constexpr auto v20 = 1.e0F128; // OK.
+  static_assert(is_same<decltype(v20), const std::float128_t>::value, "");
+  static_assert(v20 == 1.F128, "");
+#endif
+}
+
+void hexadecimal_literals() {
+  // std::bfloat16_t
+
+#if 0
+  static constexpr auto v1 = 0xfp0bf16;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'bf16', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v1 = 0xfp0bf16;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^    ~
+  // DISABLED-CHECK-MESSAGES-NEXT: BF16{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v1 = 0xfp0BF16;
+  static_assert(is_same<decltype(v1), const std::bfloat16_t>::value, "");
+  static_assert(v1 == 0xfp0BF16, "");
+
+  static constexpr auto v2 = 0xfp0BF16; // OK.
+  static_assert(is_same<decltype(v2), const std::bfloat16_t>::value, "");
+  static_assert(v2 == 0xfp0BF16, "");
+#endif
+
+  // _Float16/std::float16_t
+
+  static constexpr auto v3 = 0xfp0f16;
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'f16', which is not uppercase
+  // CHECK-MESSAGES-NEXT: static constexpr auto v3 = 0xfp0f16;
+  // CHECK-MESSAGES-NEXT: ^    ~
+  // CHECK-MESSAGES-NEXT: F16{{$}}
+  // CHECK-FIXES: static constexpr auto v3 = 0xfp0F16;
+  static_assert(is_same<decltype(v3), const _Float16>::value, "");
+  static_assert(v3 == 0xfp0F16, "");
+
+  static constexpr auto v4 = 0xfp0F16; // OK.
+  static_assert(is_same<decltype(v4), const _Float16>::value, "");
+  static_assert(v4 == 0xfp0F16, "");
+
+  // std::float32_t
+
+#if 0
+  static constexpr auto v5 = 0xfp0f32;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'f32', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v5 = 0xfp0f32;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^    ~
+  // DISABLED-CHECK-MESSAGES-NEXT: F32{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v5 = 0xfp0F32;
+  static_assert(is_same<decltype(v5), const std::float32_t>::value, "");
+  static_assert(v5 == 0xfp0F32, "");
+
+  static constexpr auto v6 = 0xfp0F32; // OK.
+  static_assert(is_same<decltype(v6), const std::float32_t>::value, "");
+  static_assert(v6 == 0xfp0F32, "");
+#endif
+
+  // std::float64_t
+
+#if 0
+  static constexpr auto v7 = 0xfp0f64;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'f64', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v7 = 0xfp0f64;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^    ~
+  // DISABLED-CHECK-MESSAGES-NEXT: F64{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v7 = 0xfp0F64;
+  static_assert(is_same<decltype(v7), const std::float64_t>::value, "");
+  static_assert(v7 == 0xfp0F64, "");
+
+  static constexpr auto v8 = 0xfp0F64; // OK.
+  static_assert(is_same<decltype(v8), const std::float64_t>::value, "");
+  static_assert(v8 == 0xfp0F64, "");
+#endif
+
+  // std::float128_t
+
+#if 0
+  static constexpr auto v9 = 0xfp0f128;
+  // DISABLED-CHECK-MESSAGES: :[[@LINE-1]]:30: warning: floating point literal has suffix 'f128', which is not uppercase
+  // DISABLED-CHECK-MESSAGES-NEXT: static constexpr auto v9 = 0xfp0f128;
+  // DISABLED-CHECK-MESSAGES-NEXT: ^    ~
+  // DISABLED-CHECK-MESSAGES-NEXT: F128{{$}}
+  // DISABLED-CHECK-FIXES: static constexpr auto v9 = 0xfp0F128;
+  static_assert(is_same<decltype(v9), const std::float128_t>::value, "");
+  static_assert(v9 == 0xfp0F128, "");
+
+  static constexpr auto v10 ...
[truncated]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants