clang 20.0.0git
Transforms.cpp
Go to the documentation of this file.
1//===--- Transforms.cpp - Transformations to ARC mode ---------------------===//
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 "Transforms.h"
10#include "Internals.h"
17#include "clang/Lex/Lexer.h"
19#include "clang/Sema/Sema.h"
20#include "clang/Sema/SemaObjC.h"
21
22using namespace clang;
23using namespace arcmt;
24using namespace trans;
25
27
29 if (!EnableCFBridgeFns)
30 EnableCFBridgeFns = SemaRef.ObjC().isKnownName("CFBridgingRetain") &&
31 SemaRef.ObjC().isKnownName("CFBridgingRelease");
32 return *EnableCFBridgeFns;
33}
34
35//===----------------------------------------------------------------------===//
36// Helpers.
37//===----------------------------------------------------------------------===//
38
40 bool AllowOnUnknownClass) {
41 if (!Ctx.getLangOpts().ObjCWeakRuntime)
42 return false;
43
44 QualType T = type;
45 if (T.isNull())
46 return false;
47
48 // iOS is always safe to use 'weak'.
49 if (Ctx.getTargetInfo().getTriple().isiOS() ||
50 Ctx.getTargetInfo().getTriple().isWatchOS())
51 AllowOnUnknownClass = true;
52
53 while (const PointerType *ptr = T->getAs<PointerType>())
54 T = ptr->getPointeeType();
55 if (const ObjCObjectPointerType *ObjT = T->getAs<ObjCObjectPointerType>()) {
56 ObjCInterfaceDecl *Class = ObjT->getInterfaceDecl();
57 if (!AllowOnUnknownClass && (!Class || Class->getName() == "NSObject"))
58 return false; // id/NSObject is not safe for weak.
59 if (!AllowOnUnknownClass && !Class->hasDefinition())
60 return false; // forward classes are not verifiable, therefore not safe.
61 if (Class && Class->isArcWeakrefUnavailable())
62 return false;
63 }
64
65 return true;
66}
67
69 if (E->getOpcode() != BO_Assign)
70 return false;
71
72 return isPlusOne(E->getRHS());
73}
74
75bool trans::isPlusOne(const Expr *E) {
76 if (!E)
77 return false;
78 if (const FullExpr *FE = dyn_cast<FullExpr>(E))
79 E = FE->getSubExpr();
80
81 if (const ObjCMessageExpr *
82 ME = dyn_cast<ObjCMessageExpr>(E->IgnoreParenCasts()))
83 if (ME->getMethodFamily() == OMF_retain)
84 return true;
85
86 if (const CallExpr *
87 callE = dyn_cast<CallExpr>(E->IgnoreParenCasts())) {
88 if (const FunctionDecl *FD = callE->getDirectCallee()) {
89 if (FD->hasAttr<CFReturnsRetainedAttr>())
90 return true;
91
92 if (FD->isGlobal() &&
93 FD->getIdentifier() &&
94 FD->getParent()->isTranslationUnit() &&
95 FD->isExternallyVisible() &&
96 ento::cocoa::isRefType(callE->getType(), "CF",
97 FD->getIdentifier()->getName())) {
98 StringRef fname = FD->getIdentifier()->getName();
99 if (fname.ends_with("Retain") || fname.contains("Create") ||
100 fname.contains("Copy"))
101 return true;
102 }
103 }
104 }
105
106 const ImplicitCastExpr *implCE = dyn_cast<ImplicitCastExpr>(E);
107 while (implCE && implCE->getCastKind() == CK_BitCast)
108 implCE = dyn_cast<ImplicitCastExpr>(implCE->getSubExpr());
109
110 return implCE && implCE->getCastKind() == CK_ARCConsumeObject;
111}
112
113/// 'Loc' is the end of a statement range. This returns the location
114/// immediately after the semicolon following the statement.
115/// If no semicolon is found or the location is inside a macro, the returned
116/// source location will be invalid.
118 ASTContext &Ctx, bool IsDecl) {
119 SourceLocation SemiLoc = findSemiAfterLocation(loc, Ctx, IsDecl);
120 if (SemiLoc.