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