/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Analysis/FlowSensitive/Models/ChromiumCheckModel.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- ChromiumCheckModel.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 "clang/Analysis/FlowSensitive/Models/ChromiumCheckModel.h" |
10 | | #include "clang/AST/Decl.h" |
11 | | #include "clang/AST/DeclCXX.h" |
12 | | #include "llvm/ADT/DenseSet.h" |
13 | | |
14 | | namespace clang { |
15 | | namespace dataflow { |
16 | | |
17 | | /// Determines whether `D` is one of the methods used to implement Chromium's |
18 | | /// `CHECK` macros. Populates `CheckDecls`, if empty. |
19 | | bool isCheckLikeMethod(llvm::SmallDenseSet<const CXXMethodDecl *> &CheckDecls, |
20 | 26 | const CXXMethodDecl &D) { |
21 | | // All of the methods of interest are static, so avoid any lookup for |
22 | | // non-static methods (the common case). |
23 | 26 | if (!D.isStatic()) |
24 | 16 | return false; |
25 | | |
26 | 10 | if (CheckDecls.empty()) { |
27 | | // Attempt to initialize `CheckDecls` with the methods in class |
28 | | // `CheckError`. |
29 | 6 | const CXXRecordDecl *ParentClass = D.getParent(); |
30 | 6 | if (ParentClass == nullptr || !ParentClass->getDeclName().isIdentifier() || |
31 | 6 | ParentClass->getName() != "CheckError") |
32 | 0 | return false; |
33 | | |
34 | | // Check whether namespace is "logging". |
35 | 6 | const auto *N = |
36 | 6 | dyn_cast_or_null<NamespaceDecl>(ParentClass->getDeclContext()); |
37 | 6 | if (N == nullptr || !N->getDeclName().isIdentifier() || |
38 | 6 | N->getName() != "logging") |
39 | 0 | return false; |
40 | | |
41 | | // Check whether "logging" is a top-level namespace. |
42 | 6 | if (N->getParent() == nullptr || !N->getParent()->isTranslationUnit()) |
43 | 2 | return false; |
44 | | |
45 | 4 | for (const CXXMethodDecl *M : ParentClass->methods()) |
46 | 44 | if (M->getDeclName().isIdentifier() && M->getName().endswith("Check")24 ) |
47 | 20 | CheckDecls.insert(M); |
48 | 4 | } |
49 | | |
50 | 8 | return CheckDecls.contains(&D); |
51 | 10 | } |
52 | | |
53 | 274 | bool ChromiumCheckModel::transfer(const CFGElement &Element, Environment &Env) { |
54 | 274 | auto CS = Element.getAs<CFGStmt>(); |
55 | 274 | if (!CS) |
56 | 18 | return false; |
57 | 256 | auto Stmt = CS->getStmt(); |
58 | 256 | if (const auto *Call = dyn_cast<CallExpr>(Stmt)) { |
59 | 26 | if (const auto *M = dyn_cast<CXXMethodDecl>(Call->getDirectCallee())) { |
60 | 26 | if (isCheckLikeMethod(CheckDecls, *M)) { |
61 | | // Mark this branch as unreachable. |
62 | 8 | Env.assume(Env.arena().makeLiteral(false)); |
63 | 8 | return true; |
64 | 8 | } |
65 | 26 | } |
66 | 26 | } |
67 | 248 | return false; |
68 | 256 | } |
69 | | |
70 | | } // namespace dataflow |
71 | | } // namespace clang |