51#include "llvm/ADT/SmallString.h"
62 std::unique_ptr<ParentMap> StmtMap;
65 mutable std::unique_ptr<ExprSet> Removables;
69 : Pass(pass), ParentD(nullptr), Body(nullptr) {
73 void transformBody(
Stmt *body,
Decl *ParentD) {
74 this->ParentD = ParentD;
83 UnbridgedCastRewriter(Pass).transformBody(
D->
getBody(),
D);
88 if (
E->getCastKind() != CK_CPointerToObjCPointerCast &&
89 E->getCastKind() != CK_BitCast &&
90 E->getCastKind() != CK_AnyPointerToBlockPointerCast)
102 if (exprRetainable == castRetainable)
return true;
113 transformNonObjCToObjCCast(
E);
115 transformObjCToNonObjCCast(
E);
121 void transformNonObjCToObjCCast(
CastExpr *
E) {
127 castToObjCObject(
E,
false);
134 if (
CallExpr *callE = dyn_cast<CallExpr>(inner)) {
136 if (FD->hasAttr<CFReturnsRetainedAttr>()) {
137 castToObjCObject(
E,
true);
140 if (FD->hasAttr<CFReturnsNotRetainedAttr>()) {
141 castToObjCObject(
E,
false);
144 if (FD->isGlobal() &&
145 FD->getIdentifier() &&
147 FD->getIdentifier()->getName())) {
148 StringRef fname = FD->getIdentifier()->getName();
149 if (fname.ends_with(
"Retain") || fname.contains(
"Create") ||
150 fname.contains(
"Copy")) {
154 if (FD->getName() ==
"CFRetain" &&
155 FD->getNumParams() == 1 &&
156 FD->getParent()->isTranslationUnit() &&
157 FD->isExternallyVisible()) {
158 Expr *Arg = callE->getArg(0);
160 const Expr *sub = ICE->getSubExpr();
166 castToObjCObject(
E,
true);
170 if (fname.contains(
"Get")) {
171 castToObjCObject(
E,
false);
181 while (isa<MemberExpr>(base))
183 if (isa<ObjCIvarRefExpr>(base) &&
184 isa<ReturnStmt>(StmtMap->getParentIgnoreParenCasts(
E))) {
185 if (
ObjCMethodDecl *method = dyn_cast_or_null<ObjCMethodDecl>(ParentD)) {
186 if (!method->hasAttr<NSReturnsRetainedAttr>()) {
187 castToObjCObject(
E,
false);
194 void castToObjCObject(
CastExpr *
E,
bool retained) {
200 rewriteToBridgedCast(
E, Kind, Trans);
209 diag::err_arc_cast_requires_bridge,
218 bridge =
"__bridge ";
break;
220 bridge =
"__bridge_transfer ";
break;
222 bridge =
"__bridge_retained ";
break;
238 if (isa<ParenExpr>(
E->getSubExpr())) {
239 TA.
insert(insertLoc, newCast.str());
242 TA.
insert(insertLoc, newCast.str());
250 Expr *WrapE =
E->getSubExpr();
260 BridgeCall +=
"CFBridgingRelease";
262 BridgeCall +=
"CFBridgingRetain";
264 if (isa<ParenExpr>(WrapE)) {
265 TA.
insert(InsertLoc, BridgeCall);
268 TA.
insert(InsertLoc, BridgeCall);
293 void rewriteBlockCopyMacro(
CastExpr *
E) {
295 getBlockMacroRanges(
E, OuterRange, InnerRange);
302 diag::err_arc_cast_requires_bridge,
306 void removeBlockReleaseMacro(
CastExpr *
E) {
308 getBlockMacroRanges(
E, OuterRange, InnerRange);
312 diag::err_arc_cast_requires_bridge,
315 if (tryRemoving(cast<Expr>(StmtMap->getParentIgnoreParenCasts(
E))))
321 bool tryRemoving(
Expr *
E)
const {
327 if (Removables->count(
E)) {
335 void transformObjCToNonObjCCast(
CastExpr *
E) {
341 if (MacroName ==
"Block_copy") {
342 rewriteBlockCopyMacro(
E);
345 if (MacroName ==
"Block_release") {
346 removeBlockReleaseMacro(
E);
351 if (isSelf(
E->getSubExpr()))
355 if (isPassedToCFRetain(
E, callE))
356 return rewriteCastForCFRetain(
E, callE);
363 std::string err =
"it is not safe to cast to '";
365 err +=
"' the result of '";
367 err +=
"' message; a __bridge cast may result in a pointer to a "
368 "destroyed object and a __bridge_retained may leak the object";
373 parent = StmtMap->getParentIgnoreParenImpCasts(parent);
374 }
while (isa_and_nonnull<FullExpr>(parent));
376 if (
ReturnStmt *retS = dyn_cast_or_null<ReturnStmt>(parent)) {
377 std::string
note =
"remove the cast and change return type of function "
380 note +=
"' to have the object automatically autoreleased";
385 Expr *subExpr =
E->getSubExpr();
389 subExpr = pseudo->getResultExpr();
390 assert(subExpr &&
"no result for pseudo-object of non-void type?");
394 if (implCE->getCastKind() == CK_ARCConsumeObject)
396 if (implCE->getCastKind() == CK_ARCReclaimReturnedObject)
400 bool isConsumed =
false;
401 if (isPassedToCParamWithKnownOwnership(
E, isConsumed))
409 return ME->getMethodFamily();
415 if ((callE = dyn_cast_or_null<CallExpr>(
416 StmtMap->getParentIgnoreParenImpCasts(
E))))
419 if (FD->getName() ==
"CFRetain" && FD->getNumParams() == 1 &&
420 FD->getParent()->isTranslationUnit() &&
421 FD->isExternallyVisible())
427 bool isPassedToCParamWithKnownOwnership(
Expr *
E,
bool &isConsumed)
const {
428 if (
CallExpr *callE = dyn_cast_or_null<CallExpr>(
429 StmtMap->getParentIgnoreParenImpCasts(
E)))
431 FD = dyn_cast_or_null<FunctionDecl>(callE->
getCalleeDecl())) {
433 for (
unsigned e = callE->
getNumArgs(); i != e; ++i) {
435 if (arg ==
E ||
arg->IgnoreParenImpCasts() ==
E)
438 if (i < callE->getNumArgs() && i < FD->getNumParams()) {
440 if (PD->
hasAttr<CFConsumedAttr>()) {
450 bool isSelf(
Expr *
E)
const {
454 if (IPD->getIdentifier() == SelfII)
Defines the clang::ASTContext interface.
Defines the SourceManager interface.
SourceManager & getSourceManager()
TranslationUnitDecl * getTranslationUnitDecl() const
const LangOptions & getLangOpts() const
const clang::PrintingPolicy & getPrintingPolicy() const
Represents a block literal declaration, which is like an unnamed FunctionDecl.
CStyleCastExpr - An explicit cast in C (C99 6.5.4) or a C-style cast in C++ (C++ [expr....
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Represents a character-granular source range.
SourceRange getAsRange() const
A reference to a declared variable, function, enum, etc.
Decl - This represents one declaration (or definition), e.g.
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
This represents one expression.
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Expr * IgnoreParenLValueCasts() LLVM_READONLY
Skip past any parentheses and lvalue casts which might surround this expression until reaching a fixe...
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
@ NPC_ValueDependentIsNull
Specifies that a value-dependent expression of integral or dependent type should be considered a null...
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents a function declaration or definition.
One of these records is kept for each identifier that is lexed.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
static StringRef getImmediateMacroName(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
Retrieve the name of the immediate macro expansion.
static bool isAsciiIdentifierContinueChar(char c, const LangOptions &LangOpts)
Returns true if the given character could appear in an identifier.
An expression that sends a message to the given Objective-C object or class.
ObjCMethodDecl - Represents an instance or class method declaration.
Represents a parameter to a function.
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
A (possibly-)qualified type.
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
bool TraverseStmt(Stmt *S, DataRecursionQueue *Queue=nullptr)
Recursively visit a statement or expression, by dispatching to Traverse*() based on the argument's dy...
bool TraverseDecl(Decl *D)
Recursively visit a declaration, by dispatching to Traverse*Decl() based on the argument's dynamic ty...
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
This class handles loading and caching of source files into memory.
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
Stmt - This represents one statement.
SourceLocation getEndLoc() const LLVM_READONLY
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
SourceLocation getBeginLoc() const LLVM_READONLY
bool isPointerType() const
bool isObjCIndirectLifetimeType() const
bool isObjCObjectPointerType() const
bool isObjCRetainableType() const
bool CFBridgingFunctionsDefined()
bool hasSideEffects(Expr *E, ASTContext &Ctx)
llvm::DenseSet< Expr * > ExprSet
void rewriteUnbridgedCasts(MigrationPass &pass)
bool isGlobalVar(Expr *E)
void collectRemovables(Stmt *S, ExprSet &exprs)
const internal::VariadicDynCastAllOfMatcher< Stmt, CastExpr > castExpr
Matches any cast nodes of Clang's AST.
bool isRefType(QualType RetTy, StringRef Prefix, StringRef Name=StringRef())
The JSON file list parser is used to communicate input to InstallAPI.
ObjCMethodFamily
A family of Objective-C methods.
@ OMF_None
No particular method family.
ObjCBridgeCastKind
The kind of bridging performed by the Objective-C bridge cast.
@ OBC_Bridge
Bridging via __bridge, which does nothing but reinterpret the bits.
@ OBC_BridgeTransfer
Bridging via __bridge_transfer, which transfers ownership of an Objective-C pointer into ARC.
@ OBC_BridgeRetained
Bridging via __bridge_retain, which makes an ARC object available as a +1 C pointer.
const FunctionProtoType * T
__DEVICE__ _Tp arg(const std::complex< _Tp > &__c)