| //=======- RawPtrRefSafetyModel.cpp -----------------------------*- C++ -*-==// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "RawPtrRefSafetyModel.h" | |
| #include "ASTUtils.h" | |
| #include "clang/AST/Decl.h" | |
| #include "clang/AST/ExprObjC.h" | |
| #include "clang/AST/Type.h" | |
| #include "clang/Analysis/DomainSpecific/CocoaConventions.h" | |
| #include "clang/Basic/SourceManager.h" | |
| using namespace clang; | |
| namespace { | |
| class RefCountedSafetyModel : public PtrRefSafetyModel { | |
| public: | |
| std::optional<bool> isUnsafeType(QualType QT) const override { | |
| return isUncounted(QT); | |
| } | |
| std::optional<bool> isUnsafePtr(QualType QT, bool) const override { | |
| return isUncountedPtr(QT.getCanonicalType()); | |
| } | |
| bool isSafePtr(const CXXRecordDecl *Record) const override { | |
| return isRefCounted(Record) || isCheckedPtr(Record); | |
| } | |
| bool isSafePtrType(QualType T) const override { | |
| return isRefOrCheckedPtrType(T); | |
| } | |
| bool isPtrType(const std::string &Name) const override { | |
| return isRefType(Name); | |
| } | |
| const char *typeName() const override { return "RefPtr-capable type"; } | |
| }; | |
| class CheckedPtrSafetyModel : public PtrRefSafetyModel { | |
| public: | |
| std::optional<bool> isUnsafeType(QualType QT) const override { | |
| return isUnchecked(QT); | |
| } | |
| std::optional<bool> isUnsafePtr(QualType QT, bool) const override { | |
| return isUncheckedPtr(QT.getCanonicalType()); | |
| } | |
| bool isSafePtr(const CXXRecordDecl *Record) const override { | |
| return isRefCounted(Record) || isCheckedPtr(Record); | |
| } | |
| bool isSafePtrType(QualType T) const override { | |
| return isRefOrCheckedPtrType(T); | |
| } | |
| bool isPtrType(const std::string &Name) const override { | |
| return isCheckedPtr(Name); | |
| } | |
| bool isSafeExpr(const Expr *E) const override { | |
| return isExprToGetCheckedPtrCapableMember(E); | |
| } | |
| const char *typeName() const override { return "CheckedPtr-capable type"; } | |
| }; | |
| class RetainPtrSafetyModel : public PtrRefSafetyModel { | |
| mutable RetainTypeChecker RTC; | |
| public: | |
| std::optional<bool> isUnsafeType(QualType QT) const override { | |
| return RTC.isUnretained(QT); | |
| } | |
| std::optional<bool> isUnsafePtr(QualType QT, bool IgnoreARC) const override { | |
| return RTC.isUnretained(QT, IgnoreARC); | |
| } | |
| bool isSafePtr(const CXXRecordDecl *Record) const override { | |
| return isRetainPtrOrOSPtr(Record); | |
| } | |
| bool isSafePtrType(QualType T) const override { | |
| return isRetainPtrOrOSPtrType(T); | |
| } | |
| bool isPtrType(const std::string &Name) const override { | |
| return isRetainPtrOrOSPtr(Name); | |
| } | |
| bool isSafeExpr(const Expr *E) const override { | |
| return ento::cocoa::isCocoaObjectRef(E->getType()) && | |
| isa<ObjCMessageExpr>(E); | |
| } | |
| bool isSafeDecl(const Decl *D, const SourceManager &SM) const override { | |
| // Treat NS/CF globals in system header as immortal. | |
| return SM.isInSystemHeader(D->getLocation()); | |
| } | |
| const char *typeName() const override { return "RetainPtr-capable type"; } | |
| RetainTypeChecker *retainTypeChecker() const override { return &RTC; } | |
| }; | |
| } // namespace | |
| std::optional<bool> clang::isUnsafePtrForStorage(const PtrRefSafetyModel &Model, | |
| QualType T, bool IgnoreARC) { | |
| // A __strong / __weak Objective-C storage location is memory managed and | |
| // thus safe. This exemption applies to variables/members/captures but not to | |
| // call arguments, so it lives here rather than in the policy itself. | |
| if (Model.retainTypeChecker() && T.hasStrongOrWeakObjCLifetime()) | |
| return false; | |
| return Model.isUnsafePtr(T, IgnoreARC); | |
| } | |
| std::unique_ptr<PtrRefSafetyModel> clang::makeRefPtrSafetyModel() { | |
| return std::make_unique<RefCountedSafetyModel>(); | |
| } | |
| std::unique_ptr<PtrRefSafetyModel> clang::makeCheckedPtrSafetyModel() { | |
| return std::make_unique<CheckedPtrSafetyModel>(); | |
| } | |
| std::unique_ptr<PtrRefSafetyModel> clang::makeRetainPtrSafetyModel() { | |
| return std::make_unique<RetainPtrSafetyModel>(); | |
| } |