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:
367 return evalBinOpLL(state, op, lhsL,
370 case nonloc::ConcreteIntKind: {
380 BasicVals.getAPSIntType(Context.
VoidPtrTy).apply(i);
381 return evalBinOpLL(state, op, lhsL, makeLoc(i), resultTy);
386 return makeTruthVal(
false, resultTy);
388 return makeTruthVal(
true, resultTy);
391 return makeSymExprValNN(state, op, InputLHS, InputRHS, resultTy);
395 case nonloc::ConcreteIntKind: {
399 if (
const llvm::APSInt *KnownRHSValue = getKnownValue(state, rhs)) {
400 llvm::APSInt RHSValue = *KnownRHSValue;
407 CompareType.
apply(LHSValue);
408 CompareType.
apply(RHSValue);
410 APSIntType IntType = BasicVals.getAPSIntType(resultTy);
411 IntType.
apply(LHSValue);
412 IntType.
apply(RHSValue);
415 const llvm::APSInt *Result =
416 BasicVals.evalAPSInt(op, LHSValue, RHSValue);
445 if (LHSValue.isAllOnesValue() && LHSValue.isSigned())
446 return evalCastFromNonLoc(lhs, resultTy);
451 return evalCastFromNonLoc(lhs, resultTy);
452 return makeSymExprValNN(state, op, InputLHS, InputRHS, resultTy);
454 return makeSymExprValNN(state, op, InputLHS, InputRHS, resultTy);
457 case nonloc::SymbolValKind: {
462 if (
const SymIntExpr *symIntExpr = dyn_cast<SymIntExpr>(Sym)) {
476 llvm_unreachable(
"Logical operators handled by branching logic.");
489 llvm_unreachable(
"'=' and ',' operators handled by ExprEngine.");
492 llvm_unreachable(
"Pointer arithmetic not handled here.");
500 resultTy == getConditionType());
501 assert(symIntExpr->getType()->isBooleanType() ||
502 getContext().hasSameUnqualifiedType(symIntExpr->getType(),
503 getConditionType()));
506 return makeNonLoc(symIntExpr->getLHS(), opc,
507 symIntExpr->getRHS(), resultTy);
512 if (
const llvm::APSInt *RHSValue = getKnownValue(state, rhs)) {
525 APSIntType IntType = BasicVals.getAPSIntType(resultTy);
526 const llvm::APSInt &first = IntType.
convert(symIntExpr->getRHS());
527 const llvm::APSInt &second = IntType.
convert(*RHSValue);
529 const llvm::APSInt *newRHS;
531 newRHS = BasicVals.evalAPSInt(BO_Add, first, second);
533 newRHS = BasicVals.evalAPSInt(BO_Sub, first, second);
535 assert(newRHS &&
"Invalid operation despite common type!");
544 return MakeSymIntVal(symIntExpr, op, *RHSValue, resultTy);
551 SVal simplifiedLhs = simplifySVal(state, lhs);
552 if (simplifiedLhs != lhs)
553 if (
auto simplifiedLhsAsNonLoc = simplifiedLhs.
getAs<
NonLoc>()) {
554 lhs = *simplifiedLhsAsNonLoc;
559 if (
const llvm::APSInt *RHSValue = getKnownValue(state, rhs))
560 return MakeSymIntVal(Sym, op, *RHSValue, resultTy);
563 return makeSymExprValNN(state, op, InputLHS, InputRHS, resultTy);
573 SimpleSValBuilder &SVB) {
596 return SVB.makeTruthVal(
false, resultTy);
598 return SVB.makeTruthVal(
true, resultTy);
604 bool leftFirst = (op == BO_LT || op == BO_LE);
605 for (
const auto *I : RD->
fields()) {
607 return SVB.makeTruthVal(leftFirst, resultTy);
609 return SVB.makeTruthVal(!leftFirst, resultTy);
612 llvm_unreachable(
"Fields not found in parent record's definition");
633 llvm_unreachable(
"Unimplemented operation for two identical values");
635 return makeZeroVal(resultTy);
639 return makeTruthVal(
true, resultTy);
643 return makeTruthVal(
false, resultTy);
649 llvm_unreachable(
"Ordering not implemented for this Loc.");
651 case loc::GotoLabelKind:
658 return evalCastFromLoc(lhs, resultTy);
662 return makeTruthVal(
false, resultTy);
666 return makeTruthVal(
true, resultTy);
676 case loc::ConcreteIntKind: {
687 return makeNonLoc(rSym, op, lVal, resultTy);
695 return evalCastFromNonLoc(*Result, resultTy);
697 assert(!ResultVal.
getAs<
Loc>() &&
"Loc-Loc ops should not produce Locs");
713 return makeTruthVal(
false, resultTy);
717 return makeTruthVal(
true, resultTy);
725 case loc::MemRegionValKind: {
731 return MakeSymIntVal(lSym, op, rInt->getValue(), resultTy);
738 if (rInt->isZeroConstant()) {
740 return evalCastFromLoc(lhs, resultTy);
743 QualType boolType = getContext().BoolTy;
746 return evalBinOpNN(state, op, l, r, resultTy);
756 assert(LeftMR &&
"MemRegionValKind SVal doesn't have a region!");
774 if (LeftMS != RightMS &&
775 ((LeftMS != UnknownMS && RightMS != UnknownMS) ||
776 (isa<StackSpaceRegion>(LeftMS) || isa<StackSpaceRegion>(RightMS)))) {
781 return makeTruthVal(
false, resultTy);
783 return makeTruthVal(
true, resultTy);
797 if (LeftBase != RightBase &&
798 ((!isa<SymbolicRegion>(LeftBase) && !isa<SymbolicRegion>(RightBase)) ||
799 (isa<HeapSpaceRegion>(LeftMS) || isa<HeapSpaceRegion>(RightMS))) ){
804 return makeTruthVal(
false, resultTy);
806 return makeTruthVal(
true, resultTy);
813 if (RightER && LeftER) {
822 SVal LeftIndexVal = LeftER->getIndex();
826 LeftIndexVal = evalCastFromNonLoc(*LeftIndex, ArrayIndexTy);
836 RightIndexVal = evalCastFromNonLoc(*RightIndex, ArrayIndexTy);
843 return evalBinOpNN(state, op, *LeftIndex, *RightIndex, resultTy);
850 if (RightFR && LeftFR) {
871 return makeTruthVal(left < right, resultTy);
873 return makeTruthVal(left > right, resultTy);
875 return makeTruthVal(left <= right, resultTy);
877 return makeTruthVal(left >= right, resultTy);
879 return makeTruthVal(left == right, resultTy);
881 return makeTruthVal(left != right, resultTy);
889 if (LHSSym && RHSSym)
890 return makeNonLoc(LHSSym, op, RHSSym, resultTy);
901 if (op >= BO_PtrMemD && op <= BO_PtrMemI) {
903 if (PTMSV->isNullMemberPointer())
908 for (
const auto &I : *PTMSV)
909 Result = StateMgr.getStoreManager().evalDerivedToBase(
910 Result, I->getType(),I->isVirtual());
911 return state->getLValue(FD, Result);
919 "arguments to comparison ops must be of the same type");
934 const llvm::APSInt &leftI = lhsInt->getValue();
935 assert(leftI.isUnsigned());
936 llvm::APSInt rightI(rhsInt->getValue(),
true);
940 rightI = rightI.extOrTrunc(leftI.getBitWidth());
943 llvm::APSInt Multiplicand(rightI.getBitWidth(),
true);
945 Multiplicand = getContext().getTypeSizeInChars(pointeeType).getQuantity();
946 rightI *= Multiplicand;
951 rightI = leftI + rightI;
954 rightI = leftI - rightI;
957 llvm_unreachable(
"Invalid pointer arithmetic operation");
972 if (
const ElementRegion *elemReg = dyn_cast<ElementRegion>(region)) {
973 assert(op == BO_Add || op == BO_Sub);
974 index = evalBinOpNN(state, op, elemReg->getIndex(), rhs,
975 getArrayIndexType());
976 superR = cast<SubRegion>(elemReg->getSuperRegion());
977 elementType = elemReg->getElementType();
979 else if (isa<SubRegion>(region)) {
980 assert(op == BO_Add || op == BO_Sub);
981 index = (op == BO_Add) ? rhs : evalMinus(rhs);
982 superR = cast<SubRegion>(region);
993 superR, getContext()));
999 const llvm::APSInt *SimpleSValBuilder::getKnownValue(
ProgramStateRef state,
1005 return &X->getValue();
1008 return &X->getValue();
1011 return state->getConstraintManager().getSymVal(state, Sym);
1028 :
State(State), SVB(State->getStateManager().getSValBuilder()) {}
1031 if (
const llvm::APSInt *I =
1083 SVal VisitSVal(
SVal V) {
return V; }
1086 return Simplifier(State).Visit(V);
An instance of this class is created to represent a function declaration or definition.
nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)
A (possibly-)qualified type.
MemRegion - The root abstract class for all memory regions.
SValBuilder * createSimpleSValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context, ProgramStateManager &stateMgr)
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
const RecordDecl * getParent() const
getParent - Returns the parent of this field declaration, which is the struct in which this field is ...
const MemRegion * getRegion() const
MemSpaceRegion - A memory region that represents a "memory space"; for example, the set of global var...
Value representing integer constant.
SymbolRef getAsLocSymbol(bool IncludeBaseRegions=false) const
If this SVal is a location and wraps a symbol, return that SymbolRef.
QualType getElementType() const
bool isAdditiveOp() const
const MemRegion * getSuperRegion() const
RecordDecl - Represents a struct/union/class.
const PTMDataType getPTMData() const
const SymbolicRegion * getSymbolicBase() const
If this is a symbolic region, returns the region.
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.
field_range fields() const
const FieldDecl * getDecl() const
FieldDecl - An instance of this class is created by Sema::ActOnField to represent a member of a struc...
bool isReferenceType() const
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 * getAsSymbolicExpression() const
getAsSymbolicExpression - If this Sval wraps a symbolic expression then return that expression...
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
static bool isLocType(QualType T)
loc::ConcreteInt makeIntLocVal(const llvm::APSInt &integer)
A record of the "type" of an APSInt, used for conversions.
Represents a symbolic expression like 'x' + 3.
Represent a region's offset within the top level base region.
const MemSpaceRegion * getMemorySpace() const
virtual QualType getType() const =0
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
static Opcode negateComparisonOp(Opcode Opc)
unsigned getSubKind() const
Loc makeLoc(SymbolRef sym)
SymbolicRegion - A special, "non-concrete" region.
const FunctionProtoType * T
static SVal getValue(SVal val, SValBuilder &svalBuilder)
SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, SVal lhs, SVal rhs, QualType type)
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
bool isComparisonOp() const
const SymExpr * getLHS() const
FunctionCodeRegion - A region that represents code texts of function.
const MemRegion * getAsRegion() const
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
bool isAnyPointerType() const
QualType getType() const override
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...
Dataflow Directional Tag Classes.
bool isZeroConstant() const
const llvm::APSInt & getRHS() const
bool isBooleanType() const
Represents symbolic expression.
unsigned computeComplexity() const
const SymExpr * getRHS() const
unsigned getIntWidth(QualType T) const
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
SubRegion - A region that subsets another larger region.
SymbolRef getSymbol() const
RegionOffset getAsOffset() const
Compute the offset within the top level memory object.
int64_t getOffset() const
char __ovld __cnfn max(char x, char y)
Returns y if x < y, otherwise it returns x.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
BinaryOperator::Opcode getOpcode() const
void apply(llvm::APSInt &Value) const
Convert a given APSInt, in place, to match this type.
const MemRegion * getBaseRegion() const
ElementRegin is used to represent both array elements and casts.
virtual const llvm::APSInt * getKnownValue(ProgramStateRef state, SVal val)=0
Evaluates a given SVal.
Represents a symbolic expression like 'x' + 'y'.
bool hasSymbolicOffset() const
bool isUnknownOrUndef() const
A symbol representing data which can be stored in a memory location (region).
const SymExpr * getLHS() const
static SVal evalBinOpFieldRegionFieldRegion(const FieldRegion *LeftFR, const FieldRegion *RightFR, BinaryOperator::Opcode op, QualType resultTy, SimpleSValBuilder &SVB)