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       if (MigrateCtx.Pass.noNSAllocReallocError())
     42         TA.reportWarning("call returns pointer to GC managed memory; "
     43                        "it will become unmanaged in ARC",
     44                        E->getLocStart(), E->getSourceRange());
     45       else
     46         TA.reportError("call returns pointer to GC managed memory; "
     47                        "it will become unmanaged in ARC",
     48                        E->getLocStart(), E->getSourceRange());
     49       return true;
     50     }
     51 
     52     Expr *CEE = E->getCallee()->IgnoreParenImpCasts();
     53     if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) {
     54       if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl())) {
     55         if (!FD->getDeclContext()->getRedeclContext()->isFileContext())
     56           return true;
     57 
     58         if (FD->getIdentifier() == NSMakeCollectableII) {
     59           Transaction Trans(TA);
     60           TA.clearDiagnostic(diag::err_unavailable,
     61                              diag::err_unavailable_message,
     62                              diag::err_ovl_deleted_call, // ObjC++
     63                              DRE->getSourceRange());
     64           TA.replace(DRE->getSourceRange(), "CFBridgingRelease");
     65 
     66         } else if (FD->getIdentifier() == CFMakeCollectableII) {
     67           TA.reportError("CFMakeCollectable will leak the object that it "
     68                          "receives in ARC", DRE->getLocation(),
     69                          DRE->getSourceRange());
     70         }
     71       }
     72     }
     73 
     74     return true;
     75   }
     76 };
     77 
     78 } // anonymous namespace
     79 
     80 void GCCollectableCallsTraverser::traverseBody(BodyContext &BodyCtx) {
     81   GCCollectableCallsChecker(BodyCtx.getMigrationContext())
     82                                             .TraverseStmt(BodyCtx.getTopStmt());
     83 }
     84