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 19 namespace clang { 20 21 namespace ento { 22 23 SimpleConstraintManager::~SimpleConstraintManager() {} 24 25 ProgramStateRef 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 (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 else 36 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 44 ProgramStateRef 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 52 ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef State, 53 NonLoc Cond, 54 bool Assumption) { 55 56 // We cannot reason about SymSymExprs, and can only reason about some 57 // 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.getSubKind()) { 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 switch 92 } 93 94 ProgramStateRef 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.getSubKind()) { 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 switch 120 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 switch 128 } 129 130 } // end of namespace ento 131 132 } // end of namespace clang 133