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()) {}
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(std::make_unique<PathSensitiveBugReport>(
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 CheckerManager &mgr) {