Home | History | Annotate | Download | only in ARCMigrate
      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 
     10 #include "Transforms.h"
     11 #include "Internals.h"
     12 #include "clang/AST/ASTContext.h"
     13 #include "clang/Sema/SemaDiagnostic.h"
     14 
     15 using namespace clang;
     16 using namespace arcmt;
     17 using namespace trans;
     18 
     19 namespace {
     20 
     21 class GCCollectableCallsChecker :
     22                          public RecursiveASTVisitor<GCCollectableCallsChecker> {
     23   MigrationContext &MigrateCtx;
     24   IdentifierInfo *NSMakeCollectableII;
     25   IdentifierInfo *CFMakeCollectableII;
     26 
     27 public:
     28   GCCollectableCallsChecker(MigrationContext &ctx)
     29     : MigrateCtx(ctx) {
     30     IdentifierTable &Ids = MigrateCtx.Pass.Ctx.Idents;
     31     NSMakeCollectableII = &Ids.get("NSMakeCollectable");
     32     CFMakeCollectableII = &Ids.get("CFMakeCollectable");
     33   }
     34 
     35   bool shouldWalkTypesOfTypeLocs() const { return false; }
     36 
     37   bool VisitCallExpr(CallExpr *E) {
     38     TransformActions &TA = MigrateCtx.Pass.TA;
     39 
     40     if (MigrateCtx.isGCOwnedNonObjC(E->getType())) {
     41       TA.report(E->getLocStart(), diag::warn_arcmt_nsalloc_realloc,
     42                 E->getSourceRange());
     43       return true;
     44     }
     45 
     46     Expr *CEE = E->getCallee()->IgnoreParenImpCasts();
     47     if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) {
     48       if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl())) {
     49         if (!FD->getDeclContext()->getRedeclContext()->isFileContext())
     50           return true;
     51 
     52         if (FD->getIdentifier() == NSMakeCollectableII) {
     53           Transaction Trans(TA);
     54           TA.clearDiagnostic(diag::err_unavailable,
     55                              diag::err_unavailable_message,
     56                              diag::err_ovl_deleted_call, // ObjC++
     57                              DRE->getSourceRange());
     58           TA.replace(DRE->getSourceRange(), "CFBridgingRelease");
     59 
     60         } else if (FD->getIdentifier() == CFMakeCollectableII) {
     61           TA.reportError("CFMakeCollectable will leak the object that it "
     62                          "receives in ARC", DRE->getLocation(),
     63                          DRE->getSourceRange());
     64         }
     65       }
     66     }
     67 
     68     return true;
     69   }
     70 };
     71 
     72 } // anonymous namespace
     73 
     74 void GCCollectableCallsTraverser::traverseBody(BodyContext &BodyCtx) {
     75   GCCollectableCallsChecker(BodyCtx.getMigrationContext())
     76                                             .TraverseStmt(BodyCtx.getTopStmt());
     77 }
     78