Coverage Report

Created: 2023-09-12 09:32

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