Author: Justin Stitt
Date: 2026-03-06T09:21:48-08:00
New Revision: 1fab5b65dc3f1616cbf58bb4696cf0dc5b8d522a

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

LOG: [Clang] Fix constexpr inc/dec operators for OverflowBehaviorTypes (#183826)

__ob_wrap types were not being handled properly by constexpr pre/post-inc/dec 
operations causing static_asserts() to fail unexpectedly. Fix those by checking 
if we're dealing with an OBT wrap type specifically.

Fixes: #183760

Added: 
    

Modified: 
    clang/lib/AST/ExprConstant.cpp
    clang/lib/Sema/SemaOverload.cpp
    clang/test/Sema/attr-overflow-behavior-constexpr.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index f233ff76632ae..43409fd2af82e 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -2627,8 +2627,11 @@ static bool EvaluateAsBooleanCondition(const Expr *E, 
bool &Result,
 template<typename T>
 static bool HandleOverflow(EvalInfo &Info, const Expr *E,
                            const T &SrcValue, QualType DestType) {
-  Info.CCEDiag(E, diag::note_constexpr_overflow)
-    << SrcValue << DestType;
+  Info.CCEDiag(E, diag::note_constexpr_overflow) << SrcValue << DestType;
+  if (const auto *OBT = DestType->getAs<OverflowBehaviorType>();
+      OBT && OBT->isTrapKind()) {
+    return false;
+  }
   return Info.noteUndefinedBehavior();
 }
 
@@ -5172,14 +5175,16 @@ struct IncDecSubobjectHandler {
     if (AccessKind == AK_Increment) {
       ++Value;
 
-      if (!WasNegative && Value.isNegative() && E->canOverflow()) {
+      if (!WasNegative && Value.isNegative() && E->canOverflow() &&
+          !SubobjType.isWrapType()) {
         APSInt ActualValue(Value, /*IsUnsigned*/true);
         return HandleOverflow(Info, E, ActualValue, SubobjType);
       }
     } else {
       --Value;
 
-      if (WasNegative && !Value.isNegative() && E->canOverflow()) {
+      if (WasNegative && !Value.isNegative() && E->canOverflow() &&
+          !SubobjType.isWrapType()) {
         unsigned BitWidth = Value.getBitWidth();
         APSInt ActualValue(Value.sext(BitWidth + 1), /*IsUnsigned*/false);
         ActualValue.setBit(BitWidth);

diff  --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index e5c4c59e9ffbb..6cada8eff0107 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -2942,6 +2942,8 @@ bool Sema::IsOverflowBehaviorTypeConversion(QualType 
FromType,
     return false;
 
   if (FromType->isOverflowBehaviorType() && !ToType->isOverflowBehaviorType()) 
{
+    if (ToType->isBooleanType())
+      return false;
     // Don't allow implicit conversion from OverflowBehaviorType to scoped enum
     if (const EnumType *ToEnumType = ToType->getAs<EnumType>()) {
       const EnumDecl *ToED = ToEnumType->getDecl()->getDefinitionOrSelf();

diff  --git a/clang/test/Sema/attr-overflow-behavior-constexpr.cpp 
b/clang/test/Sema/attr-overflow-behavior-constexpr.cpp
index ea5bc7fdb9fbe..1d81d3a243c1e 100644
--- a/clang/test/Sema/attr-overflow-behavior-constexpr.cpp
+++ b/clang/test/Sema/attr-overflow-behavior-constexpr.cpp
@@ -11,7 +11,17 @@ constexpr wrap_int add(wrap_int a, wrap_int b) {
 }
 
 constexpr no_trap_int sub(no_trap_int a, no_trap_int b) {
-  return a - b; // expected-note {{-2147483649 is outside the range of 
representable values}}
+  return a - b; // expected-note {{value -2147483649 is outside the range of 
representable values of type 'no_trap_int' (aka '__ob_trap int')}}
+}
+
+constexpr wrap_int preinc(wrap_int a) {
+  ++a;
+  return a;
+}
+
+constexpr wrap_int postinc(wrap_int a) {
+  a++;
+  return a;
 }
 
 void constexpr_test() {
@@ -22,6 +32,9 @@ void constexpr_test() {
   constexpr no_trap_int min = -2147483648;
   constexpr no_trap_int one_nw = 1;
   constexpr no_trap_int res = sub(min, one_nw); // expected-error {{constexpr 
variable 'res' must be initialized by a constant expression}} expected-note 
{{in call to 'sub(-2147483648, 1)'}}
+
+  static_assert(preinc(max) == -2147483648, "preinc wrapping failed");
+  static_assert(postinc(max) == -2147483648, "postinc wrapping failed");
 }
 
 template <typename T>


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

Reply via email to