clang  14.0.0git
ASTUtils.cpp
Go to the documentation of this file.
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"
12 #include "clang/AST/Decl.h"
13 #include "clang/AST/DeclCXX.h"
14 #include "clang/AST/ExprCXX.h"
15 
16 using llvm::Optional;
17 namespace clang {
18 
19 std::pair<const Expr *, bool>
20 tryToFindPtrOrigin(const Expr *E, bool StopAtFirstRefCountedObj) {
21  while (E) {
22  if (auto *cast = dyn_cast<CastExpr>(E)) {
23  if (StopAtFirstRefCountedObj) {
24  if (auto *ConversionFunc =
25  dyn_cast_or_null<FunctionDecl>(cast->getConversionFunction())) {
26  if (isCtorOfRefCounted(ConversionFunc))
27  return {E, true};
28  }
29  }
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  E = cast->getSubExpr();
33  continue;
34  }
35  if (auto *call = dyn_cast<CallExpr>(E)) {
36  if (auto *memberCall = dyn_cast<CXXMemberCallExpr>(call)) {
37  Optional<bool> IsGetterOfRefCt =
38  isGetterOfRefCounted(memberCall->getMethodDecl());
39  if (IsGetterOfRefCt && *IsGetterOfRefCt) {
40  E = memberCall->getImplicitObjectArgument();
41  if (StopAtFirstRefCountedObj) {
42  return {E, true};
43  }
44  continue;
45  }
46  }
47 
48  if (auto *operatorCall = dyn_cast<CXXOperatorCallExpr>(E)) {
49  if (operatorCall->getNumArgs() == 1) {
50  E = operatorCall->getArg(0);
51  continue;
52  }
53  }
54 
55  if (auto *callee = call->getDirectCallee()) {
56  if (isCtorOfRefCounted(callee)) {
57  if (StopAtFirstRefCountedObj)
58  return {E, true};
59 
60  E = call->getArg(0);
61  continue;
62  }
63 
64  if (isPtrConversion(callee)) {
65  E = call->getArg(0);
66  continue;
67  }
68  }
69  }
70  if (auto *unaryOp = dyn_cast<UnaryOperator>(E)) {
71  // FIXME: Currently accepts ANY unary operator. Is it OK?
72  E = unaryOp->getSubExpr();
73  continue;
74  }
75 
76  break;
77  }
78  // Some other expression.
79  return {E, false};
80 }
81 
82 bool isASafeCallArg(const Expr *E) {
83  assert(E);
84  if (auto *Ref = dyn_cast<DeclRefExpr>(E)) {
85  if (auto *D = dyn_cast_or_null<VarDecl>(Ref->getFoundDecl())) {
86  if (isa<ParmVarDecl>(D) || D->isLocalVarDecl())
87  return true;
88  }
89  }
90 
91  // TODO: checker for method calls on non-refcounted objects
92  return isa<CXXThisExpr>(E);
93 }
94 
95 } // namespace clang
Optional
llvm::Optional< T > Optional
Definition: ByteCodeExprGen.cpp:23
CXXInheritance.h
clang::cast
U cast(CodeGen::Address addr)
Definition: Address.h:108
DeclCXX.h
llvm::Optional< bool >
clang::tryToFindPtrOrigin
std::pair< const Expr *, bool > tryToFindPtrOrigin(const Expr *E, bool StopAtFirstRefCountedObj)
This function de-facto defines a set of transformations that we consider safe (in heuristical sense).
Definition: ASTUtils.cpp:20
clang::isASafeCallArg
bool isASafeCallArg(const Expr *E)
For E referring to a ref-countable/-counted pointer/reference we return whether it's a safe call argu...
Definition: ASTUtils.cpp:82
Decl.h
clang::isCtorOfRefCounted
bool isCtorOfRefCounted(const clang::FunctionDecl *F)
Definition: PtrTypesSemantics.cpp:98
ExprCXX.h
PtrTypesSemantics.h
clang::isPtrConversion
bool isPtrConversion(const FunctionDecl *F)
Definition: PtrTypesSemantics.cpp:178
ASTUtils.h
clang
Definition: CalledOnceCheck.h:17
clang::Expr
This represents one expression.
Definition: Expr.h:109
clang::isGetterOfRefCounted
Optional< bool > isGetterOfRefCounted(const CXXMethodDecl *M)
Definition: PtrTypesSemantics.cpp:138