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#ifndef LLVM_CLANG_ANALYZER_WEBKIT_PTRTYPESEMANTICS_H
10#define LLVM_CLANG_ANALYZER_WEBKIT_PTRTYPESEMANTICS_H
11
12#include "llvm/ADT/APInt.h"
13#include "llvm/ADT/DenseMap.h"
14#include "llvm/ADT/DenseSet.h"
15#include "llvm/ADT/PointerUnion.h"
16#include <optional>
17#include <string>
18
19namespace clang {
20class CXXBaseSpecifier;
21class CXXMethodDecl;
22class CXXRecordDecl;
23class Decl;
24class FunctionDecl;
25class NamedDecl;
26class QualType;
27class RecordType;
28class Stmt;
29class TranslationUnitDecl;
30class Type;
31class TypedefDecl;
32class VarDecl;
33
34// Ref-countability of a type is implicitly defined by Ref<T> and RefPtr<T>
35// implementation. It can be modeled as: type T having public methods ref() and
36// deref()
37
38// In WebKit there are two ref-counted templated smart pointers: RefPtr<T> and
39// Ref<T>.
40
41/// \returns CXXRecordDecl of the base if the type has ref as a public method,
42/// nullptr if not, std::nullopt if inconclusive.
43std::optional<const clang::CXXRecordDecl *>
44hasPublicMethodInBase(const CXXBaseSpecifier *Base,
45 llvm::StringRef NameToMatch);
46
47/// \returns true if \p Class is ref-countable, false if not, std::nullopt if
48/// inconclusive.
49std::optional<bool> isRefCountable(const clang::CXXRecordDecl *Class);
50
51/// \returns true if \p Class is checked-pointer compatible, false if not,
52/// std::nullopt if inconclusive.
53std::optional<bool> isCheckedPtrCapable(const clang::CXXRecordDecl *Class);
54
55/// \returns true if \p Class is ref-counted, false if not.
56bool isRefCounted(const clang::CXXRecordDecl *Class);
57
58/// \returns true if \p Class is a CheckedPtr / CheckedRef, false if not.
59bool isCheckedPtr(const clang::CXXRecordDecl *Class);
60
61/// \returns true if \p Class is a RetainPtr, false if not.
62bool isRetainPtrOrOSPtr(const clang::CXXRecordDecl *Class);
63
64/// \returns true if \p Class is a weak smart pointer (WeakPtr, InlineWeakPtr,
65/// etc...), false if not.
66bool isWeakPtr(const clang::CXXRecordDecl *Class);
67
68/// \returns true if \p Class is a smart pointer (RefPtr, WeakPtr, etc...),
69/// false if not.
70bool isSmartPtr(const clang::CXXRecordDecl *Class);
71
72/// \returns true if \p Class is ref-countable AND not ref-counted, false if
73/// not, std::nullopt if inconclusive.
74std::optional<bool> isUncounted(const clang::QualType T);
75
76/// \returns true if \p Class is CheckedPtr capable AND not checked, false if
77/// not, std::nullopt if inconclusive.
78std::optional<bool> isUnchecked(const clang::QualType T);
79
80/// An inter-procedural analysis facility that detects CF types with the
81/// underlying pointer type.
82class RetainTypeChecker {
83 llvm::DenseMap<const RecordType *, const TypedefDecl *> CFPointees;
84 llvm::DenseSet<const Type *> RecordlessTypes;
85 bool IsARCEnabled{false};
86 bool DefaultSynthProperties{true};
87
88public:
89 void visitTranslationUnitDecl(const TranslationUnitDecl *);
90 void visitTypedef(const TypedefDecl *);
91 bool isUnretained(const QualType, bool ignoreARC = false);
92 bool isARCEnabled() const { return IsARCEnabled; }
93 bool defaultSynthProperties() const { return DefaultSynthProperties; }
94 const TypedefDecl *getCanonicalDecl(QualType);
95};
96
97/// \returns true if \p Class is ref-countable AND not ref-counted, false if
98/// not, std::nullopt if inconclusive.
99std::optional<bool> isUncounted(const clang::CXXRecordDecl* Class);
100
101/// \returns true if \p Class is CheckedPtr capable AND not checked, false if
102/// not, std::nullopt if inconclusive.
103std::optional<bool> isUnchecked(const clang::CXXRecordDecl *Class);
104
105/// \returns true if \p T is either a raw pointer or reference to an uncounted
106/// class, false if not, std::nullopt if inconclusive.
107std::optional<bool> isUncountedPtr(const clang::QualType T);
108
109/// \returns true if \p T is either a raw pointer or reference to an unchecked
110/// class, false if not, std::nullopt if inconclusive.
111std::optional<bool> isUncheckedPtr(const clang::QualType T);
112
113/// \returns true if \p T is a RefPtr, Ref, CheckedPtr, CheckedRef, or its
114/// variant, false if not.
115bool isRefOrCheckedPtrType(const clang::QualType T);
116
117/// \returns true if \p T is a RetainPtr, false if not.
118bool isRetainPtrOrOSPtrType(const clang::QualType T);
119
120/// \returns true if \p T is a RefPtr, Ref, CheckedPtr, CheckedRef, or
121/// unique_ptr, false if not.
122bool isOwnerPtrType(const clang::QualType T);
123
124/// \returns true if \p F creates ref-countable object from uncounted parameter,
125/// false if not.
126bool isCtorOfRefCounted(const clang::FunctionDecl *F);
127
128/// \returns true if \p F creates checked ptr object from uncounted parameter,
129/// false if not.
130bool isCtorOfCheckedPtr(const clang::FunctionDecl *F);
131
132/// \returns true if \p F creates ref-countable or checked ptr object from
133/// uncounted parameter, false if not.
134bool isCtorOfSafePtr(const clang::FunctionDecl *F);
135
136/// \returns true if \p F is std::move or WTF::move.
137bool isStdOrWTFMove(const clang::FunctionDecl *F);
138
139/// \returns true if \p Name is RefPtr, Ref, or its variant, false if not.
140bool isRefType(const std::string &Name);
141
142/// \returns true if \p Name is CheckedRef or CheckedPtr, false if not.
143bool isCheckedPtr(const std::string &Name);
144
145/// \returns true if \p Name is RetainPtr or its variant, false if not.
146bool isRetainPtrOrOSPtr(const std::string &Name);
147
148/// \returns true if \p Name is an owning smart pointer such as Ref, CheckedPtr,
149/// and unique_ptr.
150bool isOwnerPtr(const std::string &Name);
151
152/// \returns true if \p Name is a smart pointer type name, false if not.
153bool isSmartPtrClass(const std::string &Name);
154
155/// \returns true if \p M is getter of a ref-counted class, false if not.
156std::optional<bool> isGetterOfSafePtr(const clang::CXXMethodDecl *Method);
157
158/// \returns true if \p F is a conversion between ref-countable or ref-counted
159/// pointer types.
160bool isPtrConversion(const FunctionDecl *F);
161
162/// \returns true if \p F's return type is annotated with
163/// [[clang::annotate_type("webkit.nodelete")]].
164bool isNoDeleteFunction(const FunctionDecl *F);
165
166/// \returns true if \p F is a builtin function which is considered trivial.
167bool isTrivialBuiltinFunction(const FunctionDecl *F);
168
169/// \returns true if \p F is a static singleton function.
170bool isSingleton(const NamedDecl *F);
171
172/// An inter-procedural analysis facility that detects functions with "trivial"
173/// behavior with respect to reference counting, such as simple field getters.
174class TrivialFunctionAnalysis {
175public:
176 /// \returns true if \p D is a "trivial" function.
177 bool isTrivial(const Decl *D, const Stmt **OffendingStmt = nullptr) const {
178 return isTrivialImpl(D, Cache&: TheCache, OffendingStmt);
179 }
180 bool isTrivial(const Stmt *S, const Stmt **OffendingStmt = nullptr) const {
181 return isTrivialImpl(S, Cache&: TheCache, OffendingStmt);
182 }
183 bool hasTrivialDtor(const VarDecl *VD) const {
184 return hasTrivialDtorImpl(VD, Cache&: TheCache);
185 }
186
187private:
188 friend class TrivialFunctionAnalysisVisitor;
189
190 using CacheTy =
191 llvm::DenseMap<llvm::PointerUnion<const Decl *, const Stmt *>, bool>;
192 mutable CacheTy TheCache{};
193
194 static bool isTrivialImpl(const Decl *D, CacheTy &Cache, const Stmt **);
195 static bool isTrivialImpl(const Stmt *S, CacheTy &Cache, const Stmt **);
196 static bool hasTrivialDtorImpl(const VarDecl *VD, CacheTy &Cache);
197};
198
199} // namespace clang
200
201#endif
202