clang
22.0.0git
lib
StaticAnalyzer
Checkers
ReturnValueChecker.cpp
Go to the documentation of this file.
1
//===- ReturnValueChecker - Check methods always returning true -*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This defines ReturnValueChecker, which models a very specific coding
10
// convention within the LLVM/Clang codebase: there several classes that have
11
// Error() methods which always return true.
12
// This checker was introduced to eliminate false positives caused by this
13
// peculiar "always returns true" invariant. (Normally, the analyzer assumes
14
// that a function returning `bool` can return both `true` and `false`, because
15
// otherwise it could've been a `void` function.)
16
//
17
//===----------------------------------------------------------------------===//
18
19
#include "
clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h
"
20
#include "
clang/StaticAnalyzer/Core/Checker.h
"
21
#include "
clang/StaticAnalyzer/Core/CheckerManager.h
"
22
#include "
clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h
"
23
#include "
clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
"
24
#include "
clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
"
25
#include "llvm/Support/FormatVariadic.h"
26
#include <optional>
27
28
using namespace
clang
;
29
using namespace
ento;
30
using
llvm::formatv;
31
32
namespace
{
33
class
ReturnValueChecker :
public
Checker
<check::PostCall> {
34
public
:
35
void
checkPostCall(
const
CallEvent
&
Call
,
CheckerContext
&
C
)
const
;
36
37
private
:
38
const
CallDescriptionSet
Methods = {
39
// These are known in the LLVM project: 'Error()'
40
{CDM::CXXMethod, {
"ARMAsmParser"
,
"Error"
}},
41
{CDM::CXXMethod, {
"HexagonAsmParser"
,
"Error"
}},
42
{CDM::CXXMethod, {
"LLLexer"
,
"Error"
}},
43
{CDM::CXXMethod, {
"LLParser"
,
"Error"
}},
44
{CDM::CXXMethod, {
"MCAsmParser"
,
"Error"
}},
45
{CDM::CXXMethod, {
"MCAsmParserExtension"
,
"Error"
}},
46
{CDM::CXXMethod, {
"TGParser"
,
"Error"
}},
47
{CDM::CXXMethod, {
"X86AsmParser"
,
"Error"
}},
48
// 'TokError()'
49
{CDM::CXXMethod, {
"LLParser"
,
"TokError"
}},
50
{CDM::CXXMethod, {
"MCAsmParser"
,
"TokError"
}},
51
{CDM::CXXMethod, {
"MCAsmParserExtension"
,
"TokError"
}},
52
{CDM::CXXMethod, {
"TGParser"
,
"TokError"
}},
53
// 'error()'
54
{CDM::CXXMethod, {
"MIParser"
,
"error"
}},
55
{CDM::CXXMethod, {
"WasmAsmParser"
,
"error"
}},
56
{CDM::CXXMethod, {
"WebAssemblyAsmParser"
,
"error"
}},
57
// Other
58
{CDM::CXXMethod, {
"AsmParser"
,
"printError"
}}};
59
};
60
}
// namespace
61
62
static
std::string
getFunctionName
(
const
CallEvent
&
Call
) {
63
std::string Name;
64
if
(
const
auto
*MD = dyn_cast<CXXMethodDecl>(
Call
.getDecl()))
65
if
(
const
CXXRecordDecl
*RD = MD->
getParent
())
66
Name += RD->getNameAsString() +
"::"
;
67
68
Name +=
Call
.getCalleeIdentifier()->getName();
69
return
Name;
70
}
71
72
void
ReturnValueChecker::checkPostCall(
const
CallEvent
&
Call
,
73
CheckerContext
&
C
)
const
{
74
if
(!Methods.contains(
Call
))
75
return
;
76
77
auto
ReturnV =
Call
.getReturnValue().getAs<
DefinedOrUnknownSVal
>();
78
79
if
(!ReturnV)
80
return
;
81
82
ProgramStateRef
State =
C
.getState();
83
if
(
ProgramStateRef
StTrue = State->assume(*ReturnV,
true
)) {
84
// The return value can be true, so transition to a state where it's true.
85
std::string Msg =
86
formatv(
"'{0}' returns true (by convention)"
,
getFunctionName
(
Call
));
87
C
.addTransition(StTrue,
C
.getNoteTag(Msg,
/*IsPrunable=*/
true
));
88
return
;
89
}
90
// Paranoia: if the return value is known to be false (which is highly
91
// unlikely, it's easy to ensure that the method always returns true), then
92
// produce a note that highlights that this unusual situation.
93
// Note that this checker is 'hidden' so it cannot produce a bug report.
94
std::string Msg = formatv(
"'{0}' returned false, breaking the convention "
95
"that it always returns true"
,
96
getFunctionName
(
Call
));
97
C
.addTransition(State,
C
.getNoteTag(Msg,
/*IsPrunable=*/
true
));
98
}
99
100
void
ento::registerReturnValueChecker(
CheckerManager
&Mgr) {
101
Mgr.
registerChecker
<ReturnValueChecker>();
102
}
103
104
bool
ento::shouldRegisterReturnValueChecker(
const
CheckerManager
&mgr) {
105
return
true
;
106
}
BuiltinCheckerRegistration.h
CallDescription.h
CallEvent.h
CheckerContext.h
CheckerManager.h
Checker.h
getFunctionName
static std::string getFunctionName(const CallEvent &Call)
Definition:
ReturnValueChecker.cpp:62
clang::CXXRecordDecl
Represents a C++ struct/union/class.
Definition:
DeclCXX.h:258
clang::DeclContext::getParent
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition:
DeclBase.h:2109
clang::ento::CallDescriptionSet
An immutable set of CallDescriptions.
Definition:
CallDescription.h:262
clang::ento::CallEvent
Represents an abstract call to a function or method along a particular path.
Definition:
CallEvent.h:153
clang::ento::CheckerContext
Definition:
CheckerContext.h:24
clang::ento::CheckerManager
Definition:
CheckerManager.h:126
clang::ento::CheckerManager::registerChecker
CHECKER * registerChecker(AT &&...Args)
Register a single-part checker (derived from Checker): construct its singleton instance,...
Definition:
CheckerManager.h:218
clang::ento::Checker
Simple checker classes that implement one frontend (i.e.
Definition:
Checker.h:553
clang::ento::DefinedOrUnknownSVal
Definition:
SVals.h:202
llvm::IntrusiveRefCntPtr< const ProgramState >
clang
The JSON file list parser is used to communicate input to InstallAPI.
Definition:
CalledOnceCheck.h:17
clang::LinkageSpecLanguageIDs::C
@ C
clang::OMPDeclareReductionInitKind::Call
@ Call
Generated on Tue Sep 2 2025 18:41:10 for clang by
1.9.6