Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/AssumeModeling.cpp
213799 views
1
//=== AssumeModeling.cpp --------------------------------------------------===//
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 checker evaluates the builting assume functions.
10
// This checker also sinks execution paths leaving [[assume]] attributes with
11
// false assumptions.
12
//
13
//===----------------------------------------------------------------------===//
14
15
#include "clang/AST/AttrIterator.h"
16
#include "clang/Basic/Builtins.h"
17
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
18
#include "clang/StaticAnalyzer/Core/Checker.h"
19
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
20
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
21
#include "llvm/ADT/STLExtras.h"
22
23
using namespace clang;
24
using namespace ento;
25
26
namespace {
27
class AssumeModelingChecker
28
: public Checker<eval::Call, check::PostStmt<AttributedStmt>> {
29
public:
30
void checkPostStmt(const AttributedStmt *A, CheckerContext &C) const;
31
bool evalCall(const CallEvent &Call, CheckerContext &C) const;
32
};
33
} // namespace
34
35
void AssumeModelingChecker::checkPostStmt(const AttributedStmt *A,
36
CheckerContext &C) const {
37
if (!hasSpecificAttr<CXXAssumeAttr>(A->getAttrs()))
38
return;
39
40
for (const auto *Attr : getSpecificAttrs<CXXAssumeAttr>(A->getAttrs())) {
41
SVal AssumptionVal = C.getSVal(Attr->getAssumption());
42
43
// The assumption is not evaluated at all if it had sideffects; skip them.
44
if (AssumptionVal.isUnknown())
45
continue;
46
47
const auto *Assumption = AssumptionVal.getAsInteger();
48
if (Assumption && Assumption->isZero()) {
49
C.addSink();
50
}
51
}
52
}
53
54
bool AssumeModelingChecker::evalCall(const CallEvent &Call,
55
CheckerContext &C) const {
56
ProgramStateRef State = C.getState();
57
const auto *FD = dyn_cast_or_null<FunctionDecl>(Call.getDecl());
58
if (!FD)
59
return false;
60
61
if (!llvm::is_contained({Builtin::BI__builtin_assume, Builtin::BI__assume},
62
FD->getBuiltinID())) {
63
return false;
64
}
65
66
assert(Call.getNumArgs() > 0);
67
SVal Arg = Call.getArgSVal(0);
68
if (Arg.isUndef())
69
return true; // Return true to model purity.
70
71
State = State->assume(Arg.castAs<DefinedOrUnknownSVal>(), true);
72
if (!State) {
73
C.addSink();
74
return true;
75
}
76
77
C.addTransition(State);
78
return true;
79
}
80
81
void ento::registerAssumeModeling(CheckerManager &Mgr) {
82
Mgr.registerChecker<AssumeModelingChecker>();
83
}
84
85
bool ento::shouldRegisterAssumeModeling(const CheckerManager &) { return true; }
86
87