r323115 - [analyzer] Model and check unrepresentable left shifts
Gabor Horvath via cfe-commits
cfe-commits at lists.llvm.org
Mon Jan 22 05:32:10 PST 2018
Author: xazax
Date: Mon Jan 22 05:32:10 2018
New Revision: 323115
URL: http://llvm.org/viewvc/llvm-project?rev=323115&view=rev
Log:
[analyzer] Model and check unrepresentable left shifts
Patch by: Reka Nikolett Kovacs
Differential Revision: https://reviews.llvm.org/D41816
Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
cfe/trunk/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
cfe/trunk/test/Analysis/bitwise-ops.c
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp?rev=323115&r1=323114&r2=323115&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp Mon Jan 22 05:32:10 2018
@@ -63,6 +63,15 @@ static bool isShiftOverflow(const Binary
B->getRHS(), C.getASTContext().getIntWidth(B->getLHS()->getType()));
}
+static bool isLeftShiftResultUnrepresentable(const BinaryOperator *B,
+ CheckerContext &C) {
+ SValBuilder &SB = C.getSValBuilder();
+ ProgramStateRef State = C.getState();
+ const llvm::APSInt *LHS = SB.getKnownValue(State, C.getSVal(B->getLHS()));
+ const llvm::APSInt *RHS = SB.getKnownValue(State, C.getSVal(B->getRHS()));
+ return (unsigned)RHS->getZExtValue() > LHS->countLeadingZeros();
+}
+
void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
CheckerContext &C) const {
if (C.getSVal(B).isUndef()) {
@@ -138,6 +147,19 @@ void UndefResultChecker::checkPostStmt(c
C.isNegative(B->getLHS())) {
OS << "The result of the left shift is undefined because the left "
"operand is negative";
+ } else if (B->getOpcode() == BinaryOperatorKind::BO_Shl &&
+ isLeftShiftResultUnrepresentable(B, C)) {
+ ProgramStateRef State = C.getState();
+ SValBuilder &SB = C.getSValBuilder();
+ const llvm::APSInt *LHS =
+ SB.getKnownValue(State, C.getSVal(B->getLHS()));
+ const llvm::APSInt *RHS =
+ SB.getKnownValue(State, C.getSVal(B->getRHS()));
+ OS << "The result of the left shift is undefined due to shifting \'"
+ << LHS->getSExtValue() << "\' by \'" << RHS->getZExtValue()
+ << "\', which is unrepresentable in the unsigned version of "
+ << "the return type \'" << B->getLHS()->getType().getAsString()
+ << "\'";
} else {
OS << "The result of the '"
<< BinaryOperator::getOpcodeStr(B->getOpcode())
Modified: cfe/trunk/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BasicValueFactory.cpp?rev=323115&r1=323114&r2=323115&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/BasicValueFactory.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/BasicValueFactory.cpp Mon Jan 22 05:32:10 2018
@@ -224,7 +224,6 @@ BasicValueFactory::evalAPSInt(BinaryOper
// FIXME: This logic should probably go higher up, where we can
// test these conditions symbolically.
- // FIXME: Expand these checks to include all undefined behavior.
if (V1.isSigned() && V1.isNegative())
return nullptr;
@@ -236,6 +235,9 @@ BasicValueFactory::evalAPSInt(BinaryOper
if (Amt >= V1.getBitWidth())
return nullptr;
+ if (V1.isSigned() && Amt > V1.countLeadingZeros())
+ return nullptr;
+
return &getValue( V1.operator<<( (unsigned) Amt ));
}
@@ -244,8 +246,6 @@ BasicValueFactory::evalAPSInt(BinaryOper
// FIXME: This logic should probably go higher up, where we can
// test these conditions symbolically.
- // FIXME: Expand these checks to include all undefined behavior.
-
if (V2.isSigned() && V2.isNegative())
return nullptr;
Modified: cfe/trunk/test/Analysis/bitwise-ops.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/bitwise-ops.c?rev=323115&r1=323114&r2=323115&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/bitwise-ops.c (original)
+++ cfe/trunk/test/Analysis/bitwise-ops.c Mon Jan 22 05:32:10 2018
@@ -51,3 +51,9 @@ int testNegativeLeftShift(int a) {
}
return 0;
}
+
+int testUnrepresentableLeftShift(int a) {
+ if (a == 8)
+ return a << 30; // expected-warning{{The result of the left shift is undefined due to shifting '8' by '30', which is unrepresentable in the unsigned version of the return type 'int'}}
+ return 0;
+}
More information about the cfe-commits
mailing list