r251874 - Stop back-patching 'readonly' Objective-C properties with 'readwrite' ones.

Douglas Gregor via cfe-commits cfe-commits at lists.llvm.org
Mon Nov 2 17:15:47 PST 2015


Author: dgregor
Date: Mon Nov  2 19:15:46 2015
New Revision: 251874

URL: http://llvm.org/viewvc/llvm-project?rev=251874&view=rev
Log:
Stop back-patching 'readonly' Objective-C properties with 'readwrite' ones.

A 'readonly' Objective-C property declared in the primary class can
effectively be shadowed by a 'readwrite' property declared within an
extension of that class, so long as the types and attributes of the
two property declarations are compatible.

Previously, this functionality was implemented by back-patching the
original 'readonly' property to make it 'readwrite', destroying source
information and causing some hideously redundant, incorrect
code. Simplify the implementation to express how this should actually
be modeled: as a separate property declaration in the extension that
shadows (via the name lookup rules) the declaration in the primary
class. While here, correct some broken Fix-Its, eliminate a pile of
redundant code, clean up the ARC migrator's handling of properties
declared in extensions, and fix debug info's naming of methods that
come from categories.

A wonderous side effect of doing this write is that it eliminates the
"AddedObjCPropertyInClassExtension" method from the AST mutation
listener, which in turn eliminates the last place where we rewrite
entire declarations in a chained PCH file or a module file. This
change (which fixes rdar://problem/18475765) will allow us to
eliminate the rewritten-decls logic from the serialization library,
and fixes a crash (rdar://problem/23247794) illustrated by the
test/PCH/chain-categories.m example.


Modified:
    cfe/trunk/include/clang/AST/ASTMutationListener.h
    cfe/trunk/include/clang/AST/DeclObjC.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/include/clang/Serialization/ASTWriter.h
    cfe/trunk/lib/ARCMigrate/TransProperties.cpp
    cfe/trunk/lib/AST/DeclObjC.cpp
    cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
    cfe/trunk/lib/Frontend/MultiplexConsumer.cpp
    cfe/trunk/lib/Sema/SemaDeclObjC.cpp
    cfe/trunk/lib/Sema/SemaExprObjC.cpp
    cfe/trunk/lib/Sema/SemaObjCProperty.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/test/FixIt/atomic-property.m
    cfe/trunk/test/Index/complete-kvc.m
    cfe/trunk/test/Modules/ModuleDebugInfo.m
    cfe/trunk/test/PCH/chain-categories.m
    cfe/trunk/test/SemaObjC/atomoic-property-synnthesis-rules.m
    cfe/trunk/test/SemaObjC/property-3.m
    cfe/trunk/test/SemaObjC/property-in-class-extension-1.m
    cfe/trunk/test/SemaObjCXX/property-invalid-type.mm

Modified: cfe/trunk/include/clang/AST/ASTMutationListener.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTMutationListener.h?rev=251874&r1=251873&r2=251874&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTMutationListener.h (original)
+++ cfe/trunk/include/clang/AST/ASTMutationListener.h Mon Nov  2 19:15:46 2015
@@ -92,18 +92,6 @@ public:
   virtual void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
                                             const ObjCInterfaceDecl *IFD) {}
 
-  /// \brief A objc class extension redeclared or introduced a property.
-  ///
-  /// \param Prop the property in the class extension
-  ///
-  /// \param OrigProp the property from the original interface that was declared
-  /// or null if the property was introduced.
-  ///
-  /// \param ClassExt the class extension.
-  virtual void AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop,
-                                            const ObjCPropertyDecl *OrigProp,
-                                            const ObjCCategoryDecl *ClassExt) {}
-
   /// \brief A declaration is marked used which was not previously marked used.
   ///
   /// \param D the declaration marked used

Modified: cfe/trunk/include/clang/AST/DeclObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=251874&r1=251873&r2=251874&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Mon Nov  2 19:15:46 2015
@@ -2524,11 +2524,6 @@ public:
     PropertyAttributesAsWritten = PRVal;
   }
 
- void makeitReadWriteAttribute() {
-    PropertyAttributes &= ~OBJC_PR_readonly;
-    PropertyAttributes |= OBJC_PR_readwrite;
- }
-
   // Helper methods for accessing attributes.
 
   /// isReadOnly - Return true iff the property has a setter.

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=251874&r1=251873&r2=251874&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Nov  2 19:15:46 2015
@@ -884,7 +884,8 @@ def err_property_type : Error<"property
 def error_missing_property_context : Error<
   "missing context for property implementation declaration">;
 def error_bad_property_decl : Error<
-  "property implementation must have its declaration in interface %0">;
+  "property implementation must have its declaration in interface %0 or one of "
+  "its extensions">;
 def error_category_property : Error<
   "property declared in category %0 cannot be implemented in "
   "class implementation">;

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=251874&r1=251873&r2=251874&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Nov  2 19:15:46 2015
@@ -3047,7 +3047,7 @@ public:
   /// warning) when atomic property has one but not the other user-declared
   /// setter or getter.
   void AtomicPropertySetterGetterRules(ObjCImplDecl* IMPDecl,
-                                       ObjCContainerDecl* IDecl);
+                                       ObjCInterfaceDecl* IDecl);
 
   void DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D);
 

Modified: cfe/trunk/include/clang/Serialization/ASTWriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=251874&r1=251873&r2=251874&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTWriter.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTWriter.h Mon Nov  2 19:15:46 2015
@@ -876,9 +876,6 @@ public:
   void FunctionDefinitionInstantiated(const FunctionDecl *D) override;
   void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
                                     const ObjCInterfaceDecl *IFD) override;
-  void AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop,
-                                    const ObjCPropertyDecl *OrigProp,
-                                    const ObjCCategoryDecl *ClassExt) override;
   void DeclarationMarkedUsed(const Decl *D) override;
   void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) override;
   void RedefinedHiddenDefinition(const NamedDecl *D, Module *M) override;

Modified: cfe/trunk/lib/ARCMigrate/TransProperties.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/TransProperties.cpp?rev=251874&r1=251873&r2=251874&view=diff
==============================================================================
--- cfe/trunk/lib/ARCMigrate/TransProperties.cpp (original)
+++ cfe/trunk/lib/ARCMigrate/TransProperties.cpp Mon Nov  2 19:15:46 2015
@@ -96,6 +96,10 @@ public:
 
     collectProperties(iface, AtProps);
 
+    // Look through extensions.
+    for (auto *Ext : iface->visible_extensions())
+      collectProperties(Ext, AtProps);
+
     typedef DeclContext::specific_decl_iterator<ObjCPropertyImplDecl>
         prop_impl_iterator;
     for (prop_impl_iterator
@@ -137,19 +141,6 @@ public:
       Transaction Trans(Pass.TA);
       rewriteProperty(props, atLoc);
     }
-
-    AtPropDeclsTy AtExtProps;
-    // Look through extensions.
-    for (auto *Ext : iface->visible_extensions())
-      collectProperties(Ext, AtExtProps, &AtProps);
-
-    for (AtPropDeclsTy::iterator
-           I = AtExtProps.begin(), E = AtExtProps.end(); I != E; ++I) {
-      SourceLocation atLoc = SourceLocation::getFromRawEncoding(I->first);
-      PropsTy &props = I->second;
-      Transaction Trans(Pass.TA);
-      doActionForExtensionProp(props, atLoc);
-    }
   }
 
 private:
@@ -177,15 +168,6 @@ private:
     }
   }
 
-  void doActionForExtensionProp(PropsTy &props, SourceLocation atLoc) {
-    llvm::DenseMap<IdentifierInfo *, PropActionKind>::iterator I;
-    I = ActionOnProp.find(props[0].PropD->getIdentifier());
-    if (I == ActionOnProp.end())
-      return;
-
-    doPropAction(I->second, props, atLoc, false);
-  }
-
   void rewriteProperty(PropsTy &props, SourceLocation atLoc) {
     ObjCPropertyDecl::PropertyAttributeKind propAttrs = getPropertyAttrs(props);
     

Modified: cfe/trunk/lib/AST/DeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=251874&r1=251873&r2=251874&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclObjC.cpp (original)
+++ cfe/trunk/lib/AST/DeclObjC.cpp Mon Nov  2 19:15:46 2015
@@ -161,6 +161,15 @@ ObjCPropertyDecl::findPropertyDecl(const
         return nullptr;
   }
 
+  // If context is class, then lookup property in its extensions.
+  // This comes before property is looked up in primary class.
+  if (auto *IDecl = dyn_cast<ObjCInterfaceDecl>(DC)) {
+    for (const auto *Ext : IDecl->known_extensions())
+      if (ObjCPropertyDecl *PD = ObjCPropertyDecl::findPropertyDecl(Ext,
+                                                                    propertyID))
+        return PD;
+  }
+
   DeclContext::lookup_result R = DC->lookup(propertyID);
   for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E;
        ++I)
@@ -190,6 +199,15 @@ ObjCPropertyDecl *ObjCContainerDecl::Fin
       if (Def->isHidden())
         return nullptr;
   }
+ 
+  // Search the extensions of a class first; they override what's in
+  // the class itself.
+  if (const auto *ClassDecl = dyn_cast<ObjCInterfaceDecl>(this)) {
+    for (const auto *Ext : ClassDecl->visible_extensions()) {
+      if (auto *P = Ext->FindPropertyDeclaration(PropertyId))
+        return P;
+    }
+  }
 
   if (ObjCPropertyDecl *PD =
         ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId))
@@ -207,7 +225,7 @@ ObjCPropertyDecl *ObjCContainerDecl::Fin
     }
     case Decl::ObjCInterface: {
       const ObjCInterfaceDecl *OID = cast<ObjCInterfaceDecl>(this);
-      // Look through categories (but not extensions).
+      // Look through categories (but not extensions; they were handled above).
       for (const auto *Cat : OID->visible_categories()) {
         if (!Cat->IsClassExtension())
           if (ObjCPropertyDecl *P = Cat->FindPropertyDeclaration(PropertyId))
@@ -327,6 +345,13 @@ void ObjCInterfaceDecl::collectPropertie
     PM[Prop->getIdentifier()] = Prop;
     PO.push_back(Prop);
   }
+  for (const auto *Ext : known_extensions()) {
+    const ObjCCategoryDecl *ClassExt = Ext;
+    for (auto *Prop : ClassExt->properties()) {
+      PM[Prop->getIdentifier()] = Prop;
+      PO.push_back(Prop);
+    }
+  }
   for (const auto *PI : all_referenced_protocols())
     PI->collectPropertiesToImplement(PM, PO);
   // Note, the properties declared only in class extensions are still copied
@@ -1182,18 +1207,47 @@ ObjCMethodDecl::findPropertyDecl(bool Ch
 
   if (isPropertyAccessor()) {
     const ObjCContainerDecl *Container = cast<ObjCContainerDecl>(getParent());
-    // If container is class extension, find its primary class.
-    if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(Container))
-      if (CatDecl->IsClassExtension())
-        Container = CatDecl->getClassInterface();
-    
     bool IsGetter = (NumArgs == 0);
 
-    for (const auto *I : Container->properties()) {
-      Selector NextSel = IsGetter ? I->getGetterName()
-                                  : I->getSetterName();
-      if (NextSel == Sel)
-        return I;
+    /// Local function that attempts to find a matching property within the
+    /// given Objective-C container.
+    auto findMatchingProperty =
+      [&](const ObjCContainerDecl *Container) -> const ObjCPropertyDecl * {
+
+      for (const auto *I : Container->properties()) {
+        Selector NextSel = IsGetter ? I->getGetterName()
+                                    : I->getSetterName();
+        if (NextSel == Sel)
+          return I;
+      }
+
+      return nullptr;
+    };
+
+    // Look in the container we were given.
+    if (const auto *Found = findMatchingProperty(Container))
+      return Found;
+
+    // If we're in a category or extension, look in the main class.
+    const ObjCInterfaceDecl *ClassDecl = nullptr;
+    if (const auto *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
+      ClassDecl = Category->getClassInterface();
+      if (const auto *Found = findMatchingProperty(ClassDecl))
+        return Found;
+    } else {
+      // Determine whether the container is a class.
+      ClassDecl = dyn_cast<ObjCInterfaceDecl>(Container);
+    }
+
+    // If we have a class, check its visible extensions.
+    if (ClassDecl) {
+      for (const auto *Ext : ClassDecl->visible_extensions()) {
+        if (Ext == Container)
+          continue;
+
+        if (const auto *Found = findMatchingProperty(Ext))
+          return Found;
+      }
     }
 
     llvm_unreachable("Marked as a property accessor but no property found!");

Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=251874&r1=251873&r2=251874&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Mon Nov  2 19:15:46 2015
@@ -216,6 +216,13 @@ StringRef CGDebugInfo::getObjCMethodName
   } else if (const ObjCInterfaceDecl *OID =
                  dyn_cast<const ObjCInterfaceDecl>(DC)) {
     OS << OID->getName();
+  } else if (const ObjCCategoryDecl *OC = dyn_cast<ObjCCategoryDecl>(DC)) {
+    if (OC->IsClassExtension()) {
+      OS << OC->getClassInterface()->getName();
+    } else {
+      OS << ((const NamedDecl *)OC)->getIdentifier()->getNameStart() << '('
+         << OC->getIdentifier()->getNameStart() << ')';
+    }
   } else if (const ObjCCategoryImplDecl *OCD =
                  dyn_cast<const ObjCCategoryImplDecl>(DC)) {
     OS << ((const NamedDecl *)OCD)->getIdentifier()->getNameStart() << '('

Modified: cfe/trunk/lib/Frontend/MultiplexConsumer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/MultiplexConsumer.cpp?rev=251874&r1=251873&r2=251874&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/MultiplexConsumer.cpp (original)
+++ cfe/trunk/lib/Frontend/MultiplexConsumer.cpp Mon Nov  2 19:15:46 2015
@@ -122,9 +122,6 @@ public:
   void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
                                     const ObjCInterfaceDecl *IFD) override;
   void FunctionDefinitionInstantiated(const FunctionDecl *D) override;
-  void AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop,
-                                    const ObjCPropertyDecl *OrigProp,
-                                    const ObjCCategoryDecl *ClassExt) override;
   void DeclarationMarkedUsed(const Decl *D) override;
   void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) override;
   void RedefinedHiddenDefinition(const NamedDecl *D, Module *M) override;
@@ -207,13 +204,6 @@ void MultiplexASTMutationListener::Funct
   for (auto &Listener : Listeners)
     Listener->FunctionDefinitionInstantiated(D);
 }
-void MultiplexASTMutationListener::AddedObjCPropertyInClassExtension(
-                                             const ObjCPropertyDecl *Prop,
-                                             const ObjCPropertyDecl *OrigProp,
-                                             const ObjCCategoryDecl *ClassExt) {
-  for (size_t i = 0, e = Listeners.size(); i != e; ++i)
-    Listeners[i]->AddedObjCPropertyInClassExtension(Prop, OrigProp, ClassExt);
-}
 void MultiplexASTMutationListener::DeclarationMarkedUsed(const Decl *D) {
   for (size_t i = 0, e = Listeners.size(); i != e; ++i)
     Listeners[i]->DeclarationMarkedUsed(D);

Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=251874&r1=251873&r2=251874&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Mon Nov  2 19:15:46 2015
@@ -2844,6 +2844,20 @@ void Sema::ImplMethodsVsClassMethods(Sco
   for (const auto *I : IMPDecl->instance_methods())
     InsMap.insert(I->getSelector());
 
+  // Add the selectors for getters/setters of @dynamic properties.
+  for (const auto *PImpl : IMPDecl->property_impls()) {
+    // We only care about @dynamic implementations.
+    if (PImpl->getPropertyImplementation() != ObjCPropertyImplDecl::Dynamic)
+      continue;
+
+    const auto *P = PImpl->getPropertyDecl();
+    if (!P) continue;
+
+    InsMap.insert(P->getGetterName());
+    if (!P->getSetterName().isNull())
+      InsMap.insert(P->getSetterName());
+  }
+
   // Check and see if properties declared in the interface have either 1)
   // an implementation or 2) there is a @synthesize/@dynamic implementation
   // of the property in the @implementation.

Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=251874&r1=251873&r2=251874&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Mon Nov  2 19:15:46 2015
@@ -1779,8 +1779,7 @@ HandleExprPropertyRefExpr(const ObjCObje
                           diag::err_property_not_found_forward_class,
                           MemberName, BaseRange))
     return ExprError();
-  
-  // Search for a declared property first.
+ 
   if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(Member)) {
     // Check whether we can reference this property.
     if (DiagnoseUseOfDecl(PD, MemberLoc))

Modified: cfe/trunk/lib/Sema/SemaObjCProperty.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaObjCProperty.cpp?rev=251874&r1=251873&r2=251874&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaObjCProperty.cpp (original)
+++ cfe/trunk/lib/Sema/SemaObjCProperty.cpp Mon Nov  2 19:15:46 2015
@@ -262,8 +262,12 @@ Decl *Sema::ActOnProperty(Scope *S, Sour
       }
     }
   } else if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
-    for (auto *P : Cat->protocols())
-      CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos);
+    // We don't check if class extension. Because properties in class extension
+    // are meant to override some of the attributes and checking has already done
+    // when property in class extension is constructed.
+    if (!Cat->IsClassExtension())
+      for (auto *P : Cat->protocols())
+        CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos);
   } else {
     ObjCProtocolDecl *Proto = cast<ObjCProtocolDecl>(ClassDecl);
     for (auto *P : Proto->protocols())
@@ -355,46 +359,6 @@ Sema::HandlePropertyInClassExtension(Sco
   IdentifierInfo *PropertyId = FD.D.getIdentifier();
   ObjCInterfaceDecl *CCPrimary = CDecl->getClassInterface();
   
-  if (CCPrimary) {
-    // Check for duplicate declaration of this property in current and
-    // other class extensions.
-    for (const auto *Ext : CCPrimary->known_extensions()) {
-      if (ObjCPropertyDecl *prevDecl
-            = ObjCPropertyDecl::findPropertyDecl(Ext, PropertyId)) {
-        Diag(AtLoc, diag::err_duplicate_property);
-        Diag(prevDecl->getLocation(), diag::note_property_declare);
-        return nullptr;
-      }
-    }
-  }
-
-  // Create a new ObjCPropertyDecl with the DeclContext being
-  // the class extension.
-  // FIXME. We should really be using CreatePropertyDecl for this.
-  ObjCPropertyDecl *PDecl =
-    ObjCPropertyDecl::Create(Context, DC, FD.D.getIdentifierLoc(),
-                             PropertyId, AtLoc, LParenLoc, T, TSI);
-  PDecl->setPropertyAttributesAsWritten(
-                          makePropertyAttributesAsWritten(AttributesAsWritten));
-  if (Attributes & ObjCDeclSpec::DQ_PR_readonly)
-    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly);
-  if (Attributes & ObjCDeclSpec::DQ_PR_readwrite)
-    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite);
-  if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic)
-    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic);
-  if (Attributes & ObjCDeclSpec::DQ_PR_atomic)
-    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_atomic);
-  if (Attributes & ObjCDeclSpec::DQ_PR_nullability)
-    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nullability);
-  if (Attributes & ObjCDeclSpec::DQ_PR_null_resettable)
-    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_null_resettable);
-
-  // Set setter/getter selector name. Needed later.
-  PDecl->setGetterName(GetterSel);
-  PDecl->setSetterName(SetterSel);
-  ProcessDeclAttributes(S, PDecl, FD.D);
-  DC->addDecl(PDecl);
-
   // We need to look in the @interface to see if the @property was
   // already declared.
   if (!CCPrimary) {
@@ -403,32 +367,35 @@ Sema::HandlePropertyInClassExtension(Sco
     return nullptr;
   }
 
-  // Find the property in continuation class's primary class only.
+  // Find the property in the extended class's primary class or
+  // extensions.
   ObjCPropertyDecl *PIDecl =
     CCPrimary->FindPropertyVisibleInPrimaryClass(PropertyId);
 
+  // If we found a property in an extension, complain. 
+  if (PIDecl && isa<ObjCCategoryDecl>(PIDecl->getDeclContext())) {
+    Diag(AtLoc, diag::err_duplicate_property);
+    Diag(PIDecl->getLocation(), diag::note_property_declare);
+    return nullptr;
+  }
+
+  // Create a new ObjCPropertyDecl with the DeclContext being
+  // the class extension.
+  ObjCPropertyDecl *PDecl = CreatePropertyDecl(S, CDecl, AtLoc, LParenLoc,
+                                               FD, GetterSel, SetterSel,
+                                               isAssign, isReadWrite,
+                                               Attributes, AttributesAsWritten,
+                                               T, TSI, MethodImplKind, DC);
+
+  // If there was no declaration of a property with the same name in
+  // the primary class, we're done.
   if (!PIDecl) {
-    // No matching property found in the primary class. Just fall thru
-    // and add property to continuation class's primary class.
-    ObjCPropertyDecl *PrimaryPDecl =
-      CreatePropertyDecl(S, CCPrimary, AtLoc, LParenLoc,
-                         FD, GetterSel, SetterSel, isAssign, isReadWrite,
-                         Attributes,AttributesAsWritten, T, TSI, MethodImplKind, 
-                         DC);
-
-    // A case of continuation class adding a new property in the class. This
-    // is not what it was meant for. However, gcc supports it and so should we.
-    // Make sure setter/getters are declared here.
-    ProcessPropertyDecl(PrimaryPDecl, CCPrimary,
+    ProcessPropertyDecl(PDecl, CDecl,
                         /* redeclaredProperty = */ nullptr,
                         /* lexicalDC = */ CDecl);
-    PDecl->setGetterMethodDecl(PrimaryPDecl->getGetterMethodDecl());
-    PDecl->setSetterMethodDecl(PrimaryPDecl->getSetterMethodDecl());
-    if (ASTMutationListener *L = Context.getASTMutationListener())
-      L->AddedObjCPropertyInClassExtension(PrimaryPDecl, /*OrigProp=*/nullptr,
-                                           CDecl);
-    return PrimaryPDecl;
+    return PDecl;
   }
+
   if (!Context.hasSameType(PIDecl->getType(), PDecl->getType())) {
     bool IncompatibleObjC = false;
     QualType ConvertedType;
@@ -451,82 +418,12 @@ Sema::HandlePropertyInClassExtension(Sco
       return nullptr;
     }
   }
-    
-  // The property 'PIDecl's readonly attribute will be over-ridden
-  // with continuation class's readwrite property attribute!
+
+  // A readonly property declared in the primary class can be refined
+  // by adding a rewrite property within an extension.
+  // Anything else is an error.
   unsigned PIkind = PIDecl->getPropertyAttributesAsWritten();
-  if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) {
-    PIkind &= ~ObjCPropertyDecl::OBJC_PR_readonly;
-    PIkind |= ObjCPropertyDecl::OBJC_PR_readwrite;
-    PIkind |= deducePropertyOwnershipFromType(*this, PIDecl->getType());
-    unsigned ClassExtensionMemoryModel = getOwnershipRule(Attributes);
-    unsigned PrimaryClassMemoryModel = getOwnershipRule(PIkind);
-    if (PrimaryClassMemoryModel && ClassExtensionMemoryModel &&
-        (PrimaryClassMemoryModel != ClassExtensionMemoryModel)) {
-      Diag(AtLoc, diag::warn_property_attr_mismatch);
-      Diag(PIDecl->getLocation(), diag::note_property_declare);
-    }
-    else if (getLangOpts().ObjCAutoRefCount) {
-      QualType PrimaryPropertyQT =
-        Context.getCanonicalType(PIDecl->getType()).getUnqualifiedType();
-      if (isa<ObjCObjectPointerType>(PrimaryPropertyQT)) {
-        bool PropertyIsWeak = ((PIkind & ObjCPropertyDecl::OBJC_PR_weak) != 0);
-        Qualifiers::ObjCLifetime PrimaryPropertyLifeTime =
-          PrimaryPropertyQT.getObjCLifetime();
-        if (PrimaryPropertyLifeTime == Qualifiers::OCL_None &&
-            (Attributes & ObjCDeclSpec::DQ_PR_weak) &&
-            !PropertyIsWeak) {
-              Diag(AtLoc, diag::warn_property_implicitly_mismatched);
-              Diag(PIDecl->getLocation(), diag::note_property_declare);
-            }
-        }
-    }
-    
-    DeclContext *DC = cast<DeclContext>(CCPrimary);
-    if (!ObjCPropertyDecl::findPropertyDecl(DC,
-                                 PIDecl->getDeclName().getAsIdentifierInfo())) {
-      // In mrr mode, 'readwrite' property must have an explicit
-      // memory attribute. If none specified, select the default (assign).
-      if (!getLangOpts().ObjCAutoRefCount) {
-        if (!(PIkind & (ObjCDeclSpec::DQ_PR_assign |
-                        ObjCDeclSpec::DQ_PR_retain |
-                        ObjCDeclSpec::DQ_PR_strong |
-                        ObjCDeclSpec::DQ_PR_copy |
-                        ObjCDeclSpec::DQ_PR_unsafe_unretained |
-                        ObjCDeclSpec::DQ_PR_weak)))
-          PIkind |= ObjCPropertyDecl::OBJC_PR_assign;
-      }
-      
-      // Protocol is not in the primary class. Must build one for it.
-      ObjCDeclSpec ProtocolPropertyODS;
-      // FIXME. Assuming that ObjCDeclSpec::ObjCPropertyAttributeKind
-      // and ObjCPropertyDecl::PropertyAttributeKind have identical
-      // values.  Should consolidate both into one enum type.
-      ProtocolPropertyODS.
-      setPropertyAttributes((ObjCDeclSpec::ObjCPropertyAttributeKind)
-                            PIkind);
-      // Must re-establish the context from class extension to primary
-      // class context.
-      ContextRAII SavedContext(*this, CCPrimary);
-      
-      Decl *ProtocolPtrTy =
-        ActOnProperty(S, AtLoc, LParenLoc, FD, ProtocolPropertyODS,
-                      PIDecl->getGetterName(),
-                      PIDecl->getSetterName(),
-                      isOverridingProperty,
-                      MethodImplKind,
-                      /* lexicalDC = */ CDecl);
-      PIDecl = cast<ObjCPropertyDecl>(ProtocolPtrTy);
-    }
-    PIDecl->makeitReadWriteAttribute();
-    if (Attributes & ObjCDeclSpec::DQ_PR_retain)
-      PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain);
-    if (Attributes & ObjCDeclSpec::DQ_PR_strong)
-      PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong);
-    if (Attributes & ObjCDeclSpec::DQ_PR_copy)
-      PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);
-    PIDecl->setSetterName(SetterSel);
-  } else {
+  if (!(isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly))) {
     // Tailor the diagnostics for the common case where a readwrite
     // property is declared both in the @interface and the continuation.
     // This is a common error where the user often intended the original
@@ -541,13 +438,53 @@ Sema::HandlePropertyInClassExtension(Sco
     Diag(PIDecl->getLocation(), diag::note_property_declare);
     return nullptr;
   }
+
+  PIkind &= ~ObjCPropertyDecl::OBJC_PR_readonly;
+  PIkind |= ObjCPropertyDecl::OBJC_PR_readwrite;
+  PIkind |= deducePropertyOwnershipFromType(*this, PIDecl->getType());
+  unsigned ClassExtensionMemoryModel = getOwnershipRule(Attributes);
+  unsigned PrimaryClassMemoryModel = getOwnershipRule(PIkind);
+  if (PrimaryClassMemoryModel && ClassExtensionMemoryModel &&
+      (PrimaryClassMemoryModel != ClassExtensionMemoryModel)) {
+    Diag(AtLoc, diag::warn_property_attr_mismatch);
+    Diag(PIDecl->getLocation(), diag::note_property_declare);
+  } else if (getLangOpts().ObjCAutoRefCount) {
+    QualType PrimaryPropertyQT =
+      Context.getCanonicalType(PIDecl->getType()).getUnqualifiedType();
+    if (isa<ObjCObjectPointerType>(PrimaryPropertyQT)) {
+      bool PropertyIsWeak = ((PIkind & ObjCPropertyDecl::OBJC_PR_weak) != 0);
+      Qualifiers::ObjCLifetime PrimaryPropertyLifeTime =
+        PrimaryPropertyQT.getObjCLifetime();
+      if (PrimaryPropertyLifeTime == Qualifiers::OCL_None &&
+          (Attributes & ObjCDeclSpec::DQ_PR_weak) &&
+          !PropertyIsWeak) {
+            Diag(AtLoc, diag::warn_property_implicitly_mismatched);
+            Diag(PIDecl->getLocation(), diag::note_property_declare);
+          }
+      }
+  }
+  
+  // Check that atomicity of property in class extension matches the previous
+  // declaration.
+  unsigned PDeclAtomicity =
+    PDecl->getPropertyAttributes() & (ObjCDeclSpec::DQ_PR_atomic | ObjCDeclSpec::DQ_PR_nonatomic);
+  unsigned PIDeclAtomicity =
+    PIDecl->getPropertyAttributes() & (ObjCDeclSpec::DQ_PR_atomic | ObjCDeclSpec::DQ_PR_nonatomic);
+  if (PDeclAtomicity != PIDeclAtomicity) {
+    bool PDeclAtomic = (!PDeclAtomicity || PDeclAtomicity & ObjCDeclSpec::DQ_PR_atomic);
+    bool PIDeclAtomic = (!PIDeclAtomicity || PIDeclAtomicity & ObjCDeclSpec::DQ_PR_atomic);
+    if (PDeclAtomic != PIDeclAtomic) {
+      Diag(PDecl->getLocation(), diag::warn_property_attribute)
+        << PDecl->getDeclName() << "atomic"
+        << cast<ObjCContainerDecl>(PIDecl->getDeclContext())->getName();
+      Diag(PIDecl->getLocation(), diag::note_property_declare);
+    }
+  }
+
   *isOverridingProperty = true;
-  // Make sure setter decl is synthesized, and added to primary class's list.
-  ProcessPropertyDecl(PIDecl, CCPrimary, PDecl, CDecl);
-  PDecl->setGetterMethodDecl(PIDecl->getGetterMethodDecl());
-  PDecl->setSetterMethodDecl(PIDecl->getSetterMethodDecl());
-  if (ASTMutationListener *L = Context.getASTMutationListener())
-    L->AddedObjCPropertyInClassExtension(PDecl, PIDecl, CDecl);
+
+  // Make sure setter decl is synthesized, and added to continuation class's list.
+  ProcessPropertyDecl(PDecl, CDecl, PIDecl, CDecl);
   return PDecl;
 }
 
@@ -1480,6 +1417,11 @@ static void CollectImmediateProperties(O
   if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
     for (auto *Prop : IDecl->properties())
       PropMap[Prop->getIdentifier()] = Prop;
+
+    // Collect the properties from visible extensions.
+    for (auto *Ext : IDecl->visible_extensions())
+      CollectImmediateProperties(Ext, PropMap, SuperPropMap, IncludeProtocols);
+
     if (IncludeProtocols) {
       // Scan through class's protocols.
       for (auto *PI : IDecl->all_referenced_protocols())
@@ -1487,9 +1429,8 @@ static void CollectImmediateProperties(O
     }
   }
   if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) {
-    if (!CATDecl->IsClassExtension())
-      for (auto *Prop : CATDecl->properties())
-        PropMap[Prop->getIdentifier()] = Prop;
+    for (auto *Prop : CATDecl->properties())
+      PropMap[Prop->getIdentifier()] = Prop;
     if (IncludeProtocols) {
       // Scan through class's protocols.
       for (auto *PI : CATDecl->protocols())
@@ -1549,6 +1490,14 @@ Sema::IvarBacksCurrentMethodAccessor(Obj
         (Property->getPropertyIvarDecl() == IV))
       return true;
   }
+  // Also look up property declaration in class extension whose one of its
+  // accessors is implemented by this method.
+  for (const auto *Ext : IFace->known_extensions())
+    for (const auto *Property : Ext->properties())
+      if ((Property->getGetterName() == IMD->getSelector() ||
+           Property->getSetterName() == IMD->getSelector()) &&
+          (Property->getPropertyIvarDecl() == IV))
+        return true;
   return false;
 }
 
@@ -1833,11 +1782,20 @@ void Sema::diagnoseNullResettableSynthes
 
 void
 Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl,
-                                       ObjCContainerDecl* IDecl) {
+                                       ObjCInterfaceDecl* IDecl) {
   // Rules apply in non-GC mode only
   if (getLangOpts().getGC() != LangOptions::NonGC)
     return;
-  for (const auto *Property : IDecl->properties()) {
+  ObjCContainerDecl::PropertyMap PM;
+  for (auto *Prop : IDecl->properties())
+    PM[Prop->getIdentifier()] = Prop;
+  for (const auto *Ext : IDecl->known_extensions())
+    for (auto *Prop : Ext->properties())
+      PM[Prop->getIdentifier()] = Prop;
+    
+    for (ObjCContainerDecl::PropertyMap::iterator I = PM.begin(), E = PM.end();
+         I != E; ++I) {
+    const ObjCPropertyDecl *Property = I->second;
     ObjCMethodDecl *GetterMethod = nullptr;
     ObjCMethodDecl *SetterMethod = nullptr;
     bool LookedUpGetterSetter = false;
@@ -1884,30 +1842,23 @@ Sema::AtomicPropertySetterGetterRules (O
           << Property->getIdentifier() << (GetterMethod != nullptr)
           << (SetterMethod != nullptr);
         // fixit stuff.
-        if (!AttributesAsWritten) {
-          if (Property->getLParenLoc().isValid()) {
-            // @property () ... case.
-            SourceRange PropSourceRange(Property->getAtLoc(), 
-                                        Property->getLParenLoc());
-            Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) <<
-              FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic");
-          }
-          else {
-            //@property id etc.
-            SourceLocation endLoc = 
-              Property->getTypeSourceInfo()->getTypeLoc().getBeginLoc();
-            endLoc = endLoc.getLocWithOffset(-1);
-            SourceRange PropSourceRange(Property->getAtLoc(), endLoc);
-            Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) <<
-              FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic) ");
-          }
-        }
-        else if (!(AttributesAsWritten & ObjCPropertyDecl::OBJC_PR_atomic)) {
+        if (Property->getLParenLoc().isValid() &&
+            !(AttributesAsWritten & ObjCPropertyDecl::OBJC_PR_atomic)) {
           // @property () ... case.
-          SourceLocation endLoc = Property->getLParenLoc();
-          SourceRange PropSourceRange(Property->getAtLoc(), endLoc);
-          Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) <<
-           FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic, ");
+          SourceLocation AfterLParen =
+            getLocForEndOfToken(Property->getLParenLoc());
+          StringRef NonatomicStr = AttributesAsWritten? "nonatomic, "
+                                                      : "nonatomic";
+          Diag(Property->getLocation(),
+               diag::note_atomic_property_fixup_suggest)
+            << FixItHint::CreateInsertion(AfterLParen, NonatomicStr);
+        } else if (Property->getLParenLoc().isInvalid()) {
+          //@property id etc.
+          SourceLocation startLoc = 
+            Property->getTypeSourceInfo()->getTypeLoc().getBeginLoc();
+          Diag(Property->getLocation(),
+               diag::note_atomic_property_fixup_suggest)
+            << FixItHint::CreateInsertion(startLoc, "(nonatomic) ");
         }
         else
           Diag(MethodLoc, diag::note_atomic_property_fixup_suggest);
@@ -2035,7 +1986,20 @@ void Sema::ProcessPropertyDecl(ObjCPrope
     return;
 
   GetterMethod = CD->getInstanceMethod(property->getGetterName());
+  // if setter or getter is not found in class extension, it might be
+  // in the primary class.
+  if (!GetterMethod)
+    if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CD))
+      if (CatDecl->IsClassExtension())
+        GetterMethod = CatDecl->getClassInterface()->
+                         getInstanceMethod(property->getGetterName());
+        
   SetterMethod = CD->getInstanceMethod(property->getSetterName());
+  if (!SetterMethod)
+    if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CD))
+      if (CatDecl->IsClassExtension())
+        SetterMethod = CatDecl->getClassInterface()->
+                          getInstanceMethod(property->getSetterName());
   DiagnosePropertyAccessorMismatch(property, GetterMethod,
                                    property->getLocation());
 
@@ -2068,9 +2032,7 @@ void Sema::ProcessPropertyDecl(ObjCPrope
     // No instance method of same name as property getter name was found.
     // Declare a getter method and add it to the list of methods
     // for this class.
-    SourceLocation Loc = redeclaredProperty ? 
-      redeclaredProperty->getLocation() :
-      property->getLocation();
+    SourceLocation Loc = property->getLocation();
 
     // If the property is null_resettable, the getter returns nonnull.
     QualType resultTy = property->getType();
@@ -2130,9 +2092,7 @@ void Sema::ProcessPropertyDecl(ObjCPrope
       // No instance method of same name as property setter name was found.
       // Declare a setter method and add it to the list of methods
       // for this class.
-      SourceLocation Loc = redeclaredProperty ? 
-        redeclaredProperty->getLocation() :
-        property->getLocation();
+      SourceLocation Loc = property->getLocation();
 
       SetterMethod =
         ObjCMethodDecl::Create(Context, Loc, Loc,

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=251874&r1=251873&r2=251874&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Mon Nov  2 19:15:46 2015
@@ -5756,21 +5756,6 @@ void ASTWriter::AddedObjCCategoryToInter
     const_cast<ObjCInterfaceDecl *>(IFD->getDefinition()));
 }
 
-
-void ASTWriter::AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop,
-                                          const ObjCPropertyDecl *OrigProp,
-                                          const ObjCCategoryDecl *ClassExt) {
-  const ObjCInterfaceDecl *D = ClassExt->getClassInterface();
-  if (!D)
-    return;
-
-  assert(!WritingAST && "Already writing the AST!");
-  if (!D->isFromASTFile())
-    return; // Declaration not imported from PCH.
-
-  RewriteDecl(D);
-}
-
 void ASTWriter::DeclarationMarkedUsed(const Decl *D) {
   assert(!WritingAST && "Already writing the AST!");
   if (!D->isFromASTFile())

Modified: cfe/trunk/test/FixIt/atomic-property.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/atomic-property.m?rev=251874&r1=251873&r2=251874&view=diff
==============================================================================
--- cfe/trunk/test/FixIt/atomic-property.m (original)
+++ cfe/trunk/test/FixIt/atomic-property.m Mon Nov  2 19:15:46 2015
@@ -23,7 +23,7 @@
 - (id) atomic_prop1 { return 0; }
 @end
 
-// CHECK: {4:1-4:10}:"@property (nonatomic) "
-// CHECK: {9:1-9:12}:"@property (nonatomic"
-// CHECK: {13:1-13:12}:"@property (nonatomic, "
+// CHECK-DAG: {4:11-4:11}:"(nonatomic) "
+// CHECK-DAG: {9:12-9:12}:"nonatomic"
+// CHECK-DAG: {13:12-13:12}:"nonatomic, "
 

Modified: cfe/trunk/test/Index/complete-kvc.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-kvc.m?rev=251874&r1=251873&r2=251874&view=diff
==============================================================================
--- cfe/trunk/test/Index/complete-kvc.m (original)
+++ cfe/trunk/test/Index/complete-kvc.m Mon Nov  2 19:15:46 2015
@@ -101,5 +101,5 @@ typedef signed char BOOL;
 
 // RUN: c-index-test -code-completion-at=%s:52:8 %s | FileCheck -check-prefix=CHECK-CC3 %s
 // CHECK-CC3: ObjCInstanceMethodDecl:{TypedText countOfIntProperty} (55)
-// CHECK-CC3-NEXT: ObjCInstanceMethodDecl:{TypedText intProperty} (40)
+// CHECK-CC3-NEXT: ObjCInstanceMethodDecl:{TypedText intProperty} (42)
 // CHECK-CC3-NEXT: ObjCInstanceMethodDecl:{TypedText isIntProperty} (40)

Modified: cfe/trunk/test/Modules/ModuleDebugInfo.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/ModuleDebugInfo.m?rev=251874&r1=251873&r2=251874&view=diff
==============================================================================
--- cfe/trunk/test/Modules/ModuleDebugInfo.m (original)
+++ cfe/trunk/test/Modules/ModuleDebugInfo.m Mon Nov  2 19:15:46 2015
@@ -33,7 +33,7 @@
 // CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "InnerEnum"
 // CHECK: !DISubprogram(name: "+[ObjCClass classMethod]"
 // CHECK: !DISubprogram(name: "-[ObjCClass instanceMethodWithInt:]"
-// CHECK: !DISubprogram(name: "-[ categoryMethod]"
+// CHECK: !DISubprogram(name: "-[Category(Category) categoryMethod]"
 
 // MODULE-CHECK: !DICompositeType(tag: DW_TAG_enumeration_type,
 // MODULE-CHECK-SAME:             scope: ![[MODULE:[0-9]+]],

Modified: cfe/trunk/test/PCH/chain-categories.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/chain-categories.m?rev=251874&r1=251873&r2=251874&view=diff
==============================================================================
--- cfe/trunk/test/PCH/chain-categories.m (original)
+++ cfe/trunk/test/PCH/chain-categories.m Mon Nov  2 19:15:46 2015
@@ -16,6 +16,10 @@
 - (void)finalize;
 @end
 
+ at interface NSObject (Properties)
+ at property (readonly,nonatomic) int intProp;
+ at end
+
 //===----------------------------------------------------------------------===//
 #elif !defined(HEADER2)
 #define HEADER2
@@ -34,6 +38,12 @@
 -(void)extMeth;
 @end
 
+ at interface NSObject ()
+ at property (readwrite,nonatomic) int intProp;
+ at end
+
+ at class NSObject;
+
 //===----------------------------------------------------------------------===//
 #else
 //===----------------------------------------------------------------------===//
@@ -47,6 +57,9 @@
 
 void test(NSObject *o) {
   [o extMeth];
+
+  // Make sure the property is treated as read-write.
+  o.intProp = 17;
 }
 
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/test/SemaObjC/atomoic-property-synnthesis-rules.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/atomoic-property-synnthesis-rules.m?rev=251874&r1=251873&r2=251874&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/atomoic-property-synnthesis-rules.m (original)
+++ cfe/trunk/test/SemaObjC/atomoic-property-synnthesis-rules.m Mon Nov  2 19:15:46 2015
@@ -129,10 +129,8 @@
 
 // read-only in class, read-write in class extension - might warn
 @property(readonly) int GetSet_ReadWriteInExt;
- at property(readonly) int Get_ReadWriteInExt;	// expected-note {{property declared here}} \
-                                                // expected-note {{setter and getter must both be synthesized}}
- at property(readonly) int Set_ReadWriteInExt;	// expected-note {{property declared here}} \
-                                                // expected-note {{setter and getter must both be synthesized}}
+ at property(readonly) int Get_ReadWriteInExt;
+ at property(readonly) int Set_ReadWriteInExt;
 @property(readonly) int None_ReadWriteInExt;
 @property(nonatomic,readonly) int GetSet_Nonatomic_ReadWriteInExt;
 @property(nonatomic,readonly) int Get_Nonatomic_ReadWriteInExt;
@@ -162,10 +160,8 @@
 @property(nonatomic,readonly) int None_Nonatomic_ReadOnly_LateSynthesize;
 
 @property(readonly) int GetSet_ReadWriteInExt_LateSynthesize;
- at property(readonly) int Get_ReadWriteInExt_LateSynthesize;	// expected-note {{property declared here}} \
-                                                                // expected-note {{setter and getter must both be synthesized}}
- at property(readonly) int Set_ReadWriteInExt_LateSynthesize;	// expected-note {{property declared here}} \
-                                                                // expected-note {{setter and getter must both be synthesized}}
+ at property(readonly) int Get_ReadWriteInExt_LateSynthesize;
+ at property(readonly) int Set_ReadWriteInExt_LateSynthesize;
 @property(readonly) int None_ReadWriteInExt_LateSynthesize;
 @property(nonatomic,readonly) int GetSet_Nonatomic_ReadWriteInExt_LateSynthesize;
 @property(nonatomic,readonly) int Get_Nonatomic_ReadWriteInExt_LateSynthesize;
@@ -207,8 +203,10 @@
 @interface Foo ()
 
 @property(readwrite) int GetSet_ReadWriteInExt;
- at property(readwrite) int Get_ReadWriteInExt;
- at property(readwrite) int Set_ReadWriteInExt;
+ at property(readwrite) int Get_ReadWriteInExt; // expected-note {{property declared here}} \
+                                             // expected-note {{setter and getter must both be synthesized}}
+ at property(readwrite) int Set_ReadWriteInExt; // expected-note {{property declared here}} \
+                                             // expected-note {{setter and getter must both be synthesized}}
 @property(readwrite) int None_ReadWriteInExt;
 @property(nonatomic,readwrite) int GetSet_Nonatomic_ReadWriteInExt;
 @property(nonatomic,readwrite) int Get_Nonatomic_ReadWriteInExt;
@@ -216,8 +214,10 @@
 @property(nonatomic,readwrite) int None_Nonatomic_ReadWriteInExt;
 
 @property(readwrite) int GetSet_ReadWriteInExt_LateSynthesize;
- at property(readwrite) int Get_ReadWriteInExt_LateSynthesize;
- at property(readwrite) int Set_ReadWriteInExt_LateSynthesize;
+ at property(readwrite) int Get_ReadWriteInExt_LateSynthesize;  // expected-note {{property declared here}} \
+                                                             // expected-note {{setter and getter must both be synthesized}}
+ at property(readwrite) int Set_ReadWriteInExt_LateSynthesize; // expected-note {{property declared here}} \
+                                                            // expected-note {{setter and getter must both be synthesized}}
 @property(readwrite) int None_ReadWriteInExt_LateSynthesize;
 @property(nonatomic,readwrite) int GetSet_Nonatomic_ReadWriteInExt_LateSynthesize;
 @property(nonatomic,readwrite) int Get_Nonatomic_ReadWriteInExt_LateSynthesize;

Modified: cfe/trunk/test/SemaObjC/property-3.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/property-3.m?rev=251874&r1=251873&r2=251874&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/property-3.m (original)
+++ cfe/trunk/test/SemaObjC/property-3.m Mon Nov  2 19:15:46 2015
@@ -29,5 +29,5 @@ typedef signed char BOOL;
 
 @interface EKCalendar ()  <EKProtocolMutableCalendar>
 @property (nonatomic, assign) BOOL allowReminders;
- at property (nonatomic, assign) BOOL allowNonatomicProperty; // expected-warning {{'atomic' attribute on property 'allowNonatomicProperty' does not match the property inherited from 'EKProtocolCalendar'}}
+ at property (nonatomic, assign) BOOL allowNonatomicProperty; // expected-warning {{'atomic' attribute on property 'allowNonatomicProperty' does not match the property inherited from EKProtocolCalendar}}
 @end

Modified: cfe/trunk/test/SemaObjC/property-in-class-extension-1.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/property-in-class-extension-1.m?rev=251874&r1=251873&r2=251874&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/property-in-class-extension-1.m (original)
+++ cfe/trunk/test/SemaObjC/property-in-class-extension-1.m Mon Nov  2 19:15:46 2015
@@ -10,7 +10,7 @@
 
 @property (nonatomic, copy, readonly) NSString* matchingMemoryModel;
 
- at property (nonatomic, retain, readonly) NSString* addingNoNewMemoryModel;
+ at property (atomic, retain, readonly) NSString* addingNoNewMemoryModel;
 
 @property (readonly) NSString* none;
 @property (readonly) NSString* none1;
@@ -50,10 +50,14 @@
 // rdar://12214070
 @interface radar12214070
 @property (nonatomic, atomic, readonly) float propertyName; // expected-error {{property attributes 'atomic' and 'nonatomic' are mutually exclusive}}
+							    
+ at property (nonatomic, readonly) float propertyName2; // expected-note {{property declared here}}
 @end
 
 @interface radar12214070 ()
 @property (atomic, nonatomic, readonly, readwrite) float propertyName; // expected-error {{property attributes 'readonly' and 'readwrite' are mutually exclusive}} \
 		// expected-error {{property attributes 'atomic' and 'nonatomic' are mutually exclusive}}
+
+ at property (atomic, readwrite) float propertyName2; // expected-warning {{'atomic' attribute on property 'propertyName2' does not match the property inherited from radar12214070}}
 @end
 

Modified: cfe/trunk/test/SemaObjCXX/property-invalid-type.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/property-invalid-type.mm?rev=251874&r1=251873&r2=251874&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjCXX/property-invalid-type.mm (original)
+++ cfe/trunk/test/SemaObjCXX/property-invalid-type.mm Mon Nov  2 19:15:46 2015
@@ -13,11 +13,11 @@
 @synthesize response;
 - (void) foo :(A*) a   // expected-error {{expected a type}}
 {
-  self.response = a;
+  self.response = a; // expected-error{{assigning to 'int *' from incompatible type 'id'}}
 }
 @end
 
 void foo(I *i)
 {
-  i.helper;
+  i.helper; // expected-warning{{property access result unused - getters should not be used for side effects}}
 }




More information about the cfe-commits mailing list