19 using namespace clang;
30 SimpleSValBuilder(llvm::BumpPtrAllocator &alloc,
ASTContext &context,
33 ~SimpleSValBuilder()
override {}
53 const llvm::APSInt &RHS,
QualType resultTy);
60 return new SimpleSValBuilder(alloc, context, stateMgr);
83 if (castSize == LI->getNumBits())
85 return makeLocAsInteger(LI->getLoc(), castSize);
97 if (haveSameType(T, castTy))
101 return makeNonLoc(se, T, castTy);
112 return makeTruthVal(b, castTy);
121 BasicVals.getAPSIntType(castTy).apply(i);
124 return makeIntLocVal(i);
126 return makeIntVal(i);
149 case loc::MemRegionValKind: {
152 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(FTR->getDecl()))
166 case loc::GotoLabelKind:
168 return makeTruthVal(
true, castTy);
176 return makeLocAsInteger(val, BitWidth);
179 BasicVals.getAPSIntType(castTy).apply(i);
180 return makeIntVal(i);
193 SVal SimpleSValBuilder::evalMinus(
NonLoc val) {
195 case nonloc::ConcreteIntKind:
204 case nonloc::ConcreteIntKind:
215 SVal SimpleSValBuilder::MakeSymIntVal(
const SymExpr *LHS,
217 const llvm::APSInt &RHS,
219 bool isIdempotent =
false;
229 return makeIntVal(0, resultTy);
247 return makeIntVal(0, resultTy);
261 return makeIntVal(0, resultTy);
262 else if (RHS.isAllOnesValue())
269 else if (RHS.isAllOnesValue()) {
270 const llvm::APSInt &
Result = BasicVals.Convert(resultTy, RHS);
284 const llvm::APSInt *ConvertedRHS = &RHS;
291 uint64_t ValWidth = RHS.getBitWidth();
294 if (ValWidth < TypeWidth) {
296 ConvertedRHS = &BasicVals.Convert(SymbolType, RHS);
297 }
else if (ValWidth == TypeWidth) {
302 ConvertedRHS = &BasicVals.Convert(SymbolType, RHS);
305 ConvertedRHS = &BasicVals.Convert(resultTy, RHS);
307 return makeNonLoc(LHS, op, *ConvertedRHS, resultTy);
325 return makeTruthVal(
true, resultTy);
329 return makeTruthVal(
false, resultTy);
333 return makeIntVal(0, resultTy);
334 return evalCastFromNonLoc(makeIntVal(0,
false), resultTy);
337 return evalCastFromNonLoc(lhs, resultTy);
343 return makeSymExprValNN(state, op, lhs, rhs, resultTy);
344 case nonloc::PointerToMemberKind: {
345 assert(rhs.
getSubKind() == nonloc::PointerToMemberKind &&
346 "Both SVals should have pointer-to-member-type");
349 auto LPTMD = LPTM.
getPTMData(), RPTMD = RPTM.getPTMData();
352 return makeTruthVal(LPTMD == RPTMD, resultTy);
354 return makeTruthVal(LPTMD != RPTMD, resultTy);
359 case nonloc::LocAsIntegerKind: {
362 case nonloc::LocAsIntegerKind:
363 return evalBinOpLL(state, op, lhsL,
366 case nonloc::ConcreteIntKind: {
373 return evalBinOpLL(state, op, lhsL, makeLoc(i), resultTy);
378 return makeTruthVal(
false, resultTy);
380 return makeTruthVal(
true, resultTy);
383 return makeSymExprValNN(state, op, InputLHS, InputRHS, resultTy);
387 case nonloc::ConcreteIntKind: {
391 if (
const llvm::APSInt *KnownRHSValue = getKnownValue(state, rhs)) {
392 llvm::APSInt RHSValue = *KnownRHSValue;
399 CompareType.
apply(LHSValue);
400 CompareType.
apply(RHSValue);
402 APSIntType IntType = BasicVals.getAPSIntType(resultTy);
403 IntType.
apply(LHSValue);
404 IntType.
apply(RHSValue);
407 const llvm::APSInt *
Result =
408 BasicVals.evalAPSInt(op, LHSValue, RHSValue);
437 if (LHSValue.isAllOnesValue() && LHSValue.isSigned())
438 return evalCastFromNonLoc(lhs, resultTy);
443 return evalCastFromNonLoc(lhs, resultTy);
444 return makeSymExprValNN(state, op, InputLHS, InputRHS, resultTy);
446 return makeSymExprValNN(state, op, InputLHS, InputRHS, resultTy);
449 case nonloc::SymbolValKind: {
454 if (
const SymIntExpr *symIntExpr = dyn_cast<SymIntExpr>(Sym)) {
468 llvm_unreachable(
"Logical operators handled by branching logic.");
481 llvm_unreachable(
"'=' and ',' operators handled by ExprEngine.");
484 llvm_unreachable(
"Pointer arithmetic not handled here.");
492 resultTy == getConditionType());
493 assert(symIntExpr->getType()->isBooleanType() ||
494 getContext().hasSameUnqualifiedType(symIntExpr->getType(),
495 getConditionType()));
498 return makeNonLoc(symIntExpr->getLHS(), opc,
499 symIntExpr->getRHS(), resultTy);
504 if (
const llvm::APSInt *RHSValue = getKnownValue(state, rhs)) {
517 APSIntType IntType = BasicVals.getAPSIntType(resultTy);
518 const llvm::APSInt &first = IntType.
convert(symIntExpr->getRHS());
519 const llvm::APSInt &second = IntType.
convert(*RHSValue);
521 const llvm::APSInt *newRHS;
523 newRHS = BasicVals.evalAPSInt(BO_Add, first, second);
525 newRHS = BasicVals.evalAPSInt(BO_Sub, first, second);
527 assert(newRHS &&
"Invalid operation despite common type!");
536 return MakeSymIntVal(symIntExpr, op, *RHSValue, resultTy);
543 SVal simplifiedLhs = simplifySVal(state, lhs);
544 if (simplifiedLhs != lhs)
545 if (
auto simplifiedLhsAsNonLoc = simplifiedLhs.
getAs<
NonLoc>()) {
546 lhs = *simplifiedLhsAsNonLoc;
551 if (
const llvm::APSInt *RHSValue = getKnownValue(state, rhs))
552 return MakeSymIntVal(Sym, op, *RHSValue, resultTy);
555 return makeSymExprValNN(state, op, InputLHS, InputRHS, resultTy);
565 SimpleSValBuilder &SVB) {
588 return SVB.makeTruthVal(
false, resultTy);
590 return SVB.makeTruthVal(
true, resultTy);
596 bool leftFirst = (op == BO_LT || op == BO_LE);
597 for (
const auto *
I : RD->
fields()) {
599 return SVB.makeTruthVal(leftFirst, resultTy);
601 return SVB.makeTruthVal(!leftFirst, resultTy);
604 llvm_unreachable(
"Fields not found in parent record's definition");
625 llvm_unreachable(
"Unimplemented operation for two identical values");
627 return makeZeroVal(resultTy);
631 return makeTruthVal(
true, resultTy);
635 return makeTruthVal(
false, resultTy);
641 llvm_unreachable(
"Ordering not implemented for this Loc.");
643 case loc::GotoLabelKind:
650 return evalCastFromLoc(lhs, resultTy);
654 return makeTruthVal(
false, resultTy);
658 return makeTruthVal(
true, resultTy);
668 case loc::ConcreteIntKind: {
679 return makeNonLoc(rSym, op, lVal, resultTy);
687 return evalCastFromNonLoc(*Result, resultTy);
689 assert(!ResultVal.
getAs<
Loc>() &&
"Loc-Loc ops should not produce Locs");
705 return makeTruthVal(
false, resultTy);
709 return makeTruthVal(
true, resultTy);
717 case loc::MemRegionValKind: {
722 return MakeSymIntVal(lSym, op, rInt->getValue(), resultTy);
728 if (rInt->isZeroConstant()) {
730 return evalCastFromLoc(lhs, resultTy);
733 QualType boolType = getContext().BoolTy;
736 return evalBinOpNN(state, op, l, r, resultTy);
746 assert(LeftMR &&
"MemRegionValKind SVal doesn't have a region!");
764 if (LeftMS != RightMS &&
765 ((LeftMS != UnknownMS && RightMS != UnknownMS) ||
766 (isa<StackSpaceRegion>(LeftMS) || isa<StackSpaceRegion>(RightMS)))) {
771 return makeTruthVal(
false, resultTy);
773 return makeTruthVal(
true, resultTy);
787 if (LeftBase != RightBase &&
788 ((!isa<SymbolicRegion>(LeftBase) && !isa<SymbolicRegion>(RightBase)) ||
789 (isa<HeapSpaceRegion>(LeftMS) || isa<HeapSpaceRegion>(RightMS))) ){
794 return makeTruthVal(
false, resultTy);
796 return makeTruthVal(
true, resultTy);
803 if (RightER && LeftER) {
812 SVal LeftIndexVal = LeftER->getIndex();
816 LeftIndexVal = evalCastFromNonLoc(*LeftIndex, ArrayIndexTy);
826 RightIndexVal = evalCastFromNonLoc(*RightIndex, ArrayIndexTy);
833 return evalBinOpNN(state, op, *LeftIndex, *RightIndex, resultTy);
840 if (RightFR && LeftFR) {
861 return makeTruthVal(left < right, resultTy);
863 return makeTruthVal(left > right, resultTy);
865 return makeTruthVal(left <= right, resultTy);
867 return makeTruthVal(left >= right, resultTy);
869 return makeTruthVal(left == right, resultTy);
871 return makeTruthVal(left != right, resultTy);
879 if (LHSSym && RHSSym)
880 return makeNonLoc(LHSSym, op, RHSSym, resultTy);
891 if (op >= BO_PtrMemD && op <= BO_PtrMemI) {
893 if (PTMSV->isNullMemberPointer())
898 for (
const auto &
I : *PTMSV)
899 Result = StateMgr.getStoreManager().evalDerivedToBase(
900 Result,
I->getType(),
I->isVirtual());
901 return state->getLValue(FD, Result);
909 "arguments to comparison ops must be of the same type");
920 const llvm::APSInt &leftI = lhsInt->getValue();
921 assert(leftI.isUnsigned());
922 llvm::APSInt rightI(rhsInt->getValue(),
true);
926 rightI = rightI.extOrTrunc(leftI.getBitWidth());
929 llvm::APSInt Multiplicand(rightI.getBitWidth(),
true);
930 rightI *= Multiplicand;
935 rightI = leftI + rightI;
938 rightI = leftI - rightI;
941 llvm_unreachable(
"Invalid pointer arithmetic operation");
956 if (
const ElementRegion *elemReg = dyn_cast<ElementRegion>(region)) {
957 assert(op == BO_Add || op == BO_Sub);
958 index = evalBinOpNN(state, op, elemReg->getIndex(), rhs,
959 getArrayIndexType());
960 superR = cast<SubRegion>(elemReg->getSuperRegion());
961 elementType = elemReg->getElementType();
963 else if (isa<SubRegion>(region)) {
964 assert(op == BO_Add || op == BO_Sub);
965 index = (op == BO_Add) ? rhs : evalMinus(rhs);
966 superR = cast<SubRegion>(region);
977 superR, getContext()));
983 const llvm::APSInt *SimpleSValBuilder::getKnownValue(
ProgramStateRef state,
989 return &X->getValue();
992 return &X->getValue();
995 return state->getConstraintManager().getSymVal(state, Sym);
1012 : State(State), SVB(State->getStateManager().getSValBuilder()) {}
1015 if (
const llvm::APSInt *
I =
1018 : (
SVal)SVB.makeIntVal(*
I);
1039 LHS = SVB.makeLoc(Sym);
1041 RHS = SVB.makeIntLocVal(S->
getRHS());
1043 RHS = SVB.makeIntVal(S->
getRHS());
1066 SVal VisitSVal(
SVal V) {
return V; }
1069 return Simplifier(State).Visit(V);
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
A (possibly-)qualified type.
MemRegion - The root abstract class for all memory regions.
const llvm::APSInt & getRHS() const
const SymExpr * getLHS() const
SValBuilder * createSimpleSValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context, ProgramStateManager &stateMgr)
unsigned getIntWidth(QualType T) const
bool isBooleanType() const
MemSpaceRegion - A memory region that represents a "memory space"; for example, the set of global var...
Value representing integer constant.
const SymExpr * getRHS() const
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
QualType getElementType() const
const MemRegion * getBaseRegion() const
bool isZeroConstant() const
RecordDecl - Represents a struct/union/class.
bool isComparisonOp() const
const MemSpaceRegion * getMemorySpace() const
static Opcode reverseComparisonOp(Opcode Opc)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Value representing pointer-to-member.
unsigned computeComplexity() const
bool isReferenceType() const
FieldDecl - An instance of this class is created by Sema::ActOnField to represent a member of a struc...
bool isAnyPointerType() const
SymbolRef getAsLocSymbol(bool IncludeBaseRegions=false) const
If this SVal is a location and wraps a symbol, return that SymbolRef.
FullSValVisitor - a convenient mixed visitor for all three: SVal, SymExpr and MemRegion subclasses...
i32 captured_struct **param SharedsTy A type which contains references the shared variables *param Shareds Context with the list of shared variables from the p *TaskFunction *param Data Additional data for task generation like final * state
const SymExpr * getLHS() const
static bool isLocType(QualType T)
const SymbolicRegion * getSymbolicBase() const
If this is a symbolic region, returns the region.
field_range fields() const
bool isUnknownOrUndef() const
A record of the "type" of an APSInt, used for conversions.
Represents a symbolic expression like 'x' + 3.
detail::InMemoryDirectory::const_iterator I
Represent a region's offset within the top level base region.
virtual QualType getType() const =0
const MemRegion * getSuperRegion() const
static Opcode negateComparisonOp(Opcode Opc)
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
SymbolicRegion - A special, "non-concrete" region.
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
bool hasSymbolicOffset() const
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
static SVal getValue(SVal val, SValBuilder &svalBuilder)
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
FunctionCodeRegion - A region that represents code texts of function.
const FieldDecl * getDecl() const
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
SymbolRef getSymbol() const
QualType getType() const override
const PTMDataType getPTMData() const
bool isAdditiveOp() const
RegionOffset getAsOffset() const
Compute the offset within the top level memory object.
llvm::APSInt convert(const llvm::APSInt &Value) const LLVM_READONLY
Convert and return a new APSInt with the given value, but this type's bit width and signedness...
unsigned getSubKind() const
void apply(llvm::APSInt &Value) const
Convert a given APSInt, in place, to match this type.
Represents symbolic expression.
const MemRegion * getAsRegion() const
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
SubRegion - A region that subsets another larger region.
int64_t getOffset() const
BinaryOperator::Opcode getOpcode() const
char __ovld __cnfn max(char x, char y)
Returns y if x < y, otherwise it returns x.
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
ElementRegin is used to represent both array elements and casts.
const MemRegion * getRegion() const
const SymExpr * getAsSymbolicExpression() const
getAsSymbolicExpression - If this Sval wraps a symbolic expression then return that expression...
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
Represents a symbolic expression like 'x' + 'y'.
A symbol representing data which can be stored in a memory location (region).
const RecordDecl * getParent() const
getParent - Returns the parent of this field declaration, which is the struct in which this field is ...
static SVal evalBinOpFieldRegionFieldRegion(const FieldRegion *LeftFR, const FieldRegion *RightFR, BinaryOperator::Opcode op, QualType resultTy, SimpleSValBuilder &SVB)