diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp | 87 |
1 files changed, 8 insertions, 79 deletions
diff --git a/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp b/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp index 392da4818098..4b845bb3ded2 100644 --- a/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp +++ b/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp @@ -16,7 +16,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/DynamicSize.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/raw_ostream.h" @@ -28,7 +28,7 @@ namespace { class UndefResultChecker : public Checker< check::PostStmt<BinaryOperator> > { - mutable std::unique_ptr<BugType> BT; + const BugType BT{this, "Result of operation is garbage or undefined"}; public: void checkPostStmt(const BinaryOperator *B, CheckerContext &C) const; @@ -53,33 +53,17 @@ static bool isArrayIndexOutOfBounds(CheckerContext &C, const Expr *Ex) { DefinedOrUnknownSVal Idx = ER->getIndex().castAs<DefinedOrUnknownSVal>(); DefinedOrUnknownSVal ElementCount = getDynamicElementCount( state, ER->getSuperRegion(), C.getSValBuilder(), ER->getValueType()); - ProgramStateRef StInBound = state->assumeInBound(Idx, ElementCount, true); - ProgramStateRef StOutBound = state->assumeInBound(Idx, ElementCount, false); + ProgramStateRef StInBound, StOutBound; + std::tie(StInBound, StOutBound) = state->assumeInBoundDual(Idx, ElementCount); return StOutBound && !StInBound; } -static bool isShiftOverflow(const BinaryOperator *B, CheckerContext &C) { - return C.isGreaterOrEqual( - 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())); - assert(LHS && RHS && "Values unknown, inconsistent state"); - return (unsigned)RHS->getZExtValue() > LHS->countLeadingZeros(); -} - void UndefResultChecker::checkPostStmt(const BinaryOperator *B, CheckerContext &C) const { if (C.getSVal(B).isUndef()) { // Do not report assignments of uninitialized values inside swap functions. // This should allow to swap partially uninitialized structs - // (radar://14129997) if (const FunctionDecl *EnclosingFunctionDecl = dyn_cast<FunctionDecl>(C.getStackFrame()->getDecl())) if (C.getCalleeName(EnclosingFunctionDecl) == "swap") @@ -90,10 +74,6 @@ void UndefResultChecker::checkPostStmt(const BinaryOperator *B, if (!N) return; - if (!BT) - BT.reset( - new BuiltinBug(this, "Result of operation is garbage or undefined")); - SmallString<256> sbuf; llvm::raw_svector_ostream OS(sbuf); const Expr *Ex = nullptr; @@ -116,62 +96,11 @@ void UndefResultChecker::checkPostStmt(const BinaryOperator *B, OS << " due to array index out of bounds"; } else { // Neither operand was undefined, but the result is undefined. - if ((B->getOpcode() == BinaryOperatorKind::BO_Shl || - B->getOpcode() == BinaryOperatorKind::BO_Shr) && - C.isNegative(B->getRHS())) { - OS << "The result of the " - << ((B->getOpcode() == BinaryOperatorKind::BO_Shl) ? "left" - : "right") - << " shift is undefined because the right operand is negative"; - Ex = B->getRHS(); - } else if ((B->getOpcode() == BinaryOperatorKind::BO_Shl || - B->getOpcode() == BinaryOperatorKind::BO_Shr) && - isShiftOverflow(B, C)) { - - OS << "The result of the " - << ((B->getOpcode() == BinaryOperatorKind::BO_Shl) ? "left" - : "right") - << " shift is undefined due to shifting by "; - Ex = B->getRHS(); - - SValBuilder &SB = C.getSValBuilder(); - const llvm::APSInt *I = - SB.getKnownValue(C.getState(), C.getSVal(B->getRHS())); - if (!I) - OS << "a value that is"; - else if (I->isUnsigned()) - OS << '\'' << I->getZExtValue() << "\', which is"; - else - OS << '\'' << I->getSExtValue() << "\', which is"; - - 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"; - Ex = B->getLHS(); - } 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() - << "\'"; - Ex = B->getLHS(); - } else { - OS << "The result of the '" - << BinaryOperator::getOpcodeStr(B->getOpcode()) - << "' expression is undefined"; - } + OS << "The result of the '" + << BinaryOperator::getOpcodeStr(B->getOpcode()) + << "' expression is undefined"; } - auto report = std::make_unique<PathSensitiveBugReport>(*BT, OS.str(), N); + auto report = std::make_unique<PathSensitiveBugReport>(BT, OS.str(), N); if (Ex) { report->addRange(Ex->getSourceRange()); bugreporter::trackExpressionValue(N, Ex, *report); |