r299523 - [analyzer] alpha.core.Conversion - Fix false positive for 'U32 += S16; ' expression, that is not unsafe

Daniel Marjamaki via cfe-commits cfe-commits at lists.llvm.org
Wed Apr 5 01:57:04 PDT 2017


Author: danielmarjamaki
Date: Wed Apr  5 03:57:04 2017
New Revision: 299523

URL: http://llvm.org/viewvc/llvm-project?rev=299523&view=rev
Log:
[analyzer] alpha.core.Conversion - Fix false positive for 'U32 += S16;' expression, that is not unsafe

Summary:
The alpha.core.Conversion was too strict about compound assignments and could warn even though there is no problem.

Differential Revision: https://reviews.llvm.org/D25596


Modified:
    cfe/trunk/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp
    cfe/trunk/test/Analysis/conversion.c

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp?rev=299523&r1=299522&r2=299523&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp Wed Apr  5 03:57:04 2017
@@ -41,7 +41,8 @@ private:
   mutable std::unique_ptr<BuiltinBug> BT;
 
   // Is there loss of precision
-  bool isLossOfPrecision(const ImplicitCastExpr *Cast, CheckerContext &C) const;
+  bool isLossOfPrecision(const ImplicitCastExpr *Cast, QualType DestType,
+                         CheckerContext &C) const;
 
   // Is there loss of sign
   bool isLossOfSign(const ImplicitCastExpr *Cast, CheckerContext &C) const;
@@ -73,16 +74,30 @@ void ConversionChecker::checkPreStmt(con
   // Loss of sign/precision in binary operation.
   if (const auto *B = dyn_cast<BinaryOperator>(Parent)) {
     BinaryOperator::Opcode Opc = B->getOpcode();
-    if (Opc == BO_Assign || Opc == BO_AddAssign || Opc == BO_SubAssign ||
-        Opc == BO_MulAssign) {
+    if (Opc == BO_Assign) {
       LossOfSign = isLossOfSign(Cast, C);
-      LossOfPrecision = isLossOfPrecision(Cast, C);
+      LossOfPrecision = isLossOfPrecision(Cast, Cast->getType(), C);
+    } else if (Opc == BO_AddAssign || Opc == BO_SubAssign) {
+      // No loss of sign.
+      LossOfPrecision = isLossOfPrecision(Cast, B->getLHS()->getType(), C);
+    } else if (Opc == BO_MulAssign) {
+      LossOfSign = isLossOfSign(Cast, C);
+      LossOfPrecision = isLossOfPrecision(Cast, B->getLHS()->getType(), C);
+    } else if (Opc == BO_DivAssign || Opc == BO_RemAssign) {
+      LossOfSign = isLossOfSign(Cast, C);
+      // No loss of precision.
+    } else if (Opc == BO_AndAssign) {
+      LossOfSign = isLossOfSign(Cast, C);
+      // No loss of precision.
+    } else if (Opc == BO_OrAssign || Opc == BO_XorAssign) {
+      LossOfSign = isLossOfSign(Cast, C);
+      LossOfPrecision = isLossOfPrecision(Cast, B->getLHS()->getType(), C);
     } else if (B->isRelationalOp() || B->isMultiplicativeOp()) {
       LossOfSign = isLossOfSign(Cast, C);
     }
   } else if (isa<DeclStmt>(Parent)) {
     LossOfSign = isLossOfSign(Cast, C);
-    LossOfPrecision = isLossOfPrecision(Cast, C);
+    LossOfPrecision = isLossOfPrecision(Cast, Cast->getType(), C);
   }
 
   if (LossOfSign || LossOfPrecision) {
@@ -113,6 +128,13 @@ static bool isGreaterEqual(CheckerContex
                            unsigned long long Val) {
   ProgramStateRef State = C.getState();
   SVal EVal = C.getSVal(E);
+  if (EVal.isUnknownOrUndef())
+    return false;
+  if (!EVal.getAs<NonLoc>() && EVal.getAs<Loc>()) {
+    ProgramStateManager &Mgr = C.getStateManager();
+    EVal =
+        Mgr.getStoreManager().getBinding(State->getStore(), EVal.castAs<Loc>());
+  }
   if (EVal.isUnknownOrUndef() || !EVal.getAs<NonLoc>())
     return false;
 
@@ -153,22 +175,22 @@ static bool isNegative(CheckerContext &C
 }
 
 bool ConversionChecker::isLossOfPrecision(const ImplicitCastExpr *Cast,
-                                        CheckerContext &C) const {
+                                          QualType DestType,
+                                          CheckerContext &C) const {
   // Don't warn about explicit loss of precision.
   if (Cast->isEvaluatable(C.getASTContext()))
     return false;
 
-  QualType CastType = Cast->getType();
   QualType SubType = Cast->IgnoreParenImpCasts()->getType();
 
-  if (!CastType->isIntegerType() || !SubType->isIntegerType())
+  if (!DestType->isIntegerType() || !SubType->isIntegerType())
     return false;
 
-  if (C.getASTContext().getIntWidth(CastType) >=
+  if (C.getASTContext().getIntWidth(DestType) >=
       C.getASTContext().getIntWidth(SubType))
     return false;
 
-  unsigned W = C.getASTContext().getIntWidth(CastType);
+  unsigned W = C.getASTContext().getIntWidth(DestType);
   if (W == 1 || W >= 64U)
     return false;
 

Modified: cfe/trunk/test/Analysis/conversion.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/conversion.c?rev=299523&r1=299522&r2=299523&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/conversion.c (original)
+++ cfe/trunk/test/Analysis/conversion.c Wed Apr  5 03:57:04 2017
@@ -9,9 +9,67 @@ void assign(unsigned U, signed S) {
   if (U > 300)
     S8 = U; // expected-warning {{Loss of precision in implicit conversion}}
   if (S > 10)
-    U8 = S;
+    U8 = S; // no-warning
   if (U < 200)
-    S8 = U;
+    S8 = U; // no-warning
+}
+
+void addAssign() {
+  unsigned long L = 1000;
+  int I = -100;
+  U8 += L; // expected-warning {{Loss of precision in implicit conversion}}
+  L += I; // no-warning
+}
+
+void subAssign() {
+  unsigned long L = 1000;
+  int I = -100;
+  U8 -= L; // expected-warning {{Loss of precision in implicit conversion}}
+  L -= I; // no-warning
+}
+
+void mulAssign() {
+  unsigned long L = 1000;
+  int I = -1;
+  U8 *= L; // expected-warning {{Loss of precision in implicit conversion}}
+  L *= I;  // expected-warning {{Loss of sign in implicit conversion}}
+  I = 10;
+  L *= I; // no-warning
+}
+
+void divAssign() {
+  unsigned long L = 1000;
+  int I = -1;
+  U8 /= L; // no-warning
+  L /= I; // expected-warning {{Loss of sign in implicit conversion}}
+}
+
+void remAssign() {
+  unsigned long L = 1000;
+  int I = -1;
+  U8 %= L; // no-warning
+  L %= I; // expected-warning {{Loss of sign in implicit conversion}}
+}
+
+void andAssign() {
+  unsigned long L = 1000;
+  int I = -1;
+  U8 &= L; // no-warning
+  L &= I; // expected-warning {{Loss of sign in implicit conversion}}
+}
+
+void orAssign() {
+  unsigned long L = 1000;
+  int I = -1;
+  U8 |= L; // expected-warning {{Loss of precision in implicit conversion}}
+  L |= I;  // expected-warning {{Loss of sign in implicit conversion}}
+}
+
+void xorAssign() {
+  unsigned long L = 1000;
+  int I = -1;
+  U8 ^= L; // expected-warning {{Loss of precision in implicit conversion}}
+  L ^= I;  // expected-warning {{Loss of sign in implicit conversion}}
 }
 
 void init1() {
@@ -21,7 +79,7 @@ void init1() {
 
 void relational(unsigned U, signed S) {
   if (S > 10) {
-    if (U < S) {
+    if (U < S) { // no-warning
     }
   }
   if (S < -10) {
@@ -32,14 +90,14 @@ void relational(unsigned U, signed S) {
 
 void multiplication(unsigned U, signed S) {
   if (S > 5)
-    S = U * S;
+    S = U * S; // no-warning
   if (S < -10)
     S = U * S; // expected-warning {{Loss of sign}}
 }
 
 void division(unsigned U, signed S) {
   if (S > 5)
-    S = U / S;
+    S = U / S; // no-warning
   if (S < -10)
     S = U / S; // expected-warning {{Loss of sign}}
 }




More information about the cfe-commits mailing list