[clang] [Clang] Diagnose fixed point arithmetic with `_BitInt` and `overflow` behavior types (PR #221134)
Akash Manna via cfe-commits
cfe-commits at lists.llvm.org
Sat Sep 26 23:50:54 PDT 2026
https://github.com/akash-manna-sky updated https://github.com/llvm/llvm-project/pull/221134
>From f729b942548041020759635b87462afd3c6e9a1b Mon Sep 17 00:00:00 2001
From: Akash Manna <akash.manna.mymail at gmail.com>
Date: Fri, 4 Sep 2026 10:41:21 +0530
Subject: [PATCH 1/4] [Clang] Diagnose fixed point arithmetic with _BitInt and
overflow behavior types
GetFixedPointRank assumes both operands are BuiltinTypes, but the
fixed point branch of UsualArithmeticConversions let any arithmetic
type through. _BitInt was special-cased in #199912, yet overflow
behavior types hit the same assertion.
Check for BuiltinType at the fixed point branch itself, so every
non-builtin operand is rejected with the usual invalid-operands
diagnostic, and make the conditional operator diagnose any failed
conversion instead of only the _BitInt case.
Fixes #191701
---
clang/docs/ReleaseNotes.md | 1 +
clang/lib/Sema/SemaExpr.cpp | 18 +++++++++---------
clang/test/Sema/GH191701.c | 32 ++++++++++++++++++++++++++++++++
3 files changed, 42 insertions(+), 9 deletions(-)
create mode 100644 clang/test/Sema/GH191701.c
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 042d7112dbe7d2..69566f10bb597a 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -494,6 +494,7 @@ features cannot lower the translation-unit ABI level;
- Fixed a crash when declaring a member template within a local class inside an OpenMP region. (#GH216052)
- Fixed a bug where repeated #imports of modular headers in non-modular compilation were translated to #pragma clang module import. (#GH216924)
- Fixed an assertion when `#pragma omp declare simd` or `#pragma omp declare variant` is followed by another OpenMP declarative directive containing a qualified identifier. (#GH217204)
+- Fixed an assertion failure when a fixed point type was used in arithmetic with a `_BitInt` or overflow behavior type; the combination is now diagnosed as invalid operands. (#GH191701)
#### Bug Fixes to Compiler Builtins
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index c93efeb928c563..e0d2298617a7c0 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -1757,10 +1757,6 @@ QualType Sema::UsualArithmeticConversions(ExprResult &LHS, ExprResult &RHS,
// At this point, we have two different arithmetic types.
- if ((LHSType->isFixedPointType() && RHSType->isBitIntType()) ||
- (LHSType->isBitIntType() && RHSType->isFixedPointType()))
- return QualType();
-
// Diagnose attempts to convert between __ibm128, __float128 and long double
// where such conversions currently can't be handled.
if (unsupportedTypeConversion(*this, LHSType, RHSType))
@@ -1781,8 +1777,13 @@ QualType Sema::UsualArithmeticConversions(ExprResult &LHS, ExprResult &RHS,
return handleComplexIntConversion(*this, LHS, RHS, LHSType, RHSType,
ACK == ArithConvKind::CompAssign);
- if (LHSType->isFixedPointType() || RHSType->isFixedPointType())
+ if (LHSType->isFixedPointType() || RHSType->isFixedPointType()) {
+ // N1169 4.1.4 only defines conversions between fixed point types and the
+ // standard integer types, so reject e.g. _BitInt or overflow behavior types.
+ if (!LHSType->getAs<BuiltinType>() || !RHSType->getAs<BuiltinType>())
+ return QualType();
return handleFixedPointConversion(*this, LHSType, RHSType);
+ }
if (LHSType->isOverflowBehaviorType() || RHSType->isOverflowBehaviorType())
return handleOverflowBehaviorTypeConversion(
@@ -8983,10 +8984,9 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
// If both operands have arithmetic type, do the usual arithmetic conversions
// to find a common type: C99 6.5.15p3,5.
if (LHSTy->isArithmeticType() && RHSTy->isArithmeticType()) {
- // Disallow invalid arithmetic conversions, such as those between bit-
- // precise integers types of different sizes, or between a bit-precise
- // integer and another type.
- if (ResTy.isNull() && (LHSTy->isBitIntType() || RHSTy->isBitIntType())) {
+ // Disallow invalid arithmetic conversions, such as those between a
+ // bit-precise integer and a fixed point type.
+ if (ResTy.isNull()) {
Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands)
<< LHSTy << RHSTy << LHS.get()->getSourceRange()
<< RHS.get()->getSourceRange();
diff --git a/clang/test/Sema/GH191701.c b/clang/test/Sema/GH191701.c
new file mode 100644
index 00000000000000..446f2bc3bad40f
--- /dev/null
+++ b/clang/test/Sema/GH191701.c
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -ffixed-point -fexperimental-overflow-behavior-types %s
+
+// Fixed point types have no conversions with _BitInt or overflow behavior types.
+
+#define test(e, t) _Generic (e, default : 0, t : 1)
+
+void GH191701(_Fract ci) {
+ _BitInt(31) bi = 0;
+ _Static_assert(test(ci + bi, _Complex int), ""); // expected-error {{invalid operands to binary expression ('_Fract' and '_BitInt(31)')}}
+}
+
+void bitint(int c, _Fract f, _Accum a, _Sat short _Fract sf, _BitInt(31) bi,
+ unsigned _BitInt(8) ubi) {
+ (void)(f + bi); // expected-error {{invalid operands to binary expression ('_Fract' and '_BitInt(31)')}}
+ (void)(bi + f); // expected-error {{invalid operands to binary expression ('_BitInt(31)' and '_Fract')}}
+ (void)(a - bi); // expected-error {{invalid operands to binary expression ('_Accum' and '_BitInt(31)')}}
+ (void)(bi * a); // expected-error {{invalid operands to binary expression ('_BitInt(31)' and '_Accum')}}
+ (void)(sf / ubi); // expected-error {{invalid operands to binary expression ('_Sat short _Fract' and 'unsigned _BitInt(8)')}}
+ (void)(f < bi); // expected-error {{invalid operands to binary expression ('_Fract' and '_BitInt(31)')}}
+ (void)(ubi == a); // expected-error {{invalid operands to binary expression ('unsigned _BitInt(8)' and '_Accum')}}
+ f += bi; // expected-error {{invalid operands to binary expression ('_Fract' and '_BitInt(31)')}}
+ bi -= a; // expected-error {{invalid operands to binary expression ('_BitInt(31)' and '_Accum')}}
+ (void)(c ? f : bi); // expected-error {{incompatible operand types ('_Fract' and '_BitInt(31)')}}
+}
+
+void overflow_behavior(int c, _Fract f, _Accum a, int __ob_wrap w,
+ long __ob_trap t) {
+ (void)(f + w); // expected-error {{invalid operands to binary expression ('_Fract' and '__ob_wrap int')}}
+ (void)(t * a); // expected-error {{invalid operands to binary expression ('__ob_trap long' and '_Accum')}}
+ a -= w; // expected-error {{invalid operands to binary expression ('_Accum' and '__ob_wrap int')}}
+ (void)(c ? w : f); // expected-error {{incompatible operand types ('__ob_wrap int' and '_Fract')}}
+}
>From ebe787faf87633e741952574e8e41f9518c0f244 Mon Sep 17 00:00:00 2001
From: Akash Manna <akash.manna.mymail at gmail.com>
Date: Fri, 4 Sep 2026 10:54:42 +0530
Subject: [PATCH 2/4] Fix the formatting issue
---
clang/lib/Sema/SemaExpr.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index e0d2298617a7c0..97eec9dc5b8670 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -1779,7 +1779,8 @@ QualType Sema::UsualArithmeticConversions(ExprResult &LHS, ExprResult &RHS,
if (LHSType->isFixedPointType() || RHSType->isFixedPointType()) {
// N1169 4.1.4 only defines conversions between fixed point types and the
- // standard integer types, so reject e.g. _BitInt or overflow behavior types.
+ // standard integer types, so reject e.g. _BitInt or overflow behavior
+ // types.
if (!LHSType->getAs<BuiltinType>() || !RHSType->getAs<BuiltinType>())
return QualType();
return handleFixedPointConversion(*this, LHSType, RHSType);
>From de1518de6b7b917a352730478a22f67c86346721 Mon Sep 17 00:00:00 2001
From: Akash Manna <akash.manna.mymail at gmail.com>
Date: Sat, 5 Sep 2026 00:35:23 +0530
Subject: [PATCH 3/4] Cite ISO/IEC TR 18037 instead of N1169 in the fixed point
comment
---
clang/lib/Sema/SemaExpr.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 97eec9dc5b8670..8f2de66d3c8831 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -1778,9 +1778,9 @@ QualType Sema::UsualArithmeticConversions(ExprResult &LHS, ExprResult &RHS,
ACK == ArithConvKind::CompAssign);
if (LHSType->isFixedPointType() || RHSType->isFixedPointType()) {
- // N1169 4.1.4 only defines conversions between fixed point types and the
- // standard integer types, so reject e.g. _BitInt or overflow behavior
- // types.
+ // ISO/IEC TR 18037 4.1.4 only defines conversions between fixed point
+ // types and the standard integer types, so reject e.g. _BitInt or overflow
+ // behavior types.
if (!LHSType->getAs<BuiltinType>() || !RHSType->getAs<BuiltinType>())
return QualType();
return handleFixedPointConversion(*this, LHSType, RHSType);
>From 6497d529e025c99ba87a83f3a79bd1d245b88e69 Mon Sep 17 00:00:00 2001
From: Akash Manna <akash.manna.mymail at gmail.com>
Date: Sat, 26 Sep 2026 23:58:27 +0530
Subject: [PATCH 4/4] Reposition the release notes to avoid the conflicts
---
clang/docs/ReleaseNotes.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index b8c20c9efd1c50..f8f4f42872b039 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -530,6 +530,7 @@ features cannot lower the translation-unit ABI level;
- Fixed a rejected-valid case that used an explicit object parameter in an out-of-line definition of a nested class member. (#GH136472)
- Fixed an assertion on omp taskloop transparent (#GH197162)
- Fixed a bug where `__func__`, `__PRETTY_FUNCTION__` and `__FUNCTION__` were not resolving to the proper function when inside a lambda return type (#GH211811)
+- Fixed an assertion failure when a fixed point type was used in arithmetic with a `_BitInt` or overflow behavior type; the combination is now diagnosed as invalid operands. (#GH191701)
- Fixed USR generation for declarations whose signature mentions a class-type
non-type template parameter. (#GH212351)
- Fixed an assertion caused by Microsoft integer literals exceeding the maximum value. (#GH212504)
@@ -547,7 +548,6 @@ features cannot lower the translation-unit ABI level;
- Fixed a crash when an `asm` label names the register for a global variable of incomplete type. (#GH219746)
- Fixed an ICE hat occurred when using `__imag int/float` as lvalue in assignment. (#GH119498)
- Fixed an assertion failure in `-Wsign-compare` when a negated or complemented vector of unsigned integers was compared against a signed constant. (#GH203575)
-- Fixed an assertion failure when a fixed point type was used in arithmetic with a `_BitInt` or overflow behavior type; the combination is now diagnosed as invalid operands. (#GH191701)
#### Bug Fixes to Compiler Builtins
More information about the cfe-commits
mailing list