133 lines · cpp
1//== SimpleConstraintManager.cpp --------------------------------*- C++ -*--==//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file defines SimpleConstraintManager, a class that provides a10// simplified constraint manager interface, compared to ConstraintManager.11//12//===----------------------------------------------------------------------===//13 14#include "clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h"15#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"16#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"17#include <optional>18 19namespace clang {20 21namespace ento {22 23SimpleConstraintManager::~SimpleConstraintManager() {}24 25ProgramStateRef SimpleConstraintManager::assumeInternal(ProgramStateRef State,26 DefinedSVal Cond,27 bool Assumption) {28 // If we have a Loc value, cast it to a bool NonLoc first.29 if (std::optional<Loc> LV = Cond.getAs<Loc>()) {30 SValBuilder &SVB = State->getStateManager().getSValBuilder();31 QualType T;32 const MemRegion *MR = LV->getAsRegion();33 if (const TypedRegion *TR = dyn_cast_or_null<TypedRegion>(MR))34 T = TR->getLocationType();35 else36 T = SVB.getContext().VoidPtrTy;37 38 Cond = SVB.evalCast(*LV, SVB.getContext().BoolTy, T).castAs<DefinedSVal>();39 }40 41 return assume(State, Cond.castAs<NonLoc>(), Assumption);42}43 44ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef State,45 NonLoc Cond, bool Assumption) {46 State = assumeAux(State, Cond, Assumption);47 if (EE)48 return EE->processAssume(State, Cond, Assumption);49 return State;50}51 52ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef State,53 NonLoc Cond,54 bool Assumption) {55 56 // We cannot reason about SymSymExprs, and can only reason about some57 // SymIntExprs.58 if (!canReasonAbout(Cond)) {59 // Just add the constraint to the expression without trying to simplify.60 SymbolRef Sym = Cond.getAsSymbol();61 assert(Sym);62 return assumeSymUnsupported(State, Sym, Assumption);63 }64 65 switch (Cond.getKind()) {66 default:67 llvm_unreachable("'Assume' not implemented for this NonLoc");68 69 case nonloc::SymbolValKind: {70 nonloc::SymbolVal SV = Cond.castAs<nonloc::SymbolVal>();71 SymbolRef Sym = SV.getSymbol();72 assert(Sym);73 return assumeSym(State, Sym, Assumption);74 }75 76 case nonloc::ConcreteIntKind: {77 bool b = *Cond.castAs<nonloc::ConcreteInt>().getValue() != 0;78 bool isFeasible = b ? Assumption : !Assumption;79 return isFeasible ? State : nullptr;80 }81 82 case nonloc::PointerToMemberKind: {83 bool IsNull = !Cond.castAs<nonloc::PointerToMember>().isNullMemberPointer();84 bool IsFeasible = IsNull ? Assumption : !Assumption;85 return IsFeasible ? State : nullptr;86 }87 88 case nonloc::LocAsIntegerKind:89 return assumeInternal(State, Cond.castAs<nonloc::LocAsInteger>().getLoc(),90 Assumption);91 } // end switch92}93 94ProgramStateRef SimpleConstraintManager::assumeInclusiveRangeInternal(95 ProgramStateRef State, NonLoc Value, const llvm::APSInt &From,96 const llvm::APSInt &To, bool InRange) {97 98 assert(From.isUnsigned() == To.isUnsigned() &&99 From.getBitWidth() == To.getBitWidth() &&100 "Values should have same types!");101 102 if (!canReasonAbout(Value)) {103 // Just add the constraint to the expression without trying to simplify.104 SymbolRef Sym = Value.getAsSymbol();105 assert(Sym);106 return assumeSymInclusiveRange(State, Sym, From, To, InRange);107 }108 109 switch (Value.getKind()) {110 default:111 llvm_unreachable("'assumeInclusiveRange' is not implemented"112 "for this NonLoc");113 114 case nonloc::LocAsIntegerKind:115 case nonloc::SymbolValKind: {116 if (SymbolRef Sym = Value.getAsSymbol())117 return assumeSymInclusiveRange(State, Sym, From, To, InRange);118 return State;119 } // end switch120 121 case nonloc::ConcreteIntKind: {122 const llvm::APSInt &IntVal = Value.castAs<nonloc::ConcreteInt>().getValue();123 bool IsInRange = IntVal >= From && IntVal <= To;124 bool isFeasible = (IsInRange == InRange);125 return isFeasible ? State : nullptr;126 }127 } // end switch128}129 130} // end of namespace ento131 132} // end of namespace clang133