Coverage Report

Created: 2023-09-21 18:56

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/StaticAnalyzer/Checkers/SmartPtrChecker.cpp
Line
Count
Source (jump to first uncovered line)
1
// SmartPtrChecker.cpp - Check for smart pointer dereference - 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 file defines a checker that check for null dereference of C++ smart
10
// pointer.
11
//
12
//===----------------------------------------------------------------------===//
13
#include "SmartPtr.h"
14
15
#include "clang/AST/DeclCXX.h"
16
#include "clang/AST/ExprCXX.h"
17
#include "clang/AST/Type.h"
18
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
19
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
20
#include "clang/StaticAnalyzer/Core/Checker.h"
21
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
22
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
23
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
24
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
25
#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
26
#include "llvm/ADT/StringRef.h"
27
28
using namespace clang;
29
using namespace ento;
30
31
namespace {
32
33
static const BugType *NullDereferenceBugTypePtr;
34
35
class SmartPtrChecker : public Checker<check::PreCall> {
36
public:
37
  void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
38
  BugType NullDereferenceBugType{this, "Null SmartPtr dereference",
39
                                 "C++ Smart Pointer"};
40
41
private:
42
  void reportBug(CheckerContext &C, const MemRegion *DerefRegion,
43
                 const CallEvent &Call) const;
44
  void explainDereference(llvm::raw_ostream &OS, const MemRegion *DerefRegion,
45
                          const CallEvent &Call) const;
46
};
47
} // end of anonymous namespace
48
49
// Define the inter-checker API.
50
namespace clang {
51
namespace ento {
52
namespace smartptr {
53
54
369
const BugType *getNullDereferenceBugType() { return NullDereferenceBugTypePtr; }
55
56
} // namespace smartptr
57
} // namespace ento
58
} // namespace clang
59
60
void SmartPtrChecker::checkPreCall(const CallEvent &Call,
61
1.06k
                                   CheckerContext &C) const {
62
1.06k
  if (!smartptr::isStdSmartPtrCall(Call))
63
473
    return;
64
594
  ProgramStateRef State = C.getState();
65
594
  const auto *OC = dyn_cast<CXXMemberOperatorCall>(&Call);
66
594
  if (!OC)
67
383
    return;
68
211
  const MemRegion *ThisRegion = OC->getCXXThisVal().getAsRegion();
69
211
  if (!ThisRegion)
70
0
    return;
71
72
211
  OverloadedOperatorKind OOK = OC->getOverloadedOperator();
73
211
  if (OOK == OO_Star || 
OOK == OO_Arrow197
) {
74
177
    if (smartptr::isNullSmartPtr(State, ThisRegion))
75
119
      reportBug(C, ThisRegion, Call);
76
177
  }
77
211
}
78
79
void SmartPtrChecker::reportBug(CheckerContext &C, const MemRegion *DerefRegion,
80
119
                                const CallEvent &Call) const {
81
119
  ExplodedNode *ErrNode = C.generateErrorNode();
82
119
  if (!ErrNode)
83
0
    return;
84
119
  llvm::SmallString<128> Str;
85
119
  llvm::raw_svector_ostream OS(Str);
86
119
  explainDereference(OS, DerefRegion, Call);
87
119
  auto R = std::make_unique<PathSensitiveBugReport>(NullDereferenceBugType,
88
119
                                                    OS.str(), ErrNode);
89
119
  R->markInteresting(DerefRegion);
90
119
  C.emitReport(std::move(R));
91
119
}
92
93
void SmartPtrChecker::explainDereference(llvm::raw_ostream &OS,
94
                                         const MemRegion *DerefRegion,
95
119
                                         const CallEvent &Call) const {
96
119
  OS << "Dereference of null smart pointer ";
97
119
  DerefRegion->printPretty(OS);
98
119
}
99
100
4
void ento::registerSmartPtrChecker(CheckerManager &Mgr) {
101
4
  SmartPtrChecker *Checker = Mgr.registerChecker<SmartPtrChecker>();
102
4
  NullDereferenceBugTypePtr = &Checker->NullDereferenceBugType;
103
4
}
104
105
8
bool ento::shouldRegisterSmartPtrChecker(const CheckerManager &mgr) {
106
8
  const LangOptions &LO = mgr.getLangOpts();
107
8
  return LO.CPlusPlus;
108
8
}