diff options
| author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-07-18 07:44:50 +0000 |
|---|---|---|
| committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-07-18 07:44:50 +0000 |
| commit | 91c62bfc0355e982c54ca50ca45890d1599e6156 (patch) | |
| tree | 21f686b674d7a9a8c2b3b9710ee2c8bd4dc27123 /clang/lib | |
| parent | 73a0d32df546c9780bdfa9a5a298467d07e4458c (diff) | |
| download | bcm5719-llvm-91c62bfc0355e982c54ca50ca45890d1599e6156.tar.gz bcm5719-llvm-91c62bfc0355e982c54ca50ca45890d1599e6156.zip | |
[arcmt] When a NSData's 'bytes' family of methods are used on a local var,
add __attribute__((objc_precise_lifetime)) to make sure that the object
(and its data) will not get released before the var goes out-of-scope.
rdar://9206226
llvm-svn: 135382
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/ARCMigrate/TransAPIUses.cpp | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/clang/lib/ARCMigrate/TransAPIUses.cpp b/clang/lib/ARCMigrate/TransAPIUses.cpp index 58fd3d07d0a..296aa070004 100644 --- a/clang/lib/ARCMigrate/TransAPIUses.cpp +++ b/clang/lib/ARCMigrate/TransAPIUses.cpp @@ -13,6 +13,8 @@ // // - NSInvocation's [get/set]ReturnValue and [get/set]Argument are only safe // with __unsafe_unretained objects. +// - When a NSData's 'bytes' family of methods are used on a local var, +// add __attribute__((objc_precise_lifetime)) to make it safer. // //===----------------------------------------------------------------------===// @@ -28,9 +30,13 @@ namespace { class APIChecker : public RecursiveASTVisitor<APIChecker> { MigrationPass &Pass; + Selector getReturnValueSel, setReturnValueSel; Selector getArgumentSel, setArgumentSel; + Selector bytesSel, getBytesSel, getBytesLengthSel, getBytesRangeSel; + + llvm::DenseSet<VarDecl *> ChangedNSDataVars; public: APIChecker(MigrationPass &pass) : Pass(pass) { SelectorTable &sels = Pass.Ctx.Selectors; @@ -44,6 +50,14 @@ public: getArgumentSel = sels.getSelector(2, selIds); selIds[0] = &ids.get("setArgument"); setArgumentSel = sels.getSelector(2, selIds); + + bytesSel = sels.getNullarySelector(&ids.get("bytes")); + getBytesSel = sels.getUnarySelector(&ids.get("getBytes")); + selIds[0] = &ids.get("getBytes"); + selIds[1] = &ids.get("length"); + getBytesLengthSel = sels.getSelector(2, selIds); + selIds[1] = &ids.get("range"); + getBytesRangeSel = sels.getSelector(2, selIds); } bool VisitObjCMessageExpr(ObjCMessageExpr *E) { @@ -78,6 +92,26 @@ public: return true; } + if (E->isInstanceMessage() && + E->getReceiverInterface() && + E->getReceiverInterface()->getName() == "NSData" && + E->getInstanceReceiver() && + (E->getSelector() == bytesSel || + E->getSelector() == getBytesSel || + E->getSelector() == getBytesLengthSel || + E->getSelector() == getBytesRangeSel)) { + Expr *rec = E->getInstanceReceiver(); + rec = rec->IgnoreParenCasts(); + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(rec)) + if (VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) + if (VD->hasLocalStorage() && !ChangedNSDataVars.count(VD)) { + Transaction Trans(Pass.TA); + Pass.TA.insertAfterToken(VD->getLocation(), + " __attribute__((objc_precise_lifetime))"); + ChangedNSDataVars.insert(VD); + } + } + return true; } }; |

