19 #include "llvm/ADT/Optional.h" 20 #include "llvm/ADT/SmallVector.h" 22 using namespace clang;
26 class ReturnValueChecker :
public Checker<check::PostCall, check::EndFunction> {
29 void checkPostCall(
const CallEvent &Call, CheckerContext &C)
const;
32 void checkEndFunction(
const ReturnStmt *RS, CheckerContext &C)
const;
38 {{{
"ARMAsmParser",
"Error"}},
true},
39 {{{
"HexagonAsmParser",
"Error"}},
true},
40 {{{
"LLLexer",
"Error"}},
true},
41 {{{
"LLParser",
"Error"}},
true},
42 {{{
"MCAsmParser",
"Error"}},
true},
43 {{{
"MCAsmParserExtension",
"Error"}},
true},
44 {{{
"TGParser",
"Error"}},
true},
45 {{{
"X86AsmParser",
"Error"}},
true},
47 {{{
"LLParser",
"TokError"}},
true},
48 {{{
"MCAsmParser",
"TokError"}},
true},
49 {{{
"MCAsmParserExtension",
"TokError"}},
true},
50 {{{
"TGParser",
"TokError"}},
true},
52 {{{
"MIParser",
"error"}},
true},
53 {{{
"WasmAsmParser",
"error"}},
true},
54 {{{
"WebAssemblyAsmParser",
"error"}},
true},
56 {{{
"AsmParser",
"printError"}},
true}};
61 std::string Name =
"";
62 if (
const auto *MD = dyn_cast<CXXMethodDecl>(Call.getDecl()))
64 Name += RD->getNameAsString() +
"::";
66 Name += Call.getCalleeIdentifier()->getName();
74 auto ReturnDV = ReturnV.getAs<DefinedOrUnknownSVal>();
79 return C.getState()->isNull(*ReturnDV).isConstrainedTrue();
81 return C.getState()->isNull(*ReturnDV).isConstrainedFalse();
84 void ReturnValueChecker::checkPostCall(
const CallEvent &Call,
85 CheckerContext &C)
const {
86 const bool *RawExpectedValue = CDM.lookup(Call);
87 if (!RawExpectedValue)
90 SVal ReturnV = Call.getReturnValue();
91 bool ExpectedValue = *RawExpectedValue;
93 if (!IsInvariantBreak)
97 if (*IsInvariantBreak)
100 std::string Name =
getName(Call);
101 const NoteTag *CallTag = C.getNoteTag(
102 [Name, ExpectedValue](BugReport &) -> std::string {
104 llvm::raw_svector_ostream Out(Msg);
106 Out <<
'\'' << Name <<
"' returns " 107 << (ExpectedValue ?
"true" :
"false");
113 State = State->assume(ReturnV.castAs<DefinedOrUnknownSVal>(), ExpectedValue);
114 C.addTransition(State, CallTag);
117 void ReturnValueChecker::checkEndFunction(
const ReturnStmt *RS,
118 CheckerContext &C)
const {
124 if (C.getStackFrame()->inTopFrame())
129 CallEventRef<> Call = CMgr.
getCaller(SFC, State);
133 const bool *RawExpectedValue = CDM.lookup(*Call);
134 if (!RawExpectedValue)
137 SVal ReturnV = State->getSVal(RS->
getRetValue(), C.getLocationContext());
138 bool ExpectedValue = *RawExpectedValue;
140 if (!IsInvariantBreak)
144 if (!*IsInvariantBreak)
147 std::string Name =
getName(*Call);
148 const NoteTag *CallTag = C.getNoteTag(
149 [Name, ExpectedValue](BugReport &BR) -> std::string {
151 llvm::raw_svector_ostream Out(Msg);
154 Out <<
'\'' << Name <<
"' returns " 155 << (ExpectedValue ?
"false" :
"true");
161 C.addTransition(State, CallTag);
164 void ento::registerReturnValueChecker(CheckerManager &Mgr) {
165 Mgr.registerChecker<ReturnValueChecker>();
168 bool ento::shouldRegisterReturnValueChecker(
const LangOptions &LO) {
Manages the lifetime of CallEvent objects.
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
static Optional< bool > isInvariantBreak(bool ExpectedValue, SVal ReturnV, CheckerContext &C)
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
CallEventRef getCaller(const StackFrameContext *CalleeCtx, ProgramStateRef State)
Gets an outside caller given a callee context.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
Dataflow Directional Tag Classes.
static std::string getName(const CallEvent &Call)
const StackFrameContext * getStackFrame() const
Represents a C++ struct/union/class.
An immutable map from CallDescriptions to arbitrary data.