]> granicus.if.org Git - clang/commitdiff
In Objective-C ARC, completely ignore ownership qualifiers on the
authorDouglas Gregor <dgregor@apple.com>
Thu, 17 Jan 2013 23:36:45 +0000 (23:36 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 17 Jan 2013 23:36:45 +0000 (23:36 +0000)
return type of a function by canonicalizing them away. They are
useless anyway, and conflict with our rules for template argument
deduction and __strong. Fixes <rdar://problem/12367446>.

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

include/clang/Basic/DiagnosticSemaKinds.td
lib/AST/ASTContext.cpp
lib/Sema/SemaType.cpp
test/SemaObjC/arc-objc-lifetime.m
test/SemaObjCXX/arc-templates.mm

index 328bebe9af4429c1d3faa968f9f557049e6856cd..c23d9eee4820b913a63d573c6c2e265a2daed4fc 100644 (file)
@@ -3763,6 +3763,10 @@ def err_arc_collection_forward : Error<
 def err_arc_multiple_method_decl : Error< 
   "multiple methods named %0 found with mismatched result, "
   "parameter type or attributes">;
+def warn_arc_lifetime_result_type : Warning<
+  "ARC %select{unused|__unsafe_unretained|__strong|__weak|__autoreleasing}0 "
+  "lifetime qualifier on return type is ignored">,
+  InGroup<IgnoredQualifiers>;
 
 let CategoryName = "ARC Retain Cycle" in {
 
index df64237f704877a071389b72ad992253858da841..ace9dc0146a4153e1bf156fd340e59587ab9100b 100644 (file)
@@ -2602,6 +2602,13 @@ ASTContext::getFunctionNoProtoType(QualType ResultTy,
   return QualType(New, 0);
 }
 
+/// \brief Determine whether \p T is canonical as the result type of a function.
+static bool isCanonicalResultType(QualType T) {
+  return T.isCanonical() &&
+         (T.getObjCLifetime() == Qualifiers::OCL_None ||
+          T.getObjCLifetime() == Qualifiers::OCL_ExplicitNone);
+}
+
 /// getFunctionType - Return a normal function type with a typed argument
 /// list.  isVariadic indicates whether the argument list includes '...'.
 QualType
@@ -2620,7 +2627,7 @@ ASTContext::getFunctionType(QualType ResultTy,
 
   // Determine whether the type being created is already canonical or not.
   bool isCanonical =
-    EPI.ExceptionSpecType == EST_None && ResultTy.isCanonical() &&
+    EPI.ExceptionSpecType == EST_None && isCanonicalResultType(ResultTy) &&
     !EPI.HasTrailingReturn;
   for (unsigned i = 0; i != NumArgs && isCanonical; ++i)
     if (!ArgArray[i].isCanonicalAsParam())
@@ -2646,7 +2653,15 @@ ASTContext::getFunctionType(QualType ResultTy,
     CanonicalEPI.ExtInfo
       = CanonicalEPI.ExtInfo.withCallingConv(getCanonicalCallConv(CallConv));
 
-    Canonical = getFunctionType(getCanonicalType(ResultTy),
+    // Result types do not have ARC lifetime qualifiers.
+    QualType CanResultTy = getCanonicalType(ResultTy);
+    if (ResultTy.getQualifiers().hasObjCLifetime()) {
+      Qualifiers Qs = CanResultTy.getQualifiers();
+      Qs.removeObjCLifetime();
+      CanResultTy = getQualifiedType(CanResultTy.getUnqualifiedType(), Qs);
+    }
+
+    Canonical = getFunctionType(CanResultTy,
                                 CanonicalArgs.data(), NumArgs,
                                 CanonicalEPI);
 
index 15aa39b7e4e06a616c5b439dec93c5e8eed30839..35816a42f33e9388db09c9ff37ebb646d744c9f5 100644 (file)
@@ -2471,6 +2471,44 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
                                   S);
       }
 
+      // Objective-C ARC ownership qualifiers are ignored on the function
+      // return type (by type canonicalization). Complain if this attribute
+      // was written here.
+      if (T.getQualifiers().hasObjCLifetime()) {
+        SourceLocation AttrLoc;
+        if (chunkIndex + 1 < D.getNumTypeObjects()) {
+          DeclaratorChunk ReturnTypeChunk = D.getTypeObject(chunkIndex + 1);
+          for (const AttributeList *Attr = ReturnTypeChunk.getAttrs();
+               Attr; Attr = Attr->getNext()) {
+            if (Attr->getKind() == AttributeList::AT_ObjCOwnership) {
+              AttrLoc = Attr->getLoc();
+              break;
+            }
+          }
+        }
+        if (AttrLoc.isInvalid()) {
+          for (const AttributeList *Attr
+                 = D.getDeclSpec().getAttributes().getList();
+               Attr; Attr = Attr->getNext()) {
+            if (Attr->getKind() == AttributeList::AT_ObjCOwnership) {
+              AttrLoc = Attr->getLoc();
+              break;
+            }
+          }
+        }
+
+        if (AttrLoc.isValid()) {
+          // The ownership attributes are almost always written via
+          // the predefined
+          // __strong/__weak/__autoreleasing/__unsafe_unretained.
+          if (AttrLoc.isMacroID())
+            AttrLoc = S.SourceMgr.getImmediateExpansionRange(AttrLoc).first;
+
+          S.Diag(AttrLoc, diag::warn_arc_lifetime_result_type)
+            << T.getQualifiers().getObjCLifetime();
+        }
+      }
+
       if (LangOpts.CPlusPlus && D.getDeclSpec().isTypeSpecOwned()) {
         // C++ [dcl.fct]p6:
         //   Types shall not be defined in return or parameter types.
index 08d2dbe16c87479496a979fe5c7dd84db07208c9..f2fb1393222c942e6906f82b00a522215b61f798 100644 (file)
@@ -67,3 +67,22 @@ typedef void (^T) ();
 - (void)createInferiorTransportAndSetEnvironment:(NSMutableDictionary*)environment error:(__autoreleasing NSError**)error {}
 @end
 
+// <rdar://problem/12367446>
+typedef __strong id strong_id;
+typedef NSObject *NSObject_ptr;
+typedef __strong NSObject *strong_NSObject_ptr;
+
+// Warn
+__strong id f1(); // expected-warning{{ARC __strong lifetime qualifier on return type is ignored}}
+NSObject __unsafe_unretained *f2(int); // expected-warning{{ARC __unsafe_unretained lifetime qualifier on return type is ignored}}
+__autoreleasing NSObject *f3(void); // expected-warning{{ARC __autoreleasing lifetime qualifier on return type is ignored}}
+NSObject * __strong f4(void); // expected-warning{{ARC __strong lifetime qualifier on return type is ignored}}
+NSObject_ptr __strong f5(); // expected-warning{{ARC __strong lifetime qualifier on return type is ignored}}
+
+typedef __strong id (*fptr)(int); // expected-warning{{ARC __strong lifetime qualifier on return type is ignored}}
+typedef __strong id (^block_ptr)(int); // expected-warning{{ARC __strong lifetime qualifier on return type is ignored}}
+
+// Don't warn
+strong_id f6();
+strong_NSObject_ptr f7();
+
index 80092729d34ec10af4b313a6fa42ad3ab119c32f..ef68b94e7284170fbe5262937cef93556bd57e5a 100644 (file)
@@ -283,3 +283,12 @@ namespace rdar10862386 {
       testing(@"hi");
  }
 }
+
+namespace rdar12367446 {
+  template <class T> class A;
+  template <class R> class A<R()> {};
+
+  void test() {
+    A<id()> value;
+  }
+}