clang
20.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/ADT/SmallVector.h"
26
#include "llvm/Support/FormatVariadic.h"
27
#include <optional>
28
29
using namespace
clang
;
30
using namespace
ento;
31
using
llvm::formatv;
32
33
namespace
{
34
class
ReturnValueChecker :
public
Checker
<check::PostCall> {
35
public
:
36
void
checkPostCall(
const
CallEvent
&
Call
,
CheckerContext
&
C
)
const
;
37
38
private
:
39
const
CallDescriptionSet
Methods = {
40
// These are known in the LLVM project: 'Error()'
41
{CDM::CXXMethod, {
"ARMAsmParser"
,
"Error"
}},
42
{CDM::CXXMethod, {
"HexagonAsmParser"
,
"Error"
}},
43
{CDM::CXXMethod, {
"LLLexer"
,
"Error"
}},
44
{CDM::CXXMethod, {
"LLParser"
,
"Error"
}},
45
{CDM::CXXMethod, {
"MCAsmParser"
,
"Error"
}},
46
{CDM::CXXMethod, {
"MCAsmParserExtension"
,
"Error"
}},
47
{CDM::CXXMethod, {
"TGParser"
,
"Error"
}},
48
{CDM::CXXMethod, {
"X86AsmParser"
,
"Error"
}},
49
// 'TokError()'
50
{CDM::CXXMethod, {
"LLParser"
,
"TokError"
}},
51
{CDM::CXXMethod, {
"MCAsmParser"
,
"TokError"
}},
52
{CDM::CXXMethod, {
"MCAsmParserExtension"
,
"TokError"
}},
53
{CDM::CXXMethod, {
"TGParser"
,
"TokError"
}},
54
// 'error()'
55
{CDM::CXXMethod, {
"MIParser"
,
"error"
}},
56
{CDM::CXXMethod, {
"WasmAsmParser"
,
"error"
}},
57
{CDM::CXXMethod, {
"WebAssemblyAsmParser"
,
"error"
}},
58
// Other
59
{CDM::CXXMethod, {
"AsmParser"
,
"printError"
}}};
60
};
61
}
// namespace
62
63
static
std::string
getName
(
const
CallEvent
&
Call
) {
64
std::string Name;
65
if
(
const
auto
*MD = dyn_cast<CXXMethodDecl>(
Call
.getDecl()))
66
if
(
const
CXXRecordDecl
*RD = MD->
getParent
())
67
Name += RD->getNameAsString() +
"::"
;
68
69
Name +=
Call
.getCalleeIdentifier()->getName();
70
return
Name;
71
}
72
73
void
ReturnValueChecker::checkPostCall(
const
CallEvent
&
Call
,
74
CheckerContext
&
C
)
const
{
75
if
(!Methods.contains(
Call
))
76
return
;
77
78
auto
ReturnV =
Call
.getReturnValue().getAs<
DefinedOrUnknownSVal
>();
79
80
if
(!ReturnV)
81
return
;
82
83
ProgramStateRef
State =
C
.getState();
84
if
(
ProgramStateRef
StTrue = State->assume(*ReturnV,
true
)) {
85
// The return value can be true, so transition to a state where it's true.
86
std::string Msg =
87
formatv(
"'{0}' returns true (by convention)"
,
getName
(
Call
));
88
C
.addTransition(StTrue,
C
.getNoteTag(Msg,
/*IsPrunable=*/
true
));
89
return
;
90
}
91
// Paranoia: if the return value is known to be false (which is highly
92
// unlikely, it's easy to ensure that the method always returns true), then
93
// produce a note that highlights that this unusual situation.
94
// Note that this checker is 'hidden' so it cannot produce a bug report.
95
std::string Msg = formatv(
"'{0}' returned false, breaking the convention "
96
"that it always returns true"
,
97
getName
(
Call
));
98
C
.addTransition(State,
C
.getNoteTag(Msg,
/*IsPrunable=*/
true
));
99
}
100
101
void
ento::registerReturnValueChecker(
CheckerManager
&Mgr) {
102
Mgr.
registerChecker
<ReturnValueChecker>();
103
}
104
105
bool
ento::shouldRegisterReturnValueChecker(
const
CheckerManager
&mgr) {
106
return
true
;
107
}
BuiltinCheckerRegistration.h
CallDescription.h
CallEvent.h
CheckerContext.h
CheckerManager.h
Checker.h
getName
static std::string getName(const CallEvent &Call)
Definition:
ReturnValueChecker.cpp:63
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:2090
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)
Used to register checkers.
Definition:
CheckerManager.h:204
clang::ento::Checker
Definition:
Checker.h:512
clang::ento::DefinedOrUnknownSVal
Definition:
SVals.h:199
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 Nov 19 2024 23:05:23 for clang by
1.9.6