18 #include "llvm/ADT/Optional.h" 20 using namespace clang;
24 class CastValueChecker :
public Checker<eval::Call> {
26 std::function<void(
const CastValueChecker *,
const CallExpr *,
27 DefinedOrUnknownSVal, CheckerContext &)>;
36 bool evalCall(
const CallEvent &Call, CheckerContext &C)
const;
41 {{{
"llvm",
"cast"}, 1}, &CastValueChecker::evalCast},
42 {{{
"llvm",
"dyn_cast"}, 1}, &CastValueChecker::evalDynCast},
43 {{{
"llvm",
"cast_or_null"}, 1}, &CastValueChecker::evalCastOrNull},
44 {{{
"llvm",
"dyn_cast_or_null"}, 1},
45 &CastValueChecker::evalDynCastOrNull}};
47 void evalCast(
const CallExpr *CE, DefinedOrUnknownSVal ParamDV,
48 CheckerContext &C)
const;
49 void evalDynCast(
const CallExpr *CE, DefinedOrUnknownSVal ParamDV,
50 CheckerContext &C)
const;
51 void evalCastOrNull(
const CallExpr *CE, DefinedOrUnknownSVal ParamDV,
52 CheckerContext &C)
const;
53 void evalDynCastOrNull(
const CallExpr *CE, DefinedOrUnknownSVal ParamDV,
54 CheckerContext &C)
const;
63 DefinedOrUnknownSVal ParamDV,
69 State = State->BindExpr(CE, C.getLocationContext(), ParamDV,
false);
74 const NoteTag *CastTag = C.getNoteTag(
75 [CastFromName, CastToName](BugReport &) -> std::string {
77 llvm::raw_svector_ostream Out(Msg);
79 Out <<
"Assuming dynamic cast from '" << CastFromName <<
"' to '" 80 << CastToName <<
"' succeeds";
85 C.addTransition(State, CastTag);
89 DefinedOrUnknownSVal ParamDV,
95 State = State->BindExpr(CE, C.getLocationContext(),
96 C.getSValBuilder().makeNull(),
false);
101 const NoteTag *CastTag = C.getNoteTag(
102 [CastFromName, CastToName](BugReport &) -> std::string {
104 llvm::raw_svector_ostream Out(Msg);
106 Out <<
"Assuming dynamic cast from '" << CastFromName <<
"' to '" 107 << CastToName <<
"' fails";
112 C.addTransition(State, CastTag);
116 DefinedOrUnknownSVal ParamDV,
122 State = State->BindExpr(CE, C.getLocationContext(),
123 C.getSValBuilder().makeNull(),
false);
125 const NoteTag *CastTag =
126 C.getNoteTag(
"Assuming null pointer is passed into cast",
129 C.addTransition(State, CastTag);
132 void CastValueChecker::evalCast(
const CallExpr *CE,
133 DefinedOrUnknownSVal ParamDV,
134 CheckerContext &C)
const {
138 void CastValueChecker::evalDynCast(
const CallExpr *CE,
139 DefinedOrUnknownSVal ParamDV,
140 CheckerContext &C)
const {
145 void CastValueChecker::evalCastOrNull(
const CallExpr *CE,
146 DefinedOrUnknownSVal ParamDV,
147 CheckerContext &C)
const {
152 void CastValueChecker::evalDynCastOrNull(
const CallExpr *CE,
153 DefinedOrUnknownSVal ParamDV,
154 CheckerContext &C)
const {
160 bool CastValueChecker::evalCall(
const CallEvent &Call,
161 CheckerContext &C)
const {
162 const CastCheck *Check = CDM.lookup(Call);
166 const auto *CE = cast<CallExpr>(Call.getOriginExpr());
175 SVal ParamV = Call.getArgSVal(0);
176 auto ParamDV = ParamV.getAs<DefinedOrUnknownSVal>();
180 (*Check)(
this, CE, *ParamDV, C);
184 void ento::registerCastValueChecker(CheckerManager &Mgr) {
185 Mgr.registerChecker<CastValueChecker>();
188 bool ento::shouldRegisterCastValueChecker(
const LangOptions &LO) {
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
static void evalNullParamNullReturn(const CallExpr *CE, DefinedOrUnknownSVal ParamDV, CheckerContext &C)
static void evalNonNullParamNonNullReturn(const CallExpr *CE, DefinedOrUnknownSVal ParamDV, CheckerContext &C)
This represents one expression.
const CXXRecordDecl * getPointeeCXXRecordDecl() const
If this is a pointer or reference to a RecordType, return the CXXRecordDecl that the type refers to...
static void evalNonNullParamNullReturn(const CallExpr *CE, DefinedOrUnknownSVal ParamDV, CheckerContext &C)
static std::string getCastName(const Expr *Cast)
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
Dataflow Directional Tag Classes.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
An immutable map from CallDescriptions to arbitrary data.