51 #include "llvm/ADT/SmallString.h" 53 using namespace clang;
54 using namespace arcmt;
55 using namespace trans;
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 &&
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.endswith(
"Retain") ||
150 fname.find(
"Create") != StringRef::npos ||
151 fname.find(
"Copy") != StringRef::npos) {
155 if (FD->getName() ==
"CFRetain" &&
156 FD->getNumParams() == 1 &&
157 FD->getParent()->isTranslationUnit() &&
158 FD->isExternallyVisible()) {
159 Expr *Arg = callE->getArg(0);
161 const Expr *sub = ICE->getSubExpr();
167 castToObjCObject(E,
true);
171 if (fname.find(
"Get") != StringRef::npos) {
172 castToObjCObject(E,
false);
182 while (isa<MemberExpr>(base))
184 if (isa<ObjCIvarRefExpr>(base) &&
185 isa<ReturnStmt>(StmtMap->getParentIgnoreParenCasts(E))) {
186 if (
ObjCMethodDecl *method = dyn_cast_or_null<ObjCMethodDecl>(ParentD)) {
187 if (!method->hasAttr<NSReturnsRetainedAttr>()) {
188 castToObjCObject(E,
false);
195 void castToObjCObject(
CastExpr *E,
bool retained) {
201 rewriteToBridgedCast(E, Kind, Trans);
210 diag::err_arc_cast_requires_bridge,
219 bridge =
"__bridge ";
break;
221 bridge =
"__bridge_transfer ";
break;
223 bridge =
"__bridge_retained ";
break;
227 diag::err_arc_cast_requires_bridge, E->
getBeginLoc());
240 TA.
insert(insertLoc, newCast.str());
243 TA.
insert(insertLoc, newCast.str());
260 BridgeCall +=
"CFBridgingRelease";
262 BridgeCall +=
"CFBridgingRetain";
264 if (isa<ParenExpr>(WrapE)) {
265 TA.
insert(InsertLoc, BridgeCall);
268 TA.
insert(InsertLoc, BridgeCall);
289 Outer = MacroRange.getAsRange();
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);
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 (parent && isa<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";
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();
414 bool isPassedToCFRetain(
Expr *E,
CallExpr *&callE)
const {
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) {
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.
Represents a function declaration or definition.
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
A (possibly-)qualified type.
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
ObjCBridgeCastKind
The kind of bridging performed by the Objective-C bridge cast.
Stmt - This represents one statement.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Bridging via __bridge, which does nothing but reinterpret the bits.
Defines the SourceManager interface.
Decl - This represents one declaration (or definition), e.g.
const char * getCharacterData(SourceLocation SL, bool *Invalid=nullptr) const
Return a pointer to the start of the specified location in the appropriate spelling MemoryBuffer...
SourceLocation getImmediateMacroCallerLoc(SourceLocation Loc) const
Gets the location of the immediate macro caller, one level up the stack toward the initial macro type...
ObjCMethodDecl - Represents an instance or class method declaration.
Represents a parameter to a function.
bool TraverseDecl(Decl *D)
Recursively visit a declaration, by dispatching to Traverse*Decl() based on the argument's dynamic ty...
One of these records is kept for each identifier that is lexed.
ObjCMethodFamily
A family of Objective-C methods.
SourceLocation getBeginLoc() const LLVM_READONLY
bool isGlobalVar(Expr *E)
Stmt * getBody() const override
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
const clang::PrintingPolicy & getPrintingPolicy() const
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
const internal::VariadicDynCastAllOfMatcher< Stmt, CastExpr > castExpr
Matches any cast nodes of Clang's AST.
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
Bridging via __bridge_transfer, which transfers ownership of an Objective-C pointer into ARC...
void collectRemovables(Stmt *S, ExprSet &exprs)
Represents a block literal declaration, which is like an unnamed FunctionDecl.
This represents one expression.
Represents a character-granular source range.
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
bool CFBridgingFunctionsDefined()
bool isObjCRetainableType() const
Specifies that a value-dependent expression of integral or dependent type should be considered a null...
CharSourceRange getImmediateExpansionRange(SourceLocation Loc) const
Return the start/end of the expansion information for an expansion location.
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
An expression that sends a message to the given Objective-C object or class.
SourceLocation getEnd() const
CStyleCastExpr - An explicit cast in C (C99 6.5.4) or a C-style cast in C++ (C++ [expr.cast]), which uses the syntax (Type)expr.
SourceLocation getEndLoc() const LLVM_READONLY
void rewriteUnbridgedCasts(MigrationPass &pass)
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
NullPointerConstantKind isNullPointerConstant(ASTContext &Ctx, NullPointerConstantValueDependence NPC) const
isNullPointerConstant - C99 6.3.2.3p3 - Test if this reduces down to a Null pointer constant...
Encodes a location in the source.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
CastKind getCastKind() const
bool isObjCObjectPointerType() const
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.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Dataflow Directional Tag Classes.
bool isRefType(QualType RetTy, StringRef Prefix, StringRef Name=StringRef())
bool isValid() const
Return true if this is a valid SourceLocation object.
bool hasSideEffects(Expr *E, ASTContext &Ctx)
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
bool isObjCIndirectLifetimeType() const
Bridging via __bridge_retain, which makes an ARC object available as a +1 C pointer.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Expr * IgnoreParenLValueCasts() LLVM_READONLY
Skip past any parentheses and lvalue casts which might surround this expression until reaching a fixe...
SourceManager & getSourceManager()
static bool isIdentifierBodyChar(char c, const LangOptions &LangOpts)
Returns true if the given character could appear in an identifier.
No particular method family.
TranslationUnitDecl * getTranslationUnitDecl() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
A reference to a declared variable, function, enum, etc.
bool isPointerType() const
A trivial tuple used to represent a source range.
SourceLocation getBegin() const
const LangOptions & getLangOpts() const
This class handles loading and caching of source files into memory.