[cfe-commits] r150029 - in /cfe/trunk: lib/Sema/SemaType.cpp test/SemaObjC/arc-objc-lifetime.m test/SemaObjC/arc.m test/SemaObjCXX/arc-templates.mm

John McCall rjmccall at apple.com
Tue Feb 7 16:46:41 PST 2012


Author: rjmccall
Date: Tue Feb  7 18:46:41 2012
New Revision: 150029

URL: http://llvm.org/viewvc/llvm-project?rev=150029&view=rev
Log:
Only complain about __strong __strong id, not __strong SomeStrongTypedef
or __strong __typeof__(some.strong.thing).

Modified:
    cfe/trunk/lib/Sema/SemaType.cpp
    cfe/trunk/test/SemaObjC/arc-objc-lifetime.m
    cfe/trunk/test/SemaObjC/arc.m
    cfe/trunk/test/SemaObjCXX/arc-templates.mm

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=150029&r1=150028&r2=150029&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Tue Feb  7 18:46:41 2012
@@ -3236,6 +3236,36 @@
   Type = S.Context.getAddrSpaceQualType(Type, ASIdx);
 }
 
+/// Does this type have a "direct" ownership qualifier?  That is,
+/// is it written like "__strong id", as opposed to something like
+/// "typeof(foo)", where that happens to be strong?
+static bool hasDirectOwnershipQualifier(QualType type) {
+  // Fast path: no qualifier at all.
+  assert(type.getQualifiers().hasObjCLifetime());
+
+  while (true) {
+    // __strong id
+    if (const AttributedType *attr = dyn_cast<AttributedType>(type)) {
+      if (attr->getAttrKind() == AttributedType::attr_objc_ownership)
+        return true;
+
+      type = attr->getModifiedType();
+
+    // X *__strong (...)
+    } else if (const ParenType *paren = dyn_cast<ParenType>(type)) {
+      type = paren->getInnerType();
+   
+    // That's it for things we want to complain about.  In particular,
+    // we do not want to look through typedefs, typeof(expr),
+    // typeof(type), or any other way that the type is somehow
+    // abstracted.
+    } else {
+      
+      return false;
+    }
+  }
+}
+
 /// handleObjCOwnershipTypeAttr - Process an objc_ownership
 /// attribute on the specified type.
 ///
@@ -3264,12 +3294,6 @@
   if (AttrLoc.isMacroID())
     AttrLoc = S.getSourceManager().getImmediateExpansionRange(AttrLoc).first;
 
-  if (type.getQualifiers().getObjCLifetime()) {
-    S.Diag(AttrLoc, diag::err_attr_objc_ownership_redundant)
-      << type;
-    return true;
-  }
-
   if (!attr.getParameterName()) {
     S.Diag(AttrLoc, diag::err_attribute_argument_n_not_string)
       << "objc_ownership" << 1;
@@ -3277,6 +3301,11 @@
     return true;
   }
 
+  // Consume lifetime attributes without further comment outside of
+  // ARC mode.
+  if (!S.getLangOptions().ObjCAutoRefCount)
+    return true;
+
   Qualifiers::ObjCLifetime lifetime;
   if (attr.getParameterName()->isStr("none"))
     lifetime = Qualifiers::OCL_ExplicitNone;
@@ -3293,10 +3322,31 @@
     return true;
   }
 
-  // Consume lifetime attributes without further comment outside of
-  // ARC mode.
-  if (!S.getLangOptions().ObjCAutoRefCount)
-    return true;
+  SplitQualType underlyingType = type.split();
+
+  // Check for redundant/conflicting ownership qualifiers.
+  if (Qualifiers::ObjCLifetime previousLifetime
+        = type.getQualifiers().getObjCLifetime()) {
+    // If it's written directly, that's an error.
+    if (hasDirectOwnershipQualifier(type)) {
+      S.Diag(AttrLoc, diag::err_attr_objc_ownership_redundant)
+        << type;
+      return true;
+    }
+
+    // Otherwise, if the qualifiers actually conflict, pull sugar off
+    // until we reach a type that is directly qualified.
+    if (previousLifetime != lifetime) {
+      // This should always terminate: the canonical type is
+      // qualified, so some bit of sugar must be hiding it.
+      while (!underlyingType.Quals.hasObjCLifetime()) {
+        underlyingType = underlyingType.getSingleStepDesugaredType();
+      }
+      underlyingType.Quals.removeObjCLifetime();
+    }
+  }
+
+  underlyingType.Quals.addObjCLifetime(lifetime);
 
   if (NonObjCPointer) {
     StringRef name = attr.getName()->getName();
@@ -3312,11 +3362,9 @@
       << name << type;
   }
 
-  Qualifiers qs;
-  qs.setObjCLifetime(lifetime);
   QualType origType = type;
   if (!NonObjCPointer)
-    type = S.Context.getQualifiedType(type, qs);
+    type = S.Context.getQualifiedType(underlyingType);
 
   // If we have a valid source location for the attribute, use an
   // AttributedType instead.

Modified: cfe/trunk/test/SemaObjC/arc-objc-lifetime.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/arc-objc-lifetime.m?rev=150029&r1=150028&r2=150029&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/arc-objc-lifetime.m (original)
+++ cfe/trunk/test/SemaObjC/arc-objc-lifetime.m Tue Feb  7 18:46:41 2012
@@ -32,3 +32,11 @@
         __autoreleasing id *stuff = (__autoreleasing id *)addr;
 }
 @end
+
+// rdar://problem/10711456
+__strong I *__strong test1; // expected-error {{the type 'I *__strong' is already explicitly ownership-qualified}}
+__strong I *(__strong test2); // expected-error {{the type 'I *__strong' is already explicitly ownership-qualified}}
+__strong I *(__strong (test3)); // expected-error {{the type 'I *__strong' is already explicitly ownership-qualified}}
+__unsafe_unretained __typeof__(test3) test4;
+typedef __strong I *strong_I;
+__unsafe_unretained strong_I test5;

Modified: cfe/trunk/test/SemaObjC/arc.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/arc.m?rev=150029&r1=150028&r2=150029&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/arc.m (original)
+++ cfe/trunk/test/SemaObjC/arc.m Tue Feb  7 18:46:41 2012
@@ -39,8 +39,6 @@
 }
 @end
 
-__weak __strong id x; // expected-error {{the type '__strong id' already has retainment attributes}}
-
 // rdar://8843638
 
 @interface I

Modified: cfe/trunk/test/SemaObjCXX/arc-templates.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/arc-templates.mm?rev=150029&r1=150028&r2=150029&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjCXX/arc-templates.mm (original)
+++ cfe/trunk/test/SemaObjCXX/arc-templates.mm Tue Feb  7 18:46:41 2012
@@ -97,8 +97,8 @@
 template<typename T>
 struct make_weak_fail {
   typedef T T_type;
-  typedef __weak T_type type; // expected-error{{the type 'T_type' (aka '__weak id') already has retainment attributes set on it}} \
-  // expected-error{{the type 'T_type' (aka '__strong id') already has retainment attributes set on it}}
+  typedef __weak T_type type; // expected-error{{the type 'T_type' (aka '__weak id') is already explicitly ownership-qualified}} \
+  // expected-error{{the type 'T_type' (aka '__strong id') is already explicitly ownership-qualified}}
 };
 
 int check_make_weak_fail0[is_same<make_weak_fail<__weak id>::type, __weak id>::value? 1 : -1]; // expected-note{{in instantiation of template class 'make_weak_fail<__weak id>' requested here}}





More information about the cfe-commits mailing list