danielmarjamaki updated this revision to Diff 98970.
danielmarjamaki added a comment.
minor tweak
Repository:
rL LLVM
https://reviews.llvm.org/D30295
Files:
include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h
lib/StaticAnalyzer/Checkers/ConversionChecker.cpp
lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
lib/StaticAnalyzer/Core/CheckerHelpers.cpp
test/Analysis/bitwise-ops.c
Index: test/Analysis/bitwise-ops.c
===================================================================
--- test/Analysis/bitwise-ops.c
+++ test/Analysis/bitwise-ops.c
@@ -29,4 +29,18 @@
default:
return 0;
}
-}
\ No newline at end of file
+}
+
+int testOverflowShift(int a) {
+ if (a == 323) {
+ return 1 << a; // expected-warning{{The result of the '<<' expression is undefined due to shift count >= width of type}}
+ }
+ return 0;
+}
+
+int testNegativeShift(int a) {
+ if (a == -5) {
+ return 1 << a; // expected-warning{{The result of the '<<' expression is undefined due to negative value on the right side of operand}}
+ }
+ return 0;
+}
Index: lib/StaticAnalyzer/Core/CheckerHelpers.cpp
===================================================================
--- lib/StaticAnalyzer/Core/CheckerHelpers.cpp
+++ lib/StaticAnalyzer/Core/CheckerHelpers.cpp
@@ -94,3 +94,40 @@
return std::make_pair(VD, RHS);
}
+
+bool clang::ento::exprComparesTo(SVal LHSVal, BinaryOperatorKind ComparisonOp,
+ SVal RHSVal, ProgramStateRef State) {
+
+ if (LHSVal.isUnknownOrUndef())
+ return false;
+ ProgramStateManager &Mgr = State->getStateManager();
+ if (!LHSVal.getAs<NonLoc>() && LHSVal.getAs<Loc>()) {
+ LHSVal = Mgr.getStoreManager().getBinding(State->getStore(),
+ LHSVal.castAs<Loc>());
+ }
+ if (LHSVal.isUnknownOrUndef() || !LHSVal.getAs<NonLoc>())
+ return false;
+
+ SValBuilder &Bldr = Mgr.getSValBuilder();
+ SVal Eval = Bldr.evalBinOp(State, ComparisonOp, LHSVal, RHSVal,
+ Bldr.getConditionType());
+ if (Eval.isUnknownOrUndef())
+ return false;
+ ProgramStateRef StTrue, StFalse;
+ std::tie(StTrue, StFalse) = State->assume(Eval.castAs<DefinedSVal>());
+ return StTrue && !StFalse;
+}
+
+// Is E value greater or equal than Val?
+bool clang::ento::isGreaterOrEqual(const Expr *E, unsigned long long Val,
+ CheckerContext &C) {
+ DefinedSVal V =
+ C.getSValBuilder().makeIntVal(Val, C.getASTContext().LongLongTy);
+ return exprComparesTo(C.getSVal(E), BO_GE, V, C.getState());
+}
+
+// Is E value negative?
+bool clang::ento::isNegative(const Expr *E, CheckerContext &C) {
+ DefinedSVal V = C.getSValBuilder().makeIntVal(0, false);
+ return exprComparesTo(C.getSVal(E), BO_LT, V, C.getState());
+}
Index: lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
+++ lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
@@ -17,6 +17,7 @@
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/raw_ostream.h"
@@ -59,6 +60,11 @@
return StOutBound && !StInBound;
}
+static bool isShiftOverflow(const BinaryOperator *B, CheckerContext &C) {
+ return isGreaterOrEqual(
+ B->getRHS(), C.getASTContext().getIntWidth(B->getLHS()->getType()), C);
+}
+
void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
CheckerContext &C) const {
ProgramStateRef state = C.getState();
@@ -106,9 +112,24 @@
}
else {
// Neither operand was undefined, but the result is undefined.
- OS << "The result of the '"
- << BinaryOperator::getOpcodeStr(B->getOpcode())
- << "' expression is undefined";
+ if ((B->getOpcode() == BinaryOperatorKind::BO_Shl ||
+ B->getOpcode() == BinaryOperatorKind::BO_Shr) &&
+ isNegative(B->getRHS(), C)) {
+ OS << "The result of the '"
+ << BinaryOperator::getOpcodeStr(B->getOpcode())
+ << "' expression is undefined due to negative value on the right "
+ "side of operand";
+ } else if ((B->getOpcode() == BinaryOperatorKind::BO_Shl ||
+ B->getOpcode() == BinaryOperatorKind::BO_Shr) &&
+ isShiftOverflow(B, C)) {
+ OS << "The result of the '"
+ << BinaryOperator::getOpcodeStr(B->getOpcode())
+ << "' expression is undefined due to shift count >= width of type";
+ } else {
+ OS << "The result of the '"
+ << BinaryOperator::getOpcodeStr(B->getOpcode())
+ << "' expression is undefined";
+ }
}
auto report = llvm::make_unique<BugReport>(*BT, OS.str(), N);
if (Ex) {
Index: lib/StaticAnalyzer/Checkers/ConversionChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/ConversionChecker.cpp
+++ lib/StaticAnalyzer/Checkers/ConversionChecker.cpp
@@ -28,6 +28,7 @@
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
using namespace clang;
using namespace ento;
@@ -123,57 +124,6 @@
C.emitReport(std::move(R));
}
-// Is E value greater or equal than Val?
-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;
-
- SValBuilder &Bldr = C.getSValBuilder();
- DefinedSVal V = Bldr.makeIntVal(Val, C.getASTContext().LongLongTy);
-
- // Is DefinedEVal greater or equal with V?
- SVal GE = Bldr.evalBinOp(State, BO_GE, EVal, V, Bldr.getConditionType());
- if (GE.isUnknownOrUndef())
- return false;
- ConstraintManager &CM = C.getConstraintManager();
- ProgramStateRef StGE, StLT;
- std::tie(StGE, StLT) = CM.assumeDual(State, GE.castAs<DefinedSVal>());
- return StGE && !StLT;
-}
-
-// Is E value negative?
-static bool isNegative(CheckerContext &C, const Expr *E) {
- ProgramStateRef State = C.getState();
- SVal EVal = State->getSVal(E, C.getLocationContext());
- if (EVal.isUnknownOrUndef() || !EVal.getAs<NonLoc>())
- return false;
- DefinedSVal DefinedEVal = EVal.castAs<DefinedSVal>();
-
- SValBuilder &Bldr = C.getSValBuilder();
- DefinedSVal V = Bldr.makeIntVal(0, false);
-
- SVal LT =
- Bldr.evalBinOp(State, BO_LT, DefinedEVal, V, Bldr.getConditionType());
-
- // Is E value greater than MaxVal?
- ConstraintManager &CM = C.getConstraintManager();
- ProgramStateRef StNegative, StPositive;
- std::tie(StNegative, StPositive) =
- CM.assumeDual(State, LT.castAs<DefinedSVal>());
-
- return StNegative && !StPositive;
-}
-
bool ConversionChecker::isLossOfPrecision(const ImplicitCastExpr *Cast,
QualType DestType,
CheckerContext &C) const {
@@ -195,7 +145,7 @@
return false;
unsigned long long MaxVal = 1ULL << W;
- return isGreaterEqual(C, Cast->getSubExpr(), MaxVal);
+ return isGreaterOrEqual(Cast->getSubExpr(), MaxVal, C);
}
bool ConversionChecker::isLossOfSign(const ImplicitCastExpr *Cast,
@@ -206,7 +156,7 @@
if (!CastType->isUnsignedIntegerType() || !SubType->isSignedIntegerType())
return false;
- return isNegative(C, Cast->getSubExpr());
+ return isNegative(Cast->getSubExpr(), C);
}
void ento::registerConversionChecker(CheckerManager &mgr) {
Index: include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h
===================================================================
--- include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h
+++ include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h
@@ -15,6 +15,7 @@
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CHECKERHELPERS_H
#include "clang/AST/Stmt.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include <tuple>
namespace clang {
@@ -42,6 +43,11 @@
std::pair<const clang::VarDecl *, const clang::Expr *>
parseAssignment(const Stmt *S);
+bool exprComparesTo(SVal LHSVal, BinaryOperatorKind ComparisonOp, SVal RHSVal,
+ ProgramStateRef State);
+bool isGreaterOrEqual(const Expr *E, unsigned long long Val, CheckerContext &C);
+bool isNegative(const Expr *E, CheckerContext &C);
+
} // end GR namespace
} // end clang namespace
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits