AshleyRoll created this revision.
AshleyRoll added a reviewer: rsmith.
Herald added a project: All.
AshleyRoll requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

I have modifyed GetExprRange() to capture the promotion
of boolean values to ints when applying unary not to ensure
-Wsign-compare identifies unsigned/signed comparisons as
identified in:

https://github.com/llvm/llvm-project/issues/18878


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D126960

Files:
  clang/lib/Sema/SemaChecking.cpp
  clang/test/Sema/compare.c


Index: clang/test/Sema/compare.c
===================================================================
--- clang/test/Sema/compare.c
+++ clang/test/Sema/compare.c
@@ -419,3 +419,25 @@
   if (x == y) x = y; // no warning
   if (y == x) y = x; // no warning
 }
+
+int warn_on_different_sign_after_unary_operator(unsigned a, int b) {
+  return
+      // unary not promotes boolean to int
+      (a > ~(!b)) // expected-warning {{comparison of integers of different 
signs: 'unsigned int' and 'int'}}
+      &&
+      (a > -(b)) // expected-warning {{comparison of integers of different 
signs: 'unsigned int' and 'int'}}
+      &&
+      (a > ++b) // expected-warning {{comparison of integers of different 
signs: 'unsigned int' and 'int'}}
+      &&
+      (a > --b) // expected-warning {{comparison of integers of different 
signs: 'unsigned int' and 'int'}}
+      &&
+      // unary not promotes boolean to int
+      (b > ~(!a)) // no warning
+      &&
+      (b > -(a)) // expected-warning {{comparison of integers of different 
signs: 'int' and 'unsigned int'}}
+      &&
+      (b > ++a) // expected-warning {{comparison of integers of different 
signs: 'int' and 'unsigned int'}}
+      &&
+      (b > --a) // expected-warning {{comparison of integers of different 
signs: 'int' and 'unsigned int'}}
+      ;
+}
Index: clang/lib/Sema/SemaChecking.cpp
===================================================================
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -12326,6 +12326,13 @@
     case UO_AddrOf: // should be impossible
       return IntRange::forValueOfType(C, GetExprType(E));
 
+    case UO_Not:
+      // unary not promotes boolean to integer
+      if (UO->getSubExpr()->isKnownToHaveBooleanValue())
+        return IntRange(MaxWidth, false);
+
+      LLVM_FALLTHROUGH;
+
     default:
       return GetExprRange(C, UO->getSubExpr(), MaxWidth, InConstantContext,
                           Approximate);


Index: clang/test/Sema/compare.c
===================================================================
--- clang/test/Sema/compare.c
+++ clang/test/Sema/compare.c
@@ -419,3 +419,25 @@
   if (x == y) x = y; // no warning
   if (y == x) y = x; // no warning
 }
+
+int warn_on_different_sign_after_unary_operator(unsigned a, int b) {
+  return
+      // unary not promotes boolean to int
+      (a > ~(!b)) // expected-warning {{comparison of integers of different signs: 'unsigned int' and 'int'}}
+      &&
+      (a > -(b)) // expected-warning {{comparison of integers of different signs: 'unsigned int' and 'int'}}
+      &&
+      (a > ++b) // expected-warning {{comparison of integers of different signs: 'unsigned int' and 'int'}}
+      &&
+      (a > --b) // expected-warning {{comparison of integers of different signs: 'unsigned int' and 'int'}}
+      &&
+      // unary not promotes boolean to int
+      (b > ~(!a)) // no warning
+      &&
+      (b > -(a)) // expected-warning {{comparison of integers of different signs: 'int' and 'unsigned int'}}
+      &&
+      (b > ++a) // expected-warning {{comparison of integers of different signs: 'int' and 'unsigned int'}}
+      &&
+      (b > --a) // expected-warning {{comparison of integers of different signs: 'int' and 'unsigned int'}}
+      ;
+}
Index: clang/lib/Sema/SemaChecking.cpp
===================================================================
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -12326,6 +12326,13 @@
     case UO_AddrOf: // should be impossible
       return IntRange::forValueOfType(C, GetExprType(E));
 
+    case UO_Not:
+      // unary not promotes boolean to integer
+      if (UO->getSubExpr()->isKnownToHaveBooleanValue())
+        return IntRange(MaxWidth, false);
+
+      LLVM_FALLTHROUGH;
+
     default:
       return GetExprRange(C, UO->getSubExpr(), MaxWidth, InConstantContext,
                           Approximate);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D126960: ... Ashley Roll via Phabricator via cfe-commits

Reply via email to