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);
296 void rewriteBlockCopyMacro(
CastExpr *E) {
298 getBlockMacroRanges(E, OuterRange, InnerRange);
305 diag::err_arc_cast_requires_bridge,
309 void removeBlockReleaseMacro(
CastExpr *E) {
311 getBlockMacroRanges(E, OuterRange, InnerRange);
315 diag::err_arc_cast_requires_bridge,
318 if (tryRemoving(cast<Expr>(StmtMap->getParentIgnoreParenCasts(E))))
324 bool tryRemoving(
Expr *E)
const {
330 if (Removables->count(E)) {
338 void transformObjCToNonObjCCast(
CastExpr *E) {
344 if (MacroName ==
"Block_copy") {
345 rewriteBlockCopyMacro(E);
348 if (MacroName ==
"Block_release") {
349 removeBlockReleaseMacro(E);
358 if (isPassedToCFRetain(E, callE))
359 return rewriteCastForCFRetain(E, callE);
366 std::string err =
"it is not safe to cast to '";
368 err +=
"' the result of '";
370 err +=
"' message; a __bridge cast may result in a pointer to a " 371 "destroyed object and a __bridge_retained may leak the object";
376 parent = StmtMap->getParentIgnoreParenImpCasts(parent);
377 }
while (parent && isa<ExprWithCleanups>(parent));
379 if (
ReturnStmt *retS = dyn_cast_or_null<ReturnStmt>(parent)) {
380 std::string note =
"remove the cast and change return type of function " 383 note +=
"' to have the object automatically autoreleased";
392 subExpr = pseudo->getResultExpr();
393 assert(subExpr &&
"no result for pseudo-object of non-void type?");
397 if (implCE->getCastKind() == CK_ARCConsumeObject)
399 if (implCE->getCastKind() == CK_ARCReclaimReturnedObject)
403 bool isConsumed =
false;
404 if (isPassedToCParamWithKnownOwnership(E, isConsumed))
412 return ME->getMethodFamily();
417 bool isPassedToCFRetain(
Expr *E,
CallExpr *&callE)
const {
418 if ((callE = dyn_cast_or_null<CallExpr>(
419 StmtMap->getParentIgnoreParenImpCasts(E))))
422 if (FD->getName() ==
"CFRetain" && FD->getNumParams() == 1 &&
423 FD->getParent()->isTranslationUnit() &&
424 FD->isExternallyVisible())
430 bool isPassedToCParamWithKnownOwnership(
Expr *E,
bool &isConsumed)
const {
431 if (
CallExpr *callE = dyn_cast_or_null<CallExpr>(
432 StmtMap->getParentIgnoreParenImpCasts(E)))
434 FD = dyn_cast_or_null<FunctionDecl>(callE->
getCalleeDecl())) {
436 for (
unsigned e = callE->
getNumArgs(); i != e; ++i) {
441 if (i < callE->getNumArgs() && i < FD->getNumParams()) {
443 if (PD->
hasAttr<CFConsumedAttr>()) {
453 bool isSelf(
Expr *E)
const {
457 if (IPD->getIdentifier() == SelfII)
Defines the clang::ASTContext interface.
An instance of this class is created to represent 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.
ParmVarDecl - 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...
SourceLocation getLocEnd() const LLVM_READONLY
void collectRemovables(Stmt *S, ExprSet &exprs)
BlockDecl - This represents a block literal declaration, which is like an unnamed FunctionDecl...
Expr - This represents one expression.
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
const FunctionProtoType * T
bool CFBridgingFunctionsDefined()
bool isObjCRetainableType() const
Specifies that a value-dependent expression of integral or dependent type should be considered a null...
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.
std::pair< SourceLocation, SourceLocation > getImmediateExpansionRange(SourceLocation Loc) const
Return the start/end of the expansion information for an expansion location.
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 getLocStart() const LLVM_READONLY
SourceLocation getBegin() const
const LangOptions & getLangOpts() const
This class handles loading and caching of source files into memory.