[clang] [Clang] Add __builtin_bswapg (PR #162433)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Oct 18 23:03:17 PDT 2025
https://github.com/clingfei updated https://github.com/llvm/llvm-project/pull/162433
>From 92466f3789ce1849ebee8a405efd42e191c591f5 Mon Sep 17 00:00:00 2001
From: clingfei <1599101385 at qq.com>
Date: Wed, 8 Oct 2025 15:05:44 +0800
Subject: [PATCH 01/11] [Clang] Add __builtin_bswapg
---
clang/include/clang/Basic/Builtins.td | 6 ++++
clang/lib/AST/ByteCode/InterpBuiltin.cpp | 10 ++++++-
clang/lib/AST/ExprConstant.cpp | 11 ++++++++
clang/lib/CodeGen/CGBuiltin.cpp | 1 +
clang/lib/Sema/SemaChecking.cpp | 28 +++++++++++++++++++
clang/test/AST/ByteCode/builtin-functions.cpp | 4 +++
clang/test/CodeGen/builtins.c | 2 +-
clang/test/Sema/constant-builtins-2.c | 4 +++
clang/test/Sema/constant-builtins.c | 5 +++-
9 files changed, 68 insertions(+), 3 deletions(-)
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 468121f7d20ab..e65ed2f20be97 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -755,6 +755,12 @@ def BSwap : Builtin, Template<["unsigned short", "uint32_t", "uint64_t"],
let Prototype = "T(T)";
}
+def BSwapg : Builtin {
+ let Spellings = ["__builtin_bswapg"];
+ let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking];
+ let Prototype = "int(...)";
+}
+
def Bitreverse : BitInt8_16_32_64BuiltinsTemplate, Builtin {
let Spellings = ["__builtin_bitreverse"];
let Attributes = [NoThrow, Const, Constexpr];
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index 1eea813b8c556..b8d17fbce6d4e 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -3288,7 +3288,15 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
case Builtin::BI__builtin_elementwise_ctzg:
return interp__builtin_elementwise_countzeroes(S, OpPC, Frame, Call,
BuiltinID);
-
+ case Builtin::BI__builtin_bswapg: {
+ const APSInt &Val = popToAPSInt(S, Call->getArg(0));
+ assert(Val.getActiveBits() <= 64);
+ if (Val.getBitWidth() == 8)
+ pushInteger(S, Val, Call->getType());
+ else
+ pushInteger(S, Val.byteSwap(), Call->getType());
+ return true;
+ }
case Builtin::BI__builtin_bswap16:
case Builtin::BI__builtin_bswap32:
case Builtin::BI__builtin_bswap64:
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 618e1636e9e53..058905e7fd3c0 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -13982,6 +13982,17 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
return Success(Val.reverseBits(), E);
}
+ case Builtin::BI__builtin_bswapg: {
+ APSInt Val;
+ if (!EvaluateInteger(E->getArg(0), Val, Info))
+ return false;
+ if (Val.getBitWidth() == 8) {
+ bool ret = Success(Val, E);
+ return ret;
+ }
+
+ return Success(Val.byteSwap(), E);
+ }
case Builtin::BI__builtin_bswap16:
case Builtin::BI__builtin_bswap32:
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 9ee810c9d5775..7733f4dc15f5d 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -3622,6 +3622,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
Builder.CreateArithmeticFence(ArgValue, ConvertType(ArgType)));
return RValue::get(ArgValue);
}
+ case Builtin::BI__builtin_bswapg:
case Builtin::BI__builtin_bswap16:
case Builtin::BI__builtin_bswap32:
case Builtin::BI__builtin_bswap64:
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 063db05665af1..362b53676feaa 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2200,6 +2200,30 @@ static bool BuiltinCpu(Sema &S, const TargetInfo &TI, CallExpr *TheCall,
return false;
}
+/// Checks that __builtin_bswapg was called with a single argument, which is an
+/// unsigned integer, and overrides the return value type to the integer type.
+static bool BuiltinBswapg(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);
+
+ QualType ArgTy = Arg->getType();
+
+ if (!ArgTy->isIntegerType()) {
+ S.Diag(Arg->getBeginLoc(), diag::err_builtin_invalid_arg_type)
+ << 1 << /* scalar */ 1 << /* unsigned integer ty */ 1 << /* no fp */ 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) {
@@ -3448,6 +3472,10 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
}
break;
}
+ case Builtin::BI__builtin_bswapg:
+ if (BuiltinBswapg(*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 f47bc49d9a1a8..84ff9cc137bf3 100644
--- a/clang/test/AST/ByteCode/builtin-functions.cpp
+++ b/clang/test/AST/ByteCode/builtin-functions.cpp
@@ -824,6 +824,10 @@ namespace bswap {
int h3 = __builtin_bswap16(0x1234) == 0x3412 ? 1 : f();
int h4 = __builtin_bswap32(0x1234) == 0x34120000 ? 1 : f();
int h5 = __builtin_bswap64(0x1234) == 0x3412000000000000 ? 1 : f();
+ int h6 = __builtin_bswapg(0x12) == 0x12 ? 1 : f();
+ int h7 = __builtin_bswapg(0x1234) == 0x3412 ? 1 : f();
+ int h8 = __builtin_bswapg(0x00001234) == 0x34120000 ? 1 : f();
+ int h9 = __builtin_bswapg(0x0000000000001234) == 0x3412000000000000 ? 1 : f();
}
#define CFSTR __builtin___CFStringMakeConstantString
diff --git a/clang/test/CodeGen/builtins.c b/clang/test/CodeGen/builtins.c
index 738814c88bf56..11d8302816c84 100644
--- a/clang/test/CodeGen/builtins.c
+++ b/clang/test/CodeGen/builtins.c
@@ -130,7 +130,7 @@ int main(void) {
P(object_size, (s0, 3));
// Whatever
-
+ P(bswapg, (N));
P(bswap16, (N));
P(bswap32, (N));
P(bswap64, (N));
diff --git a/clang/test/Sema/constant-builtins-2.c b/clang/test/Sema/constant-builtins-2.c
index e465a3c5f0ad8..96bd2c966c2ef 100644
--- a/clang/test/Sema/constant-builtins-2.c
+++ b/clang/test/Sema/constant-builtins-2.c
@@ -479,6 +479,10 @@ int h0 = __builtin_types_compatible_p(int, float);
int h3 = __builtin_bswap16(0x1234) == 0x3412 ? 1 : f();
int h4 = __builtin_bswap32(0x1234) == 0x34120000 ? 1 : f();
int h5 = __builtin_bswap64(0x1234) == 0x3412000000000000 ? 1 : f();
+int h6 = __builtin_bswapg((char)(0x12)) == (char)(0x12) ? 1 : f();
+int h7 = __builtin_bswapg((short)(0x1234)) == (short)(0x3412) ? 1 : f();
+int h8 = __builtin_bswapg(0x00001234) == 0x34120000 ? 1 : f();
+int h9 = __builtin_bswapg(0x0000000000001234ULL) == 0x3412000000000000 ? 1 : f();
extern long int bi0;
extern __typeof__(__builtin_expect(0, 0)) bi0;
diff --git a/clang/test/Sema/constant-builtins.c b/clang/test/Sema/constant-builtins.c
index 964ab59e787c4..6c13fe96b6b4a 100644
--- a/clang/test/Sema/constant-builtins.c
+++ b/clang/test/Sema/constant-builtins.c
@@ -25,7 +25,10 @@ int h0 = __builtin_types_compatible_p(int,float);
int h3 = __builtin_bswap16(0x1234) == 0x3412 ? 1 : f();
int h4 = __builtin_bswap32(0x1234) == 0x34120000 ? 1 : f();
int h5 = __builtin_bswap64(0x1234) == 0x3412000000000000 ? 1 : f();
-
+int h6 = __builtin_bswapg((char)0x12) == (char)0x12 ? 1 : f();
+int h7 = __builtin_bswapg((short)(0x1234)) == (short)(0x3412) ? 1 : f();
+int h8 = __builtin_bswapg(0x00001234) == 0x34120000 ? 1 : f();
+int h9 = __builtin_bswapg(0x0000000000001234ULL) == 0x3412000000000000 ? 1 : f();
short somefunc(void);
short t = __builtin_constant_p(5353) ? 42 : somefunc();
>From d4ea8686cd97c203ec458e4cd56cd67f941bbfd0 Mon Sep 17 00:00:00 2001
From: clingfei <1599101385 at qq.com>
Date: Thu, 9 Oct 2025 13:14:08 +0800
Subject: [PATCH 02/11] handle special case 8 in interp__builtin_bswap and fix
extra space in VisitBuiltinCallExpr
---
clang/lib/AST/ByteCode/InterpBuiltin.cpp | 16 +++++-----------
clang/lib/AST/ExprConstant.cpp | 6 ++----
2 files changed, 7 insertions(+), 15 deletions(-)
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index b8d17fbce6d4e..01f2cd280b175 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -1004,8 +1004,10 @@ static bool interp__builtin_bswap(InterpState &S, CodePtr OpPC,
const CallExpr *Call) {
const APSInt &Val = popToAPSInt(S, Call->getArg(0));
assert(Val.getActiveBits() <= 64);
-
- pushInteger(S, Val.byteSwap(), Call->getType());
+ if (Val.getBitWidth() == 8)
+ pushInteger(S, Val, Call->getType());
+ else
+ pushInteger(S, Val.byteSwap(), Call->getType());
return true;
}
@@ -3288,15 +3290,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
case Builtin::BI__builtin_elementwise_ctzg:
return interp__builtin_elementwise_countzeroes(S, OpPC, Frame, Call,
BuiltinID);
- case Builtin::BI__builtin_bswapg: {
- const APSInt &Val = popToAPSInt(S, Call->getArg(0));
- assert(Val.getActiveBits() <= 64);
- if (Val.getBitWidth() == 8)
- pushInteger(S, Val, Call->getType());
- else
- pushInteger(S, Val.byteSwap(), Call->getType());
- return true;
- }
+ case Builtin::BI__builtin_bswapg:
case Builtin::BI__builtin_bswap16:
case Builtin::BI__builtin_bswap32:
case Builtin::BI__builtin_bswap64:
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 058905e7fd3c0..88c3a1cbcd833 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -13986,10 +13986,8 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
APSInt Val;
if (!EvaluateInteger(E->getArg(0), Val, Info))
return false;
- if (Val.getBitWidth() == 8) {
- bool ret = Success(Val, E);
- return ret;
- }
+ if (Val.getBitWidth() == 8)
+ return Success(Val, E);
return Success(Val.byteSwap(), E);
}
>From fa016a1bf3eb112754d24aac1823abe4e326509f Mon Sep 17 00:00:00 2001
From: clingfei <1599101385 at qq.com>
Date: Thu, 9 Oct 2025 22:54:57 +0800
Subject: [PATCH 03/11] add dependent check for argument
---
clang/lib/Sema/SemaChecking.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 362b53676feaa..486fc8d083125 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2211,6 +2211,8 @@ static bool BuiltinBswapg(Sema &S, CallExpr *TheCall) {
Expr *Arg = ArgRes.get();
TheCall->setArg(0, Arg);
+ if (Arg->isTypeDependent())
+ return false;
QualType ArgTy = Arg->getType();
>From c0d0f3c179ff0dd0ccf3683cf075de492fbef12c Mon Sep 17 00:00:00 2001
From: clingfei <1599101385 at qq.com>
Date: Fri, 10 Oct 2025 10:56:22 +0800
Subject: [PATCH 04/11] fix bswapg codegen and add c++ tests
---
clang/lib/AST/ExprConstant.cpp | 2 +-
clang/lib/CodeGen/CGBuiltin.cpp | 10 ++-
clang/lib/Sema/SemaChecking.cpp | 2 +-
clang/test/CodeGen/builtins.c | 5 +-
clang/test/Sema/builtin-bswapg.cpp | 121 +++++++++++++++++++++++++++++
5 files changed, 136 insertions(+), 4 deletions(-)
create mode 100644 clang/test/Sema/builtin-bswapg.cpp
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 88c3a1cbcd833..745e8d9201183 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -13988,7 +13988,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
return false;
if (Val.getBitWidth() == 8)
return Success(Val, E);
-
+
return Success(Val.byteSwap(), E);
}
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 7733f4dc15f5d..124351e7f1e59 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -3622,7 +3622,15 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
Builder.CreateArithmeticFence(ArgValue, ConvertType(ArgType)));
return RValue::get(ArgValue);
}
- case Builtin::BI__builtin_bswapg:
+ case Builtin::BI__builtin_bswapg: {
+ Value *ArgValue = EmitScalarExpr(E->getArg(0));
+ llvm::IntegerType *IntTy = cast<llvm::IntegerType>(ArgValue->getType());
+ assert(IntTy && "LLVM's __builtin_bswapg only supports integer variants");
+ if (IntTy->getBitWidth() == 8)
+ return RValue::get(ArgValue);
+ return RValue::get(
+ emitBuiltinWithOneOverloadedType<1>(*this, E, Intrinsic::bswap));
+ }
case Builtin::BI__builtin_bswap16:
case Builtin::BI__builtin_bswap32:
case Builtin::BI__builtin_bswap64:
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 486fc8d083125..80afa08f3f3af 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -3476,7 +3476,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
}
case Builtin::BI__builtin_bswapg:
if (BuiltinBswapg(*this, TheCall))
- return ExprError();
+ return ExprError();
break;
case Builtin::BI__builtin_popcountg:
if (BuiltinPopcountg(*this, TheCall))
diff --git a/clang/test/CodeGen/builtins.c b/clang/test/CodeGen/builtins.c
index 11d8302816c84..66ac8ad7431fb 100644
--- a/clang/test/CodeGen/builtins.c
+++ b/clang/test/CodeGen/builtins.c
@@ -130,7 +130,10 @@ int main(void) {
P(object_size, (s0, 3));
// Whatever
- P(bswapg, (N));
+ P(bswapg, ((char)N));
+ P(bswapg, ((short)N));
+ P(bswapg, ((int)N));
+ P(bswapg, ((unsigned long)N));
P(bswap16, (N));
P(bswap32, (N));
P(bswap64, (N));
diff --git a/clang/test/Sema/builtin-bswapg.cpp b/clang/test/Sema/builtin-bswapg.cpp
new file mode 100644
index 0000000000000..c7fa6f2410023
--- /dev/null
+++ b/clang/test/Sema/builtin-bswapg.cpp
@@ -0,0 +1,121 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -fexperimental-new-constant-interpreter %s
+// expected-no-diagnostics
+template <class A, class B>
+static constexpr bool is_same_type = false;
+
+template <class A>
+static constexpr bool is_same_type<A, A> = true;
+
+void test_basic_type_checks() {
+ static_assert(is_same_type<char, decltype(__builtin_bswapg((char)0))>, "");
+ static_assert(is_same_type<unsigned char, decltype(__builtin_bswapg((unsigned char)0))>, "");
+ static_assert(is_same_type<short, decltype(__builtin_bswapg((short)0))>, "");
+ static_assert(is_same_type<unsigned short, decltype(__builtin_bswapg((unsigned short)0))>, "");
+ static_assert(is_same_type<int, decltype(__builtin_bswapg((int)0))>, "");
+ static_assert(is_same_type<unsigned int, decltype(__builtin_bswapg((unsigned int)0))>, "");
+ static_assert(is_same_type<long, decltype(__builtin_bswapg((long)0))>, "");
+ static_assert(is_same_type<unsigned long, decltype(__builtin_bswapg((unsigned long)0))>, "");
+}
+
+template<typename T>
+void test_template_type_check() {
+ static_assert(is_same_type<T, decltype(__builtin_bswapg(T{}))>,
+ "bswapg should return the same type as its argument");
+ constexpr T zero{};
+ constexpr T max = ~T{};
+ constexpr T one = T{1};
+
+ static_assert(is_same_type<T, decltype(__builtin_bswapg(zero))>, "");
+ static_assert(is_same_type<T, decltype(__builtin_bswapg(max))>, "");
+ static_assert(is_same_type<T, decltype(__builtin_bswapg(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<unsigned long>();
+
+void test_lambda_type_checks() {
+ auto lambda = [](auto x) {
+ static_assert(is_same_type<decltype(x), decltype(__builtin_bswapg(x))>,
+ "bswapg in lambda should preserve type");
+ return __builtin_bswapg(x);
+ };
+ auto result_long = lambda(42UL);
+ static_assert(is_same_type<unsigned long, decltype(result_long)>, "");
+
+ auto result_int = lambda(42);
+ static_assert(is_same_type<int, decltype(result_int)>, "");
+
+ auto result_short = lambda(static_cast<short>(42));
+ static_assert(is_same_type<short, decltype(result_short)>, "");
+
+ auto result_char = lambda(static_cast<char>(42));
+ static_assert(is_same_type<char, decltype(result_char)>, "");
+}
+
+auto test_auto_return_type_long(long x) {
+ auto result = __builtin_bswapg(x);
+ static_assert(is_same_type<long, decltype(result)>, "");
+ return result;
+}
+
+auto test_auto_return_type_int(int x) {
+ auto result = __builtin_bswapg(x);
+ static_assert(is_same_type<int, decltype(result)>, "");
+ return result;
+}
+
+auto test_auto_return_type_short(short x) {
+ auto result = __builtin_bswapg(x);
+ static_assert(is_same_type<short, decltype(result)>, "");
+ return result;
+}
+
+auto test_auto_return_type_char(char x) {
+ auto result = __builtin_bswapg(x);
+ static_assert(is_same_type<char, decltype(result)>, "");
+ return result;
+}
+
+void test_auto_return_type() {
+ test_auto_return_type_long(42);
+ test_auto_return_type_int(42);
+ test_auto_return_type_short(42);
+ test_auto_return_type_char(42);
+}
+
+decltype(auto) test_decltype_auto(int x) {
+ return __builtin_bswapg(x);
+}
+
+void test_decltype_auto_check() {
+ int x = 42;
+ auto result = test_decltype_auto(x);
+ static_assert(is_same_type<int, decltype(result)>, "");
+}
+
+template<auto Value>
+struct ValueTemplateTypeTest {
+ using value_type = decltype(Value);
+ using result_type = decltype(__builtin_bswapg(Value));
+
+ static constexpr bool type_matches = is_same_type<value_type, result_type>;
+ static_assert(type_matches, "Value template bswapg should preserve type");
+
+ static constexpr auto swapped_value = __builtin_bswapg(Value);
+};
+
+template<auto... Values>
+void test_template_pack_types() {
+ static_assert((is_same_type<decltype(Values), decltype(__builtin_bswapg(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>;
\ No newline at end of file
>From 1e9895c3aa7d648c5a7bdb78f6d3e3dd8bee4430 Mon Sep 17 00:00:00 2001
From: clingfei <1599101385 at qq.com>
Date: Fri, 10 Oct 2025 16:14:21 +0800
Subject: [PATCH 05/11] fix test for builtin-bswapg
---
clang/test/CodeGen/builtins.c | 4 +-
clang/test/Sema/builtin-bswapg.cpp | 121 --------------------------
clang/test/SemaCXX/builtin-bswapg.cpp | 85 ++++++++++++++++++
3 files changed, 87 insertions(+), 123 deletions(-)
delete mode 100644 clang/test/Sema/builtin-bswapg.cpp
create mode 100644 clang/test/SemaCXX/builtin-bswapg.cpp
diff --git a/clang/test/CodeGen/builtins.c b/clang/test/CodeGen/builtins.c
index 66ac8ad7431fb..f9bbc26e1473f 100644
--- a/clang/test/CodeGen/builtins.c
+++ b/clang/test/CodeGen/builtins.c
@@ -132,8 +132,8 @@ int main(void) {
// Whatever
P(bswapg, ((char)N));
P(bswapg, ((short)N));
- P(bswapg, ((int)N));
- P(bswapg, ((unsigned long)N));
+ P(bswapg, ((int)N));
+ P(bswapg, ((unsigned long)N));
P(bswap16, (N));
P(bswap32, (N));
P(bswap64, (N));
diff --git a/clang/test/Sema/builtin-bswapg.cpp b/clang/test/Sema/builtin-bswapg.cpp
deleted file mode 100644
index c7fa6f2410023..0000000000000
--- a/clang/test/Sema/builtin-bswapg.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
-// RUN: %clang_cc1 -fsyntax-only -verify -fexperimental-new-constant-interpreter %s
-// expected-no-diagnostics
-template <class A, class B>
-static constexpr bool is_same_type = false;
-
-template <class A>
-static constexpr bool is_same_type<A, A> = true;
-
-void test_basic_type_checks() {
- static_assert(is_same_type<char, decltype(__builtin_bswapg((char)0))>, "");
- static_assert(is_same_type<unsigned char, decltype(__builtin_bswapg((unsigned char)0))>, "");
- static_assert(is_same_type<short, decltype(__builtin_bswapg((short)0))>, "");
- static_assert(is_same_type<unsigned short, decltype(__builtin_bswapg((unsigned short)0))>, "");
- static_assert(is_same_type<int, decltype(__builtin_bswapg((int)0))>, "");
- static_assert(is_same_type<unsigned int, decltype(__builtin_bswapg((unsigned int)0))>, "");
- static_assert(is_same_type<long, decltype(__builtin_bswapg((long)0))>, "");
- static_assert(is_same_type<unsigned long, decltype(__builtin_bswapg((unsigned long)0))>, "");
-}
-
-template<typename T>
-void test_template_type_check() {
- static_assert(is_same_type<T, decltype(__builtin_bswapg(T{}))>,
- "bswapg should return the same type as its argument");
- constexpr T zero{};
- constexpr T max = ~T{};
- constexpr T one = T{1};
-
- static_assert(is_same_type<T, decltype(__builtin_bswapg(zero))>, "");
- static_assert(is_same_type<T, decltype(__builtin_bswapg(max))>, "");
- static_assert(is_same_type<T, decltype(__builtin_bswapg(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<unsigned long>();
-
-void test_lambda_type_checks() {
- auto lambda = [](auto x) {
- static_assert(is_same_type<decltype(x), decltype(__builtin_bswapg(x))>,
- "bswapg in lambda should preserve type");
- return __builtin_bswapg(x);
- };
- auto result_long = lambda(42UL);
- static_assert(is_same_type<unsigned long, decltype(result_long)>, "");
-
- auto result_int = lambda(42);
- static_assert(is_same_type<int, decltype(result_int)>, "");
-
- auto result_short = lambda(static_cast<short>(42));
- static_assert(is_same_type<short, decltype(result_short)>, "");
-
- auto result_char = lambda(static_cast<char>(42));
- static_assert(is_same_type<char, decltype(result_char)>, "");
-}
-
-auto test_auto_return_type_long(long x) {
- auto result = __builtin_bswapg(x);
- static_assert(is_same_type<long, decltype(result)>, "");
- return result;
-}
-
-auto test_auto_return_type_int(int x) {
- auto result = __builtin_bswapg(x);
- static_assert(is_same_type<int, decltype(result)>, "");
- return result;
-}
-
-auto test_auto_return_type_short(short x) {
- auto result = __builtin_bswapg(x);
- static_assert(is_same_type<short, decltype(result)>, "");
- return result;
-}
-
-auto test_auto_return_type_char(char x) {
- auto result = __builtin_bswapg(x);
- static_assert(is_same_type<char, decltype(result)>, "");
- return result;
-}
-
-void test_auto_return_type() {
- test_auto_return_type_long(42);
- test_auto_return_type_int(42);
- test_auto_return_type_short(42);
- test_auto_return_type_char(42);
-}
-
-decltype(auto) test_decltype_auto(int x) {
- return __builtin_bswapg(x);
-}
-
-void test_decltype_auto_check() {
- int x = 42;
- auto result = test_decltype_auto(x);
- static_assert(is_same_type<int, decltype(result)>, "");
-}
-
-template<auto Value>
-struct ValueTemplateTypeTest {
- using value_type = decltype(Value);
- using result_type = decltype(__builtin_bswapg(Value));
-
- static constexpr bool type_matches = is_same_type<value_type, result_type>;
- static_assert(type_matches, "Value template bswapg should preserve type");
-
- static constexpr auto swapped_value = __builtin_bswapg(Value);
-};
-
-template<auto... Values>
-void test_template_pack_types() {
- static_assert((is_same_type<decltype(Values), decltype(__builtin_bswapg(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>;
\ No newline at end of file
diff --git a/clang/test/SemaCXX/builtin-bswapg.cpp b/clang/test/SemaCXX/builtin-bswapg.cpp
new file mode 100644
index 0000000000000..229c7fcac1522
--- /dev/null
+++ b/clang/test/SemaCXX/builtin-bswapg.cpp
@@ -0,0 +1,85 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -fexperimental-new-constant-interpreter %s
+// expected-no-diagnostics
+
+void test_basic_type_checks() {
+ static_assert(__is_same(char, decltype(__builtin_bswapg((char)0))), "");
+ static_assert(__is_same(unsigned char, decltype(__builtin_bswapg((unsigned char)0))), "");
+ static_assert(__is_same(short, decltype(__builtin_bswapg((short)0))), "");
+ static_assert(__is_same(unsigned short, decltype(__builtin_bswapg((unsigned short)0))), "");
+ static_assert(__is_same(int, decltype(__builtin_bswapg((int)0))), "");
+ static_assert(__is_same(unsigned int, decltype(__builtin_bswapg((unsigned int)0))), "");
+ static_assert(__is_same(long, decltype(__builtin_bswapg((long)0))), "");
+ static_assert(__is_same(unsigned long, decltype(__builtin_bswapg((unsigned long)0))), "");
+}
+
+template<typename T>
+void test_template_type_check() {
+ static_assert(__is_same(T, decltype(__builtin_bswapg(T{}))),
+ "bswapg 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_bswapg(zero))), "");
+ static_assert(__is_same(T, decltype(__builtin_bswapg(max))), "");
+ static_assert(__is_same(T, decltype(__builtin_bswapg(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<unsigned long>();
+
+void test_lambda_type_checks() {
+ auto lambda = [](auto x) {
+ static_assert(__is_same(decltype(x), decltype(__builtin_bswapg(x))),
+ "bswapg in lambda should preserve type");
+ return __builtin_bswapg(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_bswapg(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_bswapg(Value));
+
+ static constexpr bool type_matches = __is_same(value_type, result_type);
+ static_assert(type_matches, "Value template bswapg should preserve type");
+
+ static constexpr auto swapped_value = __builtin_bswapg(Value);
+};
+
+template<auto... Values>
+void test_template_pack_types() {
+ static_assert((__is_same(decltype(Values), decltype(__builtin_bswapg(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>;
>From bca24f27114267572db5640ef7fced407ebde443 Mon Sep 17 00:00:00 2001
From: clingfei <1599101385 at qq.com>
Date: Sun, 12 Oct 2025 18:04:41 +0800
Subject: [PATCH 06/11] add failure tests and reference tests, and adjust
checks according to conversation
---
clang/lib/AST/ExprConstant.cpp | 13 +---
clang/lib/CodeGen/CGBuiltin.cpp | 2 +
clang/lib/Sema/SemaChecking.cpp | 2 +-
clang/test/AST/ByteCode/builtin-functions.cpp | 19 +++++
clang/test/CodeGenCXX/builtins.cpp | 37 +++++++++
clang/test/Sema/constant-builtins-2.c | 4 +
clang/test/SemaCXX/builtin-bswapg.cpp | 77 ++++++++++++++++++-
7 files changed, 142 insertions(+), 12 deletions(-)
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 745e8d9201183..f4490fcc8ac66 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -13982,22 +13982,15 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
return Success(Val.reverseBits(), E);
}
- case Builtin::BI__builtin_bswapg: {
- APSInt Val;
- if (!EvaluateInteger(E->getArg(0), Val, Info))
- return false;
- if (Val.getBitWidth() == 8)
- return Success(Val, E);
-
- return Success(Val.byteSwap(), E);
- }
-
+ case Builtin::BI__builtin_bswapg:
case Builtin::BI__builtin_bswap16:
case Builtin::BI__builtin_bswap32:
case Builtin::BI__builtin_bswap64: {
APSInt Val;
if (!EvaluateInteger(E->getArg(0), Val, Info))
return false;
+ if (Val.getBitWidth() == 8)
+ return Success(Val, E);
return Success(Val.byteSwap(), E);
}
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 124351e7f1e59..cc76024f335db 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -3626,6 +3626,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
Value *ArgValue = EmitScalarExpr(E->getArg(0));
llvm::IntegerType *IntTy = cast<llvm::IntegerType>(ArgValue->getType());
assert(IntTy && "LLVM's __builtin_bswapg only supports integer variants");
+ assert(((IntTy->getBitWidth() % 16 == 0 && IntTy->getBitWidth() != 0) || IntTy->getBitWidth() == 8) &&
+ "LLVM's __builtin_bswapg only supports integer variants that has a multiple of 16 bits as well as a single byte");
if (IntTy->getBitWidth() == 8)
return RValue::get(ArgValue);
return RValue::get(
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 80afa08f3f3af..6c9ec326f1fde 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2218,7 +2218,7 @@ static bool BuiltinBswapg(Sema &S, CallExpr *TheCall) {
if (!ArgTy->isIntegerType()) {
S.Diag(Arg->getBeginLoc(), diag::err_builtin_invalid_arg_type)
- << 1 << /* scalar */ 1 << /* unsigned integer ty */ 1 << /* no fp */ 0
+ << 1 << /*scalar=*/ 1 << /*unsigned integer=*/ 1 << /*floating point=*/ 0
<< ArgTy;
return true;
}
diff --git a/clang/test/AST/ByteCode/builtin-functions.cpp b/clang/test/AST/ByteCode/builtin-functions.cpp
index 84ff9cc137bf3..9248f835832f3 100644
--- a/clang/test/AST/ByteCode/builtin-functions.cpp
+++ b/clang/test/AST/ByteCode/builtin-functions.cpp
@@ -828,6 +828,25 @@ namespace bswap {
int h7 = __builtin_bswapg(0x1234) == 0x3412 ? 1 : f();
int h8 = __builtin_bswapg(0x00001234) == 0x34120000 ? 1 : f();
int h9 = __builtin_bswapg(0x0000000000001234) == 0x3412000000000000 ? 1 : f();
+
+ constexpr const int const_expr = 0x1234;
+
+ void test_constexpr_reference() {
+ const int expr = 0x1234;
+ const int& ref = expr; // #declare
+
+ constexpr const int& const_ref = const_expr;
+
+ constexpr auto result2 = __builtin_bswapg(ref);
+ //expected-error at -1 {{constexpr variable 'result2' must be initialized by a constant expression}}
+ //expected-note at -2 {{initializer of 'ref' is not a constant expression}}
+ //expected-note@#declare {{declared here}}
+ //ref-error at -4 {{constexpr variable 'result2' must be initialized by a constant expression}}
+ //ref-note at -5 {{initializer of 'ref' is not a constant expression}}
+ //ref-note@#declare {{declared here}}
+
+ constexpr auto result3 = __builtin_bswapg(const_ref);
+ }
}
#define CFSTR __builtin___CFStringMakeConstantString
diff --git a/clang/test/CodeGenCXX/builtins.cpp b/clang/test/CodeGenCXX/builtins.cpp
index 9169f3a3276d3..165f5cdb7cd48 100644
--- a/clang/test/CodeGenCXX/builtins.cpp
+++ b/clang/test/CodeGenCXX/builtins.cpp
@@ -83,3 +83,40 @@ int structured_binding_size() {
return __builtin_structured_binding_size(S2);
// CHECK: ret i32 2
}
+
+void test_int_reference(int& a) {
+ __builtin_bswapg(a);
+}
+// CHECK-LABEL: @_Z18test_int_referenceRi
+// CHECK: store ptr %a, ptr
+// CHECK: load ptr, ptr
+// CHECK: load i32, ptr
+// CHECK: call i32 @llvm.bswap.i32
+
+void test_long_reference(long& a) {
+ __builtin_bswapg(a);
+}
+// CHECK-LABEL: @_Z19test_long_referenceRl
+// CHECK: store ptr %a, ptr
+// CHECK: load ptr, ptr
+// CHECK: load i64, ptr
+// CHECK: call i64 @llvm.bswap.i64
+
+// 2. 不同大小的引用测试
+void test_short_reference(short& a) {
+ __builtin_bswapg(a);
+}
+// CHECK-LABEL: @_Z20test_short_referenceRs
+// CHECK: store ptr %a, ptr
+// CHECK: load ptr, ptr
+// CHECK: load i16, ptr
+// CHECK: call i16 @llvm.bswap.i16
+
+void test_char_reference(char& a) {
+ __builtin_bswapg(a);
+}
+// CHECK-LABEL: @_Z19test_char_referenceRc
+// CHECK: store ptr %a, ptr
+// CHECK: load ptr, ptr
+// CHECK-NOT: call i8 @llvm.bswap.i8
+// CHECK: ret void
diff --git a/clang/test/Sema/constant-builtins-2.c b/clang/test/Sema/constant-builtins-2.c
index 96bd2c966c2ef..ff15715a0c41c 100644
--- a/clang/test/Sema/constant-builtins-2.c
+++ b/clang/test/Sema/constant-builtins-2.c
@@ -483,6 +483,10 @@ int h6 = __builtin_bswapg((char)(0x12)) == (char)(0x12) ? 1 : f();
int h7 = __builtin_bswapg((short)(0x1234)) == (short)(0x3412) ? 1 : f();
int h8 = __builtin_bswapg(0x00001234) == 0x34120000 ? 1 : f();
int h9 = __builtin_bswapg(0x0000000000001234ULL) == 0x3412000000000000 ? 1 : f();
+float h10 = __builtin_bswapg(1.0f); // expected-error {{1st argument must be a scalar integer type (was 'float')}}
+double h12 = __builtin_bswapg(1.0L); // expected-error {{1st argument must be a scalar integer type (was 'long double')}}
+char *h13 = __builtin_bswapg("hello"); // expected-error {{1st argument must be a scalar integer type (was 'char[6]')}}
+int h14 = __builtin_bswapg(1, 2); // expected-error {{too many arguments to function call, expected 1, have 2}}
extern long int bi0;
extern __typeof__(__builtin_expect(0, 0)) bi0;
diff --git a/clang/test/SemaCXX/builtin-bswapg.cpp b/clang/test/SemaCXX/builtin-bswapg.cpp
index 229c7fcac1522..1e7f2790e60cc 100644
--- a/clang/test/SemaCXX/builtin-bswapg.cpp
+++ b/clang/test/SemaCXX/builtin-bswapg.cpp
@@ -1,6 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// RUN: %clang_cc1 -fsyntax-only -verify -fexperimental-new-constant-interpreter %s
-// expected-no-diagnostics
void test_basic_type_checks() {
static_assert(__is_same(char, decltype(__builtin_bswapg((char)0))), "");
@@ -83,3 +82,79 @@ 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_bswapg(T{}); // #invalid_type_use
+}
+
+void test_basic_errors() {
+ test_invalid_type<float>();
+ // expected-note at -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 at -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 at -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_bswapg(value)) { // #dependent_use
+ return __builtin_bswapg(value);
+}
+
+void test_dependent_errors() {
+ test_dependent_context(1.0f);
+ // expected-error at -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 at -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 at -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_bswapg(x); // #lambda_use
+ };
+
+ lambda(1.0f);
+ // expected-error@#lambda_use {{1st argument must be a scalar integer type (was 'float')}}
+ // expected-note at -2 {{in instantiation of function template specialization 'test_lambda_errors()::(anonymous class)::operator()<float>' requested here}}
+ lambda(1.0l);
+ // expected-error@#lambda_use {{1st argument must be a scalar integer type (was 'long double')}}
+ // expected-note at -2 {{in instantiation of function template specialization 'test_lambda_errors()::(anonymous class)::operator()<long double>' requested here}}
+ lambda("hello");
+ // expected-error@#lambda_use {{1st argument must be a scalar integer type (was 'const char *')}}
+ // expected-note at -2 {{in instantiation of function template specialization 'test_lambda_errors()::(anonymous class)::operator()<const char *>' requested here}}
+}
+
+void test_argument_count_errors() {
+ int h14 = __builtin_bswapg(1, 2); // expected-error {{too many arguments to function call, expected 1, have 2}}
+}
+
+void test_lvalue_reference(int& a) {
+ auto result = __builtin_bswapg(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_bswapg(a);
+ static_assert(__is_same(int, decltype(result)), "Should decay const reference to value type");
+}
+
+void test_rvalue_reference(int&& a) {
+ auto result = __builtin_bswapg(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_bswapg(a);
+ static_assert(__is_same(int, decltype(result)), "Should decay const rvalue reference to value type");
+}
>From ba83b56d21c3f74c0fa6a764b70915f8c0d7904c Mon Sep 17 00:00:00 2001
From: clingfei <1599101385 at qq.com>
Date: Wed, 15 Oct 2025 14:54:50 +0800
Subject: [PATCH 07/11] add tests for arrays, pointers, enums, class, nullptr_t
---
clang/test/Sema/constant-builtins-2.c | 7 ++++
clang/test/SemaCXX/builtin-bswapg.cpp | 58 +++++++++++++++++++++++----
2 files changed, 57 insertions(+), 8 deletions(-)
diff --git a/clang/test/Sema/constant-builtins-2.c b/clang/test/Sema/constant-builtins-2.c
index ff15715a0c41c..a7d92fe96bc06 100644
--- a/clang/test/Sema/constant-builtins-2.c
+++ b/clang/test/Sema/constant-builtins-2.c
@@ -487,6 +487,13 @@ float h10 = __builtin_bswapg(1.0f); // expected-error {{1st argument must be a s
double h12 = __builtin_bswapg(1.0L); // expected-error {{1st argument must be a scalar integer type (was 'long double')}}
char *h13 = __builtin_bswapg("hello"); // expected-error {{1st argument must be a scalar integer type (was 'char[6]')}}
int h14 = __builtin_bswapg(1, 2); // expected-error {{too many arguments to function call, expected 1, have 2}}
+int *h15 = __builtin_bswapg(&h9); // expected-error {{1st argument must be a scalar integer type (was 'int *')}}
+int arr[4] = {0x12, 0x34, 0x56, 0x78};
+int h16 = __builtin_bswapg(arr); // expected-error {{1st argument must be a scalar integer type (was 'int[4]')}}
+enum BasicEnum {
+ ENUM_VALUE1 = 0x1234,
+};
+int h17 = __builtin_bswapg(ENUM_VALUE1) == 0x34120000 ? 1 : f();
extern long int bi0;
extern __typeof__(__builtin_expect(0, 0)) bi0;
diff --git a/clang/test/SemaCXX/builtin-bswapg.cpp b/clang/test/SemaCXX/builtin-bswapg.cpp
index 1e7f2790e60cc..26bc5b54fae78 100644
--- a/clang/test/SemaCXX/builtin-bswapg.cpp
+++ b/clang/test/SemaCXX/builtin-bswapg.cpp
@@ -140,21 +140,63 @@ void test_argument_count_errors() {
}
void test_lvalue_reference(int& a) {
- auto result = __builtin_bswapg(a);
- static_assert(__is_same(int, decltype(result)), "Should decay reference to value type");
+ auto result = __builtin_bswapg(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_bswapg(a);
- static_assert(__is_same(int, decltype(result)), "Should decay const reference to value type");
+ auto result = __builtin_bswapg(a);
+ static_assert(__is_same(int, decltype(result)), "Should decay const reference to value type");
}
void test_rvalue_reference(int&& a) {
- auto result = __builtin_bswapg(a);
- static_assert(__is_same(int, decltype(result)), "Should decay rvalue reference to value type");
+ auto result = __builtin_bswapg(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_bswapg(a);
- static_assert(__is_same(int, decltype(result)), "Should decay const rvalue reference to value type");
+ auto result = __builtin_bswapg(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_bswapg(arr);
+ // expected-error at -1 {{1st argument must be a scalar integer type (was 'int[4]')}}
+}
+
+void test_pointer() {
+ int x = 0x12345678;
+ int *ptr = &x;
+ __builtin_bswapg(ptr);
+ // expected-error at -1 {{1st argument must be a scalar integer type (was 'int *')}}
+}
+
+enum BasicEnum {
+ ENUM_VALUE1 = 0x1234,
+ ENUM_VALUE2 = 0x34120000
+};
+
+void test_enum() {
+ const BasicEnum e = ENUM_VALUE1;
+ static_assert(__builtin_bswapg(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_bswapg(c);
+ // expected-error at -1 {{1st argument must be a scalar integer type (was 'testClass')}}
+}
+
+void test_nullptr() {
+ __builtin_bswapg(nullptr);
+ // expected-error at -1 {{1st argument must be a scalar integer type (was 'std::nullptr_t')}}
}
>From a2a619182ac99f6e986b74d24632f4fc1e09f45e Mon Sep 17 00:00:00 2001
From: clingfei <1599101385 at qq.com>
Date: Wed, 15 Oct 2025 15:18:29 +0800
Subject: [PATCH 08/11] add release notes
---
clang/docs/ReleaseNotes.rst | 3 +++
1 file changed, 3 insertions(+)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5e9a71e1e74d6..fe158a0a6ff03 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -257,6 +257,9 @@ Non-comprehensive list of changes in this release
- Fixed a crash when the second argument to ``__builtin_assume_aligned`` was not constant (#GH161314)
+- A new generic byte swap builtin function ``__builtin_bswapg`` that extends the existing
+ __builtin_bswap{16,32,64} function family to support all standard integer types.
+
New Compiler Flags
------------------
- New option ``-fno-sanitize-debug-trap-reasons`` added to disable emitting trap reasons into the debug info when compiling with trapping UBSan (e.g. ``-fsanitize-trap=undefined``).
>From 6afe3340410eb76e1458f106d009e78b531e1f95 Mon Sep 17 00:00:00 2001
From: clingfei <1599101385 at qq.com>
Date: Sat, 18 Oct 2025 16:31:01 +0800
Subject: [PATCH 09/11] add support and test cases for _BitInt
---
.../clang/Basic/DiagnosticSemaKinds.td | 3 ++
clang/lib/CodeGen/CGBuiltin.cpp | 6 ++--
clang/lib/Sema/SemaChecking.cpp | 8 +++++
clang/test/AST/ByteCode/builtin-functions.cpp | 10 ++++++
clang/test/CodeGen/builtins.c | 32 +++++++++++++++++++
clang/test/CodeGenCXX/builtins.cpp | 29 ++++++++++++++---
clang/test/Sema/constant-builtins-2.c | 7 ++++
clang/test/SemaCXX/builtin-bswapg.cpp | 10 ++++++
8 files changed, 98 insertions(+), 7 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 40bc7b9a4e45e..20d340e8dc159 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -12948,6 +12948,9 @@ def err_builtin_invalid_arg_type: Error<
"%plural{0:|: }3"
"%plural{[0,3]:type|:types}1 (was %4)">;
+def err_bswapg_bitint_not_16bit_aligned : Error<
+ "_BitInt type %0 (%1 bits) must be a multiple of 16 bits for byte swapping">;
+
def err_builtin_trivially_relocate_invalid_arg_type: Error <
"first%select{||| and second}0 argument%select{|||s}0 to "
"'__builtin_trivially_relocate' must be"
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index cc76024f335db..5f9807d8409a4 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -3626,8 +3626,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
Value *ArgValue = EmitScalarExpr(E->getArg(0));
llvm::IntegerType *IntTy = cast<llvm::IntegerType>(ArgValue->getType());
assert(IntTy && "LLVM's __builtin_bswapg only supports integer variants");
- assert(((IntTy->getBitWidth() % 16 == 0 && IntTy->getBitWidth() != 0) || IntTy->getBitWidth() == 8) &&
- "LLVM's __builtin_bswapg only supports integer variants that has a multiple of 16 bits as well as a single byte");
+ assert(((IntTy->getBitWidth() % 16 == 0 && IntTy->getBitWidth() != 0) ||
+ IntTy->getBitWidth() == 8) &&
+ "LLVM's __builtin_bswapg only supports integer variants that has a "
+ "multiple of 16 bits as well as a single byte");
if (IntTy->getBitWidth() == 8)
return RValue::get(ArgValue);
return RValue::get(
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 6c9ec326f1fde..244640e6a5a99 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2222,6 +2222,14 @@ static bool BuiltinBswapg(Sema &S, CallExpr *TheCall) {
<< ArgTy;
return true;
}
+ const auto *bitIntType = dyn_cast<BitIntType>(ArgTy);
+ if (bitIntType != nullptr) {
+ if (bitIntType->getNumBits() % 16 != 0 && bitIntType->getNumBits() != 8) {
+ S.Diag(Arg->getBeginLoc(), diag::err_bswapg_bitint_not_16bit_aligned)
+ << ArgTy << bitIntType->getNumBits();
+ return true;
+ }
+ }
TheCall->setType(ArgTy);
return false;
}
diff --git a/clang/test/AST/ByteCode/builtin-functions.cpp b/clang/test/AST/ByteCode/builtin-functions.cpp
index 9248f835832f3..4e061afff0941 100644
--- a/clang/test/AST/ByteCode/builtin-functions.cpp
+++ b/clang/test/AST/ByteCode/builtin-functions.cpp
@@ -828,6 +828,16 @@ namespace bswap {
int h7 = __builtin_bswapg(0x1234) == 0x3412 ? 1 : f();
int h8 = __builtin_bswapg(0x00001234) == 0x34120000 ? 1 : f();
int h9 = __builtin_bswapg(0x0000000000001234) == 0x3412000000000000 ? 1 : f();
+#ifndef __AVR__
+ int h10 = __builtin_bswapg((_BitInt(8))0x12) == (_BitInt(8))0x12 ? 1 : f();
+ int h11 = __builtin_bswapg((_BitInt(16))0x1234) == (_BitInt(16))0x3412 ? 1 : f();
+ int h12 = __builtin_bswapg((_BitInt(32))0x00001234) == (_BitInt(32))0x34120000 ? 1 : f();
+ int h13 = __builtin_bswapg((_BitInt(64))0x0000000000001234) == (_BitInt(64))0x3412000000000000 ? 1 : f();
+ int h14 = __builtin_bswapg(~(_BitInt(128))0) == (~(_BitInt(128))0) ? 1 : f();
+ int h15 = __builtin_bswapg((_BitInt(24))0x1234) == (_BitInt(24))0x3412 ? 1 : f();
+ // expected-error at -1 {{_BitInt type '_BitInt(24)' (24 bits) must be a multiple of 16 bits for byte swapping}}
+ // ref-error at -2 {{_BitInt type '_BitInt(24)' (24 bits) must be a multiple of 16 bits for byte swapping}}
+#endif
constexpr const int const_expr = 0x1234;
diff --git a/clang/test/CodeGen/builtins.c b/clang/test/CodeGen/builtins.c
index f9bbc26e1473f..e6d636d5f4a95 100644
--- a/clang/test/CodeGen/builtins.c
+++ b/clang/test/CodeGen/builtins.c
@@ -1280,3 +1280,35 @@ void test_builtin_ctzg(unsigned char uc, unsigned short us, unsigned int ui,
}
#endif
+
+// CHECK-LABEL: define{{.*}} void @test_builtin_bswapg
+void test_builtin_bswapg(unsigned char uc, unsigned short us, unsigned int ui,
+ unsigned long ul, unsigned long long ull,
+ unsigned __int128 ui128, _BitInt(8) bi8,
+ _BitInt(16) bi16, _BitInt(32) bi32,
+ _BitInt(64) bi64, _BitInt(128) bi128) {
+ uc = __builtin_bswapg(uc);
+ // CHECK: %1 = load i8, ptr %uc.addr
+ // CHECK: store i8 %1, ptr %uc.addr
+ us = __builtin_bswapg(us);
+ // CHECK: call i16 @llvm.bswap.i16
+ ui = __builtin_bswapg(ui);
+ // CHECK: call i32 @llvm.bswap.i32
+ ul = __builtin_bswapg(ul);
+ // CHECK: call i64 @llvm.bswap.i64
+ ull = __builtin_bswapg(ull);
+ // CHECK: call i64 @llvm.bswap.i64
+ ui128 = __builtin_bswapg(ui128);
+ // CHECK: call i128 @llvm.bswap.i128
+ bi8 = __builtin_bswapg(bi8);
+ // CHECK: %17 = load i8, ptr %bi8.addr, align 1
+ // CHECK: store i8 %17, ptr %bi8.addr
+ bi16 = __builtin_bswapg(bi16);
+ // CHECK: call i16 @llvm.bswap.i16
+ bi32 = __builtin_bswapg(bi32);
+ // CHECK: call i32 @llvm.bswap.i32
+ bi64 = __builtin_bswapg(bi64);
+ // CHECK: call i64 @llvm.bswap.i64
+ bi128 = __builtin_bswapg(bi128);
+ // CHECK: call i128 @llvm.bswap.i128
+}
diff --git a/clang/test/CodeGenCXX/builtins.cpp b/clang/test/CodeGenCXX/builtins.cpp
index 165f5cdb7cd48..ef30a25a17922 100644
--- a/clang/test/CodeGenCXX/builtins.cpp
+++ b/clang/test/CodeGenCXX/builtins.cpp
@@ -85,7 +85,7 @@ int structured_binding_size() {
}
void test_int_reference(int& a) {
- __builtin_bswapg(a);
+ __builtin_bswapg(a);
}
// CHECK-LABEL: @_Z18test_int_referenceRi
// CHECK: store ptr %a, ptr
@@ -94,7 +94,7 @@ void test_int_reference(int& a) {
// CHECK: call i32 @llvm.bswap.i32
void test_long_reference(long& a) {
- __builtin_bswapg(a);
+ __builtin_bswapg(a);
}
// CHECK-LABEL: @_Z19test_long_referenceRl
// CHECK: store ptr %a, ptr
@@ -102,9 +102,8 @@ void test_long_reference(long& a) {
// CHECK: load i64, ptr
// CHECK: call i64 @llvm.bswap.i64
-// 2. 不同大小的引用测试
void test_short_reference(short& a) {
- __builtin_bswapg(a);
+ __builtin_bswapg(a);
}
// CHECK-LABEL: @_Z20test_short_referenceRs
// CHECK: store ptr %a, ptr
@@ -113,10 +112,30 @@ void test_short_reference(short& a) {
// CHECK: call i16 @llvm.bswap.i16
void test_char_reference(char& a) {
- __builtin_bswapg(a);
+ __builtin_bswapg(a);
}
// CHECK-LABEL: @_Z19test_char_referenceRc
// CHECK: store ptr %a, ptr
// CHECK: load ptr, ptr
// CHECK-NOT: call i8 @llvm.bswap.i8
// CHECK: ret void
+
+void test_bitint() {
+ _BitInt(8) a = 0x12;
+ __builtin_bswapg(a);
+ _BitInt(16) b = 0x1234;
+ __builtin_bswapg(b);
+ _BitInt(32) c = 0x00001234;
+ __builtin_bswapg(c);
+ _BitInt(64) d = 0x0000000000001234;
+ __builtin_bswapg(d);
+ _BitInt(128) e = ~(_BitInt(128))0;
+ __builtin_bswapg(e);
+}
+// CHECK-LABEL: @_Z11test_bitintv
+// CHECK-NOT: call i8 @llvm.bswap.i8
+// CHECK: call i16 @llvm.bswap.i16
+// CHECK: call i32 @llvm.bswap.i32
+// CHECK: call i64 @llvm.bswap.i64
+// CHECK: call i128 @llvm.bswap.i128
+// CHECK: ret void
diff --git a/clang/test/Sema/constant-builtins-2.c b/clang/test/Sema/constant-builtins-2.c
index a7d92fe96bc06..9579052b1f76b 100644
--- a/clang/test/Sema/constant-builtins-2.c
+++ b/clang/test/Sema/constant-builtins-2.c
@@ -494,6 +494,13 @@ enum BasicEnum {
ENUM_VALUE1 = 0x1234,
};
int h17 = __builtin_bswapg(ENUM_VALUE1) == 0x34120000 ? 1 : f();
+int h18 = __builtin_bswapg((_BitInt(8))0x12) == (_BitInt(8))0x12 ? 1 : f();
+int h19 = __builtin_bswapg((_BitInt(16))0x1234) == (_BitInt(16))0x3412 ? 1 : f();
+int h20 = __builtin_bswapg((_BitInt(32))0x00001234) == (_BitInt(32))0x34120000 ? 1 : f();
+int h21 = __builtin_bswapg((_BitInt(64))0x0000000000001234) == (_BitInt(64))0x3412000000000000 ? 1 : f();
+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 at -1 {{_BitInt type '_BitInt(24)' (24 bits) must be a multiple of 16 bits for byte swapping}}
extern long int bi0;
extern __typeof__(__builtin_expect(0, 0)) bi0;
diff --git a/clang/test/SemaCXX/builtin-bswapg.cpp b/clang/test/SemaCXX/builtin-bswapg.cpp
index 26bc5b54fae78..7b4d769df9ba7 100644
--- a/clang/test/SemaCXX/builtin-bswapg.cpp
+++ b/clang/test/SemaCXX/builtin-bswapg.cpp
@@ -200,3 +200,13 @@ void test_nullptr() {
__builtin_bswapg(nullptr);
// expected-error at -1 {{1st argument must be a scalar integer type (was 'std::nullptr_t')}}
}
+
+void test_bitint() {
+ static_assert(__builtin_bswapg((_BitInt(8))0x12) == (_BitInt(8))0x12, "");
+ static_assert(__builtin_bswapg((_BitInt(16))0x1234) == (_BitInt(16))0x3412, "");
+ static_assert(__builtin_bswapg((_BitInt(32))0x00001234) == (_BitInt(32))0x34120000, "");
+ static_assert(__builtin_bswapg((_BitInt(64))0x0000000000001234) == (_BitInt(64))0x3412000000000000, "");
+ static_assert(__builtin_bswapg(~(_BitInt(128))0) == (~(_BitInt(128))0), "");
+ static_assert(__builtin_bswapg((_BitInt(24))0x1234) == (_BitInt(24))0x3412, "");
+ // expected-error at -1 {{_BitInt type '_BitInt(24)' (24 bits) must be a multiple of 16 bits for byte swapping}}
+}
>From ed8c33a07dadfd28c0821187661a022d151c7ae9 Mon Sep 17 00:00:00 2001
From: clingfei <1599101385 at qq.com>
Date: Sat, 18 Oct 2025 16:38:29 +0800
Subject: [PATCH 10/11] remove extra spaces
---
clang/test/AST/ByteCode/builtin-functions.cpp | 12 ++---
clang/test/CodeGen/builtins.c | 50 +++++++++----------
2 files changed, 31 insertions(+), 31 deletions(-)
diff --git a/clang/test/AST/ByteCode/builtin-functions.cpp b/clang/test/AST/ByteCode/builtin-functions.cpp
index 4e061afff0941..92bc04be0767d 100644
--- a/clang/test/AST/ByteCode/builtin-functions.cpp
+++ b/clang/test/AST/ByteCode/builtin-functions.cpp
@@ -831,12 +831,12 @@ namespace bswap {
#ifndef __AVR__
int h10 = __builtin_bswapg((_BitInt(8))0x12) == (_BitInt(8))0x12 ? 1 : f();
int h11 = __builtin_bswapg((_BitInt(16))0x1234) == (_BitInt(16))0x3412 ? 1 : f();
- int h12 = __builtin_bswapg((_BitInt(32))0x00001234) == (_BitInt(32))0x34120000 ? 1 : f();
- int h13 = __builtin_bswapg((_BitInt(64))0x0000000000001234) == (_BitInt(64))0x3412000000000000 ? 1 : f();
- int h14 = __builtin_bswapg(~(_BitInt(128))0) == (~(_BitInt(128))0) ? 1 : f();
- int h15 = __builtin_bswapg((_BitInt(24))0x1234) == (_BitInt(24))0x3412 ? 1 : f();
- // expected-error at -1 {{_BitInt type '_BitInt(24)' (24 bits) must be a multiple of 16 bits for byte swapping}}
- // ref-error at -2 {{_BitInt type '_BitInt(24)' (24 bits) must be a multiple of 16 bits for byte swapping}}
+ int h12 = __builtin_bswapg((_BitInt(32))0x00001234) == (_BitInt(32))0x34120000 ? 1 : f();
+ int h13 = __builtin_bswapg((_BitInt(64))0x0000000000001234) == (_BitInt(64))0x3412000000000000 ? 1 : f();
+ int h14 = __builtin_bswapg(~(_BitInt(128))0) == (~(_BitInt(128))0) ? 1 : f();
+ int h15 = __builtin_bswapg((_BitInt(24))0x1234) == (_BitInt(24))0x3412 ? 1 : f();
+ // expected-error at -1 {{_BitInt type '_BitInt(24)' (24 bits) must be a multiple of 16 bits for byte swapping}}
+ // ref-error at -2 {{_BitInt type '_BitInt(24)' (24 bits) must be a multiple of 16 bits for byte swapping}}
#endif
constexpr const int const_expr = 0x1234;
diff --git a/clang/test/CodeGen/builtins.c b/clang/test/CodeGen/builtins.c
index e6d636d5f4a95..b3d40992fc975 100644
--- a/clang/test/CodeGen/builtins.c
+++ b/clang/test/CodeGen/builtins.c
@@ -1285,30 +1285,30 @@ void test_builtin_ctzg(unsigned char uc, unsigned short us, unsigned int ui,
void test_builtin_bswapg(unsigned char uc, unsigned short us, unsigned int ui,
unsigned long ul, unsigned long long ull,
unsigned __int128 ui128, _BitInt(8) bi8,
- _BitInt(16) bi16, _BitInt(32) bi32,
- _BitInt(64) bi64, _BitInt(128) bi128) {
- uc = __builtin_bswapg(uc);
- // CHECK: %1 = load i8, ptr %uc.addr
- // CHECK: store i8 %1, ptr %uc.addr
- us = __builtin_bswapg(us);
- // CHECK: call i16 @llvm.bswap.i16
- ui = __builtin_bswapg(ui);
- // CHECK: call i32 @llvm.bswap.i32
- ul = __builtin_bswapg(ul);
- // CHECK: call i64 @llvm.bswap.i64
- ull = __builtin_bswapg(ull);
- // CHECK: call i64 @llvm.bswap.i64
- ui128 = __builtin_bswapg(ui128);
- // CHECK: call i128 @llvm.bswap.i128
- bi8 = __builtin_bswapg(bi8);
- // CHECK: %17 = load i8, ptr %bi8.addr, align 1
+ _BitInt(16) bi16, _BitInt(32) bi32,
+ _BitInt(64) bi64, _BitInt(128) bi128) {
+ uc = __builtin_bswapg(uc);
+ // CHECK: %1 = load i8, ptr %uc.addr
+ // CHECK: store i8 %1, ptr %uc.addr
+ us = __builtin_bswapg(us);
+ // CHECK: call i16 @llvm.bswap.i16
+ ui = __builtin_bswapg(ui);
+ // CHECK: call i32 @llvm.bswap.i32
+ ul = __builtin_bswapg(ul);
+ // CHECK: call i64 @llvm.bswap.i64
+ ull = __builtin_bswapg(ull);
+ // CHECK: call i64 @llvm.bswap.i64
+ ui128 = __builtin_bswapg(ui128);
+ // CHECK: call i128 @llvm.bswap.i128
+ bi8 = __builtin_bswapg(bi8);
+ // CHECK: %17 = load i8, ptr %bi8.addr, align 1
// CHECK: store i8 %17, ptr %bi8.addr
- bi16 = __builtin_bswapg(bi16);
- // CHECK: call i16 @llvm.bswap.i16
- bi32 = __builtin_bswapg(bi32);
- // CHECK: call i32 @llvm.bswap.i32
- bi64 = __builtin_bswapg(bi64);
- // CHECK: call i64 @llvm.bswap.i64
- bi128 = __builtin_bswapg(bi128);
- // CHECK: call i128 @llvm.bswap.i128
+ bi16 = __builtin_bswapg(bi16);
+ // CHECK: call i16 @llvm.bswap.i16
+ bi32 = __builtin_bswapg(bi32);
+ // CHECK: call i32 @llvm.bswap.i32
+ bi64 = __builtin_bswapg(bi64);
+ // CHECK: call i64 @llvm.bswap.i64
+ bi128 = __builtin_bswapg(bi128);
+ // CHECK: call i128 @llvm.bswap.i128
}
>From 63336688b08767d44402fca453aba8105bebd343 Mon Sep 17 00:00:00 2001
From: clingfei <1599101385 at qq.com>
Date: Sun, 19 Oct 2025 14:02:56 +0800
Subject: [PATCH 11/11] add more test cases for _BitInt
---
clang/test/SemaCXX/builtin-bswapg.cpp | 24 +++++++++++++++++++++---
1 file changed, 21 insertions(+), 3 deletions(-)
diff --git a/clang/test/SemaCXX/builtin-bswapg.cpp b/clang/test/SemaCXX/builtin-bswapg.cpp
index 7b4d769df9ba7..9d8d103e77c51 100644
--- a/clang/test/SemaCXX/builtin-bswapg.cpp
+++ b/clang/test/SemaCXX/builtin-bswapg.cpp
@@ -10,6 +10,11 @@ void test_basic_type_checks() {
static_assert(__is_same(unsigned int, decltype(__builtin_bswapg((unsigned int)0))), "");
static_assert(__is_same(long, decltype(__builtin_bswapg((long)0))), "");
static_assert(__is_same(unsigned long, decltype(__builtin_bswapg((unsigned long)0))), "");
+ static_assert(__is_same(_BitInt(8), decltype(__builtin_bswapg((_BitInt(8))0))), "");
+ static_assert(__is_same(_BitInt(16), decltype(__builtin_bswapg((_BitInt(16))0))), "");
+ static_assert(__is_same(_BitInt(32), decltype(__builtin_bswapg((_BitInt(32))0))), "");
+ static_assert(__is_same(_BitInt(64), decltype(__builtin_bswapg((_BitInt(64))0))), "");
+ static_assert(__is_same(_BitInt(128), decltype(__builtin_bswapg((_BitInt(128))0))), "");
}
template<typename T>
@@ -31,7 +36,11 @@ 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<unsigned 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) {
@@ -135,8 +144,17 @@ void test_lambda_errors() {
// expected-note at -2 {{in instantiation of function template specialization 'test_lambda_errors()::(anonymous class)::operator()<const char *>' requested here}}
}
-void test_argument_count_errors() {
- int h14 = __builtin_bswapg(1, 2); // expected-error {{too many arguments to function call, expected 1, have 2}}
+template <class... Args> void test_variadic_template_argument_count(Args... args) {
+ int result = __builtin_bswapg(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 at -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 at -2 {{in instantiation of function template specialization 'test_variadic_template_argument_count<int, int>' requested here}}
}
void test_lvalue_reference(int& a) {
More information about the cfe-commits
mailing list