//== SimpleConstraintManager.cpp --------------------------------*- C++ -*--==// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file defines SimpleConstraintManager, a class that provides a // simplified constraint manager interface, compared to ConstraintManager. // //===----------------------------------------------------------------------===// #include "clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" namespace clang { namespace ento { SimpleConstraintManager::~SimpleConstraintManager() {} ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef State, DefinedSVal Cond, bool Assumption) { // If we have a Loc value, cast it to a bool NonLoc first. if (Optional LV = Cond.getAs()) { SValBuilder &SVB = State->getStateManager().getSValBuilder(); QualType T; const MemRegion *MR = LV->getAsRegion(); if (const TypedRegion *TR = dyn_cast_or_null(MR)) T = TR->getLocationType(); else T = SVB.getContext().VoidPtrTy; Cond = SVB.evalCast(*LV, SVB.getContext().BoolTy, T).castAs(); } return assume(State, Cond.castAs(), Assumption); } ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef State, NonLoc Cond, bool Assumption) { State = assumeAux(State, Cond, Assumption); if (NotifyAssumeClients && SU) return SU->processAssume(State, Cond, Assumption); return State; } ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef State, NonLoc Cond, bool Assumption) { // We cannot reason about SymSymExprs, and can only reason about some // SymIntExprs. if (!canReasonAbout(Cond)) { // Just add the constraint to the expression without trying to simplify. SymbolRef Sym = Cond.getAsSymExpr(); assert(Sym); return assumeSymUnsupported(State, Sym, Assumption); } switch (Cond.getSubKind()) { default: llvm_unreachable("'Assume' not implemented for this NonLoc"); case nonloc::SymbolValKind: { nonloc::SymbolVal SV = Cond.castAs(); SymbolRef Sym = SV.getSymbol(); assert(Sym); return assumeSym(State, Sym, Assumption); } case nonloc::ConcreteIntKind: { bool b = Cond.castAs().getValue() != 0; bool isFeasible = b ? Assumption : !Assumption; return isFeasible ? State : nullptr; } case nonloc::PointerToMemberKind: { bool IsNull = !Cond.castAs().isNullMemberPointer(); bool IsFeasible = IsNull ? Assumption : !Assumption; return IsFeasible ? State : nullptr; } case nonloc::LocAsIntegerKind: return assume(State, Cond.castAs().getLoc(), Assumption); } // end switch } ProgramStateRef SimpleConstraintManager::assumeInclusiveRange( ProgramStateRef State, NonLoc Value, const llvm::APSInt &From, const llvm::APSInt &To, bool InRange) { assert(From.isUnsigned() == To.isUnsigned() && From.getBitWidth() == To.getBitWidth() && "Values should have same types!"); if (!canReasonAbout(Value)) { // Just add the constraint to the expression without trying to simplify. SymbolRef Sym = Value.getAsSymExpr(); assert(Sym); return assumeSymInclusiveRange(State, Sym, From, To, InRange); } switch (Value.getSubKind()) { default: llvm_unreachable("'assumeInclusiveRange' is not implemented" "for this NonLoc"); case nonloc::LocAsIntegerKind: case nonloc::SymbolValKind: { if (SymbolRef Sym = Value.getAsSymbol()) return assumeSymInclusiveRange(State, Sym, From, To, InRange); return State; } // end switch case nonloc::ConcreteIntKind: { const llvm::APSInt &IntVal = Value.castAs().getValue(); bool IsInRange = IntVal >= From && IntVal <= To; bool isFeasible = (IsInRange == InRange); return isFeasible ? State : nullptr; } } // end switch } } // end of namespace ento } // end of namespace clang