]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/llvm/tools/clang/lib/ARCMigrate/TransGCCalls.cpp
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / llvm / tools / clang / lib / ARCMigrate / TransGCCalls.cpp
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 }