]> granicus.if.org Git - clang/commitdiff
[ARC] Do not transfer ARC ownership if the cast is going to result in r-value,
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Fri, 28 Oct 2011 22:54:28 +0000 (22:54 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Fri, 28 Oct 2011 22:54:28 +0000 (22:54 +0000)
in which case the ownership is redundant. Thanks to John for the suggestion.

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

lib/Sema/SemaType.cpp
test/SemaObjC/arc-type-conversion.m

index f828b144d6c886625e25971f5aabad1608c3fe46..802b36db078919247ba8b6effb623d1ec1d2e7b1 100644 (file)
@@ -2665,6 +2665,7 @@ static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state,
   // TODO: mark whether we did this inference?
 }
 
+/// \brief Used for transfering ownership in casts resulting in l-values.
 static void transferARCOwnership(TypeProcessingState &state,
                                  QualType &declSpecTy,
                                  Qualifiers::ObjCLifetime ownership) {
@@ -2672,6 +2673,7 @@ static void transferARCOwnership(TypeProcessingState &state,
   Declarator &D = state.getDeclarator();
 
   int inner = -1;
+  bool hasIndirection = false;
   for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
     DeclaratorChunk &chunk = D.getTypeObject(i);
     switch (chunk.Kind) {
@@ -2682,11 +2684,15 @@ static void transferARCOwnership(TypeProcessingState &state,
     case DeclaratorChunk::Array:
     case DeclaratorChunk::Reference:
     case DeclaratorChunk::Pointer:
+      if (inner != -1)
+        hasIndirection = true;
       inner = i;
       break;
 
     case DeclaratorChunk::BlockPointer:
-      return transferARCOwnershipToDeclaratorChunk(state, ownership, i);
+      if (inner != -1)
+        transferARCOwnershipToDeclaratorChunk(state, ownership, i);
+      return;
 
     case DeclaratorChunk::Function:
     case DeclaratorChunk::MemberPointer:
@@ -2695,13 +2701,13 @@ static void transferARCOwnership(TypeProcessingState &state,
   }
 
   if (inner == -1)
-    return transferARCOwnershipToDeclSpec(S, declSpecTy, ownership);
+    return;
 
   DeclaratorChunk &chunk = D.getTypeObject(inner); 
   if (chunk.Kind == DeclaratorChunk::Pointer) {
     if (declSpecTy->isObjCRetainableType())
       return transferARCOwnershipToDeclSpec(S, declSpecTy, ownership);
-    if (declSpecTy->isObjCObjectType())
+    if (declSpecTy->isObjCObjectType() && hasIndirection)
       return transferARCOwnershipToDeclaratorChunk(state, ownership, inner);
   } else {
     assert(chunk.Kind == DeclaratorChunk::Array ||
index c626cedcc5e4a683f7e5e964fb195e46b4a630e8..78bb180707ff383072d36b4483e1bdfc1776635c 100644 (file)
@@ -77,4 +77,12 @@ void ownership_transfer_in_cast(void *vp, Block *pblk) {
   Block_strong blk_strong1;
   Block_strong blk_strong2 = (Block)blk_strong1;
   Block_autoreleasing *blk_auto = (Block*)pblk;
+
+  id lv;
+  (void)(id)&lv; // expected-error {{cast of an indirect pointer to an Objective-C pointer to 'id'}}
+  (void)(id*)lv; // expected-error {{cast of an Objective-C pointer to '__strong id *'}}
+  (void)(NSString*)&lv; // expected-error {{cast of an indirect pointer to an Objective-C pointer to 'NSString *'}}
+  (void)(NSString**)lv; // expected-error {{cast of an Objective-C pointer to 'NSString *__strong *'}}
+  (void)(Block)&lv; // expected-error {{cast of an indirect pointer to an Objective-C pointer to 'Block'}}
+  (void)(Block*)lv; // expected-error {{cast of an Objective-C pointer to '__strong Block *'}}
 }