From 4581f7497b41a90595a5a850c6a031b9cf60f50e Mon Sep 17 00:00:00 2001 From: Gabor Horvath Date: Mon, 30 Oct 2017 17:06:42 +0000 Subject: [PATCH] [analyzer] Left shifting a negative value is undefined The analyzer did not return an UndefVal in case a negative value was left shifted. I also altered the UndefResultChecker to emit a clear warning in this case. Differential Revision: https://reviews.llvm.org/D39423 llvm-svn: 316924 --- clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp | 4 ++++ clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp | 2 ++ clang/test/Analysis/bitwise-ops.c | 7 +++++++ 3 files changed, 13 insertions(+) diff --git a/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp index 21e8b10..172ce34 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp @@ -137,6 +137,10 @@ void UndefResultChecker::checkPostStmt(const BinaryOperator *B, OS << " greater or equal to the width of type '" << B->getLHS()->getType().getAsString() << "'."; + } else if (B->getOpcode() == BinaryOperatorKind::BO_Shl && + C.isNegative(B->getLHS())) { + OS << "The result of the left shift is undefined because the left " + "operand is negative"; } else { OS << "The result of the '" << BinaryOperator::getOpcodeStr(B->getOpcode()) diff --git a/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp b/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp index ebbace4..ec7a7e9 100644 --- a/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp +++ b/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp @@ -225,6 +225,8 @@ BasicValueFactory::evalAPSInt(BinaryOperator::Opcode Op, // test these conditions symbolically. // FIXME: Expand these checks to include all undefined behavior. + if (V1.isSigned() && V1.isNegative()) + return nullptr; if (V2.isSigned() && V2.isNegative()) return nullptr; diff --git a/clang/test/Analysis/bitwise-ops.c b/clang/test/Analysis/bitwise-ops.c index acef668..fe54658 100644 --- a/clang/test/Analysis/bitwise-ops.c +++ b/clang/test/Analysis/bitwise-ops.c @@ -44,3 +44,10 @@ int testNegativeShift(int a) { } return 0; } + +int testNegativeLeftShift(int a) { + if (a == -3) { + return a << 1; // expected-warning{{The result of the left shift is undefined because the left operand is negative}} + } + return 0; +} -- 2.7.4