/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //=======- ASTUtils.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 "ASTUtils.h" |
10 | | #include "PtrTypesSemantics.h" |
11 | | #include "clang/AST/CXXInheritance.h" |
12 | | #include "clang/AST/Decl.h" |
13 | | #include "clang/AST/DeclCXX.h" |
14 | | #include "clang/AST/ExprCXX.h" |
15 | | #include <optional> |
16 | | |
17 | | namespace clang { |
18 | | |
19 | | std::pair<const Expr *, bool> |
20 | 54 | tryToFindPtrOrigin(const Expr *E, bool StopAtFirstRefCountedObj) { |
21 | 106 | while (E) { |
22 | 106 | if (auto *cast = dyn_cast<CastExpr>(E)) { |
23 | 27 | if (StopAtFirstRefCountedObj) { |
24 | 25 | if (auto *ConversionFunc = |
25 | 25 | dyn_cast_or_null<FunctionDecl>(cast->getConversionFunction())) { |
26 | 1 | if (isCtorOfRefCounted(ConversionFunc)) |
27 | 0 | return {E, true}; |
28 | 1 | } |
29 | 25 | } |
30 | | // FIXME: This can give false "origin" that would lead to false negatives |
31 | | // in checkers. See https://reviews.llvm.org/D37023 for reference. |
32 | 27 | E = cast->getSubExpr(); |
33 | 27 | continue; |
34 | 27 | } |
35 | 79 | if (auto *call = dyn_cast<CallExpr>(E)) { |
36 | 40 | if (auto *memberCall = dyn_cast<CXXMemberCallExpr>(call)) { |
37 | 16 | std::optional<bool> IsGetterOfRefCt = isGetterOfRefCounted(memberCall->getMethodDecl()); |
38 | 16 | if (IsGetterOfRefCt && *IsGetterOfRefCt) { |
39 | 12 | E = memberCall->getImplicitObjectArgument(); |
40 | 12 | if (StopAtFirstRefCountedObj) { |
41 | 5 | return {E, true}; |
42 | 5 | } |
43 | 7 | continue; |
44 | 12 | } |
45 | 16 | } |
46 | | |
47 | 28 | if (auto *operatorCall = dyn_cast<CXXOperatorCallExpr>(E)) { |
48 | 0 | if (operatorCall->getNumArgs() == 1) { |
49 | 0 | E = operatorCall->getArg(0); |
50 | 0 | continue; |
51 | 0 | } |
52 | 0 | } |
53 | | |
54 | 28 | if (auto *callee = call->getDirectCallee()) { |
55 | 28 | if (isCtorOfRefCounted(callee)) { |
56 | 0 | if (StopAtFirstRefCountedObj) |
57 | 0 | return {E, true}; |
58 | | |
59 | 0 | E = call->getArg(0); |
60 | 0 | continue; |
61 | 0 | } |
62 | | |
63 | 28 | if (isPtrConversion(callee)) { |
64 | 11 | E = call->getArg(0); |
65 | 11 | continue; |
66 | 11 | } |
67 | 28 | } |
68 | 28 | } |
69 | 56 | if (auto *unaryOp = dyn_cast<UnaryOperator>(E)) { |
70 | | // FIXME: Currently accepts ANY unary operator. Is it OK? |
71 | 7 | E = unaryOp->getSubExpr(); |
72 | 7 | continue; |
73 | 7 | } |
74 | | |
75 | 49 | break; |
76 | 56 | } |
77 | | // Some other expression. |
78 | 49 | return {E, false}; |
79 | 54 | } |
80 | | |
81 | 36 | bool isASafeCallArg(const Expr *E) { |
82 | 36 | assert(E); |
83 | 36 | if (auto *Ref = dyn_cast<DeclRefExpr>(E)) { |
84 | 21 | if (auto *D = dyn_cast_or_null<VarDecl>(Ref->getFoundDecl())) { |
85 | 21 | if (isa<ParmVarDecl>(D) || D->isLocalVarDecl()3 ) |
86 | 18 | return true; |
87 | 21 | } |
88 | 21 | } |
89 | | |
90 | | // TODO: checker for method calls on non-refcounted objects |
91 | 18 | return isa<CXXThisExpr>(E); |
92 | 36 | } |
93 | | |
94 | | } // namespace clang |