diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -586,14 +586,6 @@ static std::pair geteagerlyAssumeBinOpBifurcationTags(); - SVal evalMinus(SVal X) { - return X.isValid() ? svalBuilder.evalMinus(X.castAs()) : X; - } - - SVal evalComplement(SVal X) { - return X.isValid() ? svalBuilder.evalComplement(X.castAs()) : X; - } - ProgramStateRef handleLValueBitCast(ProgramStateRef state, const Expr *Ex, const LocationContext *LCtx, QualType T, QualType ExTy, const CastExpr *CastE, diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h @@ -120,9 +120,8 @@ SVal evalIntegralCast(ProgramStateRef state, SVal val, QualType castTy, QualType originalType); - virtual SVal evalMinus(NonLoc val) = 0; - - virtual SVal evalComplement(NonLoc val) = 0; + SVal evalMinus(NonLoc val); + SVal evalComplement(NonLoc val); /// Create a new value which represents a binary expression with two non- /// location operands. diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -154,9 +154,6 @@ bool isZeroConstant() const; - /// hasConjuredSymbol - If this SVal wraps a conjured symbol, return true; - bool hasConjuredSymbol() const; - /// getAsFunctionDecl - If this SVal is a MemRegionVal and wraps a /// CodeTextRegion wrapping a FunctionDecl, return that FunctionDecl. /// Otherwise return 0. @@ -390,14 +387,6 @@ return *static_cast(Data); } - // Transfer functions for binary/unary operations on ConcreteInts. - SVal evalBinOp(SValBuilder &svalBuilder, BinaryOperator::Opcode Op, - const ConcreteInt& R) const; - - ConcreteInt evalComplement(SValBuilder &svalBuilder) const; - - ConcreteInt evalMinus(SValBuilder &svalBuilder) const; - private: friend class SVal; @@ -645,10 +634,6 @@ return *static_cast(Data); } - // Transfer functions for binary/unary operations on ConcreteInts. - SVal evalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op, - const ConcreteInt& R) const; - private: friend class SVal; diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp --- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -271,8 +271,9 @@ SVal OrigV = state->getSVal(Ex, LCtx); SVal V = svalBuilder.evalCast(OrigV, T, ExTy); // Negate the result if we're treating the boolean as a signed i1 - if (CastE->getCastKind() == CK_BooleanToSignedIntegral) - V = evalMinus(V); + if (CastE->getCastKind() == CK_BooleanToSignedIntegral && V.isValid()) + V = svalBuilder.evalMinus(V.castAs()); + state = state->BindExpr(CastE, LCtx, V); if (V.isUnknown() && !OrigV.isUnknown()) { state = escapeValues(state, OrigV, PSK_EscapeOther); @@ -1029,11 +1030,13 @@ llvm_unreachable("Invalid Opcode."); case UO_Not: // FIXME: Do we need to handle promotions? - state = state->BindExpr(U, LCtx, evalComplement(V.castAs())); + state = state->BindExpr( + U, LCtx, svalBuilder.evalComplement(V.castAs())); break; case UO_Minus: // FIXME: Do we need to handle promotions? - state = state->BindExpr(U, LCtx, evalMinus(V.castAs())); + state = state->BindExpr(U, LCtx, + svalBuilder.evalMinus(V.castAs())); break; case UO_LNot: // C99 6.5.3.3: "The expression !E is equivalent to (0==E)." diff --git a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp --- a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp +++ b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -434,6 +434,18 @@ return UnknownVal(); } +SVal SValBuilder::evalMinus(NonLoc V) { + if (auto C = V.getAs()) + return makeIntVal(-C->getValue()); + return UnknownVal(); +} + +SVal SValBuilder::evalComplement(NonLoc V) { + if (auto C = V.getAs()) + return makeIntVal(~C->getValue()); + return UnknownVal(); +} + SVal SValBuilder::evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, SVal lhs, SVal rhs, QualType type) { if (lhs.isUndef() || rhs.isUndef()) diff --git a/clang/lib/StaticAnalyzer/Core/SVals.cpp b/clang/lib/StaticAnalyzer/Core/SVals.cpp --- a/clang/lib/StaticAnalyzer/Core/SVals.cpp +++ b/clang/lib/StaticAnalyzer/Core/SVals.cpp @@ -43,25 +43,6 @@ // Utility methods. //===----------------------------------------------------------------------===// -bool SVal::hasConjuredSymbol() const { - if (Optional SV = getAs()) { - SymbolRef sym = SV->getSymbol(); - if (isa(sym)) - return true; - } - - if (Optional RV = getAs()) { - const MemRegion *R = RV->getRegion(); - if (const auto *SR = dyn_cast(R)) { - SymbolRef sym = SR->getSymbol(); - if (isa(sym)) - return true; - } - } - - return false; -} - const FunctionDecl *SVal::getAsFunctionDecl() const { if (Optional X = getAs()) { const MemRegion* R = X->getRegion(); @@ -196,8 +177,7 @@ } const MemRegion *loc::MemRegionVal::stripCasts(bool StripBaseCasts) const { - const MemRegion *R = getRegion(); - return R ? R->StripCasts(StripBaseCasts) : nullptr; + return getRegion()->StripCasts(StripBaseCasts); } const void *nonloc::LazyCompoundVal::getStore() const { @@ -272,49 +252,6 @@ return isConstant(0); } -//===----------------------------------------------------------------------===// -// Transfer function dispatch for Non-Locs. -//===----------------------------------------------------------------------===// - -SVal nonloc::ConcreteInt::evalBinOp(SValBuilder &svalBuilder, - BinaryOperator::Opcode Op, - const nonloc::ConcreteInt& R) const { - const llvm::APSInt* X = - svalBuilder.getBasicValueFactory().evalAPSInt(Op, getValue(), R.getValue()); - - if (X) - return nonloc::ConcreteInt(*X); - else - return UndefinedVal(); -} - -nonloc::ConcreteInt -nonloc::ConcreteInt::evalComplement(SValBuilder &svalBuilder) const { - return svalBuilder.makeIntVal(~getValue()); -} - -nonloc::ConcreteInt -nonloc::ConcreteInt::evalMinus(SValBuilder &svalBuilder) const { - return svalBuilder.makeIntVal(-getValue()); -} - -//===----------------------------------------------------------------------===// -// Transfer function dispatch for Locs. -//===----------------------------------------------------------------------===// - -SVal loc::ConcreteInt::evalBinOp(BasicValueFactory& BasicVals, - BinaryOperator::Opcode Op, - const loc::ConcreteInt& R) const { - assert(BinaryOperator::isComparisonOp(Op) || Op == BO_Sub); - - const llvm::APSInt *X = BasicVals.evalAPSInt(Op, getValue(), R.getValue()); - - if (X) - return nonloc::ConcreteInt(*X); - else - return UndefinedVal(); -} - //===----------------------------------------------------------------------===// // Pretty-Printing. //===----------------------------------------------------------------------===// diff --git a/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp --- a/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp +++ b/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp @@ -56,8 +56,6 @@ : SValBuilder(alloc, context, stateMgr) {} ~SimpleSValBuilder() override {} - SVal evalMinus(NonLoc val) override; - SVal evalComplement(NonLoc val) override; SVal evalBinOpNN(ProgramStateRef state, BinaryOperator::Opcode op, NonLoc lhs, NonLoc rhs, QualType resultTy) override; SVal evalBinOpLL(ProgramStateRef state, BinaryOperator::Opcode op, @@ -82,28 +80,6 @@ return new SimpleSValBuilder(alloc, context, stateMgr); } -//===----------------------------------------------------------------------===// -// Transfer function for unary operators. -//===----------------------------------------------------------------------===// - -SVal SimpleSValBuilder::evalMinus(NonLoc val) { - switch (val.getSubKind()) { - case nonloc::ConcreteIntKind: - return val.castAs().evalMinus(*this); - default: - return UnknownVal(); - } -} - -SVal SimpleSValBuilder::evalComplement(NonLoc X) { - switch (X.getSubKind()) { - case nonloc::ConcreteIntKind: - return X.castAs().evalComplement(*this); - default: - return UnknownVal(); - } -} - // Checks if the negation the value and flipping sign preserve // the semantics on the operation in the resultType static bool isNegationValuePreserving(const llvm::APSInt &Value, @@ -845,6 +821,8 @@ return UnknownVal(); case loc::ConcreteIntKind: { + auto L = lhs.castAs(); + // If one of the operands is a symbol and the other is a constant, // build an expression for use by the constraint manager. if (SymbolRef rSym = rhs.getAsLocSymbol()) { @@ -853,19 +831,17 @@ if (!BinaryOperator::isComparisonOp(op) || op == BO_Cmp) return UnknownVal(); - const llvm::APSInt &lVal = lhs.castAs().getValue(); op = BinaryOperator::reverseComparisonOp(op); - return makeNonLoc(rSym, op, lVal, resultTy); + return makeNonLoc(rSym, op, L.getValue(), resultTy); } // If both operands are constants, just perform the operation. if (Optional rInt = rhs.getAs()) { - SVal ResultVal = - lhs.castAs().evalBinOp(BasicVals, op, *rInt); - if (Optional Result = ResultVal.getAs()) - return evalCast(*Result, resultTy, QualType{}); + assert(BinaryOperator::isComparisonOp(op) || op == BO_Sub); - assert(!ResultVal.getAs() && "Loc-Loc ops should not produce Locs"); + if (const auto *ResultInt = + BasicVals.evalAPSInt(op, L.getValue(), rInt->getValue())) + return evalCast(nonloc::ConcreteInt(*ResultInt), resultTy, QualType{}); return UnknownVal(); }