26 using namespace clang;
34 class ConstraintBasedEQEvaluator {
35 const DefinedOrUnknownSVal CompareValue;
40 ConstraintBasedEQEvaluator(CheckerContext &C,
41 const DefinedOrUnknownSVal CompareValue)
42 : CompareValue(CompareValue), PS(C.getState()), SVB(C.getSValBuilder()) {}
44 bool operator()(
const llvm::APSInt &EnumDeclInitValue) {
45 DefinedOrUnknownSVal EnumDeclValue = SVB.makeIntVal(EnumDeclInitValue);
46 DefinedOrUnknownSVal ElemEqualsValueToCast =
47 SVB.evalEQ(PS, EnumDeclValue, CompareValue);
49 return static_cast<bool>(PS->assume(ElemEqualsValueToCast,
true));
59 class EnumCastOutOfRangeChecker :
public Checker<check::PreStmt<CastExpr>> {
60 mutable std::unique_ptr<BuiltinBug> EnumValueCastOutOfRange;
61 void reportWarning(CheckerContext &C)
const;
64 void checkPreStmt(
const CastExpr *CE, CheckerContext &C)
const;
70 EnumValueVector getDeclValuesForEnum(
const EnumDecl *ED) {
71 EnumValueVector DeclValues(
73 llvm::transform(ED->
enumerators(), DeclValues.begin(),
79 void EnumCastOutOfRangeChecker::reportWarning(CheckerContext &C)
const {
80 if (
const ExplodedNode *N = C.generateNonFatalErrorNode()) {
81 if (!EnumValueCastOutOfRange)
82 EnumValueCastOutOfRange.reset(
83 new BuiltinBug(
this,
"Enum cast out of range",
84 "The value provided to the cast expression is not in " 85 "the valid range of values for the enum"));
86 C.emitReport(llvm::make_unique<BugReport>(
87 *EnumValueCastOutOfRange, EnumValueCastOutOfRange->getDescription(),
92 void EnumCastOutOfRangeChecker::checkPreStmt(
const CastExpr *CE,
93 CheckerContext &C)
const {
102 case CK_IntegralCast:
112 C.getSVal(CE->
getSubExpr()).getAs<DefinedOrUnknownSVal>();
130 EnumValueVector DeclValues = getDeclValuesForEnum(ED);
132 bool PossibleValueMatch = llvm::any_of(
133 DeclValues, ConstraintBasedEQEvaluator(C, *ValueToCast));
137 if (!PossibleValueMatch)
141 void ento::registerEnumCastOutOfRangeChecker(CheckerManager &mgr) {
142 mgr.registerChecker<EnumCastOutOfRangeChecker>();
145 bool ento::shouldRegisterEnumCastOutOfRangeChecker(
const LangOptions &LO) {
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
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
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...
CastKind getCastKind() const
Dataflow Directional Tag Classes.