[clang-tools-extra] [clang-tidy] Add modernize-use-to-underlying check (PR #210459)
Baranov Victor via cfe-commits
cfe-commits at lists.llvm.org
Sun Jul 26 00:28:13 PDT 2026
================
@@ -0,0 +1,135 @@
+// RUN: %check_clang_tidy -std=c++23-or-later %s modernize-use-to-underlying %t
+
+// The <utility> header for std::to_underlying is not yet included, so the check
+// must insert it.
+// CHECK-FIXES: #include <utility>
+
+enum class ColorInt : int { Red, Green, Blue };
+enum class ByteEnum : unsigned char { A, B };
+enum class DefaultEnum { X, Y }; // underlying type is int
+enum class OtherEnum : int {};
+enum Unscoped : int { U0, U1 }; // not a scoped enum
+
+// A precise cast (destination type equals the underlying type) is always
+// diagnosed and the whole cast is replaced. static_cast, C-style and
+// functional-style casts are all matched.
+void precise(ColorInt c, ByteEnum b, DefaultEnum d) {
+ int A = static_cast<int>(c);
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use 'std::to_underlying' to convert a scoped enumeration to its underlying type [modernize-use-to-underlying]
+ // CHECK-FIXES: int A = std::to_underlying(c);
+ unsigned char B = static_cast<unsigned char>(b);
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: use 'std::to_underlying' to convert a scoped enumeration to its underlying type [modernize-use-to-underlying]
+ // CHECK-FIXES: unsigned char B = std::to_underlying(b);
+ int C = static_cast<int>(d);
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use 'std::to_underlying' to convert a scoped enumeration to its underlying type [modernize-use-to-underlying]
+ // CHECK-FIXES: int C = std::to_underlying(d);
+ int D = (int)c;
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use 'std::to_underlying' to convert a scoped enumeration to its underlying type [modernize-use-to-underlying]
+ // CHECK-FIXES: int D = std::to_underlying(c);
+ int E = int(c);
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use 'std::to_underlying' to convert a scoped enumeration to its underlying type [modernize-use-to-underlying]
+ // CHECK-FIXES: int E = std::to_underlying(c);
+}
+
+// With the default ImpreciseCasts=Warn, an imprecise cast (destination type
+// differs from the underlying type in width or signedness) is diagnosed but no
+// fix-it is applied.
+void imprecise(ColorInt c) {
+ long W = static_cast<long>(c);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use 'std::to_underlying' to convert a scoped enumeration to its underlying type [modernize-use-to-underlying]
+ // CHECK-FIXES: long W = static_cast<long>(c);
+ unsigned S = static_cast<unsigned>(c);
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use 'std::to_underlying' to convert a scoped enumeration to its underlying type [modernize-use-to-underlying]
+ // CHECK-FIXES: unsigned S = static_cast<unsigned>(c);
+}
+
+// Cases that must never be flagged.
----------------
vbvictor wrote:
Ditto
https://github.com/llvm/llvm-project/pull/210459
More information about the cfe-commits
mailing list