]> granicus.if.org Git - clang/commitdiff
[arcmt] In GC, error out when there is a call that returns a pointer to
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Fri, 4 Nov 2011 23:43:03 +0000 (23:43 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Fri, 4 Nov 2011 23:43:03 +0000 (23:43 +0000)
GC managed non-objc object memory.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@143747 91177308-0d34-0410-b5e6-96231b3b80d8

lib/ARCMigrate/TransGCCalls.cpp
lib/ARCMigrate/TransformActions.cpp
lib/ARCMigrate/Transforms.cpp
lib/ARCMigrate/Transforms.h
test/ARCMT/GC-check.m

index 8042c6caba737f9e3ea34423348d67fab6692b48..94e965df188f38220428f639a2c2246fdfd08467 100644 (file)
@@ -35,6 +35,13 @@ public:
   bool VisitCallExpr(CallExpr *E) {
     TransformActions &TA = MigrateCtx.getPass().TA;
 
+    if (MigrateCtx.isGCOwnedNonObjC(E->getType())) {
+      TA.reportError("call returns pointer to GC managed memory; "
+                     "it will become unmanaged in ARC",
+                     E->getLocStart(), E->getSourceRange());
+      return true;
+    }
+
     Expr *CEE = E->getCallee()->IgnoreParenImpCasts();
     if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) {
       if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl())) {
index ec676e909a3bccb0472ec4fe39539d8fe6ac43b2..7ad9b6005dca8c1268d0c20e8e2a033320e15758 100644 (file)
@@ -122,6 +122,8 @@ public:
                        ASTContext &ctx, Preprocessor &PP)
     : CapturedDiags(capturedDiags), Ctx(ctx), PP(PP), IsInTransaction(false) { }
 
+  ASTContext &getASTContext() { return Ctx; }
+
   void startTransaction();
   bool commitTransaction();
   void abortTransaction();
@@ -674,6 +676,12 @@ void TransformActions::reportError(StringRef error, SourceLocation loc,
                                    SourceRange range) {
   assert(!static_cast<TransformActionsImpl*>(Impl)->isInTransaction() &&
          "Errors should be emitted out of a transaction");
+
+  SourceManager &SM = static_cast<TransformActionsImpl*>(Impl)->
+                                             getASTContext().getSourceManager();
+  if (SM.isInSystemHeader(SM.getExpansionLoc(loc)))
+    return;
+
   // FIXME: Use a custom category name to distinguish rewriter errors.
   std::string rewriteErr = "[rewriter] ";
   rewriteErr += error;
@@ -688,6 +696,12 @@ void TransformActions::reportNote(StringRef note, SourceLocation loc,
                                   SourceRange range) {
   assert(!static_cast<TransformActionsImpl*>(Impl)->isInTransaction() &&
          "Errors should be emitted out of a transaction");
+
+  SourceManager &SM = static_cast<TransformActionsImpl*>(Impl)->
+                                             getASTContext().getSourceManager();
+  if (SM.isInSystemHeader(SM.getExpansionLoc(loc)))
+    return;
+
   // FIXME: Use a custom category name to distinguish rewriter errors.
   std::string rewriteNote = "[rewriter] ";
   rewriteNote += note;
index 0decdd6b43be537787b4d80e73e83286d7e69ec6..d0c9bc69c8552ad2bc7c5673935349aa654041db 100644 (file)
@@ -324,6 +324,26 @@ MigrationContext::~MigrationContext() {
     delete *I;
 }
 
+bool MigrationContext::isGCOwnedNonObjC(QualType T) {
+  while (!T.isNull()) {
+    if (const AttributedType *AttrT = T->getAs<AttributedType>()) {
+      if (AttrT->getAttrKind() == AttributedType::attr_objc_ownership)
+        return !AttrT->getModifiedType()->isObjCRetainableType();
+    }
+
+    if (T->isArrayType())
+      T = Pass.Ctx.getBaseElementType(T);
+    else if (const PointerType *PT = T->getAs<PointerType>())
+      T = PT->getPointeeType();
+    else if (const ReferenceType *RT = T->getAs<ReferenceType>())
+      T = RT->getPointeeType();
+    else
+      break;
+  }
+
+  return false;
+}
+
 void MigrationContext::traverse(TranslationUnitDecl *TU) {
   ASTTransform(*this).TraverseDecl(TU);
 }
index d935e86ae7348a54cf312109cc507986736e8902..515844656a0f4a45b4a19b79dacf685157752cf8 100644 (file)
@@ -82,6 +82,8 @@ public:
     Traversers.push_back(traverser);
   }
 
+  bool isGCOwnedNonObjC(QualType T);
+
   void traverse(TranslationUnitDecl *TU);
 };
 
index 0d5e878d76157fd5be20ce03d5ab3c1e817cac1b..f71787ce029c3e8618e55d3f6d1351b6ad42db47 100644 (file)
@@ -2,10 +2,13 @@
 // RUN: %clang_cc1 -arcmt-check -verify -triple x86_64-apple-darwin10 -fobjc-gc-only -x objective-c++ %s
 
 #define CF_AUTOMATED_REFCOUNT_UNAVAILABLE __attribute__((unavailable("not available in automatic reference counting mode")))
+typedef unsigned NSUInteger;
 typedef const void * CFTypeRef;
 CFTypeRef CFMakeCollectable(CFTypeRef cf) CF_AUTOMATED_REFCOUNT_UNAVAILABLE; // expected-note {{unavailable}}
+void *__strong NSAllocateCollectable(NSUInteger size, NSUInteger options);
 
 void test1(CFTypeRef *cft) {
   CFTypeRef c = CFMakeCollectable(cft); // expected-error {{CFMakeCollectable will leak the object that it receives in ARC}} \
                 // expected-error {{unavailable}}
+  NSAllocateCollectable(100, 0); // expected-error {{call returns pointer to GC managed memory; it will become unmanaged in ARC}}
 }