37#include "llvm/ADT/APSInt.h"
38#include "llvm/Support/Compiler.h"
50void SValBuilder::anchor() {}
66 if (
type->isIntegralOrEnumerationType())
69 if (
type->isArrayType() ||
type->isRecordType() ||
type->isVectorType() ||
70 type->isAnyComplexType())
122 if (std::optional<nonloc::ConcreteInt> CI =
124 const llvm::APSInt& I = CI->getValue();
140 if (
T->isNullPtrType())
159 assert(Ex &&
"elem must be a CFGStmt containing an Expr");
162 if (
T->isNullPtrType())
179 if (
type->isNullPtrType())
196 unsigned visitCount) {
202 const void *symbolTag) {
211 const void *symbolTag) {
219 unsigned VisitCount) {
222 if (
type->isNullPtrType()) {
234 unsigned VisitCount) {
260 if (
T->isNullPtrType())
277 if (
const auto *MD = dyn_cast_or_null<CXXMethodDecl>(ND)) {
283 if (!MD->isImplicitObjectMemberFunction())
297 unsigned blockCount) {
304std::optional<loc::MemRegionVal>
306 if (
auto OptR =
StateMgr.getStoreManager().castRegion(R, Ty))
340 case Stmt::AddrLabelExprClass:
343 case Stmt::CXXScalarValueInitExprClass:
344 case Stmt::ImplicitValueInitExprClass:
347 case Stmt::ObjCStringLiteralClass: {
352 case Stmt::StringLiteralClass: {
357 case Stmt::PredefinedExprClass: {
359 assert(PE->getFunctionName() &&
360 "Since we analyze only instantiated functions, PredefinedExpr "
361 "should have a function name.");
367 case Stmt::CharacterLiteralClass: {
372 case Stmt::CXXBoolLiteralExprClass:
375 case Stmt::TypeTraitExprClass: {
377 if (TE->isStoredAsBoolean())
379 if (TE->isStoredAsComparisonResult())
381 assert(TE->getAPValue().isInt() &&
"APValue type not supported");
385 case Stmt::IntegerLiteralClass:
388 case Stmt::ObjCBoolLiteralExprClass:
391 case Stmt::CXXNullPtrLiteralExprClass:
394 case Stmt::CStyleCastExprClass:
395 case Stmt::CXXFunctionalCastExprClass:
396 case Stmt::CXXConstCastExprClass:
397 case Stmt::CXXReinterpretCastExprClass:
398 case Stmt::CXXStaticCastExprClass:
399 case Stmt::ImplicitCastExprClass: {
401 switch (CE->getCastKind()) {
404 case CK_ArrayToPointerDecay:
405 case CK_IntegralToPointer:
408 const Expr *SE = CE->getSubExpr();
446 const unsigned MaxComp =
AnOpts.MaxSymbolComplexity;
448 if (symLHS && symRHS &&
450 return makeNonLoc(symLHS, Op, symRHS, ResultTy);
453 if (std::optional<nonloc::ConcreteInt> rInt =
455 return makeNonLoc(symLHS, Op, rInt->getValue(), ResultTy);
458 if (std::optional<nonloc::ConcreteInt> lInt =
460 return makeNonLoc(lInt->getValue(), Op, symRHS, ResultTy);
466 switch (
X.getKind()) {
467 case nonloc::ConcreteIntKind:
469 case nonloc::SymbolValKind:
478 switch (
X.getKind()) {
479 case nonloc::ConcreteIntKind:
481 case nonloc::SymbolValKind:
499 llvm_unreachable(
"Unexpected unary operator");
514 if (op == BinaryOperatorKind::BO_Cmp) {
522 if (std::optional<Loc> LV = lhs.
getAs<
Loc>()) {
523 if (std::optional<Loc> RV = rhs.
getAs<
Loc>())
529 if (
const std::optional<Loc> RV = rhs.
getAs<
Loc>()) {
531 return Op == BO_Mul || Op == BO_Add || Op == BO_And || Op == BO_Xor ||
535 if (IsCommutative(op)) {
554 return state->isNonNull(
evalEQ(state, lhs, rhs));
564 return evalEQ(state,
static_cast<SVal>(lhs),
static_cast<SVal>(rhs))
573 while (Context.UnwrapSimilarTypes(ToTy, FromTy)) {
575 ToTy = Context.getUnqualifiedArrayType(ToTy, Quals1);
576 FromTy = Context.getUnqualifiedArrayType(FromTy, Quals2);
582 if (Quals1 != Quals2)
608 return evalCast(val, castTy, originalTy);
612 if (!AsSymbol || !AsNonLoc)
613 return evalCast(val, castTy, originalTy);
628 std::tie(IsNotTruncated, IsTruncated) = state->assume(CompVal);
629 if (!IsNotTruncated && IsTruncated) {
631 return makeNonLoc(AsSymbol, originalTy, castTy);
633 return evalCast(val, castTy, originalTy);
642class EvalCastVisitor :
public SValVisitor<EvalCastVisitor, SVal> {
650 : VB(VB), Context(VB.getContext()), CastTy(CastTy),
651 OriginalTy(OriginalTy) {}
659 const bool IsUnknownOriginalType = OriginalTy.
isNull();
660 if (!IsUnknownOriginalType) {
663 if (CastTy == OriginalTy)
671 Context.getPointerType(OriginalTy)))
676 SVal VisitUndefinedVal(UndefinedVal
V) {
return V; }
677 SVal VisitUnknownVal(UnknownVal
V) {
return V; }
678 SVal VisitConcreteInt(loc::ConcreteInt
V) {
681 return VB.
makeTruthVal(
V.getValue()->getBoolValue(), CastTy);
685 llvm::APSInt
Value =
V.getValue();
692 llvm::APSInt
Value =
V.getValue();
700 SVal VisitGotoLabel(loc::GotoLabel
V) {
708 const unsigned BitWidth = Context.
getIntWidth(CastTy);
712 const bool IsUnknownOriginalType = OriginalTy.
isNull();
713 if (!IsUnknownOriginalType) {
727 SVal VisitMemRegionVal(loc::MemRegionVal
V) {
730 const MemRegion *
R =
V.getRegion();
731 if (
const FunctionCodeRegion *FTR = dyn_cast<FunctionCodeRegion>(R))
732 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(FTR->getDecl()))
737 return nonloc::SymbolVal(
740 if (
const SymbolicRegion *SymR =
R->getSymbolicBase()) {
755 const bool IsUnknownOriginalType = OriginalTy.
isNull();
757 const auto *ArrayTy =
758 IsUnknownOriginalType
768 QualType ElemTy = ArrayTy->getElementType();
775 const unsigned BitWidth = Context.
getIntWidth(CastTy);
782 if (IsUnknownOriginalType) {
791 const MemRegion *
R =
V.getRegion();
793 if (
const auto *SR = dyn_cast<SymbolicRegion>(R)) {
794 QualType SRTy = SR->getSymbol()->getType();
796 auto HasSameUnqualifiedPointeeType = [](QualType ty1,
801 if (!HasSameUnqualifiedPointeeType(SRTy, CastTy)) {
809 if (
const auto *ER = dyn_cast<ElementRegion>(R)) {
828 QualType ElemTy = ArrayTy->getElementType();
856 const MemRegion *
R =
V.getRegion();
872 SVal VisitCompoundVal(nonloc::CompoundVal
V) {
876 SVal VisitConcreteInt(nonloc::ConcreteInt
V) {
877 auto CastedValue = [
V,
this]() {
878 llvm::APSInt
Value =
V.getValue();
885 return VB.
makeTruthVal(
V.getValue()->getBoolValue(), CastTy);
898 SVal VisitLazyCompoundVal(nonloc::LazyCompoundVal
V) {
902 SVal VisitLocAsInteger(nonloc::LocAsInteger
V) {
910 const bool IsUnknownOriginalType = OriginalTy.
isNull();
922 if (!IsUnknownOriginalType && R) {
924 return VisitMemRegionVal(loc::MemRegionVal(R));
937 if (IsUnknownOriginalType)
938 return VisitMemRegionVal(loc::MemRegionVal(R));
944 if (
const SymbolicRegion *SR =
945 dyn_cast<SymbolicRegion>(
R->StripCasts())) {
946 SE = SR->getSymbol();
952 const unsigned CastSize = Context.
getIntWidth(CastTy);
953 if (CastSize ==
V.getNumBits())
963 SVal VisitSymbolVal(nonloc::SymbolVal
V) {
966 const bool IsUnknownOriginalType = OriginalTy.
isNull();
992 return simplifySymbolCast(
V, CastTy);
1006 return UnknownVal();
1008 SVal VisitPointerToMember(nonloc::PointerToMember
V) {
1023 nonloc::SymbolVal simplifySymbolCast(nonloc::SymbolVal
V, QualType CastTy) {
1083 const bool isSameType = (RT == CastTy);
1085 return nonloc::SymbolVal(RootSym);
1094 if (((WT > WR) && (UR || !UT)) || ((WT == WR) && (UT == UR)))
1114 EvalCastVisitor TRV{*
this, CastTy, OriginalTy};
1115 return TRV.Visit(
V);
Defines the clang::ASTContext interface.
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::Expr interface and subclasses for C++ expressions.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
static bool shouldBeModeledWithNoOp(ASTContext &Context, QualType ToTy, QualType FromTy)
Recursively check if the pointer types are equal modulo const, volatile, and restrict qualifiers.
C Language Family Type Representation.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
unsigned getIntWidth(QualType T) const
static CanQualType getCanonicalType(QualType T)
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
ASTContext & getASTContext() const
bool analyzerSymbolicIntegerCasts() const
BinaryOperatorKind Opcode
Represents a block literal declaration, which is like an unnamed FunctionDecl.
const Stmt * getStmt() const
A boolean literal, per ([C++ lex.bool] Boolean literals).
Represents a static or instance method of a struct/union/class.
QualType getThisType() const
Return the type of the this pointer.
Represents a C++ struct/union/class.
This represents one expression.
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
@ NPC_ValueDependentIsNotNull
Specifies that a value-dependent expression should be considered to never be a null pointer constant.
Decl * getReferencedDeclOfCallee()
NullPointerConstantKind isNullPointerConstant(ASTContext &Ctx, NullPointerConstantValueDependence NPC) const
isNullPointerConstant - C99 6.3.2.3p3 - Test if this reduces down to a Null pointer constant.
Represents a function declaration or definition.
This represents a decl that may have a name.
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
QualType getCanonicalType() const
The collection of all-type qualifiers we support.
void removeCVRQualifiers(unsigned mask)
It represents a stack frame of the call stack.
LLVM_ATTRIBUTE_RETURNS_NONNULL AnalysisDeclContext * getAnalysisDeclContext() const
StmtClass getStmtClass() const
bool isBlockPointerType() const
bool isBooleanType() const
bool isIntegralOrUnscopedEnumerationType() const
Determine whether this type is an integral or unscoped enumeration type.
bool isVoidPointerType() const
bool isFunctionPointerType() const
bool isPointerType() const
bool isReferenceType() const
bool isVariableArrayType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
bool isMemberPointerType() const
bool isFunctionType() const
bool isFloatingType() const
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
A safe wrapper around APSInt objects allocated and owned by BasicValueFactory.
A record of the "type" of an APSInt, used for conversions.
uint32_t getBitWidth() const
llvm::APSInt getMaxValue() const LLVM_READONLY
Returns the maximum value for this type.
void apply(llvm::APSInt &Value) const
Convert a given APSInt, in place, to match this type.
AllocaRegion - A region that represents an untyped blob of bytes created by a call to 'alloca'.
AnalyzerOptions & getAnalyzerOptions() override
APSIntPtr getZeroWithTypeSize(QualType T)
APSIntType getAPSIntType(QualType T) const
Returns the type of the APSInt used to store values of the given QualType.
BlockCodeRegion - A region that represents code texts of blocks (closures).
BlockDataRegion - A region that represents a block instance.
Represents an abstract call to a function or method along a particular path.
QualType getResultType() const
Returns the result type, adjusted for references.
const StackFrame * getStackFrame() const
The stack frame in which the call is being evaluated.
const CFGBlock::ConstCFGElementRef & getCFGElementRef() const
AnalysisManager & getAnalysisManager()
static bool isLocType(QualType T)
const AllocaRegion * getAllocaRegion(const Expr *Ex, unsigned Cnt, const StackFrame *SF)
getAllocaRegion - Retrieve a region associated with a call to alloca().
MemRegion - The root abstract class for all memory regions.
ExprEngine & getOwningEngine()
SVal ArrayToPointer(Loc Array, QualType ElementTy)
DefinedOrUnknownSVal makeZeroVal(QualType type)
Construct an SVal representing '0' for the specified type.
DefinedSVal getMemberPointer(const NamedDecl *ND)
SVal evalMinus(NonLoc val)
SVal evalComplement(NonLoc val)
BasicValueFactory & getBasicValueFactory()
NonLoc makeCompoundVal(QualType type, llvm::ImmutableList< SVal > vals)
SymbolManager SymMgr
Manages the creation of symbols.
virtual SVal evalBinOpLN(ProgramStateRef state, BinaryOperator::Opcode op, Loc lhs, NonLoc rhs, QualType resultTy)=0
Create a new value which represents a binary expression with a memory location and non-location opera...
MemRegionManager & getRegionManager()
ProgramStateManager & getStateManager()
SVal makeSymExprValNN(BinaryOperator::Opcode op, NonLoc lhs, NonLoc rhs, QualType resultTy)
Constructs a symbolic expression for two non-location values.
virtual SVal evalBinOpLL(ProgramStateRef state, BinaryOperator::Opcode op, Loc lhs, Loc rhs, QualType resultTy)=0
Create a new value which represents a binary expression with two memory location operands.
const unsigned ArrayIndexWidth
The width of the scalar type used for array indices.
DefinedSVal getFunctionPointer(const FunctionDecl *func)
const QualType ArrayIndexTy
The scalar type to use for array indices.
ASTContext & getContext()
nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)
SVal convertToArrayIndex(SVal val)
loc::MemRegionVal makeLoc(SymbolRef sym)
DefinedSVal getBlockPointer(const BlockDecl *block, CanQualType locTy, const StackFrame *SF, unsigned blockCount)
virtual SVal evalBinOpNN(ProgramStateRef state, BinaryOperator::Opcode op, NonLoc lhs, NonLoc rhs, QualType resultTy)=0
Create a new value which represents a binary expression with two non- location operands.
SVal evalCast(SVal V, QualType CastTy, QualType OriginalTy)
Cast a given SVal to another SVal using given QualType's.
const AnalyzerOptions & getAnalyzerOptions() const
BasicValueFactory BasicVals
Manager of APSInt values.
ConditionTruthVal areEqual(ProgramStateRef state, SVal lhs, SVal rhs)
QualType getConditionType() const
MemRegionManager MemMgr
Manages the creation of memory regions.
SVal evalEQ(ProgramStateRef state, SVal lhs, SVal rhs)
SVal evalUnaryOp(ProgramStateRef state, UnaryOperator::Opcode opc, SVal operand, QualType type)
DefinedOrUnknownSVal getDerivedRegionValueSymbolVal(SymbolRef parentSymbol, const TypedValueRegion *region)
nonloc::ConcreteInt makeTruthVal(bool b, QualType type)
loc::ConcreteInt makeNullWithType(QualType type)
Create NULL pointer, with proper pointer bit-width for given address space.
loc::MemRegionVal getAllocaRegionVal(const Expr *E, const StackFrame *SF, unsigned Count)
Create an SVal representing the result of an alloca()-like call, that is, an AllocaRegion on the stac...
ProgramStateManager & StateMgr
DefinedSVal getConjuredHeapSymbolVal(ConstCFGElementRef elem, const StackFrame *SF, QualType type, unsigned Count)
Conjure a symbol representing heap allocated memory region.
std::optional< SVal > getConstantVal(const Expr *E)
Returns the value of E, if it can be determined in a non-path-sensitive manner.
NonLoc makeLocAsInteger(Loc loc, unsigned bits)
SVal evalIntegralCast(ProgramStateRef state, SVal val, QualType castTy, QualType originalType)
SymbolManager & getSymbolManager()
DefinedOrUnknownSVal getRegionValueSymbolVal(const TypedValueRegion *region)
Make a unique symbol for value of region.
loc::MemRegionVal getCXXThis(const CXXMethodDecl *D, const StackFrame *SF)
Return a memory region for the 'this' object reference.
SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, SVal lhs, SVal rhs, QualType type)
loc::ConcreteInt makeIntLocVal(const llvm::APSInt &integer)
DefinedSVal getMetadataSymbolVal(const void *symbolTag, const MemRegion *region, const Expr *expr, QualType type, const StackFrame *SF, unsigned count)
DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, ConstCFGElementRef elem, const StackFrame *SF, unsigned count)
Create a new symbol with a unique 'name'.
nonloc::SymbolVal makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op, APSIntPtr rhs, QualType type)
const AnalyzerOptions & AnOpts
std::optional< loc::MemRegionVal > getCastedMemRegionVal(const MemRegion *region, QualType type)
Return MemRegionVal on success cast, otherwise return std::nullopt.
nonloc::ConcreteInt makeBoolVal(const ObjCBoolLiteralExpr *boolean)
SValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context, ProgramStateManager &stateMgr)
SValVisitor - this class implements a simple visitor for SVal subclasses.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
bool isUnknownOrUndef() const
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
std::optional< T > getAs() const
Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.
const MemRegion * getAsRegion() const
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
virtual QualType getType() const =0
virtual unsigned computeComplexity() const =0
Represents a cast expression.
A symbol representing the value of a MemRegion whose parent region has symbolic value.
const SymExprT * acquire(Args &&...args)
Create or retrieve a SymExpr of type SymExprT for the given arguments.
static bool canSymbolicate(QualType T)
A symbol representing the value stored at a MemRegion.
TypedValueRegion - An abstract class representing regions having a typed value.
virtual QualType getValueType() const =0
Represents a symbolic expression involving a unary operator.
Value representing integer constant.
APSIntPtr getValue() const
Value representing pointer-to-member.
Represents symbolic expression that isn't a location.
LLVM_ATTRIBUTE_RETURNS_NONNULL SymbolRef getSymbol() const
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
BinarySymExprImpl< APSIntPtr, const SymExpr *, SymExpr::Kind::IntSymExprKind > IntSymExpr
Represents a symbolic expression like 3 - 'x'.
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
const SymExpr * SymbolRef
BinarySymExprImpl< const SymExpr *, const SymExpr *, SymExpr::Kind::SymSymExprKind > SymSymExpr
Represents a symbolic expression like 'x' + 'y'.
BinarySymExprImpl< const SymExpr *, APSIntPtr, SymExpr::Kind::SymIntExprKind > SymIntExpr
Represents a symbolic expression like 'x' + 3.
Top level wrappers for InstallAPI frontend operations.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
CFGBlock::ConstCFGElementRef ConstCFGElementRef
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ Result
The result type of a method or function.
const FunctionProtoType * T
U cast(CodeGen::Address addr)
EvalResult is a struct with detailed info about an evaluated expression.