clang  14.0.0git
PtrTypesSemantics.cpp
Go to the documentation of this file.
1 //=======- PtrTypesSemantics.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 "PtrTypesSemantics.h"
10 #include "ASTUtils.h"
12 #include "clang/AST/Decl.h"
13 #include "clang/AST/DeclCXX.h"
14 #include "clang/AST/ExprCXX.h"
15 #include "llvm/ADT/Optional.h"
16 
17 using llvm::Optional;
18 using namespace clang;
19 
20 namespace {
21 
22 bool hasPublicRefAndDeref(const CXXRecordDecl *R) {
23  assert(R);
24  assert(R->hasDefinition());
25 
26  bool hasRef = false;
27  bool hasDeref = false;
28  for (const CXXMethodDecl *MD : R->methods()) {
29  const auto MethodName = safeGetName(MD);
30 
31  if (MethodName == "ref" && MD->getAccess() == AS_public) {
32  if (hasDeref)
33  return true;
34  hasRef = true;
35  } else if (MethodName == "deref" && MD->getAccess() == AS_public) {
36  if (hasRef)
37  return true;
38  hasDeref = true;
39  }
40  }
41  return false;
42 }
43 
44 } // namespace
45 
46 namespace clang {
47 
50  assert(Base);
51 
52  const Type *T = Base->getType().getTypePtrOrNull();
53  if (!T)
54  return llvm::None;
55 
56  const CXXRecordDecl *R = T->getAsCXXRecordDecl();
57  if (!R)
58  return llvm::None;
59  if (!R->hasDefinition())
60  return llvm::None;
61 
62  return hasPublicRefAndDeref(R) ? R : nullptr;
63 }
64 
66  assert(R);
67 
68  R = R->getDefinition();
69  if (!R)
70  return llvm::None;
71 
72  if (hasPublicRefAndDeref(R))
73  return true;
74 
75  CXXBasePaths Paths;
76  Paths.setOrigin(const_cast<CXXRecordDecl *>(R));
77 
78  bool AnyInconclusiveBase = false;
79  const auto isRefCountableBase =
80  [&AnyInconclusiveBase](const CXXBaseSpecifier *Base, CXXBasePath &) {
83  if (!IsRefCountable) {
84  AnyInconclusiveBase = true;
85  return false;
86  }
87  return (*IsRefCountable) != nullptr;
88  };
89 
90  bool BasesResult = R->lookupInBases(isRefCountableBase, Paths,
91  /*LookupInDependent =*/true);
92  if (AnyInconclusiveBase)
93  return llvm::None;
94 
95  return BasesResult;
96 }
97 
99  assert(F);
100  const auto &FunctionName = safeGetName(F);
101 
102  return FunctionName == "Ref" || FunctionName == "makeRef"
103 
104  || FunctionName == "RefPtr" || FunctionName == "makeRefPtr"
105 
106  || FunctionName == "UniqueRef" || FunctionName == "makeUniqueRef" ||
107  FunctionName == "makeUniqueRefWithoutFastMallocCheck"
108 
109  || FunctionName == "String" || FunctionName == "AtomString" ||
110  FunctionName == "UniqueString"
111  // FIXME: Implement as attribute.
112  || FunctionName == "Identifier";
113 }
114 
116  // Keep isRefCounted first as it's cheaper.
117  if (isRefCounted(Class))
118  return false;
119 
120  llvm::Optional<bool> IsRefCountable = isRefCountable(Class);
121  if (!IsRefCountable)
122  return llvm::None;
123 
124  return (*IsRefCountable);
125 }
126 
128  assert(T);
129 
130  if (T->isPointerType() || T->isReferenceType()) {
131  if (auto *CXXRD = T->getPointeeCXXRecordDecl()) {
132  return isUncounted(CXXRD);
133  }
134  }
135  return false;
136 }
137 
139  assert(M);
140 
141  if (isa<CXXMethodDecl>(M)) {
142  const CXXRecordDecl *calleeMethodsClass = M->getParent();
143  auto className = safeGetName(calleeMethodsClass);
144  auto methodName = safeGetName(M);
145 
146  if (((className == "Ref" || className == "RefPtr") &&
147  methodName == "get") ||
148  ((className == "String" || className == "AtomString" ||
149  className == "AtomStringImpl" || className == "UniqueString" ||
150  className == "UniqueStringImpl" || className == "Identifier") &&
151  methodName == "impl"))
152  return true;
153 
154  // Ref<T> -> T conversion
155  // FIXME: Currently allowing any Ref<T> -> whatever cast.
156  if (className == "Ref" || className == "RefPtr") {
157  if (auto *maybeRefToRawOperator = dyn_cast<CXXConversionDecl>(M)) {
158  if (auto *targetConversionType =
159  maybeRefToRawOperator->getConversionType().getTypePtrOrNull()) {
160  return isUncountedPtr(targetConversionType);
161  }
162  }
163  }
164  }
165  return false;
166 }
167 
168 bool isRefCounted(const CXXRecordDecl *R) {
169  assert(R);
170  if (auto *TmplR = R->getTemplateInstantiationPattern()) {
171  // FIXME: String/AtomString/UniqueString
172  const auto &ClassName = safeGetName(TmplR);
173  return ClassName == "RefPtr" || ClassName == "Ref";
174  }
175  return false;
176 }
177 
179  assert(F);
180  if (isCtorOfRefCounted(F))
181  return true;
182 
183  // FIXME: check # of params == 1
184  const auto FunctionName = safeGetName(F);
185  if (FunctionName == "getPtr" || FunctionName == "WeakPtr" ||
186  FunctionName == "makeWeakPtr"
187 
188  || FunctionName == "downcast" || FunctionName == "bitwise_cast")
189  return true;
190 
191  return false;
192 }
193 
194 } // namespace clang
clang::isUncounted
llvm::Optional< bool > isUncounted(const CXXRecordDecl *Class)
Definition: PtrTypesSemantics.cpp:115
Optional
llvm::Optional< T > Optional
Definition: ByteCodeExprGen.cpp:23
CXXInheritance.h
clang::CXXRecordDecl::getDefinition
CXXRecordDecl * getDefinition() const
Definition: DeclCXX.h:535
clang::isUncountedPtr
llvm::Optional< bool > isUncountedPtr(const Type *T)
Definition: PtrTypesSemantics.cpp:127
DeclCXX.h
llvm::Optional
Definition: LLVM.h:40
clang::CXXRecordDecl::lookupInBases
bool lookupInBases(BaseMatchesCallback BaseMatches, CXXBasePaths &Paths, bool LookupInDependent=false) const
Look for entities within the base classes of this C++ class, transitively searching all base class su...
Definition: CXXInheritance.cpp:307
clang::Type
The base class of the type hierarchy.
Definition: Type.h:1490
Decl.h
clang::Type::isReferenceType
bool isReferenceType() const
Definition: Type.h:6684
clang::isCtorOfRefCounted
bool isCtorOfRefCounted(const clang::FunctionDecl *F)
Definition: PtrTypesSemantics.cpp:98
clang::CXXRecordDecl::methods
method_range methods() const
Definition: DeclCXX.h:631
clang::isRefCounted
bool isRefCounted(const CXXRecordDecl *R)
Definition: PtrTypesSemantics.cpp:168
clang::AS_public
@ AS_public
Definition: Specifiers.h:109
clang::Type::getPointeeCXXRecordDecl
const CXXRecordDecl * getPointeeCXXRecordDecl() const
If this is a pointer or reference to a RecordType, return the CXXRecordDecl that the type refers to.
Definition: Type.cpp:1745
clang::safeGetName
std::string safeGetName(const T *ASTNode)
Definition: ASTUtils.h:69
clang::Type::getAsCXXRecordDecl
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.cpp:1760
ExprCXX.h
Base
clang::isRefCountable
llvm::Optional< const clang::CXXRecordDecl * > isRefCountable(const CXXBaseSpecifier *Base)
Definition: PtrTypesSemantics.cpp:49
clang::CXXRecordDecl
Represents a C++ struct/union/class.
Definition: DeclCXX.h:255
PtrTypesSemantics.h
clang::Type::isPointerType
bool isPointerType() const
Definition: Type.h:6672
clang::isPtrConversion
bool isPtrConversion(const FunctionDecl *F)
Definition: PtrTypesSemantics.cpp:178
ASTUtils.h
clang::CXXBasePath
Represents a path from a specific derived class (which is not represented as part of the path) to a p...
Definition: CXXInheritance.h:70
clang
Definition: CalledOnceCheck.h:17
clang::CXXBaseSpecifier
Represents a base class of a C++ class.
Definition: DeclCXX.h:147
clang::CXXRecordDecl::hasDefinition
bool hasDefinition() const
Definition: DeclCXX.h:542
clang::CXXBasePaths
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
Definition: CXXInheritance.h:117
clang::CXXRecordDecl::getTemplateInstantiationPattern
const CXXRecordDecl * getTemplateInstantiationPattern() const
Retrieve the record declaration from which this record could be instantiated.
Definition: DeclCXX.cpp:1842
clang::FunctionDecl
Represents a function declaration or definition.
Definition: Decl.h:1856
clang::isGetterOfRefCounted
Optional< bool > isGetterOfRefCounted(const CXXMethodDecl *M)
Definition: PtrTypesSemantics.cpp:138
clang::CXXMethodDecl::getParent
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Definition: DeclCXX.h:2063
clang::CXXMethodDecl
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:1948