-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[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
Conversation
… and C23 suffixes
@llvm/pr-subscribers-clang-tools-extra Author: Victor Chernyakin (localspook) ChangesC++23 integer literal suffixes:
C++23 floating-point literal suffixes:
C23 integer literal suffixes:
C23 floating-point literal suffixes:
Clang doesn't actually support any of the new floating point types yet (except for 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:
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]
|
@llvm/pr-subscribers-clang-tidy Author: Victor Chernyakin (localspook) ChangesC++23 integer literal suffixes:
C++23 floating-point literal suffixes:
C23 integer literal suffixes:
C23 floating-point literal suffixes:
Clang doesn't actually support any of the new floating point types yet (except for 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:
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]
|
clang-tools-extra/test/clang-tidy/checkers/readability/uppercase-literal-suffix-c23.c
Outdated
Show resolved
Hide resolved
...ra/test/clang-tidy/checkers/readability/uppercase-literal-suffix-extended-floating-point.cpp
Outdated
Show resolved
Hide resolved
// 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need this target aarch64-linux-gnu
? Seems odd to me, maybe we can delete it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1, we use the default target (x86_64) in tests
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I copied this from the existing uppercase-literal-suffix-float16.cpp
test; apparently clang doesn't support _Float16
on x86_64. Should I add a TODO
to remove the -target
once compiler support improves?
|
||
#include "integral_constant.h" | ||
#if 0 | ||
#include <stdfloat> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this a real header or a fake one from %clang_tidy_headers
? We should not depend on real-world headers in tests. If it is expected to be real, we should create a fake one instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added stub stdfloat
. I can't add the actual type aliases yet though, we need to wait for compiler support.
clang-tools-extra/test/clang-tidy/checkers/readability/uppercase-literal-suffix-integer.cpp
Outdated
Show resolved
Hide resolved
// CHECK-MESSAGES-NEXT: static constexpr auto v1 = 1wb; | ||
// CHECK-MESSAGES-NEXT: ^~~ | ||
// CHECK-MESSAGES-NEXT: WB{{$}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need these messages? I haven't seen them in other tests and they look obsolete (considering we have CHECK-FIXES).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm parroting the existing uppercase-literal-suffix-*
tests here. I agree that they seem unnecessary; should I go and remove them from the existing tests too? (ditto for grep
, it looks like it could just be a cp
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think yes, remove unnecessary CHECK-FIXES-NEXT.
But i still don't understand what we need cp
for. Could we just make two separate test files instead of creating one on the fly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The idea is that we copy the test, run the check and apply fixes, then run the check again to make sure there are no more warnings. (I’m not sure how much value this adds on top of the usual CHECK-FIXES
. I wouldn’t be against removing it too.) But making a separate file would cause duplication: we would need to check in both the original and the fixed file, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for description! A separate file won't do much, and I don't see any value in running check multiple times over corrected file, so I vote to remove it. If this thing is ever needed, I think it should go to check_clang_tidy.py
as an opt-in for tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only benefit I see is to don't write GOOD cases. So the workflow would be like:
- Write only "bad" cases in test file
- First run corrects that they are all become "good"
- Second run checks that none of "good" are not flagged as FP.
So since we write all good cases explicitly (I hope so) then we don't need double-run.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this thing is ever needed, I think it should go to check_clang_tidy.py as an opt-in for tests.
+1
I’ll go and remove it from this and existing tests
// 3. Deleting this message. | ||
|
||
// RUN: %check_clang_tidy -std=c23-or-later %s readability-uppercase-literal-suffix %t | ||
// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.c |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need grep
? What if build env doesn't have it, e.g. Windows
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Our win tests may have grep
but downstream users may not
|
||
#include "integral_constant.h" | ||
|
||
void integer_suffix() { | ||
static constexpr auto v0 = __LINE__; // synthetic | ||
static_assert(v0 == 9 || v0 == 5, ""); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm removing this assert (here and in 2 other places) because it depends on absolute line numbers. I considered changing it to relative numbers (static_assert(v0 == (__LINE__ - 1), "");
), but I think it's better to remove it, because all we care about is that the check doesn't fire here, we don't care about line numbers at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/79/builds/2119 Here is the relevant piece of the build log for the reference
|
That CI failure looks unrelated. (I see the same error on |
I'm sorry, but what about 0x1b test case? |
What do you mean by that? 🤔 |
Sorry for not being clear enough. My point is the checker will report literal 0x1b as an issue since b is in the list of suffixes, however 0x1b is a valid hex integer literal. Actually we are missing LIT tests for hex literals. |
Good catch, thank you! Opened #156584 with a fix. |
C++23 integer literal suffixes:
z
std::make_signed_t<std::size_t>
uz
std::size_t
C++23 floating-point literal suffixes:
bf16
std::bfloat16_t
f16
std::float16_t
f32
std::float32_t
f64
std::float64_t
f128
std::float128_t
C23 integer literal suffixes:
wb
_BitInt(N)
uwb
unsigned _BitInt(N)
C23 floating-point literal suffixes:
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.