@@ -59,7 +59,8 @@ class ConstraintBasedEQEvaluator {
59
59
// value can be matching.
60
60
class EnumCastOutOfRangeChecker : public Checker <check::PreStmt<CastExpr>> {
61
61
mutable std::unique_ptr<BugType> EnumValueCastOutOfRange;
62
- void reportWarning (CheckerContext &C) const ;
62
+ void reportWarning (CheckerContext &C, const CastExpr *CE,
63
+ const EnumDecl *E) const ;
63
64
64
65
public:
65
66
void checkPreStmt (const CastExpr *CE, CheckerContext &C) const ;
@@ -72,21 +73,38 @@ EnumValueVector getDeclValuesForEnum(const EnumDecl *ED) {
72
73
EnumValueVector DeclValues (
73
74
std::distance (ED->enumerator_begin (), ED->enumerator_end ()));
74
75
llvm::transform (ED->enumerators (), DeclValues.begin (),
75
- [](const EnumConstantDecl *D) { return D->getInitVal (); });
76
+ [](const EnumConstantDecl *D) { return D->getInitVal (); });
76
77
return DeclValues;
77
78
}
78
79
} // namespace
79
80
80
- void EnumCastOutOfRangeChecker::reportWarning (CheckerContext &C) const {
81
+ void EnumCastOutOfRangeChecker::reportWarning (CheckerContext &C,
82
+ const CastExpr *CE,
83
+ const EnumDecl *E) const {
84
+ assert (E && " valid EnumDecl* is expected" );
81
85
if (const ExplodedNode *N = C.generateNonFatalErrorNode ()) {
82
86
if (!EnumValueCastOutOfRange)
83
87
EnumValueCastOutOfRange.reset (
84
88
new BugType (this , " Enum cast out of range" ));
85
- constexpr llvm::StringLiteral Msg =
86
- " The value provided to the cast expression is not in the valid range"
87
- " of values for the enum" ;
88
- C.emitReport (std::make_unique<PathSensitiveBugReport>(
89
- *EnumValueCastOutOfRange, Msg, N));
89
+
90
+ llvm::SmallString<128 > Msg{" The value provided to the cast expression is "
91
+ " not in the valid range of values for " };
92
+ StringRef EnumName{E->getName ()};
93
+ if (EnumName.empty ()) {
94
+ Msg += " the enum" ;
95
+ } else {
96
+ Msg += ' \' ' ;
97
+ Msg += EnumName;
98
+ Msg += ' \' ' ;
99
+ }
100
+
101
+ auto BR = std::make_unique<PathSensitiveBugReport>(*EnumValueCastOutOfRange,
102
+ Msg, N);
103
+ bugreporter::trackExpressionValue (N, CE->getSubExpr (), *BR);
104
+ BR->addNote (" enum declared here" ,
105
+ PathDiagnosticLocation::create (E, C.getSourceManager ()),
106
+ {E->getSourceRange ()});
107
+ C.emitReport (std::move (BR));
90
108
}
91
109
}
92
110
@@ -138,13 +156,13 @@ void EnumCastOutOfRangeChecker::checkPreStmt(const CastExpr *CE,
138
156
return ;
139
157
140
158
// Check if any of the enum values possibly match.
141
- bool PossibleValueMatch = llvm::any_of (
142
- DeclValues, ConstraintBasedEQEvaluator (C, *ValueToCast));
159
+ bool PossibleValueMatch =
160
+ llvm::any_of ( DeclValues, ConstraintBasedEQEvaluator (C, *ValueToCast));
143
161
144
162
// If there is no value that can possibly match any of the enum values, then
145
163
// warn.
146
164
if (!PossibleValueMatch)
147
- reportWarning (C);
165
+ reportWarning (C, CE, ED );
148
166
}
149
167
150
168
void ento::registerEnumCastOutOfRangeChecker (CheckerManager &mgr) {
0 commit comments