clang-tools  14.0.0git
Aliasing.cpp
Go to the documentation of this file.
1 //===------------- Aliasing.cpp - clang-tidy ------------------------------===//
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 "Aliasing.h"
10 
11 #include "clang/AST/Expr.h"
12 #include "clang/AST/ExprCXX.h"
13 
14 namespace clang {
15 namespace tidy {
16 namespace utils {
17 
18 /// Return whether \p S is a reference to the declaration of \p Var.
19 static bool isAccessForVar(const Stmt *S, const VarDecl *Var) {
20  if (const auto *DRE = dyn_cast<DeclRefExpr>(S))
21  return DRE->getDecl() == Var;
22 
23  return false;
24 }
25 
26 static bool capturesByRef(const CXXRecordDecl *RD, const VarDecl *Var) {
27  return llvm::any_of(RD->captures(), [Var](const LambdaCapture &C) {
28  return C.capturesVariable() && C.getCaptureKind() == LCK_ByRef &&
29  C.getCapturedVar() == Var;
30  });
31 }
32 
33 /// Return whether \p Var has a pointer or reference in \p S.
34 static bool isPtrOrReferenceForVar(const Stmt *S, const VarDecl *Var) {
35  // Treat block capture by reference as a form of taking a reference.
36  if (Var->isEscapingByref())
37  return true;
38 
39  if (const auto *DS = dyn_cast<DeclStmt>(S)) {
40  for (const Decl *D : DS->getDeclGroup()) {
41  if (const auto *LeftVar = dyn_cast<VarDecl>(D)) {
42  if (LeftVar->hasInit() && LeftVar->getType()->isReferenceType()) {
43  return isAccessForVar(LeftVar->getInit(), Var);
44  }
45  }
46  }
47  } else if (const auto *UnOp = dyn_cast<UnaryOperator>(S)) {
48  if (UnOp->getOpcode() == UO_AddrOf)
49  return isAccessForVar(UnOp->getSubExpr(), Var);
50  } else if (const auto *LE = dyn_cast<LambdaExpr>(S)) {
51  // Treat lambda capture by reference as a form of taking a reference.
52  return capturesByRef(LE->getLambdaClass(), Var);
53  } else if (const auto *ILE = dyn_cast<InitListExpr>(S)) {
54  return llvm::any_of(ILE->inits(), [Var](const Expr *ChildE) {
55  // If the child expression is a reference to Var, this means that it's
56  // used as an initializer of a reference-typed field. Otherwise
57  // it would have been surrounded with an implicit lvalue-to-rvalue cast.
58  return isAccessForVar(ChildE, Var);
59  });
60  }
61 
62  return false;
63 }
64 
65 /// Return whether \p Var has a pointer or reference in \p S.
66 static bool hasPtrOrReferenceInStmt(const Stmt *S, const VarDecl *Var) {
67  if (isPtrOrReferenceForVar(S, Var))
68  return true;
69 
70  for (const Stmt *Child : S->children()) {
71  if (!Child)
72  continue;
73 
74  if (hasPtrOrReferenceInStmt(Child, Var))
75  return true;
76  }
77 
78  return false;
79 }
80 
81 static bool refersToEnclosingLambdaCaptureByRef(const Decl *Func,
82  const VarDecl *Var) {
83  const auto *MD = dyn_cast<CXXMethodDecl>(Func);
84  if (!MD)
85  return false;
86 
87  const CXXRecordDecl *RD = MD->getParent();
88  if (!RD->isLambda())
89  return false;
90 
91  return capturesByRef(RD, Var);
92 }
93 
94 bool hasPtrOrReferenceInFunc(const Decl *Func, const VarDecl *Var) {
95  return hasPtrOrReferenceInStmt(Func->getBody(), Var) ||
97 }
98 
99 } // namespace utils
100 } // namespace tidy
101 } // namespace clang
clang::doc::MD
static GeneratorRegistry::Add< MDGenerator > MD(MDGenerator::Format, "Generator for MD output.")
clang::tidy::utils::isPtrOrReferenceForVar
static bool isPtrOrReferenceForVar(const Stmt *S, const VarDecl *Var)
Return whether Var has a pointer or reference in S.
Definition: Aliasing.cpp:34
ns1::ns2::D
@ D
Definition: CategoricalFeature.h:3
Decl
const FunctionDecl * Decl
Definition: AvoidBindCheck.cpp:100
clang::tidy::utils::refersToEnclosingLambdaCaptureByRef
static bool refersToEnclosingLambdaCaptureByRef(const Decl *Func, const VarDecl *Var)
Definition: Aliasing.cpp:81
clang::tidy::utils::isAccessForVar
static bool isAccessForVar(const Stmt *S, const VarDecl *Var)
Return whether S is a reference to the declaration of Var.
Definition: Aliasing.cpp:19
clang::tidy::utils::hasPtrOrReferenceInFunc
bool hasPtrOrReferenceInFunc(const Decl *Func, const VarDecl *Var)
Returns whether Var has a pointer or reference in Func.
Definition: Aliasing.cpp:94
Aliasing.h
C
const Criteria C
Definition: FunctionCognitiveComplexityCheck.cpp:93
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
clang::tidy::utils::hasPtrOrReferenceInStmt
static bool hasPtrOrReferenceInStmt(const Stmt *S, const VarDecl *Var)
Return whether Var has a pointer or reference in S.
Definition: Aliasing.cpp:66
clang::tidy::utils::capturesByRef
static bool capturesByRef(const CXXRecordDecl *RD, const VarDecl *Var)
Definition: Aliasing.cpp:26