summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer
diff options
context:
space:
mode:
authorDaniel Marjamaki <daniel.marjamaki@evidente.se>2017-04-05 08:57:04 +0000
committerDaniel Marjamaki <daniel.marjamaki@evidente.se>2017-04-05 08:57:04 +0000
commit2641a52ee4e2fab1a3643e87e0ffc75dc5878966 (patch)
tree9e3b24a445a9e517ffc74b6b47d5bf10d29b50ee /clang/lib/StaticAnalyzer
parentbe55c60d94f1c1fc4a969a2f40a95cbf21e8eaca (diff)
downloadbcm5719-llvm-2641a52ee4e2fab1a3643e87e0ffc75dc5878966.tar.gz
bcm5719-llvm-2641a52ee4e2fab1a3643e87e0ffc75dc5878966.zip
[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 llvm-svn: 299523
Diffstat (limited to 'clang/lib/StaticAnalyzer')
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp42
1 files changed, 32 insertions, 10 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp
index 2bb9e858731..ea894c81011 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp
@@ -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(const ImplicitCastExpr *Cast,
// 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(CheckerContext &C, const Expr *E,
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, const Expr *E) {
}
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;
OpenPOWER on IntegriCloud