TransGCCalls.cpp 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. //===--- TransGCCalls.cpp - Transformations to ARC mode -------------------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #include "Transforms.h"
  10. #include "Internals.h"
  11. #include "clang/AST/ASTContext.h"
  12. #include "clang/Sema/SemaDiagnostic.h"
  13. using namespace clang;
  14. using namespace arcmt;
  15. using namespace trans;
  16. namespace {
  17. class GCCollectableCallsChecker :
  18. public RecursiveASTVisitor<GCCollectableCallsChecker> {
  19. MigrationContext &MigrateCtx;
  20. IdentifierInfo *NSMakeCollectableII;
  21. IdentifierInfo *CFMakeCollectableII;
  22. public:
  23. GCCollectableCallsChecker(MigrationContext &ctx)
  24. : MigrateCtx(ctx) {
  25. IdentifierTable &Ids = MigrateCtx.Pass.Ctx.Idents;
  26. NSMakeCollectableII = &Ids.get("NSMakeCollectable");
  27. CFMakeCollectableII = &Ids.get("CFMakeCollectable");
  28. }
  29. bool shouldWalkTypesOfTypeLocs() const { return false; }
  30. bool VisitCallExpr(CallExpr *E) {
  31. TransformActions &TA = MigrateCtx.Pass.TA;
  32. if (MigrateCtx.isGCOwnedNonObjC(E->getType())) {
  33. TA.report(E->getLocStart(), diag::warn_arcmt_nsalloc_realloc,
  34. E->getSourceRange());
  35. return true;
  36. }
  37. Expr *CEE = E->getCallee()->IgnoreParenImpCasts();
  38. if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) {
  39. if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl())) {
  40. if (!FD->getDeclContext()->getRedeclContext()->isFileContext())
  41. return true;
  42. if (FD->getIdentifier() == NSMakeCollectableII) {
  43. Transaction Trans(TA);
  44. TA.clearDiagnostic(diag::err_unavailable,
  45. diag::err_unavailable_message,
  46. diag::err_ovl_deleted_call, // ObjC++
  47. DRE->getSourceRange());
  48. TA.replace(DRE->getSourceRange(), "CFBridgingRelease");
  49. } else if (FD->getIdentifier() == CFMakeCollectableII) {
  50. TA.reportError("CFMakeCollectable will leak the object that it "
  51. "receives in ARC", DRE->getLocation(),
  52. DRE->getSourceRange());
  53. }
  54. }
  55. }
  56. return true;
  57. }
  58. };
  59. } // anonymous namespace
  60. void GCCollectableCallsTraverser::traverseBody(BodyContext &BodyCtx) {
  61. GCCollectableCallsChecker(BodyCtx.getMigrationContext())
  62. .TraverseStmt(BodyCtx.getTopStmt());
  63. }