https://github.com/MadhurKumar004 updated 
https://github.com/llvm/llvm-project/pull/179126

>From 9b2e01f1324c4b1126b1ffebec75426d52a6e70a Mon Sep 17 00:00:00 2001
From: Madhur Kumar <[email protected]>
Date: Mon, 2 Feb 2026 02:50:42 +0530
Subject: [PATCH] Add __builtin_bitreverseg

---
 clang/docs/ReleaseNotes.rst                   |   4 +
 clang/include/clang/Basic/Builtins.td         |   6 +
 clang/lib/AST/ByteCode/InterpBuiltin.cpp      |   1 +
 clang/lib/AST/ExprConstant.cpp                |   1 +
 clang/lib/CodeGen/CGBuiltin.cpp               |  10 +
 clang/lib/Sema/SemaChecking.cpp               |  30 +++
 clang/test/AST/ByteCode/builtin-functions.cpp |  30 +++
 clang/test/CodeGen/builtins.c                 |  58 +++++
 clang/test/CodeGenCXX/builtins.cpp            |  56 +++++
 clang/test/Sema/constant-builtins-2.c         |  27 ++
 clang/test/SemaCXX/builtin-bitreverseg.cpp    | 232 ++++++++++++++++++
 11 files changed, 455 insertions(+)
 create mode 100644 clang/test/SemaCXX/builtin-bitreverseg.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 3a3d76112a02b..d8d819a4b2522 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -119,6 +119,10 @@ Non-comprehensive list of changes in this release
   Usable in constant expressions. Implicit conversion is supported for
   class/struct types with conversion operators.
 
+- A new generaic bit-reverse builtin function ``__builtin_reverseg`` that
+  extends bit-reversal support to all standard integers type, including
+  ``_BitInt``
+
 New Compiler Flags
 ------------------
 - New option ``-fms-anonymous-structs`` / ``-fno-ms-anonymous-structs`` added
diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index a410a138836eb..5a58c24d7021c 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -767,6 +767,12 @@ def Bitreverse : BitInt8_16_32_64BuiltinsTemplate, Builtin 
{
   let Prototype = "T(T)";
 }
 
+def Bitreverseg : Builtin {
+  let Spellings = ["__builtin_bitreverseg"];
+  let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking];
+  let Prototype = "int(...)";
+}
+
 def RotateLeft : BitInt8_16_32_64BuiltinsTemplate, Builtin {
   let Spellings = ["__builtin_rotateleft"];
   let Attributes = [NoThrow, Const, Constexpr];
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp 
b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index 42ed44ff3c3ea..7d18a4e423e84 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -4265,6 +4265,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const 
CallExpr *Call,
           return APInt(Val.getBitWidth(),
                        Val.getBitWidth() - Val.getSignificantBits());
         });
+  case Builtin::BI__builtin_bitreverseg:
   case Builtin::BI__builtin_bitreverse8:
   case Builtin::BI__builtin_bitreverse16:
   case Builtin::BI__builtin_bitreverse32:
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 73768f7dd612b..80bbd90b9dca2 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -16156,6 +16156,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const 
CallExpr *E,
     return Success(AlignedVal, E);
   }
 
+  case Builtin::BI__builtin_bitreverseg:
   case Builtin::BI__builtin_bitreverse8:
   case Builtin::BI__builtin_bitreverse16:
   case Builtin::BI__builtin_bitreverse32:
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 339d6cff0a386..c17a025d175e9 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -3683,6 +3683,16 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl 
GD, unsigned BuiltinID,
     return RValue::get(
         emitBuiltinWithOneOverloadedType<1>(*this, E, Intrinsic::bswap));
   }
+  case Builtin::BI__builtin_bitreverseg: {
+    Value *ArgValue = EmitScalarExpr(E->getArg(0));
+    llvm::IntegerType *IntTy = cast<llvm::IntegerType>(ArgValue->getType());
+    assert(IntTy &&
+           "LLVM's __builtin_bitreverseg only support integer variants");
+    if (IntTy->getBitWidth() == 1)
+      return RValue::get(ArgValue);
+    return RValue::get(
+        emitBuiltinWithOneOverloadedType<1>(*this, E, Intrinsic::bitreverse));
+  }
   case Builtin::BI__builtin_bitreverse8:
   case Builtin::BI__builtin_bitreverse16:
   case Builtin::BI__builtin_bitreverse32:
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index e2e1b37572364..6622427b1a2f9 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2259,6 +2259,32 @@ static bool BuiltinBswapg(Sema &S, CallExpr *TheCall) {
   return false;
 }
 
+/// Checks that __builtin_bitreverseg was called with a single argument, which
+/// is an integer
+static bool BuiltinBitreverseg(Sema &S, CallExpr *TheCall) {
+  if (S.checkArgCount(TheCall, 1))
+    return true;
+  ExprResult ArgRes = S.DefaultLvalueConversion(TheCall->getArg(0));
+  if (ArgRes.isInvalid())
+    return true;
+
+  Expr *Arg = ArgRes.get();
+  TheCall->setArg(0, Arg);
+  if (Arg->isTypeDependent())
+    return false;
+
+  QualType ArgTy = Arg->getType();
+
+  if (!ArgTy->isIntegerType()) {
+    S.Diag(Arg->getBeginLoc(), diag::err_builtin_invalid_arg_type)
+      << 1 << /*scalar=*/1 << /*unsigned integer*/ 1 << /*float point*/ 0
+      << ArgTy;
+    return true;
+  }
+  TheCall->setType(ArgTy);
+  return false;
+}
+
 /// Checks that __builtin_popcountg was called with a single argument, which is
 /// an unsigned integer.
 static bool BuiltinPopcountg(Sema &S, CallExpr *TheCall) {
@@ -3666,6 +3692,10 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, 
unsigned BuiltinID,
     if (BuiltinBswapg(*this, TheCall))
       return ExprError();
     break;
+  case Builtin::BI__builtin_bitreverseg:
+    if (BuiltinBitreverseg(*this, TheCall))
+      return ExprError();
+    break;
   case Builtin::BI__builtin_popcountg:
     if (BuiltinPopcountg(*this, TheCall))
       return ExprError();
diff --git a/clang/test/AST/ByteCode/builtin-functions.cpp 
b/clang/test/AST/ByteCode/builtin-functions.cpp
index b2f0213cfea05..125d83e9b8c57 100644
--- a/clang/test/AST/ByteCode/builtin-functions.cpp
+++ b/clang/test/AST/ByteCode/builtin-functions.cpp
@@ -553,6 +553,36 @@ namespace bitreverse {
   char bitreverse2[__builtin_bitreverse16(0x3C48) == 0x123C ? 1 : -1];
   char bitreverse3[__builtin_bitreverse32(0x12345678) == 0x1E6A2C48 ? 1 : -1];
   char bitreverse4[__builtin_bitreverse64(0x0123456789ABCDEFULL) == 
0xF7B3D591E6A2C480 ? 1 : -1];
+  char bitreverse5[(char)__builtin_bitreverseg((char)0x01) == (char)0x80 ? 1 : 
-1];
+  char bitreverse6[(short)__builtin_bitreverseg((short)0x3C48) == 
(short)0x123C ? 1 : -1];
+  char bitreverse7[__builtin_bitreverseg(0x12345678) == 0x1E6A2C48 ? 1 : -1];
+  char bitreverse8[__builtin_bitreverseg(0x0123456789ABCDEFULL) == 
0xF7B3D591E6A2C480 ? 1 : -1];
+#ifndef __AVR__
+  char test5[__builtin_bitreverseg((_BitInt(8))0x12) == (_BitInt(8))0x48 ? 1 : 
-1];
+  char test6[__builtin_bitreverseg((_BitInt(16))0x1234) == (_BitInt(16))0x2C48 
? 1 : -1];
+  char test7[__builtin_bitreverseg((_BitInt(32))0x00001234) == 
(_BitInt(32))0x2C480000 ? 1 : -1];
+  char test8[__builtin_bitreverseg((_BitInt(64))0x0000000000001234) == 
(_BitInt(64))0x2C48000000000000 ? 1 : -1];
+  char test9[__builtin_bitreverseg((_BitInt(128))0x1) == ((_BitInt(128))1 << 
127) ? 1 : -1];
+#endif
+
+    constexpr const int const_expr = 0x1234;
+
+    void test_constexpr_reference_bitreverseg() {
+    const int expr = 0x1234;
+    const int& ref = expr; // #declare_bitreverseg
+
+    constexpr const int& const_ref = const_expr;
+
+    constexpr auto result2 = __builtin_bitreverseg(ref);
+    //expected-error@-1 {{constexpr variable 'result2' must be initialized by 
a constant expression}}
+    //expected-note@-2 {{initializer of 'ref' is not a constant expression}}
+    //expected-note@#declare_bitreverseg {{declared here}}
+    //ref-error@-4 {{constexpr variable 'result2' must be initialized by a 
constant expression}}
+    //ref-note@-5 {{initializer of 'ref' is not a constant expression}}
+    //ref-note@#declare_bitreverseg {{declared here}}
+
+    constexpr auto result3 = __builtin_bitreverseg(const_ref);
+    }
 }
 
 namespace expect {
diff --git a/clang/test/CodeGen/builtins.c b/clang/test/CodeGen/builtins.c
index 3545588aec654..fc0e3a482985a 100644
--- a/clang/test/CodeGen/builtins.c
+++ b/clang/test/CodeGen/builtins.c
@@ -152,6 +152,17 @@ int main(void) {
   // CHECK: @llvm.bitreverse.i16
   // CHECK: @llvm.bitreverse.i32
   // CHECK: @llvm.bitreverse.i64
+  // CHECK: @llvm.bitreverse.i128
+  P(bitreverseg, ((char)N));
+  P(bitreverseg, ((short)N));
+  P(bitreverseg, ((int)N));
+  P(bitreverseg, ((unsigned long)N));
+  P(bitreverseg, ((_BitInt(8))N));
+  P(bitreverseg, ((_BitInt(16))N));
+  P(bitreverseg, ((_BitInt(32))N));
+  P(bitreverseg, ((_BitInt(64))N));
+  P(bitreverseg, ((_BitInt(128))N));
+  P(bitreverseg, (N));
   P(bitreverse8, (N));
   P(bitreverse16, (N));
   P(bitreverse32, (N));
@@ -962,3 +973,50 @@ void test_builtin_bswapg(unsigned char uc, unsigned short 
us, unsigned int ui,
   bi128 = __builtin_bswapg(bi128);
   // CHECK: call i128 @llvm.bswap.i128
 }
+// CHECK-LABEL: define{{.*}} void @test_builtin_bitreverseg
+void test_builtin_bitreverseg(unsigned char uc, unsigned short us, unsigned 
int ui,
+                       unsigned long ul, unsigned long long ull, bool b,
+#ifdef __SIZEOF_INT128__
+                       unsigned __int128 ui128,
+#endif
+                       _BitInt(8) bi8,
+                       _BitInt(16) bi16, _BitInt(32) bi32, 
+                       _BitInt(64) bi64, _BitInt(128) bi128) {
+#if __aarch64__
+  int x = 0;
+  x = x * 2;
+#endif
+  b = __builtin_bitreverseg(b);
+  // CHECK: %{{.*}} = load i8, ptr %b.addr
+  // CHECK: %{{.*}} = trunc i8 %{{.*}} to i1
+  // CHECK: %{{.*}} = zext i1 %{{.*}} to i8
+  // CHECK: store i8 %{{.*}}, ptr %b.addr
+  uc = __builtin_bitreverseg(uc);
+  // CHECK: %{{.*}} = load i8, ptr %uc.addr
+  // CHECK: %{{.*}} = call i8 @llvm.bitreverse.i8(i8 %{{.*}})
+  // CHECK: store i8 %{{.*}}, ptr %uc.addr
+  us = __builtin_bitreverseg(us);
+  // CHECK: call i16 @llvm.bitreverse.i16
+  ui = __builtin_bitreverseg(ui);
+  // CHECK: call i32 @llvm.bitreverse.i32
+  ul = __builtin_bitreverseg(ul);
+  // CHECK: call [[LONGINTTY]] @llvm.bitreverse.[[LONGINTTY]]
+  ull = __builtin_bitreverseg(ull);
+  // CHECK: call i64 @llvm.bitreverse.i64
+#ifdef __SIZEOF_INT128__
+  ui128 = __builtin_bitreverseg(ui128);
+  // I128: call i128 @llvm.bitreverse.i128
+#endif
+  bi8 = __builtin_bitreverseg(bi8);
+  // CHECK: %{{.*}} = load i8, ptr %bi8.addr, align 1
+  // CHECK: %{{.*}} = call i8 @llvm.bitreverse.i8(i8 %{{.*}})
+  // CHECK: store i8 %{{.*}}, ptr %bi8.addr
+  bi16 = __builtin_bitreverseg(bi16);
+  // CHECK: call i16 @llvm.bitreverse.i16
+  bi32 = __builtin_bitreverseg(bi32);
+  // CHECK: call i32 @llvm.bitreverse.i32
+  bi64 = __builtin_bitreverseg(bi64);
+  // CHECK: call i64 @llvm.bitreverse.i64
+  bi128 = __builtin_bitreverseg(bi128);
+  // CHECK: call i128 @llvm.bitreverse.i128
+}
diff --git a/clang/test/CodeGenCXX/builtins.cpp 
b/clang/test/CodeGenCXX/builtins.cpp
index ef30a25a17922..2248b3800f7bd 100644
--- a/clang/test/CodeGenCXX/builtins.cpp
+++ b/clang/test/CodeGenCXX/builtins.cpp
@@ -139,3 +139,59 @@ void test_bitint() {
 // CHECK: call i64 @llvm.bswap.i64
 // CHECK: call i128 @llvm.bswap.i128
 // CHECK: ret void
+
+void test_int_reference(int* a) {
+  __builtin_bitreverseg(*a);
+// CHECK-LABEL: @_Z18test_int_referencePi
+  // CHECK: store ptr %a, ptr
+  // CHECK: load ptr, ptr
+  // CHECK: load i32, ptr
+  // CHECK: call i32 @llvm.bitreverse.i32
+}
+
+void test_long_reference(long* a) {
+  __builtin_bitreverseg(*a);
+// CHECK-LABEL: @_Z19test_long_referencePl
+  // CHECK: store ptr %a, ptr
+  // CHECK: load ptr, ptr
+  // CHECK: load i64, ptr
+  // CHECK: call i64 @llvm.bitreverse.i64
+}
+
+void test_short_reference(short* a) {
+  __builtin_bitreverseg(*a);
+// CHECK-LABEL: @_Z20test_short_referencePs
+  // CHECK: store ptr %a, ptr
+  // CHECK: load ptr, ptr
+  // CHECK: load i16, ptr
+  // CHECK: call i16 @llvm.bitreverse.i16
+}
+
+void test_char_reference(char* a) {
+  __builtin_bitreverseg(*a);
+// CHECK-LABEL: @_Z19test_char_referencePc
+  // CHECK: store ptr %a, ptr
+  // CHECK: load ptr, ptr
+  // CHECK: load i8, ptr
+  // CHECK: call i8 @llvm.bitreverse.i8
+  // CHECK: ret void
+}
+
+void test_bitint_reference() {
+  _BitInt(8) a = 0x12;
+  __builtin_bitreverseg(a);
+  _BitInt(16) b = 0x1234;
+  __builtin_bitreverseg(b);
+  _BitInt(32) c = 0x00001234;
+  __builtin_bitreverseg(c);
+  _BitInt(64) d = 0x0000000000001234;
+  __builtin_bitreverseg(d);
+  _BitInt(128) e = ~(_BitInt(128))0;
+  __builtin_bitreverseg(e);
+}
+// CHECK-LABEL: @_Z21test_bitint_referencev
+// CHECK: call i16 @llvm.bitreverse.i16
+// CHECK: call i32 @llvm.bitreverse.i32
+// CHECK: call i64 @llvm.bitreverse.i64
+// CHECK: call i128 @llvm.bitreverse.i128
+// CHECK: ret void
diff --git a/clang/test/Sema/constant-builtins-2.c 
b/clang/test/Sema/constant-builtins-2.c
index 9579052b1f76b..73d53504d1dc3 100644
--- a/clang/test/Sema/constant-builtins-2.c
+++ b/clang/test/Sema/constant-builtins-2.c
@@ -501,6 +501,33 @@ int h21 = 
__builtin_bswapg((_BitInt(64))0x0000000000001234) == (_BitInt(64))0x34
 int h22 = __builtin_bswapg(~(_BitInt(128))0) == (~(_BitInt(128))0) ? 1 : f();
 int h23 = __builtin_bswapg((_BitInt(24))0x1234) == (_BitInt(24))0x3412 ? 1 : 
f();
 // expected-error@-1 {{_BitInt type '_BitInt(24)' (24 bits) must be a multiple 
of 16 bits for byte swapping}}
+
+char h24[__builtin_bitreverseg((char)0x01) == (char)0x80 ? 1 : -1];
+char h25[__builtin_bitreverseg((short)0x3C48) == (short)0x123C ? 1 : -1];
+char h26[__builtin_bitreverseg(0x12345678) == 0x1E6A2C48 ? 1 : -1];
+char h27[__builtin_bitreverseg(0x0123456789ABCDEFULL) == 0xF7B3D591E6A2C480 ? 
1 : -1];
+int h28 = __builtin_bitreverseg((char)(0x12)) == (char)0x48 ? 1 : f();
+int h29 = __builtin_bitreverseg((short)(0x1234)) == (short)0x2C48 ? 1 : f();
+int h30 = __builtin_bitreverseg((__UINT32_TYPE__)0x1234) == 
(__UINT32_TYPE__)0x2C480000 ? 1 : f();
+int h31 = __builtin_bitreverseg(0x0000000000001234ULL) == 0x2C48000000000000 ? 
1 : f();
+float h32 = __builtin_bitreverseg(1.0f); // expected-error {{1st argument must 
be a scalar integer type (was 'float')}}
+double h33 = __builtin_bitreverseg(1.0L); // expected-error {{1st argument 
must be a scalar integer type (was 'long double')}}
+char *h34 = __builtin_bitreverseg("hello"); // expected-error {{1st argument 
must be a scalar integer type (was 'char[6]')}}
+int h35 = __builtin_bitreverseg(1, 2); // expected-error {{too many arguments 
to function call, expected 1, have 2}}
+int *h36 = __builtin_bitreverseg(&h31); // expected-error {{1st argument must 
be a scalar integer type (was 'int *')}}
+int arr2[4] = {0x12, 0x34, 0x56, 0x78};
+int h37 = __builtin_bitreverseg(arr2); // expected-error {{1st argument must 
be a scalar integer type (was 'int[4]')}}
+enum BitreverseEnum {
+  BITREVERSE_ENUM_VALUE1 = 0x1234,
+};
+int h38 = __builtin_bitreverseg(BITREVERSE_ENUM_VALUE1) == 0x2C480000 ? 1 : 
f();
+int h39 = __builtin_bitreverseg((_BitInt(8))0x12) == (_BitInt(8))0x48 ? 1 : 
f();
+int h40 = __builtin_bitreverseg((_BitInt(16))0x1234) == (_BitInt(16))0x2C48 ? 
1 : f();
+int h41 = __builtin_bitreverseg((_BitInt(32))0x00001234) == 
(_BitInt(32))0x2C480000 ? 1 : f();
+int h42 = __builtin_bitreverseg((_BitInt(64))0x0000000000001234) == 
(_BitInt(64))0x2C48000000000000 ? 1 : f();
+int h43 = __builtin_bitreverseg(~(_BitInt(128))0) == (~(_BitInt(128))0) ? 1 : 
f();
+
+
 extern long int bi0;
 extern __typeof__(__builtin_expect(0, 0)) bi0;
 
diff --git a/clang/test/SemaCXX/builtin-bitreverseg.cpp 
b/clang/test/SemaCXX/builtin-bitreverseg.cpp
new file mode 100644
index 0000000000000..8e5f747049501
--- /dev/null
+++ b/clang/test/SemaCXX/builtin-bitreverseg.cpp
@@ -0,0 +1,232 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify 
-fexperimental-new-constant-interpreter %s
+
+void test_basic_type_checks() {
+  static_assert(__is_same(char, decltype(__builtin_bitreverseg((char)0))), "");
+  static_assert(__is_same(unsigned char, 
decltype(__builtin_bitreverseg((unsigned char)0))), "");
+  static_assert(__is_same(short, decltype(__builtin_bitreverseg((short)0))), 
"");
+  static_assert(__is_same(unsigned short, 
decltype(__builtin_bitreverseg((unsigned short)0))), "");
+  static_assert(__is_same(int, decltype(__builtin_bitreverseg((int)0))), "");
+  static_assert(__is_same(unsigned int, 
decltype(__builtin_bitreverseg((unsigned int)0))), "");
+  static_assert(__is_same(long, decltype(__builtin_bitreverseg((long)0))), "");
+  static_assert(__is_same(unsigned long, 
decltype(__builtin_bitreverseg((unsigned long)0))), "");
+  static_assert(__is_same(_BitInt(8), 
decltype(__builtin_bitreverseg((_BitInt(8))0))), "");
+  static_assert(__is_same(_BitInt(16), 
decltype(__builtin_bitreverseg((_BitInt(16))0))), "");
+  static_assert(__is_same(_BitInt(32), 
decltype(__builtin_bitreverseg((_BitInt(32))0))), "");
+  static_assert(__is_same(_BitInt(64), 
decltype(__builtin_bitreverseg((_BitInt(64))0))), "");
+  static_assert(__is_same(_BitInt(128), 
decltype(__builtin_bitreverseg((_BitInt(128))0))), "");
+}
+
+template<typename T>
+void test_template_type_check() {
+  static_assert(__is_same(T, decltype(__builtin_bitreverseg(T{}))),
+                "bitreverseg should return the same type as its argument");
+  constexpr T zero{};
+  constexpr T max = ~T{};
+  constexpr T one = T{1};
+
+  static_assert(__is_same(T, decltype(__builtin_bitreverseg(zero))), "");
+  static_assert(__is_same(T, decltype(__builtin_bitreverseg(max))), "");
+  static_assert(__is_same(T, decltype(__builtin_bitreverseg(one))), "");
+}
+
+template void test_template_type_check<char>();
+template void test_template_type_check<unsigned char>();
+template void test_template_type_check<short>();
+template void test_template_type_check<unsigned short>();
+template void test_template_type_check<int>();
+template void test_template_type_check<unsigned int>();
+template void test_template_type_check<long>();
+template void test_template_type_check<_BitInt(8)>();
+template void test_template_type_check<_BitInt(16)>();
+template void test_template_type_check<_BitInt(32)>();
+template void test_template_type_check<_BitInt(64)>();
+template void test_template_type_check<_BitInt(128)>();
+
+void test_lambda_type_checks() {
+  auto lambda = [](auto x) {
+    static_assert(__is_same(decltype(x), decltype(__builtin_bitreverseg(x))),
+                  "bitreverseg in lambda should preserve type");
+    return __builtin_bitreverseg(x);
+  };
+  auto result_long = lambda(42UL);
+  static_assert(__is_same(unsigned long, decltype(result_long)), "");
+
+  auto result_int = lambda(42);
+  static_assert(__is_same(int, decltype(result_int)), "");
+
+  auto result_short = lambda(static_cast<short>(42));
+  static_assert(__is_same(short, decltype(result_short)), "");
+
+  auto result_char = lambda(static_cast<char>(42));
+  static_assert(__is_same(char, decltype(result_char)), "");
+}
+
+decltype(auto) test_decltype_auto(int x) {
+  return __builtin_bitreverseg(x);
+}
+
+void test_decltype_auto_check() {
+  int x = 42;
+  auto result = test_decltype_auto(x);
+  static_assert(__is_same(int, decltype(result)), "");
+}
+
+template<auto Value>
+struct ValueTemplateTypeTest {
+  using value_type = decltype(Value);
+  using result_type = decltype(__builtin_bitreverseg(Value));
+
+  static constexpr bool type_matches = __is_same(value_type, result_type);
+  static_assert(type_matches, "Value template bitreverseg should preserve 
type");
+
+  static constexpr auto reversed_value = __builtin_bitreverseg(Value);
+};
+
+template<auto... Values>
+void test_template_pack_types() {
+  static_assert((__is_same(decltype(Values), 
decltype(__builtin_bitreverseg(Values))) && ...),
+                "All pack elements should preserve type");
+}
+
+template struct ValueTemplateTypeTest<0x1234>;
+template struct ValueTemplateTypeTest<0x12345678UL>;
+template struct ValueTemplateTypeTest<(short)0x1234>;
+template struct ValueTemplateTypeTest<(char)0x12>;
+
+template<typename T>
+void test_invalid_type() {
+  __builtin_bitreverseg(T{}); // #invalid_type_use
+}
+
+void test_basic_errors() {
+  test_invalid_type<float>();
+  // expected-note@-1 {{in instantiation of function template specialization 
'test_invalid_type<float>' requested here}}
+  // expected-error@#invalid_type_use {{1st argument must be a scalar integer 
type (was 'float')}}
+
+  test_invalid_type<double>();
+  // expected-note@-1 {{in instantiation of function template specialization 
'test_invalid_type<double>' requested here}}
+  // expected-error@#invalid_type_use {{1st argument must be a scalar integer 
type (was 'double')}}
+
+  test_invalid_type<void*>();
+  // expected-note@-1 {{in instantiation of function template specialization 
'test_invalid_type<void *>' requested here}}
+  // expected-error@#invalid_type_use {{1st argument must be a scalar integer 
type (was 'void *')}}
+}
+
+template<typename T>
+auto test_dependent_context(T value) -> decltype(__builtin_bitreverseg(value)) 
{ // #dependent_use
+  return __builtin_bitreverseg(value);
+}
+
+void test_dependent_errors() {
+  test_dependent_context(1.0f);
+  // expected-error@-1 {{no matching function for call to 
'test_dependent_context'}}
+  // expected-note@#dependent_use {{candidate template ignored: substitution 
failure [with T = float]: 1st argument must be a scalar integer type (was 
'float')}}
+  test_dependent_context(1.0l);
+  // expected-error@-1 {{no matching function for call to 
'test_dependent_context'}}
+  // expected-note@#dependent_use {{candidate template ignored: substitution 
failure [with T = long double]: 1st argument must be a scalar integer type (was 
'long double')}}
+  test_dependent_context("hello");
+  // expected-error@-1 {{no matching function for call to 
'test_dependent_context'}}
+  // expected-note@#dependent_use {{candidate template ignored: substitution 
failure [with T = const char *]: 1st argument must be a scalar integer type 
(was 'const char *')}}
+}
+
+void test_lambda_errors() {
+  auto lambda = [](auto x) {
+    return __builtin_bitreverseg(x); // #lambda_use
+  };
+
+  lambda(1.0f);
+  // expected-error@#lambda_use {{1st argument must be a scalar integer type 
(was 'float')}}
+  // expected-note@-2 {{in instantiation of function template specialization 
'test_lambda_errors()::(lambda)::operator()<float>' requested here}}
+  lambda(1.0l);
+  // expected-error@#lambda_use {{1st argument must be a scalar integer type 
(was 'long double')}}
+  // expected-note@-2 {{in instantiation of function template specialization 
'test_lambda_errors()::(lambda)::operator()<long double>' requested here}}
+  lambda("hello");
+  // expected-error@#lambda_use {{1st argument must be a scalar integer type 
(was 'const char *')}}
+  // expected-note@-2 {{in instantiation of function template specialization 
'test_lambda_errors()::(lambda)::operator()<const char *>' requested here}}
+}
+
+template <class... Args> void test_variadic_template_argument_count(Args... 
args) {
+  int result = __builtin_bitreverseg(args...); // #arg_use
+}
+
+void test_variadic_template_args() {
+  test_variadic_template_argument_count();
+  // expected-error@#arg_use {{too few arguments to function call, expected 1, 
have 0}}
+  // expected-note@-2 {{in instantiation of function template specialization 
'test_variadic_template_argument_count<>' requested here}}
+  test_variadic_template_argument_count(1);
+  test_variadic_template_argument_count(1, 2);
+  // expected-error@#arg_use {{too many arguments to function call, expected 
1, have 2}}
+  // expected-note@-2 {{in instantiation of function template specialization 
'test_variadic_template_argument_count<int, int>' requested here}}
+}
+
+void test_lvalue_reference(int& a) {
+  auto result = __builtin_bitreverseg(a);
+  static_assert(__is_same(int, decltype(result)), "Should decay reference to 
value type");
+}
+
+void test_const_lvalue_reference(const int& a) {
+  auto result = __builtin_bitreverseg(a);
+  static_assert(__is_same(int, decltype(result)), "Should decay const 
reference to value type");
+}
+
+void test_rvalue_reference(int&& a) {
+  auto result = __builtin_bitreverseg(a);
+  static_assert(__is_same(int, decltype(result)), "Should decay rvalue 
reference to value type");
+}
+
+void test_const_rvalue_reference(const int&& a) {
+  auto result = __builtin_bitreverseg(a);
+  static_assert(__is_same(int, decltype(result)), "Should decay const rvalue 
reference to value type");
+}
+
+void test_array() {
+  int arr[4] = {0x12, 0x34, 0x56, 0x78};
+  __builtin_bitreverseg(arr);
+  // expected-error@-1 {{1st argument must be a scalar integer type (was 
'int[4]')}}
+}
+
+void test_pointer() {
+  int x = 0x12345678;
+  int *ptr = &x;
+  __builtin_bitreverseg(ptr);
+  // expected-error@-1 {{1st argument must be a scalar integer type (was 'int 
*')}}
+}
+
+enum BasicEnum {
+  ENUM_VALUE1 = 0x1234,
+  ENUM_VALUE2 = 0x2C480000
+};
+
+void test_enum() {
+  const BasicEnum e = ENUM_VALUE1;
+  static_assert(__builtin_bitreverseg(e) == ENUM_VALUE2, "");
+}
+
+class testClass {
+public:
+  int value;
+  testClass(int v) : value(v) {}
+
+  int getValue() { return value; }
+};
+
+void test_class() {
+  testClass c((int)0x12345678);
+  __builtin_bitreverseg(c);
+  // expected-error@-1 {{1st argument must be a scalar integer type (was 
'testClass')}}
+}
+
+void test_nullptr() {
+  __builtin_bitreverseg(nullptr);
+  // expected-error@-1 {{1st argument must be a scalar integer type (was 
'std::nullptr_t')}}
+}
+
+void test_bitint() {
+  static_assert(__builtin_bitreverseg((_BitInt(8))0x12) == (_BitInt(8))0x48, 
"");
+  static_assert(__builtin_bitreverseg((_BitInt(16))0x1234) == 
(_BitInt(16))0x2C48, "");
+  static_assert(__builtin_bitreverseg((_BitInt(32))0x00001234) == 
(_BitInt(32))0x2C480000, "");
+  static_assert(__builtin_bitreverseg((_BitInt(64))0x0000000000001234) == 
(_BitInt(64))0x2C48000000000000, "");
+  static_assert(__builtin_bitreverseg((_BitInt(128))0x1) == ((_BitInt(128))1 
<< 127), "");
+  static_assert(__builtin_bitreverseg((_BitInt(24))0x1234) == 
(_BitInt(24))0x2C4800, "");
+}

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

Reply via email to