20 #include "llvm/ADT/Optional.h"
21 #include "llvm/ADT/SmallVector.h"
23 using namespace clang;
27 class ReturnValueChecker :
public Checker<check::PostCall, check::EndFunction> {
30 void checkPostCall(
const CallEvent &Call, CheckerContext &C)
const;
33 void checkEndFunction(
const ReturnStmt *RS, CheckerContext &C)
const;
37 const CallDescriptionMap<bool> CDM = {
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();
75 auto ReturnDV = ReturnV.getAs<DefinedOrUnknownSVal>();
80 return C.getState()->isNull(*ReturnDV).isConstrainedTrue();
82 return C.getState()->isNull(*ReturnDV).isConstrainedFalse();
85 void ReturnValueChecker::checkPostCall(
const CallEvent &Call,
86 CheckerContext &C)
const {
87 const bool *RawExpectedValue = CDM.lookup(Call);
88 if (!RawExpectedValue)
91 SVal ReturnV =
Call.getReturnValue();
92 bool ExpectedValue = *RawExpectedValue;
94 if (!IsInvariantBreak)
98 if (*IsInvariantBreak)
102 const NoteTag *CallTag =
C.getNoteTag(
103 [Name, ExpectedValue](PathSensitiveBugReport &) ->
std::string {
105 llvm::raw_svector_ostream Out(Msg);
107 Out <<
'\'' << Name <<
"' returns "
108 << (ExpectedValue ?
"true" :
"false");
114 State =
State->assume(ReturnV.castAs<DefinedOrUnknownSVal>(), ExpectedValue);
115 C.addTransition(
State, CallTag);
118 void ReturnValueChecker::checkEndFunction(
const ReturnStmt *RS,
119 CheckerContext &C)
const {
125 if (
C.getStackFrame()->inTopFrame())
129 CallEventManager &CMgr =
C.getStateManager().getCallEventManager();
130 CallEventRef<>
Call = CMgr.getCaller(SFC,
State);
134 const bool *RawExpectedValue = CDM.lookup(*Call);
135 if (!RawExpectedValue)
139 bool ExpectedValue = *RawExpectedValue;
141 if (!IsInvariantBreak)
145 if (!*IsInvariantBreak)
149 const NoteTag *CallTag =
C.getNoteTag(
150 [Name, ExpectedValue](BugReport &BR) ->
std::string {
152 llvm::raw_svector_ostream Out(Msg);
155 Out <<
'\'' << Name <<
"' returns "
156 << (ExpectedValue ?
"false" :
"true");
162 C.addTransition(
State, CallTag);
165 void ento::registerReturnValueChecker(CheckerManager &Mgr) {
166 Mgr.registerChecker<ReturnValueChecker>();
169 bool ento::shouldRegisterReturnValueChecker(
const CheckerManager &mgr) {