20#include "llvm/ADT/SmallVector.h"
27class ReturnValueChecker :
public Checker<check::PostCall, check::EndFunction> {
39 {{{
"ARMAsmParser",
"Error"}},
true},
40 {{{
"HexagonAsmParser",
"Error"}},
true},
41 {{{
"LLLexer",
"Error"}},
true},
42 {{{
"LLParser",
"Error"}},
true},
43 {{{
"MCAsmParser",
"Error"}},
true},
44 {{{
"MCAsmParserExtension",
"Error"}},
true},
45 {{{
"TGParser",
"Error"}},
true},
46 {{{
"X86AsmParser",
"Error"}},
true},
48 {{{
"LLParser",
"TokError"}},
true},
49 {{{
"MCAsmParser",
"TokError"}},
true},
50 {{{
"MCAsmParserExtension",
"TokError"}},
true},
51 {{{
"TGParser",
"TokError"}},
true},
53 {{{
"MIParser",
"error"}},
true},
54 {{{
"WasmAsmParser",
"error"}},
true},
55 {{{
"WebAssemblyAsmParser",
"error"}},
true},
57 {{{
"AsmParser",
"printError"}},
true}};
63 if (
const auto *MD = dyn_cast<CXXMethodDecl>(Call.getDecl()))
65 Name += RD->getNameAsString() +
"::";
67 Name += Call.getCalleeIdentifier()->getName();
80 return C.getState()->isNull(*ReturnDV).isConstrainedTrue();
82 return C.getState()->isNull(*ReturnDV).isConstrainedFalse();
85void ReturnValueChecker::checkPostCall(
const CallEvent &Call,
87 const bool *RawExpectedValue = CDM.lookup(Call);
88 if (!RawExpectedValue)
91 SVal ReturnV =
Call.getReturnValue();
92 bool ExpectedValue = *RawExpectedValue;
93 std::optional<bool> IsInvariantBreak =
95 if (!IsInvariantBreak)
99 if (*IsInvariantBreak)
102 std::string Name =
getName(Call);
103 const NoteTag *CallTag =
C.getNoteTag(
106 llvm::raw_svector_ostream Out(Msg);
108 Out <<
'\'' << Name <<
"' returns "
109 << (ExpectedValue ?
"true" :
"false");
110 return std::string(Out.str());
116 C.addTransition(State, CallTag);
119void ReturnValueChecker::checkEndFunction(
const ReturnStmt *RS,
126 if (
C.getStackFrame()->inTopFrame())
135 const bool *RawExpectedValue = CDM.lookup(*Call);
136 if (!RawExpectedValue)
140 bool ExpectedValue = *RawExpectedValue;
141 std::optional<bool> IsInvariantBreak =
143 if (!IsInvariantBreak)
147 if (!*IsInvariantBreak)
150 std::string Name =
getName(*Call);
151 const NoteTag *CallTag =
C.getNoteTag(
152 [Name, ExpectedValue](
BugReport &BR) -> std::string {
154 llvm::raw_svector_ostream Out(Msg);
157 Out <<
'\'' << Name <<
"' returns "
158 << (ExpectedValue ?
"false" :
"true");
160 return std::string(Out.str());
164 C.addTransition(State, CallTag);
171bool ento::shouldRegisterReturnValueChecker(
const CheckerManager &mgr) {
static std::string getName(const CallEvent &Call)
static std::optional< bool > isInvariantBreak(bool ExpectedValue, SVal ReturnV, CheckerContext &C)
Represents a C++ struct/union/class.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
It represents a stack frame of the call stack (based on CallEvent).
This class provides an interface through which checkers can create individual bug reports.
An immutable map from CallDescriptions to arbitrary data.
Manages the lifetime of CallEvent objects.
CallEventRef getCaller(const StackFrameContext *CalleeCtx, ProgramStateRef State)
Gets an outside caller given a callee context.
Represents an abstract call to a function or method along a particular path.
CHECKER * registerChecker(AT &&... Args)
Used to register checkers.
The tag upon which the TagVisitor reacts.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
std::optional< T > getAs() const
Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
bool Call(InterpState &S, CodePtr OpPC, const Function *Func)
@ C
Languages that the frontend can parse and compile.