Author: Jan Schultke
Date: 2026-05-08T12:37:21Z
New Revision: c48b74fbcf604c14f4e53d284c3f3da4076db427

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

LOG: [clang] Deduce _BitInt(N) template parameter as size_t (#195534)

Update template argument deduction to deduce the `N` in `_BitInt(N)` as
`size_t` rather than `int`. This increases consistency with deduction of
array sizes, and matches the behavior proposed in P3666.

Fixes #195033

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/Sema/SemaTemplateDeduction.cpp
    clang/test/SemaCXX/ext-int.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index ac462e3bf4732..aea89aebd0c31 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -49,6 +49,11 @@ C++ Specific Potentially Breaking Changes
 - Clang now correctly rejects ``export`` declarations in module implementation
   partitions. (#GH107602)
 
+- Template argument deduction now treats the ``N`` in ``_BitInt(N)``
+  as being of type ``std::size_t`` instead of ``int``,
+  matching the deduction of array sizes from ``int(&)[N]``.
+  This is a breaking change for code that depended on the previously deduced 
type. (#GH195033)
+
 ABI Changes in This Version
 ---------------------------
 

diff  --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index c71c40526ccdc..defdd9ca6968a 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -2511,11 +2511,13 @@ static TemplateDeductionResult 
DeduceTemplateArgumentsByTypeMatch(
         if (!NTTP)
           return TemplateDeductionResult::Success;
 
-        llvm::APSInt ArgSize(S.Context.getTypeSize(S.Context.IntTy), false);
+        // Deduce the size parameter of _BitInt as std::size_t
+        QualType T = S.Context.getSizeType();
+        llvm::APSInt ArgSize(S.Context.getTypeSize(T), /*IsUnsigned=*/true);
         ArgSize = IA->getNumBits();
 
         return DeduceNonTypeTemplateArgument(
-            S, TemplateParams, NTTP, ArgSize, S.Context.IntTy, true, Info,
+            S, TemplateParams, NTTP, ArgSize, T, true, Info,
             POK != PartialOrderingKind::None, Deduced, HasDeducedAnyParam);
       }
 

diff  --git a/clang/test/SemaCXX/ext-int.cpp b/clang/test/SemaCXX/ext-int.cpp
index 5c566dafed931..281ae3d3c1779 100644
--- a/clang/test/SemaCXX/ext-int.cpp
+++ b/clang/test/SemaCXX/ext-int.cpp
@@ -61,6 +61,29 @@ template<typename T>
 void deduced_whole_type(T){}
 template<int I>
 void deduced_bound(_BitInt(I)){}
+template<int I>
+void deduced_bound_unsigned(unsigned _BitInt(I)){}
+
+using size_t = decltype(sizeof(0));
+
+#if __cplusplus >= 201703L
+template<auto X> void deduced_bound_auto(_BitInt(X)) {
+  static_assert(__is_same(decltype(X), size_t), "");
+  static_assert(X == 9, "");
+}
+template<auto X> void deduced_bound_auto_unsigned(unsigned _BitInt(X)) {
+  static_assert(__is_same(decltype(X), size_t), "");
+  static_assert(X == 11, "");
+}
+template<typename T, T V> void deduced_bound_dependent(_BitInt(V)) {
+  static_assert(__is_same(T, size_t), "");
+  static_assert(V == 9, "");
+}
+template<typename T, T V> void deduced_bound_dependent_unsigned(unsigned 
_BitInt(V)) {
+  static_assert(__is_same(T, size_t), "");
+  static_assert(V == 11, "");
+}
+#endif
 
 // Ensure ext-int can be used in template places.
 void Templates() {
@@ -69,20 +92,20 @@ void Templates() {
   ExtIntTemplParam<b> c;
   constexpr _BitInt(9) d = 1;
   ExtIntTemplParam<b> e;
+  constexpr unsigned _BitInt(11) f = 1;
 
   deduced_whole_type(b);
+  deduced_whole_type(f);
   deduced_bound(b);
+  deduced_bound_unsigned(f);
+#if __cplusplus >= 201703L
+  deduced_bound_auto(d);
+  deduced_bound_auto_unsigned(f);
+  deduced_bound_dependent(d);
+  deduced_bound_dependent_unsigned(f);
+#endif
 }
 
-template <typename T, typename U>
-struct is_same {
-  static constexpr bool value = false;
-};
-template <typename T>
-struct is_same<T,T> {
-  static constexpr bool value = true;
-};
-
 // Reject vector types:
 // expected-error@+1{{'_BitInt' vector element width must be a power of 2}}
 typedef _BitInt(5) __attribute__((vector_size(16))) VecTy3;
@@ -143,16 +166,16 @@ void Ops() {
   x4_u - b;
   x43_s + b;
   x43_u - b;
-  static_assert(is_same<decltype(x43_s + x_int), _BitInt(43)>::value, "");
-  static_assert(is_same<decltype(x43_u + x_int), unsigned _BitInt(43)>::value, 
"");
-  static_assert(is_same<decltype(x32_s + x_int), int>::value, "");
-  static_assert(is_same<decltype(x32_u + x_int), unsigned int>::value, "");
-  static_assert(is_same<decltype(x32_s + x_uint), unsigned int>::value, "");
-  static_assert(is_same<decltype(x32_u + x_uint), unsigned int>::value, "");
-  static_assert(is_same<decltype(x4_s + x_int), int>::value, "");
-  static_assert(is_same<decltype(x4_u + x_int), int>::value, "");
-  static_assert(is_same<decltype(x4_s + x_uint), unsigned int>::value, "");
-  static_assert(is_same<decltype(x4_u + x_uint), unsigned int>::value, "");
+  static_assert(__is_same(decltype(x43_s + x_int), _BitInt(43)), "");
+  static_assert(__is_same(decltype(x43_u + x_int), unsigned _BitInt(43)), "");
+  static_assert(__is_same(decltype(x32_s + x_int), int), "");
+  static_assert(__is_same(decltype(x32_u + x_int), unsigned int), "");
+  static_assert(__is_same(decltype(x32_s + x_uint), unsigned int), "");
+  static_assert(__is_same(decltype(x32_u + x_uint), unsigned int), "");
+  static_assert(__is_same(decltype(x4_s + x_int), int), "");
+  static_assert(__is_same(decltype(x4_u + x_int), int), "");
+  static_assert(__is_same(decltype(x4_s + x_uint), unsigned int), "");
+  static_assert(__is_same(decltype(x4_u + x_uint), unsigned int), "");
 
   // Bitwise checks.
   x43_s % y4_u;
@@ -168,28 +191,28 @@ void Ops() {
   x4_s > 33; // expected-warning {{result of comparison of constant 33 with 
expression of type '_BitInt(4)' is always false}}
 
   // Same size/sign ops don't change type.
-  static_assert(is_same<decltype(x43_s + y43_s), _BitInt(43)>::value,"");
-  static_assert(is_same<decltype(x4_s - y4_s), _BitInt(4)>::value,"");
-  static_assert(is_same<decltype(x43_u * y43_u), unsigned 
_BitInt(43)>::value,"");
-  static_assert(is_same<decltype(x4_u / y4_u), unsigned _BitInt(4)>::value,"");
+  static_assert(__is_same(decltype(x43_s + y43_s), _BitInt(43)),"");
+  static_assert(__is_same(decltype(x4_s - y4_s), _BitInt(4)),"");
+  static_assert(__is_same(decltype(x43_u * y43_u), unsigned _BitInt(43)),"");
+  static_assert(__is_same(decltype(x4_u / y4_u), unsigned _BitInt(4)),"");
 
   // Unary ops shouldn't go through integer promotions.
-  static_assert(is_same<decltype(~x43_s), _BitInt(43)>::value,"");
-  static_assert(is_same<decltype(~x4_s), _BitInt(4)>::value,"");
-  static_assert(is_same<decltype(+x43_s), _BitInt(43)>::value,"");
-  static_assert(is_same<decltype(+x4_s), _BitInt(4)>::value,"");
-  static_assert(is_same<decltype(-x43_u), unsigned _BitInt(43)>::value,"");
-  static_assert(is_same<decltype(-x4_u), unsigned _BitInt(4)>::value,"");
+  static_assert(__is_same(decltype(~x43_s), _BitInt(43)),"");
+  static_assert(__is_same(decltype(~x4_s), _BitInt(4)),"");
+  static_assert(__is_same(decltype(+x43_s), _BitInt(43)),"");
+  static_assert(__is_same(decltype(+x4_s), _BitInt(4)),"");
+  static_assert(__is_same(decltype(-x43_u), unsigned _BitInt(43)),"");
+  static_assert(__is_same(decltype(-x4_u), unsigned _BitInt(4)),"");
   // expected-warning@+1{{expression with side effects has no effect in an 
unevaluated context}}
-  static_assert(is_same<decltype(++x43_s), _BitInt(43)&>::value,"");
+  static_assert(__is_same(decltype(++x43_s), _BitInt(43)&),"");
   // expected-warning@+1{{expression with side effects has no effect in an 
unevaluated context}}
-  static_assert(is_same<decltype(--x4_s), _BitInt(4)&>::value,"");
+  static_assert(__is_same(decltype(--x4_s), _BitInt(4)&),"");
   // expected-warning@+1{{expression with side effects has no effect in an 
unevaluated context}}
-  static_assert(is_same<decltype(x43_s--), _BitInt(43)>::value,"");
+  static_assert(__is_same(decltype(x43_s--), _BitInt(43)),"");
   // expected-warning@+1{{expression with side effects has no effect in an 
unevaluated context}}
-  static_assert(is_same<decltype(x4_s++), _BitInt(4)>::value,"");
-  static_assert(is_same<decltype(x4_s >> 1), _BitInt(4)>::value,"");
-  static_assert(is_same<decltype(x4_u << 1), unsigned _BitInt(4)>::value,"");
+  static_assert(__is_same(decltype(x4_s++), _BitInt(4)),"");
+  static_assert(__is_same(decltype(x4_s >> 1), _BitInt(4)),"");
+  static_assert(__is_same(decltype(x4_u << 1), unsigned _BitInt(4)),"");
 
   static_assert(sizeof(x43_s) == 8, "");
   static_assert(sizeof(x4_s) == 1, "");
@@ -202,7 +225,7 @@ constexpr int func() { return 42;}
 
 void ConstexprBitsize() {
   _BitInt(func()) F;
-  static_assert(is_same<decltype(F), _BitInt(42)>::value, "");
+  static_assert(__is_same(decltype(F), _BitInt(42)), "");
 }
 
 // Not useable as an underlying type.
@@ -273,9 +296,9 @@ void Ternary(_BitInt(30) s30, _BitInt(31) s31a, _BitInt(31) 
s31b,
   (void)(b ? s31a : s31b);
   (void)(s30 ? s31a : s31b);
 
-  static_assert(is_same<decltype(b ? s30 : s31a), _BitInt(31)>::value, "");
-  static_assert(is_same<decltype(b ? s32 : s30), _BitInt(32)>::value, "");
-  static_assert(is_same<decltype(b ? s30 : 0), int>::value, "");
+  static_assert(__is_same(decltype(b ? s30 : s31a), _BitInt(31)), "");
+  static_assert(__is_same(decltype(b ? s32 : s30), _BitInt(32)), "");
+  static_assert(__is_same(decltype(b ? s30 : 0), int), "");
 }
 
 void FromPaper1() {
@@ -285,11 +308,11 @@ void FromPaper1() {
   _BitInt(33) a33 = 1;
   char c = 3;
 
-  static_assert(is_same<decltype(a2 * a3), _BitInt(3)>::value, "");
-  static_assert(is_same<decltype(a2 * c), int>::value, "");
-  static_assert(is_same<decltype(a33 * c), _BitInt(33)>::value, "");
+  static_assert(__is_same(decltype(a2 * a3), _BitInt(3)), "");
+  static_assert(__is_same(decltype(a2 * c), int), "");
+  static_assert(__is_same(decltype(a33 * c), _BitInt(33)), "");
 }
 
 void FromPaper2(_BitInt(8) a1, _BitInt(24) a2) {
-  static_assert(is_same<decltype(a1 * (_BitInt(32))a2), _BitInt(32)>::value, 
"");
+  static_assert(__is_same(decltype(a1 * (_BitInt(32))a2), _BitInt(32)), "");
 }


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to