clang 24.0.0git
RawPtrRefSafetyModel.cpp
Go to the documentation of this file.
1//=======- RawPtrRefSafetyModel.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
10#include "ASTUtils.h"
11#include "DiagOutputUtils.h"
12#include "clang/AST/Decl.h"
13#include "clang/AST/Expr.h"
14#include "clang/AST/ExprObjC.h"
15#include "clang/AST/Type.h"
18
19using namespace clang;
20
21namespace {
22
23class RefCountedSafetyModel : public PtrRefSafetyModel {
24public:
25 std::optional<bool> isUnsafeType(QualType QT) const override {
26 return isUncounted(QT);
27 }
28 std::optional<bool> isUnsafePtr(QualType QT, bool) const override {
30 }
31 bool isSafePtr(const CXXRecordDecl *Record) const override {
33 }
34 bool isSafePtrType(QualType T) const override {
36 }
37 bool isPtrType(const std::string &Name) const override {
38 return isRefType(Name);
39 }
40 const char *typeName() const override { return "RefPtr-capable type"; }
41};
42
43class CheckedPtrSafetyModel : public PtrRefSafetyModel {
44public:
45 std::optional<bool> isUnsafeType(QualType QT) const override {
46 return isUnchecked(QT);
47 }
48 std::optional<bool> isUnsafePtr(QualType QT, bool) const override {
50 }
51 bool isSafePtr(const CXXRecordDecl *Record) const override {
53 }
54 bool isSafePtrType(QualType T) const override {
56 }
57 bool isPtrType(const std::string &Name) const override {
58 return isCheckedPtr(Name);
59 }
60 bool isSafeExpr(const Expr *E, bool) const override {
62 }
63 const char *typeName() const override { return "CheckedPtr-capable type"; }
64};
65
66class RetainPtrSafetyModel : public PtrRefSafetyModel {
67 mutable RetainTypeChecker RTC;
68
69public:
70 std::optional<bool> isUnsafeType(QualType QT) const override {
71 return RTC.isUnretained(QT);
72 }
73 std::optional<bool> isUnsafePtr(QualType QT, bool IgnoreARC) const override {
74 return RTC.isUnretained(QT, IgnoreARC);
75 }
76 bool isSafePtr(const CXXRecordDecl *Record) const override {
78 }
79 bool isSafePtrType(QualType T) const override {
81 }
82 bool isPtrType(const std::string &Name) const override {
83 return isRetainPtrOrOSPtr(Name);
84 }
85 bool isSafeExpr(const Expr *E, bool) const override {
88 }
89 bool isSafeDecl(const Decl *D, const SourceManager &SM) const override {
90 // Treat NS/CF globals in system header as immortal.
91 return SM.isInSystemHeader(D->getLocation());
92 }
93 void describeHazard(llvm::raw_ostream &Os, const Expr *Origin,
94 QualType SinkType) const override {
95 auto *VarType = SinkType.getTypePtr();
96 if (isa<TypedefType>(VarType)) {
97 Os << typeName() << " ";
98 if (auto *Decl = RTC.getCanonicalDecl(SinkType)) {
100 } else {
101 const auto *Typedef = VarType->getAs<TypedefType>();
102 assert(Typedef);
103 printQuotedQualifiedName(Os, Typedef->getDecl());
104 }
105 return;
106 }
107 PtrRefSafetyModel::describeHazard(Os, Origin, SinkType);
108 }
109 const char *typeName() const override { return "RetainPtr-capable type"; }
110 RetainTypeChecker *retainTypeChecker() const override { return &RTC; }
111};
112
113class BorrowSafetyModel : public PtrRefSafetyModel {
114public:
115 std::optional<bool> isUnsafeType(QualType QT) const override {
116 return isView(QT);
117 }
118 std::optional<bool> isUnsafePtr(QualType QT, bool) const override {
119 return isView(QT);
120 }
121 bool isSafePtr(const CXXRecordDecl *Record) const override {
122 return isBorrow(Record);
123 }
124 bool isSafePtrType(QualType T) const override { return isBorrowType(T); }
125 bool isPtrType(const std::string &Name) const override {
126 return isBorrow(Name);
127 }
128
129 bool isSafeExpr(const Expr *Origin,
130 bool PtrIsLifetimeBoundToOrigin) const override {
131 if (!PtrIsLifetimeBoundToOrigin)
132 return true;
133
134 QualType OriginType = pointeeType(Origin->getType());
135
136 if (OriginType.isNull())
137 return true;
138
139 if (isBorrowType(OriginType))
140 return true;
141
142 auto *Record = OriginType->getAsCXXRecordDecl();
143 if (!Record)
144 return true;
145
146 auto Borrowable = isBorrowable(Record);
147 return !Borrowable || !*Borrowable;
148 }
149
150 bool checksForInteriorDestruction() const override { return true; }
151 bool recognizesIndirectStores() const override { return true; }
152 const char *typeName() const override { return "CanBorrow type"; }
153
154 void describeHazard(llvm::raw_ostream &Os, const Expr *Origin,
155 QualType) const override {
156 Os << "loan on ";
157 QualType OriginType = Origin ? pointeeType(Origin->getType()) : QualType();
158
159 // Name the borrowed type, not the Borrow<T> guard, when the loan was
160 // taken from a Borrow<T> temporary.
161 if (!OriginType.isNull() && isBorrowType(OriginType))
162 OriginType = borrowedType(OriginType);
163
164 if (!OriginType.isNull() && OriginType->getAsRecordDecl()) {
165 Os << "CanBorrow type ";
166 printTypeName(Os, OriginType);
167 } else
168 Os << "a CanBorrow object";
169 Os << " that is not guarded by a Borrow";
170 }
171};
172
173} // namespace
174
175std::optional<bool> clang::isUnsafePtrForStorage(const PtrRefSafetyModel &Model,
176 QualType T, bool IgnoreARC) {
177 // A __strong / __weak Objective-C storage location is memory managed and
178 // thus safe. This exemption applies to variables/members/captures but not to
179 // call arguments, so it lives here rather than in the policy itself.
180 if (Model.retainTypeChecker() && T.hasStrongOrWeakObjCLifetime())
181 return false;
182 return Model.isUnsafePtr(T, IgnoreARC);
183}
184
185std::unique_ptr<PtrRefSafetyModel> clang::makeRefPtrSafetyModel() {
186 return std::make_unique<RefCountedSafetyModel>();
187}
188
189std::unique_ptr<PtrRefSafetyModel> clang::makeCheckedPtrSafetyModel() {
190 return std::make_unique<CheckedPtrSafetyModel>();
191}
192
193std::unique_ptr<PtrRefSafetyModel> clang::makeRetainPtrSafetyModel() {
194 return std::make_unique<RetainPtrSafetyModel>();
195}
196
197std::unique_ptr<PtrRefSafetyModel> clang::makeBorrowSafetyModel() {
198 return std::make_unique<BorrowSafetyModel>();
199}
llvm::MachO::Record Record
Definition MachO.h:31
Defines the SourceManager interface.
C Language Family Type Representation.
SourceLocation getLocation() const
Definition DeclBase.h:447
QualType getType() const
Definition Expr.h:145
Models one WebKit pointer-safety policy: ref-counted (RefPtr), checked (CheckedPtr),...
virtual void describeHazard(llvm::raw_ostream &Os, const Expr *, QualType SinkType) const
Prints a phrase describing why the reported value is unsafe, completing a sentence of the form "Local...
A (possibly-)qualified type.
Definition TypeBase.h:938
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1005
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8428
QualType getCanonicalType() const
Definition TypeBase.h:8480
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition Type.h:41
bool isCocoaObjectRef(QualType T)
constexpr bool isPtrType(PrimType T)
Definition PrimType.h:55
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
Definition Address.h:330
std::unique_ptr< PtrRefSafetyModel > makeBorrowSafetyModel()
bool isExprToGetCheckedPtrCapableMember(const clang::Expr *E)
Definition ASTUtils.cpp:531
QualType pointeeType(QualType T)
std::optional< bool > isUnchecked(const QualType T)
QualType borrowedType(QualType T)
bool isRefOrCheckedPtrType(const clang::QualType T)
bool isView(const clang::QualType T)
std::unique_ptr< PtrRefSafetyModel > makeCheckedPtrSafetyModel()
void printQuotedQualifiedName(llvm::raw_ostream &Os, const NamedDeclDerivedT &D)
bool isRetainPtrOrOSPtrType(const clang::QualType T)
std::optional< bool > isUnsafePtrForStorage(const PtrRefSafetyModel &Model, QualType T, bool IgnoreARC=false)
Applies the memory-management exemptions that hold for a variable, member, or lambda capture (but not...
bool isBorrow(const clang::CXXRecordDecl *R)
std::optional< bool > isBorrowable(const clang::CXXRecordDecl *R)
const FunctionProtoType * T
bool isRefCounted(const CXXRecordDecl *R)
bool isRetainPtrOrOSPtr(const std::string &Name)
bool isRefType(const std::string &Name)
std::optional< bool > isUncountedPtr(const QualType T)
bool isSafePtr(clang::CXXRecordDecl *Decl)
Definition ASTUtils.cpp:23
bool isCheckedPtr(const std::string &Name)
bool isBorrowType(const clang::QualType T)
std::unique_ptr< PtrRefSafetyModel > makeRefPtrSafetyModel()
std::unique_ptr< PtrRefSafetyModel > makeRetainPtrSafetyModel()
std::optional< bool > isUncounted(const QualType T)
std::optional< bool > isUncheckedPtr(const QualType T)