Changeset View
Changeset View
Standalone View
Standalone View
clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
Show First 20 Lines • Show All 228 Lines • ▼ Show 20 Lines | public: | ||||
// We want calling these methods to be a compiler error since they are | // We want calling these methods to be a compiler error since they are | ||||
// tautologically false. | // tautologically false. | ||||
bool isUndef() const = delete; | bool isUndef() const = delete; | ||||
bool isValid() const = delete; | bool isValid() const = delete; | ||||
static bool classof(SVal V) { return !V.isUndef(); } | static bool classof(SVal V) { return !V.isUndef(); } | ||||
protected: | protected: | ||||
DefinedOrUnknownSVal() = default; | |||||
explicit DefinedOrUnknownSVal(const void *d, bool isLoc, unsigned ValKind) | explicit DefinedOrUnknownSVal(const void *d, bool isLoc, unsigned ValKind) | ||||
: SVal(d, isLoc, ValKind) {} | : SVal(d, isLoc, ValKind) {} | ||||
explicit DefinedOrUnknownSVal(BaseKind k, void *D = nullptr) : SVal(k, D) {} | explicit DefinedOrUnknownSVal(BaseKind k, void *D = nullptr) : SVal(k, D) {} | ||||
}; | }; | ||||
class UnknownVal : public DefinedOrUnknownSVal { | class UnknownVal : public DefinedOrUnknownSVal { | ||||
public: | public: | ||||
explicit UnknownVal() : DefinedOrUnknownSVal(UnknownValKind) {} | explicit UnknownVal() : DefinedOrUnknownSVal(UnknownValKind) {} | ||||
static bool classof(SVal V) { return V.getBaseKind() == UnknownValKind; } | static bool classof(SVal V) { return V.getBaseKind() == UnknownValKind; } | ||||
}; | }; | ||||
class DefinedSVal : public DefinedOrUnknownSVal { | class DefinedSVal : public DefinedOrUnknownSVal { | ||||
public: | public: | ||||
// We want calling these methods to be a compiler error since they are | // We want calling these methods to be a compiler error since they are | ||||
// tautologically true/false. | // tautologically true/false. | ||||
bool isUnknown() const = delete; | bool isUnknown() const = delete; | ||||
bool isUnknownOrUndef() const = delete; | bool isUnknownOrUndef() const = delete; | ||||
bool isValid() const = delete; | bool isValid() const = delete; | ||||
static bool classof(SVal V) { return !V.isUnknownOrUndef(); } | static bool classof(SVal V) { return !V.isUnknownOrUndef(); } | ||||
protected: | protected: | ||||
DefinedSVal() = default; | |||||
explicit DefinedSVal(const void *d, bool isLoc, unsigned ValKind) | explicit DefinedSVal(const void *d, bool isLoc, unsigned ValKind) | ||||
: DefinedOrUnknownSVal(d, isLoc, ValKind) {} | : DefinedOrUnknownSVal(d, isLoc, ValKind) {} | ||||
}; | }; | ||||
/// Represents an SVal that is guaranteed to not be UnknownVal. | /// Represents an SVal that is guaranteed to not be UnknownVal. | ||||
class KnownSVal : public SVal { | class KnownSVal : public SVal { | ||||
KnownSVal() = default; | |||||
public: | public: | ||||
KnownSVal(const DefinedSVal &V) : SVal(V) {} | KnownSVal(const DefinedSVal &V) : SVal(V) {} | ||||
KnownSVal(const UndefinedVal &V) : SVal(V) {} | KnownSVal(const UndefinedVal &V) : SVal(V) {} | ||||
static bool classof(SVal V) { return !V.isUnknown(); } | static bool classof(SVal V) { return !V.isUnknown(); } | ||||
}; | }; | ||||
class NonLoc : public DefinedSVal { | class NonLoc : public DefinedSVal { | ||||
protected: | protected: | ||||
NonLoc() = default; | |||||
explicit NonLoc(unsigned SubKind, const void *d) | explicit NonLoc(unsigned SubKind, const void *d) | ||||
: DefinedSVal(d, false, SubKind) {} | : DefinedSVal(d, false, SubKind) {} | ||||
public: | public: | ||||
void dumpToStream(raw_ostream &Out) const; | void dumpToStream(raw_ostream &Out) const; | ||||
static bool isCompoundType(QualType T) { | static bool isCompoundType(QualType T) { | ||||
return T->isArrayType() || T->isRecordType() || | return T->isArrayType() || T->isRecordType() || | ||||
T->isAnyComplexType() || T->isVectorType(); | T->isAnyComplexType() || T->isVectorType(); | ||||
} | } | ||||
static bool classof(SVal V) { return V.getBaseKind() == NonLocKind; } | static bool classof(SVal V) { return V.getBaseKind() == NonLocKind; } | ||||
}; | }; | ||||
class Loc : public DefinedSVal { | class Loc : public DefinedSVal { | ||||
protected: | protected: | ||||
Loc() = default; | |||||
explicit Loc(unsigned SubKind, const void *D) | explicit Loc(unsigned SubKind, const void *D) | ||||
: DefinedSVal(const_cast<void *>(D), true, SubKind) {} | : DefinedSVal(const_cast<void *>(D), true, SubKind) {} | ||||
public: | public: | ||||
void dumpToStream(raw_ostream &Out) const; | void dumpToStream(raw_ostream &Out) const; | ||||
static bool isLocType(QualType T) { | static bool isLocType(QualType T) { | ||||
return T->isAnyPointerType() || T->isBlockPointerType() || | return T->isAnyPointerType() || T->isBlockPointerType() || | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | public: | ||||
ConcreteInt evalMinus(SValBuilder &svalBuilder) const; | ConcreteInt evalMinus(SValBuilder &svalBuilder) const; | ||||
static bool classof(SVal V) { | static bool classof(SVal V) { | ||||
return V.getBaseKind() == NonLocKind && V.getSubKind() == ConcreteIntKind; | return V.getBaseKind() == NonLocKind && V.getSubKind() == ConcreteIntKind; | ||||
} | } | ||||
static bool classof(NonLoc V) { return V.getSubKind() == ConcreteIntKind; } | static bool classof(NonLoc V) { return V.getSubKind() == ConcreteIntKind; } | ||||
private: | |||||
ConcreteInt() = default; | |||||
}; | }; | ||||
class LocAsInteger : public NonLoc { | class LocAsInteger : public NonLoc { | ||||
friend class ento::SValBuilder; | friend class ento::SValBuilder; | ||||
explicit LocAsInteger(const std::pair<SVal, uintptr_t> &data) | explicit LocAsInteger(const std::pair<SVal, uintptr_t> &data) | ||||
: NonLoc(LocAsIntegerKind, &data) { | : NonLoc(LocAsIntegerKind, &data) { | ||||
// We do not need to represent loc::ConcreteInt as LocAsInteger, | // We do not need to represent loc::ConcreteInt as LocAsInteger, | ||||
Show All 23 Lines | unsigned getNumBits() const { | ||||
return D->second; | return D->second; | ||||
} | } | ||||
static bool classof(SVal V) { | static bool classof(SVal V) { | ||||
return V.getBaseKind() == NonLocKind && V.getSubKind() == LocAsIntegerKind; | return V.getBaseKind() == NonLocKind && V.getSubKind() == LocAsIntegerKind; | ||||
} | } | ||||
static bool classof(NonLoc V) { return V.getSubKind() == LocAsIntegerKind; } | static bool classof(NonLoc V) { return V.getSubKind() == LocAsIntegerKind; } | ||||
private: | |||||
LocAsInteger() = default; | |||||
}; | }; | ||||
class CompoundVal : public NonLoc { | class CompoundVal : public NonLoc { | ||||
friend class ento::SValBuilder; | friend class ento::SValBuilder; | ||||
explicit CompoundVal(const CompoundValData* D) : NonLoc(CompoundValKind, D) {} | explicit CompoundVal(const CompoundValData* D) : NonLoc(CompoundValKind, D) {} | ||||
public: | public: | ||||
const CompoundValData* getValue() const { | const CompoundValData* getValue() const { | ||||
return static_cast<const CompoundValData *>(Data); | return static_cast<const CompoundValData *>(Data); | ||||
} | } | ||||
using iterator = llvm::ImmutableList<SVal>::iterator; | using iterator = llvm::ImmutableList<SVal>::iterator; | ||||
iterator begin() const; | iterator begin() const; | ||||
iterator end() const; | iterator end() const; | ||||
static bool classof(SVal V) { | static bool classof(SVal V) { | ||||
return V.getBaseKind() == NonLocKind && V.getSubKind() == CompoundValKind; | return V.getBaseKind() == NonLocKind && V.getSubKind() == CompoundValKind; | ||||
} | } | ||||
static bool classof(NonLoc V) { return V.getSubKind() == CompoundValKind; } | static bool classof(NonLoc V) { return V.getSubKind() == CompoundValKind; } | ||||
private: | |||||
CompoundVal() = default; | |||||
}; | }; | ||||
class LazyCompoundVal : public NonLoc { | class LazyCompoundVal : public NonLoc { | ||||
friend class ento::SValBuilder; | friend class ento::SValBuilder; | ||||
explicit LazyCompoundVal(const LazyCompoundValData *D) | explicit LazyCompoundVal(const LazyCompoundValData *D) | ||||
: NonLoc(LazyCompoundValKind, D) {} | : NonLoc(LazyCompoundValKind, D) {} | ||||
public: | public: | ||||
const LazyCompoundValData *getCVData() const { | const LazyCompoundValData *getCVData() const { | ||||
return static_cast<const LazyCompoundValData *>(Data); | return static_cast<const LazyCompoundValData *>(Data); | ||||
} | } | ||||
const void *getStore() const; | const void *getStore() const; | ||||
const TypedValueRegion *getRegion() const; | const TypedValueRegion *getRegion() const; | ||||
static bool classof(SVal V) { | static bool classof(SVal V) { | ||||
return V.getBaseKind() == NonLocKind && | return V.getBaseKind() == NonLocKind && | ||||
V.getSubKind() == LazyCompoundValKind; | V.getSubKind() == LazyCompoundValKind; | ||||
} | } | ||||
static bool classof(NonLoc V) { | static bool classof(NonLoc V) { | ||||
return V.getSubKind() == LazyCompoundValKind; | return V.getSubKind() == LazyCompoundValKind; | ||||
} | } | ||||
private: | |||||
LazyCompoundVal() = default; | |||||
}; | }; | ||||
/// Value representing pointer-to-member. | /// Value representing pointer-to-member. | ||||
/// | /// | ||||
/// This value is qualified as NonLoc because neither loading nor storing | /// This value is qualified as NonLoc because neither loading nor storing | ||||
/// operations are applied to it. Instead, the analyzer uses the L-value coming | /// operations are applied to it. Instead, the analyzer uses the L-value coming | ||||
/// from pointer-to-member applied to an object. | /// from pointer-to-member applied to an object. | ||||
/// This SVal is represented by a NamedDecl which can be a member function | /// This SVal is represented by a NamedDecl which can be a member function | ||||
Show All 31 Lines | return V.getBaseKind() == NonLocKind && | ||||
V.getSubKind() == PointerToMemberKind; | V.getSubKind() == PointerToMemberKind; | ||||
} | } | ||||
static bool classof(NonLoc V) { | static bool classof(NonLoc V) { | ||||
return V.getSubKind() == PointerToMemberKind; | return V.getSubKind() == PointerToMemberKind; | ||||
} | } | ||||
private: | private: | ||||
PointerToMember() = default; | |||||
explicit PointerToMember(const PTMDataType D) | explicit PointerToMember(const PTMDataType D) | ||||
: NonLoc(PointerToMemberKind, D.getOpaqueValue()) {} | : NonLoc(PointerToMemberKind, D.getOpaqueValue()) {} | ||||
}; | }; | ||||
} // namespace nonloc | } // namespace nonloc | ||||
//==------------------------------------------------------------------------==// | //==------------------------------------------------------------------------==// | ||||
// Subclasses of Loc. | // Subclasses of Loc. | ||||
Show All 11 Lines | const LabelDecl *getLabel() const { | ||||
return static_cast<const LabelDecl *>(Data); | return static_cast<const LabelDecl *>(Data); | ||||
} | } | ||||
static bool classof(SVal V) { | static bool classof(SVal V) { | ||||
return V.getBaseKind() == LocKind && V.getSubKind() == GotoLabelKind; | return V.getBaseKind() == LocKind && V.getSubKind() == GotoLabelKind; | ||||
} | } | ||||
static bool classof(Loc V) { return V.getSubKind() == GotoLabelKind; } | static bool classof(Loc V) { return V.getSubKind() == GotoLabelKind; } | ||||
private: | |||||
GotoLabel() = default; | |||||
}; | }; | ||||
class MemRegionVal : public Loc { | class MemRegionVal : public Loc { | ||||
public: | public: | ||||
explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionValKind, r) { | explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionValKind, r) { | ||||
assert(r); | assert(r); | ||||
} | } | ||||
Show All 18 Lines | bool operator!=(const MemRegionVal &R) const { | ||||
return getRegion() != R.getRegion(); | return getRegion() != R.getRegion(); | ||||
} | } | ||||
static bool classof(SVal V) { | static bool classof(SVal V) { | ||||
return V.getBaseKind() == LocKind && V.getSubKind() == MemRegionValKind; | return V.getBaseKind() == LocKind && V.getSubKind() == MemRegionValKind; | ||||
} | } | ||||
static bool classof(Loc V) { return V.getSubKind() == MemRegionValKind; } | static bool classof(Loc V) { return V.getSubKind() == MemRegionValKind; } | ||||
private: | |||||
MemRegionVal() = default; | |||||
}; | }; | ||||
class ConcreteInt : public Loc { | class ConcreteInt : public Loc { | ||||
public: | public: | ||||
explicit ConcreteInt(const llvm::APSInt& V) : Loc(ConcreteIntKind, &V) {} | explicit ConcreteInt(const llvm::APSInt& V) : Loc(ConcreteIntKind, &V) {} | ||||
const llvm::APSInt &getValue() const { | const llvm::APSInt &getValue() const { | ||||
return *static_cast<const llvm::APSInt *>(Data); | return *static_cast<const llvm::APSInt *>(Data); | ||||
} | } | ||||
// Transfer functions for binary/unary operations on ConcreteInts. | // Transfer functions for binary/unary operations on ConcreteInts. | ||||
SVal evalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op, | SVal evalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op, | ||||
const ConcreteInt& R) const; | const ConcreteInt& R) const; | ||||
static bool classof(SVal V) { | static bool classof(SVal V) { | ||||
return V.getBaseKind() == LocKind && V.getSubKind() == ConcreteIntKind; | return V.getBaseKind() == LocKind && V.getSubKind() == ConcreteIntKind; | ||||
} | } | ||||
static bool classof(Loc V) { return V.getSubKind() == ConcreteIntKind; } | static bool classof(Loc V) { return V.getSubKind() == ConcreteIntKind; } | ||||
private: | |||||
ConcreteInt() = default; | |||||
}; | }; | ||||
} // namespace loc | } // namespace loc | ||||
} // namespace ento | } // namespace ento | ||||
} // namespace clang | } // namespace clang | ||||
#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALS_H | #endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALS_H |