27 using namespace clang;
35 class ConstraintBasedEQEvaluator {
36 const DefinedOrUnknownSVal CompareValue;
41 ConstraintBasedEQEvaluator(CheckerContext &C,
42 const DefinedOrUnknownSVal CompareValue)
43 : CompareValue(CompareValue), PS(C.getState()), SVB(C.getSValBuilder()) {}
45 bool operator()(
const llvm::APSInt &EnumDeclInitValue) {
46 DefinedOrUnknownSVal EnumDeclValue = SVB.makeIntVal(EnumDeclInitValue);
47 DefinedOrUnknownSVal ElemEqualsValueToCast =
48 SVB.evalEQ(PS, EnumDeclValue, CompareValue);
50 return static_cast<bool>(PS->assume(ElemEqualsValueToCast,
true));
60 class EnumCastOutOfRangeChecker :
public Checker<check::PreStmt<CastExpr>> {
61 mutable std::unique_ptr<BuiltinBug> EnumValueCastOutOfRange;
62 void reportWarning(CheckerContext &C)
const;
65 void checkPreStmt(
const CastExpr *CE, CheckerContext &C)
const;
71 EnumValueVector getDeclValuesForEnum(
const EnumDecl *ED) {
72 EnumValueVector DeclValues(
74 llvm::transform(ED->
enumerators(), DeclValues.begin(),
80 void EnumCastOutOfRangeChecker::reportWarning(CheckerContext &C)
const {
81 if (
const ExplodedNode *N = C.generateNonFatalErrorNode()) {
82 if (!EnumValueCastOutOfRange)
83 EnumValueCastOutOfRange.reset(
84 new BuiltinBug(
this,
"Enum cast out of range",
85 "The value provided to the cast expression is not in " 86 "the valid range of values for the enum"));
87 C.emitReport(llvm::make_unique<BugReport>(
88 *EnumValueCastOutOfRange, EnumValueCastOutOfRange->getDescription(),
93 void EnumCastOutOfRangeChecker::checkPreStmt(
const CastExpr *CE,
94 CheckerContext &C)
const {
97 C.getSVal(CE->
getSubExpr()).getAs<DefinedOrUnknownSVal>();
115 EnumValueVector DeclValues = getDeclValuesForEnum(ED);
117 bool PossibleValueMatch = llvm::any_of(
118 DeclValues, ConstraintBasedEQEvaluator(C, *ValueToCast));
122 if (!PossibleValueMatch)
126 void ento::registerEnumCastOutOfRangeChecker(CheckerManager &mgr) {
127 mgr.registerChecker<EnumCastOutOfRangeChecker>();
enumerator_iterator enumerator_end() const
A (possibly-)qualified type.
An instance of this object exists for each enum constant that is defined.
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
float __ovld __cnfn distance(float p0, float p1)
Returns the distance between p0 and p1.
enumerator_range enumerators() const
bool isEnumeralType() const
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
const T * castAs() const
Member-template castAs<specific type>.
enumerator_iterator enumerator_begin() const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums...
Dataflow Directional Tag Classes.