Coverage Report

Created: 2022-07-16 07:03

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp
Line
Count
Source (jump to first uncovered line)
1
//=======- UncountedLambdaCapturesChecker.cpp --------------------*- 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
#include "DiagOutputUtils.h"
10
#include "PtrTypesSemantics.h"
11
#include "clang/AST/CXXInheritance.h"
12
#include "clang/AST/RecursiveASTVisitor.h"
13
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
14
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
15
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
16
#include "clang/StaticAnalyzer/Core/Checker.h"
17
18
using namespace clang;
19
using namespace ento;
20
21
namespace {
22
class UncountedLambdaCapturesChecker
23
    : public Checker<check::ASTDecl<TranslationUnitDecl>> {
24
private:
25
  BugType Bug{this, "Lambda capture of uncounted variable",
26
              "WebKit coding guidelines"};
27
  mutable BugReporter *BR;
28
29
public:
30
  void checkASTDecl(const TranslationUnitDecl *TUD, AnalysisManager &MGR,
31
1
                    BugReporter &BRArg) const {
32
1
    BR = &BRArg;
33
34
    // The calls to checkAST* from AnalysisConsumer don't
35
    // visit template instantiations or lambda classes. We
36
    // want to visit those, so we make our own RecursiveASTVisitor.
37
1
    struct LocalVisitor : public RecursiveASTVisitor<LocalVisitor> {
38
1
      const UncountedLambdaCapturesChecker *Checker;
39
1
      explicit LocalVisitor(const UncountedLambdaCapturesChecker *Checker)
40
1
          : Checker(Checker) {
41
1
        assert(Checker);
42
1
      }
43
44
9
      bool shouldVisitTemplateInstantiations() const { return true; }
45
105
      bool shouldVisitImplicitCode() const { return false; }
46
47
10
      bool VisitLambdaExpr(LambdaExpr *L) {
48
10
        Checker->visitLambdaExpr(L);
49
10
        return true;
50
10
      }
51
1
    };
52
53
1
    LocalVisitor visitor(this);
54
1
    visitor.TraverseDecl(const_cast<TranslationUnitDecl *>(TUD));
55
1
  }
56
57
10
  void visitLambdaExpr(LambdaExpr *L) const {
58
10
    for (const LambdaCapture &C : L->captures()) {
59
8
      if (C.capturesVariable()) {
60
8
        VarDecl *CapturedVar = C.getCapturedVar();
61
8
        if (auto *CapturedVarType = CapturedVar->getType().getTypePtrOrNull()) {
62
8
          Optional<bool> IsUncountedPtr = isUncountedPtr(CapturedVarType);
63
8
          if (IsUncountedPtr && *IsUncountedPtr) {
64
8
            reportBug(C, CapturedVar, CapturedVarType);
65
8
          }
66
8
        }
67
8
      }
68
8
    }
69
10
  }
70
71
  void reportBug(const LambdaCapture &Capture, VarDecl *CapturedVar,
72
8
                 const Type *T) const {
73
8
    assert(CapturedVar);
74
75
0
    SmallString<100> Buf;
76
8
    llvm::raw_svector_ostream Os(Buf);
77
78
8
    if (Capture.isExplicit()) {
79
4
      Os << "Captured ";
80
4
    } else {
81
4
      Os << "Implicitly captured ";
82
4
    }
83
8
    if (T->isPointerType()) {
84
4
      Os << "raw-pointer ";
85
4
    } else {
86
4
      assert(T->isReferenceType());
87
0
      Os << "reference ";
88
4
    }
89
90
0
    printQuotedQualifiedName(Os, Capture.getCapturedVar());
91
8
    Os << " to uncounted type is unsafe.";
92
93
8
    PathDiagnosticLocation BSLoc(Capture.getLocation(), BR->getSourceManager());
94
8
    auto Report = std::make_unique<BasicBugReport>(Bug, Os.str(), BSLoc);
95
8
    BR->emitReport(std::move(Report));
96
8
  }
97
};
98
} // namespace
99
100
1
void ento::registerUncountedLambdaCapturesChecker(CheckerManager &Mgr) {
101
1
  Mgr.registerChecker<UncountedLambdaCapturesChecker>();
102
1
}
103
104
bool ento::shouldRegisterUncountedLambdaCapturesChecker(
105
2
    const CheckerManager &mgr) {
106
2
  return true;
107
2
}