52 #include "llvm/ADT/SmallString.h" 54 using namespace clang;
55 using namespace arcmt;
56 using namespace trans;
63 std::unique_ptr<ParentMap> StmtMap;
66 mutable std::unique_ptr<ExprSet> Removables;
70 : Pass(pass), ParentD(nullptr), Body(nullptr) {
74 void transformBody(
Stmt *body,
Decl *ParentD) {
75 this->ParentD = ParentD;
84 UnbridgedCastRewriter(Pass).transformBody(D->
getBody(), D);
89 if (E->
getCastKind() != CK_CPointerToObjCPointerCast &&
91 E->
getCastKind() != CK_AnyPointerToBlockPointerCast)
103 if (exprRetainable == castRetainable)
return true;
114 transformNonObjCToObjCCast(E);
116 transformObjCToNonObjCCast(E);
122 void transformNonObjCToObjCCast(
CastExpr *E) {
128 castToObjCObject(E,
false);
135 if (
CallExpr *callE = dyn_cast<CallExpr>(inner)) {
137 if (FD->hasAttr<CFReturnsRetainedAttr>()) {
138 castToObjCObject(E,
true);
141 if (FD->hasAttr<CFReturnsNotRetainedAttr>()) {
142 castToObjCObject(E,
false);
145 if (FD->isGlobal() &&
146 FD->getIdentifier() &&
148 FD->getIdentifier()->getName())) {
149 StringRef fname = FD->getIdentifier()->getName();
150 if (fname.endswith(
"Retain") ||
151 fname.find(
"Create") != StringRef::npos ||
152 fname.find(
"Copy") != StringRef::npos) {
156 if (FD->getName() ==
"CFRetain" &&
157 FD->getNumParams() == 1 &&
158 FD->getParent()->isTranslationUnit() &&
159 FD->isExternallyVisible()) {
160 Expr *Arg = callE->getArg(0);
162 const Expr *sub = ICE->getSubExpr();
168 castToObjCObject(E,
true);
172 if (fname.find(
"Get") != StringRef::npos) {
173 castToObjCObject(E,
false);
183 while (isa<MemberExpr>(base))
185 if (isa<ObjCIvarRefExpr>(base) &&
186 isa<ReturnStmt>(StmtMap->getParentIgnoreParenCasts(E))) {
187 if (
ObjCMethodDecl *method = dyn_cast_or_null<ObjCMethodDecl>(ParentD)) {
188 if (!method->hasAttr<NSReturnsRetainedAttr>()) {
189 castToObjCObject(E,
false);
196 void castToObjCObject(
CastExpr *E,
bool retained) {
202 rewriteToBridgedCast(E, Kind, Trans);
211 diag::err_arc_cast_requires_bridge,
220 bridge =
"__bridge ";
break;
222 bridge =
"__bridge_transfer ";
break;
224 bridge =
"__bridge_retained ";
break;
228 diag::err_arc_cast_requires_bridge, E->
getBeginLoc());
241 TA.
insert(insertLoc, newCast.str());
244 TA.
insert(insertLoc, newCast.str());
261 BridgeCall +=
"CFBridgingRelease";
263 BridgeCall +=
"CFBridgingRetain";
265 if (isa<ParenExpr>(WrapE)) {
266 TA.
insert(InsertLoc, BridgeCall);
269 TA.
insert(InsertLoc, BridgeCall);
290 Outer = MacroRange.getAsRange();
294 void rewriteBlockCopyMacro(
CastExpr *E) {
296 getBlockMacroRanges(E, OuterRange, InnerRange);
303 diag::err_arc_cast_requires_bridge,
307 void removeBlockReleaseMacro(
CastExpr *E) {
309 getBlockMacroRanges(E, OuterRange, InnerRange);
313 diag::err_arc_cast_requires_bridge,
316 if (tryRemoving(cast<Expr>(StmtMap->getParentIgnoreParenCasts(E))))
322 bool tryRemoving(
Expr *E)
const {
328 if (Removables->count(E)) {
336 void transformObjCToNonObjCCast(
CastExpr *E) {
342 if (MacroName ==
"Block_copy") {
343 rewriteBlockCopyMacro(E);
346 if (MacroName ==
"Block_release") {
347 removeBlockReleaseMacro(E);
356 if (isPassedToCFRetain(E, callE))
357 return rewriteCastForCFRetain(E, callE);
364 std::string err =
"it is not safe to cast to '";
366 err +=
"' the result of '";
368 err +=
"' message; a __bridge cast may result in a pointer to a " 369 "destroyed object and a __bridge_retained may leak the object";
374 parent = StmtMap->getParentIgnoreParenImpCasts(parent);
375 }
while (parent && isa<FullExpr>(parent));
377 if (
ReturnStmt *retS = dyn_cast_or_null<ReturnStmt>(parent)) {
378 std::string note =
"remove the cast and change return type of function " 381 note +=
"' to have the object automatically autoreleased";
390 subExpr = pseudo->getResultExpr();
391 assert(subExpr &&
"no result for pseudo-object of non-void type?");
395 if (implCE->getCastKind() == CK_ARCConsumeObject)
397 if (implCE->getCastKind() == CK_ARCReclaimReturnedObject)
401 bool isConsumed =
false;
402 if (isPassedToCParamWithKnownOwnership(E, isConsumed))
410 return ME->getMethodFamily();
415 bool isPassedToCFRetain(
Expr *E,
CallExpr *&callE)
const {
416 if ((callE = dyn_cast_or_null<CallExpr>(
417 StmtMap->getParentIgnoreParenImpCasts(E))))
420 if (FD->getName() ==
"CFRetain" && FD->getNumParams() == 1 &&
421 FD->getParent()->isTranslationUnit() &&
422 FD->isExternallyVisible())
428 bool isPassedToCParamWithKnownOwnership(
Expr *E,
bool &isConsumed)
const {
429 if (
CallExpr *callE = dyn_cast_or_null<CallExpr>(
430 StmtMap->getParentIgnoreParenImpCasts(E)))
432 FD = dyn_cast_or_null<FunctionDecl>(callE->
getCalleeDecl())) {
434 for (
unsigned e = callE->
getNumArgs(); i != e; ++i) {
439 if (i < callE->getNumArgs() && i < FD->getNumParams()) {
441 if (PD->
hasAttr<CFConsumedAttr>()) {
451 bool isSelf(
Expr *E)
const {
455 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
IgnoreParenCasts - Ignore parentheses and casts.
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)
Pepresents 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
IgnoreParenImpCasts - Ignore parentheses and implicit casts.
Expr * IgnoreParenLValueCasts() LLVM_READONLY
Ignore parentheses and lvalue casts.
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.