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,
242 TA.
insert(insertLoc, newCast.str());
245 TA.
insert(insertLoc, newCast.str());
262 BridgeCall +=
"CFBridgingRelease";
264 BridgeCall +=
"CFBridgingRetain";
266 if (isa<ParenExpr>(WrapE)) {
267 TA.
insert(InsertLoc, BridgeCall);
270 TA.
insert(InsertLoc, BridgeCall);
291 Outer = MacroRange.getAsRange();
295 void rewriteBlockCopyMacro(
CastExpr *E) {
297 getBlockMacroRanges(E, OuterRange, InnerRange);
304 diag::err_arc_cast_requires_bridge,
308 void removeBlockReleaseMacro(
CastExpr *E) {
310 getBlockMacroRanges(E, OuterRange, InnerRange);
314 diag::err_arc_cast_requires_bridge,
317 if (tryRemoving(cast<Expr>(StmtMap->getParentIgnoreParenCasts(E))))
323 bool tryRemoving(
Expr *E)
const {
329 if (Removables->count(E)) {
337 void transformObjCToNonObjCCast(
CastExpr *E) {
343 if (MacroName ==
"Block_copy") {
344 rewriteBlockCopyMacro(E);
347 if (MacroName ==
"Block_release") {
348 removeBlockReleaseMacro(E);
357 if (isPassedToCFRetain(E, callE))
358 return rewriteCastForCFRetain(E, callE);
365 std::string err =
"it is not safe to cast to '";
367 err +=
"' the result of '";
369 err +=
"' message; a __bridge cast may result in a pointer to a " 370 "destroyed object and a __bridge_retained may leak the object";
375 parent = StmtMap->getParentIgnoreParenImpCasts(parent);
376 }
while (parent && isa<ExprWithCleanups>(parent));
378 if (
ReturnStmt *retS = dyn_cast_or_null<ReturnStmt>(parent)) {
379 std::string note =
"remove the cast and change return type of function " 382 note +=
"' to have the object automatically autoreleased";
391 subExpr = pseudo->getResultExpr();
392 assert(subExpr &&
"no result for pseudo-object of non-void type?");
396 if (implCE->getCastKind() == CK_ARCConsumeObject)
398 if (implCE->getCastKind() == CK_ARCReclaimReturnedObject)
402 bool isConsumed =
false;
403 if (isPassedToCParamWithKnownOwnership(E, isConsumed))
411 return ME->getMethodFamily();
416 bool isPassedToCFRetain(
Expr *E,
CallExpr *&callE)
const {
417 if ((callE = dyn_cast_or_null<CallExpr>(
418 StmtMap->getParentIgnoreParenImpCasts(E))))
421 if (FD->getName() ==
"CFRetain" && FD->getNumParams() == 1 &&
422 FD->getParent()->isTranslationUnit() &&
423 FD->isExternallyVisible())
429 bool isPassedToCParamWithKnownOwnership(
Expr *E,
bool &isConsumed)
const {
430 if (
CallExpr *callE = dyn_cast_or_null<CallExpr>(
431 StmtMap->getParentIgnoreParenImpCasts(E)))
433 FD = dyn_cast_or_null<FunctionDecl>(callE->
getCalleeDecl())) {
435 for (
unsigned e = callE->
getNumArgs(); i != e; ++i) {
440 if (i < callE->getNumArgs() && i < FD->getNumParams()) {
442 if (PD->
hasAttr<CFConsumedAttr>()) {
452 bool isSelf(
Expr *E)
const {
456 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.
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.
Expr - 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.
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
SourceLocation getLocStart() const LLVM_READONLY
bool isObjCObjectPointerType() const
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
SourceLocation getLocEnd() const LLVM_READONLY
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.