[clang] [sema] Improve -Wsign-compare (PR #65684)

Aaron Ballman via cfe-commits cfe-commits at lists.llvm.org
Fri Oct 6 10:44:55 PDT 2023


=?utf-8?q?FĂ©lix?= Cloutier <fcloutier at apple.com>
Message-ID:
In-Reply-To: <llvm/llvm-project/pull/65684/clang at github.com>


================
@@ -14160,10 +14193,58 @@ static void AnalyzeComparison(Sema &S, BinaryOperator *E) {
       return;
   }
 
-  S.DiagRuntimeBehavior(E->getOperatorLoc(), E,
-                        S.PDiag(diag::warn_mixed_sign_comparison)
-                            << LHS->getType() << RHS->getType()
-                            << LHS->getSourceRange() << RHS->getSourceRange());
+  // For `S < U`, propose something like `S < 0 || (typeof(U))S < U`.
+  // The whole operation needs to have no side effects, since the signed
+  // operand will be duplicated, and the unsigned operand might not execute
+  // anymore.
+  auto MixedSignDiag = S.PDiag(diag::warn_mixed_sign_comparison)
+                       << (signedOperand == RHS) << signedOperand->getType()
+                       << T << signedOperand->getSourceRange();
+  if (!E->HasSideEffects(S.Context)) {
+    bool ParenthesizeCheck =
+        !TopLevelExpr || E != TopLevelExpr->IgnoreImplicit();
+    std::string Prefix;
+    llvm::raw_string_ostream PrefixS(Prefix);
+    if (ParenthesizeCheck)
+      PrefixS << '(';
+    auto TokRange =
+        CharSourceRange::getTokenRange(signedOperand->getSourceRange());
+    bool Invalid;
+    PrefixS << Lexer::getSourceText(TokRange, S.SourceMgr, S.getLangOpts(),
+                                    &Invalid);
+    if (!Invalid) {
+      bool ParenthesizeForCast = S.getLangOpts().CPlusPlus ||
+                                 isa<BinaryOperator>(signedOperand) ||
+                                 isa<ConditionalOperator>(signedOperand);
+      bool IsSignedLHS = signedOperand == LHS;
+      bool IsLTOrLE = E->getOpcode() == BO_LT || E->getOpcode() == BO_LE;
+      bool IsGTOrGE = E->getOpcode() == BO_GT || E->getOpcode() == BO_GE;
+      if ((IsSignedLHS && IsLTOrLE) || (!IsSignedLHS && IsGTOrGE)) {
+        PrefixS << " < 0 || ";
+      } else {
+        PrefixS << " >= 0 && ";
+      }
+      if (S.getLangOpts().CPlusPlus)
+        PrefixS << "static_cast<" << T.getAsString(S.getLangOpts()) << ">";
+      else
+        PrefixS << "(" << T.getAsString(S.getLangOpts()) << ")";
+      if (ParenthesizeForCast)
+        PrefixS << "(";
+      PrefixS.flush();
----------------
AaronBallman wrote:

```suggestion
```
No need to call flush according to the API's documentation.

https://github.com/llvm/llvm-project/pull/65684


More information about the cfe-commits mailing list