<div dir="ltr">r254622, thanks! The attached patch does the same for debug info. It doesn't completely restore the behavior before your change though: The DIObjCProperty now always goes with the redeclared line, while it didn't always do this before (see test). This seems like a progression though.<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Dec 3, 2015 at 9:25 AM, Douglas Gregor <span dir="ltr"><<a href="mailto:dgregor@apple.com" target="_blank">dgregor@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word">This looks great, please commit. Thanks Nico!<div><br></div><div><span style="white-space:pre-wrap">       </span>- Doug</div><div><br><div><blockquote type="cite"><div><div class="h5"><div>On Dec 3, 2015, at 8:58 AM, Nico Weber <<a href="mailto:thakis@chromium.org" target="_blank">thakis@chromium.org</a>> wrote:</div><br></div></div><div><div><div class="h5"><div dir="ltr" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">Here's a version that gets that right.</div><div class="gmail_extra" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br><div class="gmail_quote">On Wed, Dec 2, 2015 at 8:16 PM, Douglas Gregor<span> </span><span dir="ltr"><<a href="mailto:dgregor@apple.com" target="_blank">dgregor@apple.com</a>></span><span> </span>wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word"><br><div><span><blockquote type="cite"><div>On Dec 2, 2015, at 7:22 PM, Nico Weber <<a href="mailto:thakis@chromium.org" target="_blank">thakis@chromium.org</a>> wrote:</div><br><div><div dir="ltr">It looks like one place in CGObjCMac.cpp still walks ObjCContainerDecl::properties(), while it probably should use collectPropertiesToImplement() which you extended to also find properites from known_extensions(). The attached patch has a fix that restores the observed prior behavior and a reduced lit test that makes sure this doesn't regress. Does this look right?</div></div></blockquote><div><br></div></span><div>Thank you for working on this!</div><div><br></div>It’s close; I suggest testing the case where you have a readonly property in the class definition and a readwrite property with the same name in an extension, to make sure we get the correct metadata (readwrite, without duplicates).</div><div><span><br><blockquote type="cite"><div><div dir="ltr"><div><br></div><div>If so, something like this would probably be needed in CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty) in CGDebugInfo.cpp too.</div></div></div></blockquote><div><br></div></span><div>Yep, there too.</div><div><br></div><span style="white-space:pre-wrap">  </span>- Doug</div><div><br><blockquote type="cite"><div><div><div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Dec 1, 2015 at 2:44 PM, Nico Weber<span> </span><span dir="ltr"><<a href="mailto:thakis@chromium.org" target="_blank">thakis@chromium.org</a>></span><span> </span>wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr">Actually, looking at it again Foo derives from NSObject and shouldn't shadow anything. So maybe this isn't an intentional behavior change even?</div><div><div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Dec 1, 2015 at 2:39 PM, Nico Weber<span> </span><span dir="ltr"><<a href="mailto:thakis@chromium.org" target="_blank">thakis@chromium.org</a>></span><span> </span>wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr">Hi Doug and Argyrios,<div><br></div><div>this is breaking things for us. We have a class ObjCPropertyReleaser that automatically releases synthesized Objective-C properties marked retain or copy [1]. It does this by looking at the result of property_getAttributes() and looking for 'C' or '&' (copy or retain).</div><div><br>After this change, this longer works. Here's a reduced example:</div><div><br></div><div><div>$ cat<span> </span><a href="http://main.mm/" target="_blank">main.mm</a></div><div>#import <Foundation/Foundation.h></div><div>#import <UIKit/UIKit.h></div><div><br></div><div>@interface Foo : NSObject</div><div>@end</div><div><br></div><div>@interface Foo ()</div><div><br></div><div>@property(nonatomic, retain) UIView* contentView;</div><div>@end</div><div><br></div><div>@implementation Foo</div><div>@synthesize contentView = _contentView;</div><div>@end</div></div><div><br></div><div><div>$ newclang++ -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator9.1.sdk -c<span> </span><a href="http://main.mm/" target="_blank">main.mm</a><span> </span>-o main.o && strings main.o | grep "&,N,V_contentView"</div><div># Nothing found.</div><div><br></div><div>$ oldclang++ -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator9.1.sdk -c<span> </span><a href="http://main.mm/" target="_blank">main.mm</a><span> </span>-o main.o && strings main.o | grep "&,N,V_contentView"</div><div>T@"UIView",&,N,V_contentView</div><div># ^ Found as expected</div></div><div><br></div><div><br></div><div>I suppose this is intentional and the fix is to not shadow readonly superclass properties? Finding these is a bit difficult though as clang doesn't warn about this as far as I can tell.</div><div><br></div><div>Thanks,</div><div>Nico</div><div><br></div><div>1: <a href="https://code.google.com/p/chromium/codesearch#chromium/src/base/mac/objc_property_releaser.h" target="_blank">https://code.google.com/p/chromium/codesearch#chromium/src/base/mac/objc_property_releaser.h</a></div></div><div><div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Nov 2, 2015 at 8:22 PM, Douglas Gregor via cfe-commits<span> </span><span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span><span> </span>wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">… and I forgot the most important part, which is that this is based on the good work of Mr. Kyrtzidis that I failed to acknowledge in the commit message.<br><br>       <span> </span>- Doug<br><div><div><br><br>> On Nov 2, 2015, at 5:15 PM, Douglas Gregor via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>> wrote:<br>><br>> Author: dgregor<br>> Date: Mon Nov  2 19:15:46 2015<br>> New Revision: 251874<br>><br>> URL:<span> </span><a href="http://llvm.org/viewvc/llvm-project?rev=251874&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=251874&view=rev</a><br>> Log:<br>> Stop back-patching 'readonly' Objective-C properties with 'readwrite' ones.<br>><br>> A 'readonly' Objective-C property declared in the primary class can<br>> effectively be shadowed by a 'readwrite' property declared within an<br>> extension of that class, so long as the types and attributes of the<br>> two property declarations are compatible.<br>><br>> Previously, this functionality was implemented by back-patching the<br>> original 'readonly' property to make it 'readwrite', destroying source<br>> information and causing some hideously redundant, incorrect<br>> code. Simplify the implementation to express how this should actually<br>> be modeled: as a separate property declaration in the extension that<br>> shadows (via the name lookup rules) the declaration in the primary<br>> class. While here, correct some broken Fix-Its, eliminate a pile of<br>> redundant code, clean up the ARC migrator's handling of properties<br>> declared in extensions, and fix debug info's naming of methods that<br>> come from categories.<br>><br>> A wonderous side effect of doing this write is that it eliminates the<br>> "AddedObjCPropertyInClassExtension" method from the AST mutation<br>> listener, which in turn eliminates the last place where we rewrite<br>> entire declarations in a chained PCH file or a module file. This<br>> change (which fixes<span> </span><a>rdar://problem/18475765</a>) will allow us to<br>> eliminate the rewritten-decls logic from the serialization library,<br>> and fixes a crash (<a>rdar://problem/23247794</a>) illustrated by the<br>> test/PCH/chain-categories.m example.<br>><br>><br>> Modified:<br>>    cfe/trunk/include/clang/AST/ASTMutationListener.h<br>>    cfe/trunk/include/clang/AST/DeclObjC.h<br>>    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>>    cfe/trunk/include/clang/Sema/Sema.h<br>>    cfe/trunk/include/clang/Serialization/ASTWriter.h<br>>    cfe/trunk/lib/ARCMigrate/TransProperties.cpp<br>>    cfe/trunk/lib/AST/DeclObjC.cpp<br>>    cfe/trunk/lib/CodeGen/CGDebugInfo.cpp<br>>    cfe/trunk/lib/Frontend/MultiplexConsumer.cpp<br>>    cfe/trunk/lib/Sema/SemaDeclObjC.cpp<br>>    cfe/trunk/lib/Sema/SemaExprObjC.cpp<br>>    cfe/trunk/lib/Sema/SemaObjCProperty.cpp<br>>    cfe/trunk/lib/Serialization/ASTWriter.cpp<br>>    cfe/trunk/test/FixIt/atomic-property.m<br>>    cfe/trunk/test/Index/complete-kvc.m<br>>    cfe/trunk/test/Modules/ModuleDebugInfo.m<br>>    cfe/trunk/test/PCH/chain-categories.m<br>>    cfe/trunk/test/SemaObjC/atomoic-property-synnthesis-rules.m<br>>    cfe/trunk/test/SemaObjC/property-3.m<br>>    cfe/trunk/test/SemaObjC/property-in-class-extension-1.m<br>>    cfe/trunk/test/SemaObjCXX/<a href="http://property-invalid-type.mm/" rel="noreferrer" target="_blank">property-invalid-type.mm</a><br>><br>> Modified: cfe/trunk/include/clang/AST/ASTMutationListener.h<br>> URL:<span> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTMutationListener.h?rev=251874&r1=251873&r2=251874&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTMutationListener.h?rev=251874&r1=251873&r2=251874&view=diff</a><br>> ==============================================================================<br>> --- cfe/trunk/include/clang/AST/ASTMutationListener.h (original)<br>> +++ cfe/trunk/include/clang/AST/ASTMutationListener.h Mon Nov  2 19:15:46 2015<br>> @@ -92,18 +92,6 @@ public:<br>>   virtual void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,<br>>                                             const ObjCInterfaceDecl *IFD) {}<br>><br>> -  /// \brief A objc class extension redeclared or introduced a property.<br>> -  ///<br>> -  /// \param Prop the property in the class extension<br>> -  ///<br>> -  /// \param OrigProp the property from the original interface that was declared<br>> -  /// or null if the property was introduced.<br>> -  ///<br>> -  /// \param ClassExt the class extension.<br>> -  virtual void AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop,<br>> -                                            const ObjCPropertyDecl *OrigProp,<br>> -                                            const ObjCCategoryDecl *ClassExt) {}<br>> -<br>>   /// \brief A declaration is marked used which was not previously marked used.<br>>   ///<br>>   /// \param D the declaration marked used<br>><br>> Modified: cfe/trunk/include/clang/AST/DeclObjC.h<br>> URL:<span> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=251874&r1=251873&r2=251874&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=251874&r1=251873&r2=251874&view=diff</a><br>> ==============================================================================<br>> --- cfe/trunk/include/clang/AST/DeclObjC.h (original)<br>> +++ cfe/trunk/include/clang/AST/DeclObjC.h Mon Nov  2 19:15:46 2015<br>> @@ -2524,11 +2524,6 @@ public:<br>>     PropertyAttributesAsWritten = PRVal;<br>>   }<br>><br>> - void makeitReadWriteAttribute() {<br>> -    PropertyAttributes &= ~OBJC_PR_readonly;<br>> -    PropertyAttributes |= OBJC_PR_readwrite;<br>> - }<br>> -<br>>   // Helper methods for accessing attributes.<br>><br>>   /// isReadOnly - Return true iff the property has a setter.<br>><br>> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>> URL:<span> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=251874&r1=251873&r2=251874&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=251874&r1=251873&r2=251874&view=diff</a><br>> ==============================================================================<br>> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)<br>> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Nov  2 19:15:46 2015<br>> @@ -884,7 +884,8 @@ def err_property_type : Error<"property<br>> def error_missing_property_context : Error<<br>>   "missing context for property implementation declaration">;<br>> def error_bad_property_decl : Error<<br>> -  "property implementation must have its declaration in interface %0">;<br>> +  "property implementation must have its declaration in interface %0 or one of "<br>> +  "its extensions">;<br>> def error_category_property : Error<<br>>   "property declared in category %0 cannot be implemented in "<br>>   "class implementation">;<br>><br>> Modified: cfe/trunk/include/clang/Sema/Sema.h<br>> URL:<span> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=251874&r1=251873&r2=251874&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=251874&r1=251873&r2=251874&view=diff</a><br>> ==============================================================================<br>> --- cfe/trunk/include/clang/Sema/Sema.h (original)<br>> +++ cfe/trunk/include/clang/Sema/Sema.h Mon Nov  2 19:15:46 2015<br>> @@ -3047,7 +3047,7 @@ public:<br>>   /// warning) when atomic property has one but not the other user-declared<br>>   /// setter or getter.<br>>   void AtomicPropertySetterGetterRules(ObjCImplDecl* IMPDecl,<br>> -                                       ObjCContainerDecl* IDecl);<br>> +                                       ObjCInterfaceDecl* IDecl);<br>><br>>   void DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D);<br>><br>><br>> Modified: cfe/trunk/include/clang/Serialization/ASTWriter.h<br>> URL:<span> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=251874&r1=251873&r2=251874&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=251874&r1=251873&r2=251874&view=diff</a><br>> ==============================================================================<br>> --- cfe/trunk/include/clang/Serialization/ASTWriter.h (original)<br>> +++ cfe/trunk/include/clang/Serialization/ASTWriter.h Mon Nov  2 19:15:46 2015<br>> @@ -876,9 +876,6 @@ public:<br>>   void FunctionDefinitionInstantiated(const FunctionDecl *D) override;<br>>   void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,<br>>                                     const ObjCInterfaceDecl *IFD) override;<br>> -  void AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop,<br>> -                                    const ObjCPropertyDecl *OrigProp,<br>> -                                    const ObjCCategoryDecl *ClassExt) override;<br>>   void DeclarationMarkedUsed(const Decl *D) override;<br>>   void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) override;<br>>   void RedefinedHiddenDefinition(const NamedDecl *D, Module *M) override;<br>><br>> Modified: cfe/trunk/lib/ARCMigrate/TransProperties.cpp<br>> URL:<span> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/TransProperties.cpp?rev=251874&r1=251873&r2=251874&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/TransProperties.cpp?rev=251874&r1=251873&r2=251874&view=diff</a><br>> ==============================================================================<br>> --- cfe/trunk/lib/ARCMigrate/TransProperties.cpp (original)<br>> +++ cfe/trunk/lib/ARCMigrate/TransProperties.cpp Mon Nov  2 19:15:46 2015<br>> @@ -96,6 +96,10 @@ public:<br>><br>>     collectProperties(iface, AtProps);<br>><br>> +    // Look through extensions.<br>> +    for (auto *Ext : iface->visible_extensions())<br>> +      collectProperties(Ext, AtProps);<br>> +<br>>     typedef DeclContext::specific_decl_iterator<ObjCPropertyImplDecl><br>>         prop_impl_iterator;<br>>     for (prop_impl_iterator<br>> @@ -137,19 +141,6 @@ public:<br>>       Transaction Trans(Pass.TA);<br>>       rewriteProperty(props, atLoc);<br>>     }<br>> -<br>> -    AtPropDeclsTy AtExtProps;<br>> -    // Look through extensions.<br>> -    for (auto *Ext : iface->visible_extensions())<br>> -      collectProperties(Ext, AtExtProps, &AtProps);<br>> -<br>> -    for (AtPropDeclsTy::iterator<br>> -           I = AtExtProps.begin(), E = AtExtProps.end(); I != E; ++I) {<br>> -      SourceLocation atLoc = SourceLocation::getFromRawEncoding(I->first);<br>> -      PropsTy &props = I->second;<br>> -      Transaction Trans(Pass.TA);<br>> -      doActionForExtensionProp(props, atLoc);<br>> -    }<br>>   }<br>><br>> private:<br>> @@ -177,15 +168,6 @@ private:<br>>     }<br>>   }<br>><br>> -  void doActionForExtensionProp(PropsTy &props, SourceLocation atLoc) {<br>> -    llvm::DenseMap<IdentifierInfo *, PropActionKind>::iterator I;<br>> -    I = ActionOnProp.find(props[0].PropD->getIdentifier());<br>> -    if (I == ActionOnProp.end())<br>> -      return;<br>> -<br>> -    doPropAction(I->second, props, atLoc, false);<br>> -  }<br>> -<br>>   void rewriteProperty(PropsTy &props, SourceLocation atLoc) {<br>>     ObjCPropertyDecl::PropertyAttributeKind propAttrs = getPropertyAttrs(props);<br>><br>><br>> Modified: cfe/trunk/lib/AST/DeclObjC.cpp<br>> URL:<span> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=251874&r1=251873&r2=251874&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=251874&r1=251873&r2=251874&view=diff</a><br>> ==============================================================================<br>> --- cfe/trunk/lib/AST/DeclObjC.cpp (original)<br>> +++ cfe/trunk/lib/AST/DeclObjC.cpp Mon Nov  2 19:15:46 2015<br>> @@ -161,6 +161,15 @@ ObjCPropertyDecl::findPropertyDecl(const<br>>         return nullptr;<br>>   }<br>><br>> +  // If context is class, then lookup property in its extensions.<br>> +  // This comes before property is looked up in primary class.<br>> +  if (auto *IDecl = dyn_cast<ObjCInterfaceDecl>(DC)) {<br>> +    for (const auto *Ext : IDecl->known_extensions())<br>> +      if (ObjCPropertyDecl *PD = ObjCPropertyDecl::findPropertyDecl(Ext,<br>> +                                                                    propertyID))<br>> +        return PD;<br>> +  }<br>> +<br>>   DeclContext::lookup_result R = DC->lookup(propertyID);<br>>   for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E;<br>>        ++I)<br>> @@ -190,6 +199,15 @@ ObjCPropertyDecl *ObjCContainerDecl::Fin<br>>       if (Def->isHidden())<br>>         return nullptr;<br>>   }<br>> +<br>> +  // Search the extensions of a class first; they override what's in<br>> +  // the class itself.<br>> +  if (const auto *ClassDecl = dyn_cast<ObjCInterfaceDecl>(this)) {<br>> +    for (const auto *Ext : ClassDecl->visible_extensions()) {<br>> +      if (auto *P = Ext->FindPropertyDeclaration(PropertyId))<br>> +        return P;<br>> +    }<br>> +  }<br>><br>>   if (ObjCPropertyDecl *PD =<br>>         ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId))<br>> @@ -207,7 +225,7 @@ ObjCPropertyDecl *ObjCContainerDecl::Fin<br>>     }<br>>     case Decl::ObjCInterface: {<br>>       const ObjCInterfaceDecl *OID = cast<ObjCInterfaceDecl>(this);<br>> -      // Look through categories (but not extensions).<br>> +      // Look through categories (but not extensions; they were handled above).<br>>       for (const auto *Cat : OID->visible_categories()) {<br>>         if (!Cat->IsClassExtension())<br>>           if (ObjCPropertyDecl *P = Cat->FindPropertyDeclaration(PropertyId))<br>> @@ -327,6 +345,13 @@ void ObjCInterfaceDecl::collectPropertie<br>>     PM[Prop->getIdentifier()] = Prop;<br>>     PO.push_back(Prop);<br>>   }<br>> +  for (const auto *Ext : known_extensions()) {<br>> +    const ObjCCategoryDecl *ClassExt = Ext;<br>> +    for (auto *Prop : ClassExt->properties()) {<br>> +      PM[Prop->getIdentifier()] = Prop;<br>> +      PO.push_back(Prop);<br>> +    }<br>> +  }<br>>   for (const auto *PI : all_referenced_protocols())<br>>     PI->collectPropertiesToImplement(PM, PO);<br>>   // Note, the properties declared only in class extensions are still copied<br>> @@ -1182,18 +1207,47 @@ ObjCMethodDecl::findPropertyDecl(bool Ch<br>><br>>   if (isPropertyAccessor()) {<br>>     const ObjCContainerDecl *Container = cast<ObjCContainerDecl>(getParent());<br>> -    // If container is class extension, find its primary class.<br>> -    if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(Container))<br>> -      if (CatDecl->IsClassExtension())<br>> -        Container = CatDecl->getClassInterface();<br>> -<br>>     bool IsGetter = (NumArgs == 0);<br>><br>> -    for (const auto *I : Container->properties()) {<br>> -      Selector NextSel = IsGetter ? I->getGetterName()<br>> -                                  : I->getSetterName();<br>> -      if (NextSel == Sel)<br>> -        return I;<br>> +    /// Local function that attempts to find a matching property within the<br>> +    /// given Objective-C container.<br>> +    auto findMatchingProperty =<br>> +      [&](const ObjCContainerDecl *Container) -> const ObjCPropertyDecl * {<br>> +<br>> +      for (const auto *I : Container->properties()) {<br>> +        Selector NextSel = IsGetter ? I->getGetterName()<br>> +                                    : I->getSetterName();<br>> +        if (NextSel == Sel)<br>> +          return I;<br>> +      }<br>> +<br>> +      return nullptr;<br>> +    };<br>> +<br>> +    // Look in the container we were given.<br>> +    if (const auto *Found = findMatchingProperty(Container))<br>> +      return Found;<br>> +<br>> +    // If we're in a category or extension, look in the main class.<br>> +    const ObjCInterfaceDecl *ClassDecl = nullptr;<br>> +    if (const auto *Category = dyn_cast<ObjCCategoryDecl>(Container)) {<br>> +      ClassDecl = Category->getClassInterface();<br>> +      if (const auto *Found = findMatchingProperty(ClassDecl))<br>> +        return Found;<br>> +    } else {<br>> +      // Determine whether the container is a class.<br>> +      ClassDecl = dyn_cast<ObjCInterfaceDecl>(Container);<br>> +    }<br>> +<br>> +    // If we have a class, check its visible extensions.<br>> +    if (ClassDecl) {<br>> +      for (const auto *Ext : ClassDecl->visible_extensions()) {<br>> +        if (Ext == Container)<br>> +          continue;<br>> +<br>> +        if (const auto *Found = findMatchingProperty(Ext))<br>> +          return Found;<br>> +      }<br>>     }<br>><br>>     llvm_unreachable("Marked as a property accessor but no property found!");<br>><br>> Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp<br>> URL:<span> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=251874&r1=251873&r2=251874&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=251874&r1=251873&r2=251874&view=diff</a><br>> ==============================================================================<br>> --- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)<br>> +++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Mon Nov  2 19:15:46 2015<br>> @@ -216,6 +216,13 @@ StringRef CGDebugInfo::getObjCMethodName<br>>   } else if (const ObjCInterfaceDecl *OID =<br>>                  dyn_cast<const ObjCInterfaceDecl>(DC)) {<br>>     OS << OID->getName();<br>> +  } else if (const ObjCCategoryDecl *OC = dyn_cast<ObjCCategoryDecl>(DC)) {<br>> +    if (OC->IsClassExtension()) {<br>> +      OS << OC->getClassInterface()->getName();<br>> +    } else {<br>> +      OS << ((const NamedDecl *)OC)->getIdentifier()->getNameStart() << '('<br>> +         << OC->getIdentifier()->getNameStart() << ')';<br>> +    }<br>>   } else if (const ObjCCategoryImplDecl *OCD =<br>>                  dyn_cast<const ObjCCategoryImplDecl>(DC)) {<br>>     OS << ((const NamedDecl *)OCD)->getIdentifier()->getNameStart() << '('<br>><br>> Modified: cfe/trunk/lib/Frontend/MultiplexConsumer.cpp<br>> URL:<span> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/MultiplexConsumer.cpp?rev=251874&r1=251873&r2=251874&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/MultiplexConsumer.cpp?rev=251874&r1=251873&r2=251874&view=diff</a><br>> ==============================================================================<br>> --- cfe/trunk/lib/Frontend/MultiplexConsumer.cpp (original)<br>> +++ cfe/trunk/lib/Frontend/MultiplexConsumer.cpp Mon Nov  2 19:15:46 2015<br>> @@ -122,9 +122,6 @@ public:<br>>   void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,<br>>                                     const ObjCInterfaceDecl *IFD) override;<br>>   void FunctionDefinitionInstantiated(const FunctionDecl *D) override;<br>> -  void AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop,<br>> -                                    const ObjCPropertyDecl *OrigProp,<br>> -                                    const ObjCCategoryDecl *ClassExt) override;<br>>   void DeclarationMarkedUsed(const Decl *D) override;<br>>   void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) override;<br>>   void RedefinedHiddenDefinition(const NamedDecl *D, Module *M) override;<br>> @@ -207,13 +204,6 @@ void MultiplexASTMutationListener::Funct<br>>   for (auto &Listener : Listeners)<br>>     Listener->FunctionDefinitionInstantiated(D);<br>> }<br>> -void MultiplexASTMutationListener::AddedObjCPropertyInClassExtension(<br>> -                                             const ObjCPropertyDecl *Prop,<br>> -                                             const ObjCPropertyDecl *OrigProp,<br>> -                                             const ObjCCategoryDecl *ClassExt) {<br>> -  for (size_t i = 0, e = Listeners.size(); i != e; ++i)<br>> -    Listeners[i]->AddedObjCPropertyInClassExtension(Prop, OrigProp, ClassExt);<br>> -}<br>> void MultiplexASTMutationListener::DeclarationMarkedUsed(const Decl *D) {<br>>   for (size_t i = 0, e = Listeners.size(); i != e; ++i)<br>>     Listeners[i]->DeclarationMarkedUsed(D);<br>><br>> Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp<br>> URL:<span> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=251874&r1=251873&r2=251874&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=251874&r1=251873&r2=251874&view=diff</a><br>> ==============================================================================<br>> --- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)<br>> +++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Mon Nov  2 19:15:46 2015<br>> @@ -2844,6 +2844,20 @@ void Sema::ImplMethodsVsClassMethods(Sco<br>>   for (const auto *I : IMPDecl->instance_methods())<br>>     InsMap.insert(I->getSelector());<br>><br>> +  // Add the selectors for getters/setters of @dynamic properties.<br>> +  for (const auto *PImpl : IMPDecl->property_impls()) {<br>> +    // We only care about @dynamic implementations.<br>> +    if (PImpl->getPropertyImplementation() != ObjCPropertyImplDecl::Dynamic)<br>> +      continue;<br>> +<br>> +    const auto *P = PImpl->getPropertyDecl();<br>> +    if (!P) continue;<br>> +<br>> +    InsMap.insert(P->getGetterName());<br>> +    if (!P->getSetterName().isNull())<br>> +      InsMap.insert(P->getSetterName());<br>> +  }<br>> +<br>>   // Check and see if properties declared in the interface have either 1)<br>>   // an implementation or 2) there is a @synthesize/@dynamic implementation<br>>   // of the property in the @implementation.<br>><br>> Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp<br>> URL:<span> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=251874&r1=251873&r2=251874&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=251874&r1=251873&r2=251874&view=diff</a><br>> ==============================================================================<br>> --- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)<br>> +++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Mon Nov  2 19:15:46 2015<br>> @@ -1779,8 +1779,7 @@ HandleExprPropertyRefExpr(const ObjCObje<br>>                           diag::err_property_not_found_forward_class,<br>>                           MemberName, BaseRange))<br>>     return ExprError();<br>> -<br>> -  // Search for a declared property first.<br>> +<br>>   if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(Member)) {<br>>     // Check whether we can reference this property.<br>>     if (DiagnoseUseOfDecl(PD, MemberLoc))<br>><br>> Modified: cfe/trunk/lib/Sema/SemaObjCProperty.cpp<br>> URL:<span> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaObjCProperty.cpp?rev=251874&r1=251873&r2=251874&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaObjCProperty.cpp?rev=251874&r1=251873&r2=251874&view=diff</a><br>> ==============================================================================<br>> --- cfe/trunk/lib/Sema/SemaObjCProperty.cpp (original)<br>> +++ cfe/trunk/lib/Sema/SemaObjCProperty.cpp Mon Nov  2 19:15:46 2015<br>> @@ -262,8 +262,12 @@ Decl *Sema::ActOnProperty(Scope *S, Sour<br>>       }<br>>     }<br>>   } else if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {<br>> -    for (auto *P : Cat->protocols())<br>> -      CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos);<br>> +    // We don't check if class extension. Because properties in class extension<br>> +    // are meant to override some of the attributes and checking has already done<br>> +    // when property in class extension is constructed.<br>> +    if (!Cat->IsClassExtension())<br>> +      for (auto *P : Cat->protocols())<br>> +        CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos);<br>>   } else {<br>>     ObjCProtocolDecl *Proto = cast<ObjCProtocolDecl>(ClassDecl);<br>>     for (auto *P : Proto->protocols())<br>> @@ -355,46 +359,6 @@ Sema::HandlePropertyInClassExtension(Sco<br>>   IdentifierInfo *PropertyId = FD.D.getIdentifier();<br>>   ObjCInterfaceDecl *CCPrimary = CDecl->getClassInterface();<br>><br>> -  if (CCPrimary) {<br>> -    // Check for duplicate declaration of this property in current and<br>> -    // other class extensions.<br>> -    for (const auto *Ext : CCPrimary->known_extensions()) {<br>> -      if (ObjCPropertyDecl *prevDecl<br>> -            = ObjCPropertyDecl::findPropertyDecl(Ext, PropertyId)) {<br>> -        Diag(AtLoc, diag::err_duplicate_property);<br>> -        Diag(prevDecl->getLocation(), diag::note_property_declare);<br>> -        return nullptr;<br>> -      }<br>> -    }<br>> -  }<br>> -<br>> -  // Create a new ObjCPropertyDecl with the DeclContext being<br>> -  // the class extension.<br>> -  // FIXME. We should really be using CreatePropertyDecl for this.<br>> -  ObjCPropertyDecl *PDecl =<br>> -    ObjCPropertyDecl::Create(Context, DC, FD.D.getIdentifierLoc(),<br>> -                             PropertyId, AtLoc, LParenLoc, T, TSI);<br>> -  PDecl->setPropertyAttributesAsWritten(<br>> -                          makePropertyAttributesAsWritten(AttributesAsWritten));<br>> -  if (Attributes & ObjCDeclSpec::DQ_PR_readonly)<br>> -    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly);<br>> -  if (Attributes & ObjCDeclSpec::DQ_PR_readwrite)<br>> -    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite);<br>> -  if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic)<br>> -    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic);<br>> -  if (Attributes & ObjCDeclSpec::DQ_PR_atomic)<br>> -    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_atomic);<br>> -  if (Attributes & ObjCDeclSpec::DQ_PR_nullability)<br>> -    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nullability);<br>> -  if (Attributes & ObjCDeclSpec::DQ_PR_null_resettable)<br>> -    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_null_resettable);<br>> -<br>> -  // Set setter/getter selector name. Needed later.<br>> -  PDecl->setGetterName(GetterSel);<br>> -  PDecl->setSetterName(SetterSel);<br>> -  ProcessDeclAttributes(S, PDecl, FD.D);<br>> -  DC->addDecl(PDecl);<br>> -<br>>   // We need to look in the @interface to see if the @property was<br>>   // already declared.<br>>   if (!CCPrimary) {<br>> @@ -403,32 +367,35 @@ Sema::HandlePropertyInClassExtension(Sco<br>>     return nullptr;<br>>   }<br>><br>> -  // Find the property in continuation class's primary class only.<br>> +  // Find the property in the extended class's primary class or<br>> +  // extensions.<br>>   ObjCPropertyDecl *PIDecl =<br>>     CCPrimary->FindPropertyVisibleInPrimaryClass(PropertyId);<br>><br>> +  // If we found a property in an extension, complain.<br>> +  if (PIDecl && isa<ObjCCategoryDecl>(PIDecl->getDeclContext())) {<br>> +    Diag(AtLoc, diag::err_duplicate_property);<br>> +    Diag(PIDecl->getLocation(), diag::note_property_declare);<br>> +    return nullptr;<br>> +  }<br>> +<br>> +  // Create a new ObjCPropertyDecl with the DeclContext being<br>> +  // the class extension.<br>> +  ObjCPropertyDecl *PDecl = CreatePropertyDecl(S, CDecl, AtLoc, LParenLoc,<br>> +                                               FD, GetterSel, SetterSel,<br>> +                                               isAssign, isReadWrite,<br>> +                                               Attributes, AttributesAsWritten,<br>> +                                               T, TSI, MethodImplKind, DC);<br>> +<br>> +  // If there was no declaration of a property with the same name in<br>> +  // the primary class, we're done.<br>>   if (!PIDecl) {<br>> -    // No matching property found in the primary class. Just fall thru<br>> -    // and add property to continuation class's primary class.<br>> -    ObjCPropertyDecl *PrimaryPDecl =<br>> -      CreatePropertyDecl(S, CCPrimary, AtLoc, LParenLoc,<br>> -                         FD, GetterSel, SetterSel, isAssign, isReadWrite,<br>> -                         Attributes,AttributesAsWritten, T, TSI, MethodImplKind,<br>> -                         DC);<br>> -<br>> -    // A case of continuation class adding a new property in the class. This<br>> -    // is not what it was meant for. However, gcc supports it and so should we.<br>> -    // Make sure setter/getters are declared here.<br>> -    ProcessPropertyDecl(PrimaryPDecl, CCPrimary,<br>> +    ProcessPropertyDecl(PDecl, CDecl,<br>>                         /* redeclaredProperty = */ nullptr,<br>>                         /* lexicalDC = */ CDecl);<br>> -    PDecl->setGetterMethodDecl(PrimaryPDecl->getGetterMethodDecl());<br>> -    PDecl->setSetterMethodDecl(PrimaryPDecl->getSetterMethodDecl());<br>> -    if (ASTMutationListener *L = Context.getASTMutationListener())<br>> -      L->AddedObjCPropertyInClassExtension(PrimaryPDecl, /*OrigProp=*/nullptr,<br>> -                                           CDecl);<br>> -    return PrimaryPDecl;<br>> +    return PDecl;<br>>   }<br>> +<br>>   if (!Context.hasSameType(PIDecl->getType(), PDecl->getType())) {<br>>     bool IncompatibleObjC = false;<br>>     QualType ConvertedType;<br>> @@ -451,82 +418,12 @@ Sema::HandlePropertyInClassExtension(Sco<br>>       return nullptr;<br>>     }<br>>   }<br>> -<br>> -  // The property 'PIDecl's readonly attribute will be over-ridden<br>> -  // with continuation class's readwrite property attribute!<br>> +<br>> +  // A readonly property declared in the primary class can be refined<br>> +  // by adding a rewrite property within an extension.<br>> +  // Anything else is an error.<br>>   unsigned PIkind = PIDecl->getPropertyAttributesAsWritten();<br>> -  if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) {<br>> -    PIkind &= ~ObjCPropertyDecl::OBJC_PR_readonly;<br>> -    PIkind |= ObjCPropertyDecl::OBJC_PR_readwrite;<br>> -    PIkind |= deducePropertyOwnershipFromType(*this, PIDecl->getType());<br>> -    unsigned ClassExtensionMemoryModel = getOwnershipRule(Attributes);<br>> -    unsigned PrimaryClassMemoryModel = getOwnershipRule(PIkind);<br>> -    if (PrimaryClassMemoryModel && ClassExtensionMemoryModel &&<br>> -        (PrimaryClassMemoryModel != ClassExtensionMemoryModel)) {<br>> -      Diag(AtLoc, diag::warn_property_attr_mismatch);<br>> -      Diag(PIDecl->getLocation(), diag::note_property_declare);<br>> -    }<br>> -    else if (getLangOpts().ObjCAutoRefCount) {<br>> -      QualType PrimaryPropertyQT =<br>> -        Context.getCanonicalType(PIDecl->getType()).getUnqualifiedType();<br>> -      if (isa<ObjCObjectPointerType>(PrimaryPropertyQT)) {<br>> -        bool PropertyIsWeak = ((PIkind & ObjCPropertyDecl::OBJC_PR_weak) != 0);<br>> -        Qualifiers::ObjCLifetime PrimaryPropertyLifeTime =<br>> -          PrimaryPropertyQT.getObjCLifetime();<br>> -        if (PrimaryPropertyLifeTime == Qualifiers::OCL_None &&<br>> -            (Attributes & ObjCDeclSpec::DQ_PR_weak) &&<br>> -            !PropertyIsWeak) {<br>> -              Diag(AtLoc, diag::warn_property_implicitly_mismatched);<br>> -              Diag(PIDecl->getLocation(), diag::note_property_declare);<br>> -            }<br>> -        }<br>> -    }<br>> -<br>> -    DeclContext *DC = cast<DeclContext>(CCPrimary);<br>> -    if (!ObjCPropertyDecl::findPropertyDecl(DC,<br>> -                                 PIDecl->getDeclName().getAsIdentifierInfo())) {<br>> -      // In mrr mode, 'readwrite' property must have an explicit<br>> -      // memory attribute. If none specified, select the default (assign).<br>> -      if (!getLangOpts().ObjCAutoRefCount) {<br>> -        if (!(PIkind & (ObjCDeclSpec::DQ_PR_assign |<br>> -                        ObjCDeclSpec::DQ_PR_retain |<br>> -                        ObjCDeclSpec::DQ_PR_strong |<br>> -                        ObjCDeclSpec::DQ_PR_copy |<br>> -                        ObjCDeclSpec::DQ_PR_unsafe_unretained |<br>> -                        ObjCDeclSpec::DQ_PR_weak)))<br>> -          PIkind |= ObjCPropertyDecl::OBJC_PR_assign;<br>> -      }<br>> -<br>> -      // Protocol is not in the primary class. Must build one for it.<br>> -      ObjCDeclSpec ProtocolPropertyODS;<br>> -      // FIXME. Assuming that ObjCDeclSpec::ObjCPropertyAttributeKind<br>> -      // and ObjCPropertyDecl::PropertyAttributeKind have identical<br>> -      // values.  Should consolidate both into one enum type.<br>> -      ProtocolPropertyODS.<br>> -      setPropertyAttributes((ObjCDeclSpec::ObjCPropertyAttributeKind)<br>> -                            PIkind);<br>> -      // Must re-establish the context from class extension to primary<br>> -      // class context.<br>> -      ContextRAII SavedContext(*this, CCPrimary);<br>> -<br>> -      Decl *ProtocolPtrTy =<br>> -        ActOnProperty(S, AtLoc, LParenLoc, FD, ProtocolPropertyODS,<br>> -                      PIDecl->getGetterName(),<br>> -                      PIDecl->getSetterName(),<br>> -                      isOverridingProperty,<br>> -                      MethodImplKind,<br>> -                      /* lexicalDC = */ CDecl);<br>> -      PIDecl = cast<ObjCPropertyDecl>(ProtocolPtrTy);<br>> -    }<br>> -    PIDecl->makeitReadWriteAttribute();<br>> -    if (Attributes & ObjCDeclSpec::DQ_PR_retain)<br>> -      PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain);<br>> -    if (Attributes & ObjCDeclSpec::DQ_PR_strong)<br>> -      PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong);<br>> -    if (Attributes & ObjCDeclSpec::DQ_PR_copy)<br>> -      PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);<br>> -    PIDecl->setSetterName(SetterSel);<br>> -  } else {<br>> +  if (!(isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly))) {<br>>     // Tailor the diagnostics for the common case where a readwrite<br>>     // property is declared both in the @interface and the continuation.<br>>     // This is a common error where the user often intended the original<br>> @@ -541,13 +438,53 @@ Sema::HandlePropertyInClassExtension(Sco<br>>     Diag(PIDecl->getLocation(), diag::note_property_declare);<br>>     return nullptr;<br>>   }<br>> +<br>> +  PIkind &= ~ObjCPropertyDecl::OBJC_PR_readonly;<br>> +  PIkind |= ObjCPropertyDecl::OBJC_PR_readwrite;<br>> +  PIkind |= deducePropertyOwnershipFromType(*this, PIDecl->getType());<br>> +  unsigned ClassExtensionMemoryModel = getOwnershipRule(Attributes);<br>> +  unsigned PrimaryClassMemoryModel = getOwnershipRule(PIkind);<br>> +  if (PrimaryClassMemoryModel && ClassExtensionMemoryModel &&<br>> +      (PrimaryClassMemoryModel != ClassExtensionMemoryModel)) {<br>> +    Diag(AtLoc, diag::warn_property_attr_mismatch);<br>> +    Diag(PIDecl->getLocation(), diag::note_property_declare);<br>> +  } else if (getLangOpts().ObjCAutoRefCount) {<br>> +    QualType PrimaryPropertyQT =<br>> +      Context.getCanonicalType(PIDecl->getType()).getUnqualifiedType();<br>> +    if (isa<ObjCObjectPointerType>(PrimaryPropertyQT)) {<br>> +      bool PropertyIsWeak = ((PIkind & ObjCPropertyDecl::OBJC_PR_weak) != 0);<br>> +      Qualifiers::ObjCLifetime PrimaryPropertyLifeTime =<br>> +        PrimaryPropertyQT.getObjCLifetime();<br>> +      if (PrimaryPropertyLifeTime == Qualifiers::OCL_None &&<br>> +          (Attributes & ObjCDeclSpec::DQ_PR_weak) &&<br>> +          !PropertyIsWeak) {<br>> +            Diag(AtLoc, diag::warn_property_implicitly_mismatched);<br>> +            Diag(PIDecl->getLocation(), diag::note_property_declare);<br>> +          }<br>> +      }<br>> +  }<br>> +<br>> +  // Check that atomicity of property in class extension matches the previous<br>> +  // declaration.<br>> +  unsigned PDeclAtomicity =<br>> +    PDecl->getPropertyAttributes() & (ObjCDeclSpec::DQ_PR_atomic | ObjCDeclSpec::DQ_PR_nonatomic);<br>> +  unsigned PIDeclAtomicity =<br>> +    PIDecl->getPropertyAttributes() & (ObjCDeclSpec::DQ_PR_atomic | ObjCDeclSpec::DQ_PR_nonatomic);<br>> +  if (PDeclAtomicity != PIDeclAtomicity) {<br>> +    bool PDeclAtomic = (!PDeclAtomicity || PDeclAtomicity & ObjCDeclSpec::DQ_PR_atomic);<br>> +    bool PIDeclAtomic = (!PIDeclAtomicity || PIDeclAtomicity & ObjCDeclSpec::DQ_PR_atomic);<br>> +    if (PDeclAtomic != PIDeclAtomic) {<br>> +      Diag(PDecl->getLocation(), diag::warn_property_attribute)<br>> +        << PDecl->getDeclName() << "atomic"<br>> +        << cast<ObjCContainerDecl>(PIDecl->getDeclContext())->getName();<br>> +      Diag(PIDecl->getLocation(), diag::note_property_declare);<br>> +    }<br>> +  }<br>> +<br>>   *isOverridingProperty = true;<br>> -  // Make sure setter decl is synthesized, and added to primary class's list.<br>> -  ProcessPropertyDecl(PIDecl, CCPrimary, PDecl, CDecl);<br>> -  PDecl->setGetterMethodDecl(PIDecl->getGetterMethodDecl());<br>> -  PDecl->setSetterMethodDecl(PIDecl->getSetterMethodDecl());<br>> -  if (ASTMutationListener *L = Context.getASTMutationListener())<br>> -    L->AddedObjCPropertyInClassExtension(PDecl, PIDecl, CDecl);<br>> +<br>> +  // Make sure setter decl is synthesized, and added to continuation class's list.<br>> +  ProcessPropertyDecl(PDecl, CDecl, PIDecl, CDecl);<br>>   return PDecl;<br>> }<br>><br>> @@ -1480,6 +1417,11 @@ static void CollectImmediateProperties(O<br>>   if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) {<br>>     for (auto *Prop : IDecl->properties())<br>>       PropMap[Prop->getIdentifier()] = Prop;<br>> +<br>> +    // Collect the properties from visible extensions.<br>> +    for (auto *Ext : IDecl->visible_extensions())<br>> +      CollectImmediateProperties(Ext, PropMap, SuperPropMap, IncludeProtocols);<br>> +<br>>     if (IncludeProtocols) {<br>>       // Scan through class's protocols.<br>>       for (auto *PI : IDecl->all_referenced_protocols())<br>> @@ -1487,9 +1429,8 @@ static void CollectImmediateProperties(O<br>>     }<br>>   }<br>>   if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) {<br>> -    if (!CATDecl->IsClassExtension())<br>> -      for (auto *Prop : CATDecl->properties())<br>> -        PropMap[Prop->getIdentifier()] = Prop;<br>> +    for (auto *Prop : CATDecl->properties())<br>> +      PropMap[Prop->getIdentifier()] = Prop;<br>>     if (IncludeProtocols) {<br>>       // Scan through class's protocols.<br>>       for (auto *PI : CATDecl->protocols())<br>> @@ -1549,6 +1490,14 @@ Sema::IvarBacksCurrentMethodAccessor(Obj<br>>         (Property->getPropertyIvarDecl() == IV))<br>>       return true;<br>>   }<br>> +  // Also look up property declaration in class extension whose one of its<br>> +  // accessors is implemented by this method.<br>> +  for (const auto *Ext : IFace->known_extensions())<br>> +    for (const auto *Property : Ext->properties())<br>> +      if ((Property->getGetterName() == IMD->getSelector() ||<br>> +           Property->getSetterName() == IMD->getSelector()) &&<br>> +          (Property->getPropertyIvarDecl() == IV))<br>> +        return true;<br>>   return false;<br>> }<br>><br>> @@ -1833,11 +1782,20 @@ void Sema::diagnoseNullResettableSynthes<br>><br>> void<br>> Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl,<br>> -                                       ObjCContainerDecl* IDecl) {<br>> +                                       ObjCInterfaceDecl* IDecl) {<br>>   // Rules apply in non-GC mode only<br>>   if (getLangOpts().getGC() != LangOptions::NonGC)<br>>     return;<br>> -  for (const auto *Property : IDecl->properties()) {<br>> +  ObjCContainerDecl::PropertyMap PM;<br>> +  for (auto *Prop : IDecl->properties())<br>> +    PM[Prop->getIdentifier()] = Prop;<br>> +  for (const auto *Ext : IDecl->known_extensions())<br>> +    for (auto *Prop : Ext->properties())<br>> +      PM[Prop->getIdentifier()] = Prop;<br>> +<br>> +    for (ObjCContainerDecl::PropertyMap::iterator I = PM.begin(), E = PM.end();<br>> +         I != E; ++I) {<br>> +    const ObjCPropertyDecl *Property = I->second;<br>>     ObjCMethodDecl *GetterMethod = nullptr;<br>>     ObjCMethodDecl *SetterMethod = nullptr;<br>>     bool LookedUpGetterSetter = false;<br>> @@ -1884,30 +1842,23 @@ Sema::AtomicPropertySetterGetterRules (O<br>>           << Property->getIdentifier() << (GetterMethod != nullptr)<br>>           << (SetterMethod != nullptr);<br>>         // fixit stuff.<br>> -        if (!AttributesAsWritten) {<br>> -          if (Property->getLParenLoc().isValid()) {<br>> -            // @property () ... case.<br>> -            SourceRange PropSourceRange(Property->getAtLoc(),<br>> -                                        Property->getLParenLoc());<br>> -            Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) <<<br>> -              FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic");<br>> -          }<br>> -          else {<br>> -            //@property id etc.<br>> -            SourceLocation endLoc =<br>> -              Property->getTypeSourceInfo()->getTypeLoc().getBeginLoc();<br>> -            endLoc = endLoc.getLocWithOffset(-1);<br>> -            SourceRange PropSourceRange(Property->getAtLoc(), endLoc);<br>> -            Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) <<<br>> -              FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic) ");<br>> -          }<br>> -        }<br>> -        else if (!(AttributesAsWritten & ObjCPropertyDecl::OBJC_PR_atomic)) {<br>> +        if (Property->getLParenLoc().isValid() &&<br>> +            !(AttributesAsWritten & ObjCPropertyDecl::OBJC_PR_atomic)) {<br>>           // @property () ... case.<br>> -          SourceLocation endLoc = Property->getLParenLoc();<br>> -          SourceRange PropSourceRange(Property->getAtLoc(), endLoc);<br>> -          Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) <<<br>> -           FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic, ");<br>> +          SourceLocation AfterLParen =<br>> +            getLocForEndOfToken(Property->getLParenLoc());<br>> +          StringRef NonatomicStr = AttributesAsWritten? "nonatomic, "<br>> +                                                      : "nonatomic";<br>> +          Diag(Property->getLocation(),<br>> +               diag::note_atomic_property_fixup_suggest)<br>> +            << FixItHint::CreateInsertion(AfterLParen, NonatomicStr);<br>> +        } else if (Property->getLParenLoc().isInvalid()) {<br>> +          //@property id etc.<br>> +          SourceLocation startLoc =<br>> +            Property->getTypeSourceInfo()->getTypeLoc().getBeginLoc();<br>> +          Diag(Property->getLocation(),<br>> +               diag::note_atomic_property_fixup_suggest)<br>> +            << FixItHint::CreateInsertion(startLoc, "(nonatomic) ");<br>>         }<br>>         else<br>>           Diag(MethodLoc, diag::note_atomic_property_fixup_suggest);<br>> @@ -2035,7 +1986,20 @@ void Sema::ProcessPropertyDecl(ObjCPrope<br>>     return;<br>><br>>   GetterMethod = CD->getInstanceMethod(property->getGetterName());<br>> +  // if setter or getter is not found in class extension, it might be<br>> +  // in the primary class.<br>> +  if (!GetterMethod)<br>> +    if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CD))<br>> +      if (CatDecl->IsClassExtension())<br>> +        GetterMethod = CatDecl->getClassInterface()-><br>> +                         getInstanceMethod(property->getGetterName());<br>> +<br>>   SetterMethod = CD->getInstanceMethod(property->getSetterName());<br>> +  if (!SetterMethod)<br>> +    if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CD))<br>> +      if (CatDecl->IsClassExtension())<br>> +        SetterMethod = CatDecl->getClassInterface()-><br>> +                          getInstanceMethod(property->getSetterName());<br>>   DiagnosePropertyAccessorMismatch(property, GetterMethod,<br>>                                    property->getLocation());<br>><br>> @@ -2068,9 +2032,7 @@ void Sema::ProcessPropertyDecl(ObjCPrope<br>>     // No instance method of same name as property getter name was found.<br>>     // Declare a getter method and add it to the list of methods<br>>     // for this class.<br>> -    SourceLocation Loc = redeclaredProperty ?<br>> -      redeclaredProperty->getLocation() :<br>> -      property->getLocation();<br>> +    SourceLocation Loc = property->getLocation();<br>><br>>     // If the property is null_resettable, the getter returns nonnull.<br>>     QualType resultTy = property->getType();<br>> @@ -2130,9 +2092,7 @@ void Sema::ProcessPropertyDecl(ObjCPrope<br>>       // No instance method of same name as property setter name was found.<br>>       // Declare a setter method and add it to the list of methods<br>>       // for this class.<br>> -      SourceLocation Loc = redeclaredProperty ?<br>> -        redeclaredProperty->getLocation() :<br>> -        property->getLocation();<br>> +      SourceLocation Loc = property->getLocation();<br>><br>>       SetterMethod =<br>>         ObjCMethodDecl::Create(Context, Loc, Loc,<br>><br>> Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp<br>> URL:<span> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=251874&r1=251873&r2=251874&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=251874&r1=251873&r2=251874&view=diff</a><br>> ==============================================================================<br>> --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)<br>> +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Mon Nov  2 19:15:46 2015<br>> @@ -5756,21 +5756,6 @@ void ASTWriter::AddedObjCCategoryToInter<br>>     const_cast<ObjCInterfaceDecl *>(IFD->getDefinition()));<br>> }<br>><br>> -<br>> -void ASTWriter::AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop,<br>> -                                          const ObjCPropertyDecl *OrigProp,<br>> -                                          const ObjCCategoryDecl *ClassExt) {<br>> -  const ObjCInterfaceDecl *D = ClassExt->getClassInterface();<br>> -  if (!D)<br>> -    return;<br>> -<br>> -  assert(!WritingAST && "Already writing the AST!");<br>> -  if (!D->isFromASTFile())<br>> -    return; // Declaration not imported from PCH.<br>> -<br>> -  RewriteDecl(D);<br>> -}<br>> -<br>> void ASTWriter::DeclarationMarkedUsed(const Decl *D) {<br>>   assert(!WritingAST && "Already writing the AST!");<br>>   if (!D->isFromASTFile())<br>><br>> Modified: cfe/trunk/test/FixIt/atomic-property.m<br>> URL:<span> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/atomic-property.m?rev=251874&r1=251873&r2=251874&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/atomic-property.m?rev=251874&r1=251873&r2=251874&view=diff</a><br>> ==============================================================================<br>> --- cfe/trunk/test/FixIt/atomic-property.m (original)<br>> +++ cfe/trunk/test/FixIt/atomic-property.m Mon Nov  2 19:15:46 2015<br>> @@ -23,7 +23,7 @@<br>> - (id) atomic_prop1 { return 0; }<br>> @end<br>><br>> -// CHECK: {4:1-4:10}:"@property (nonatomic) "<br>> -// CHECK: {9:1-9:12}:"@property (nonatomic"<br>> -// CHECK: {13:1-13:12}:"@property (nonatomic, "<br>> +// CHECK-DAG: {4:11-4:11}:"(nonatomic) "<br>> +// CHECK-DAG: {9:12-9:12}:"nonatomic"<br>> +// CHECK-DAG: {13:12-13:12}:"nonatomic, "<br>><br>><br>> Modified: cfe/trunk/test/Index/complete-kvc.m<br>> URL:<span> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-kvc.m?rev=251874&r1=251873&r2=251874&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-kvc.m?rev=251874&r1=251873&r2=251874&view=diff</a><br>> ==============================================================================<br>> --- cfe/trunk/test/Index/complete-kvc.m (original)<br>> +++ cfe/trunk/test/Index/complete-kvc.m Mon Nov  2 19:15:46 2015<br>> @@ -101,5 +101,5 @@ typedef signed char BOOL;<br>><br>> // RUN: c-index-test -code-completion-at=%s:52:8 %s | FileCheck -check-prefix=CHECK-CC3 %s<br>> // CHECK-CC3: ObjCInstanceMethodDecl:{TypedText countOfIntProperty} (55)<br>> -// CHECK-CC3-NEXT: ObjCInstanceMethodDecl:{TypedText intProperty} (40)<br>> +// CHECK-CC3-NEXT: ObjCInstanceMethodDecl:{TypedText intProperty} (42)<br>> // CHECK-CC3-NEXT: ObjCInstanceMethodDecl:{TypedText isIntProperty} (40)<br>><br>> Modified: cfe/trunk/test/Modules/ModuleDebugInfo.m<br>> URL:<span> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/ModuleDebugInfo.m?rev=251874&r1=251873&r2=251874&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/ModuleDebugInfo.m?rev=251874&r1=251873&r2=251874&view=diff</a><br>> ==============================================================================<br>> --- cfe/trunk/test/Modules/ModuleDebugInfo.m (original)<br>> +++ cfe/trunk/test/Modules/ModuleDebugInfo.m Mon Nov  2 19:15:46 2015<br>> @@ -33,7 +33,7 @@<br>> // CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "InnerEnum"<br>> // CHECK: !DISubprogram(name: "+[ObjCClass classMethod]"<br>> // CHECK: !DISubprogram(name: "-[ObjCClass instanceMethodWithInt:]"<br>> -// CHECK: !DISubprogram(name: "-[ categoryMethod]"<br>> +// CHECK: !DISubprogram(name: "-[Category(Category) categoryMethod]"<br>><br>> // MODULE-CHECK: !DICompositeType(tag: DW_TAG_enumeration_type,<br>> // MODULE-CHECK-SAME:             scope: ![[MODULE:[0-9]+]],<br>><br>> Modified: cfe/trunk/test/PCH/chain-categories.m<br>> URL:<span> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/chain-categories.m?rev=251874&r1=251873&r2=251874&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/chain-categories.m?rev=251874&r1=251873&r2=251874&view=diff</a><br>> ==============================================================================<br>> --- cfe/trunk/test/PCH/chain-categories.m (original)<br>> +++ cfe/trunk/test/PCH/chain-categories.m Mon Nov  2 19:15:46 2015<br>> @@ -16,6 +16,10 @@<br>> - (void)finalize;<br>> @end<br>><br>> +@interface NSObject (Properties)<br>> +@property (readonly,nonatomic) int intProp;<br>> +@end<br>> +<br>> //===----------------------------------------------------------------------===//<br>> #elif !defined(HEADER2)<br>> #define HEADER2<br>> @@ -34,6 +38,12 @@<br>> -(void)extMeth;<br>> @end<br>><br>> +@interface NSObject ()<br>> +@property (readwrite,nonatomic) int intProp;<br>> +@end<br>> +<br>> +@class NSObject;<br>> +<br>> //===----------------------------------------------------------------------===//<br>> #else<br>> //===----------------------------------------------------------------------===//<br>> @@ -47,6 +57,9 @@<br>><br>> void test(NSObject *o) {<br>>   [o extMeth];<br>> +<br>> +  // Make sure the property is treated as read-write.<br>> +  o.intProp = 17;<br>> }<br>><br>> //===----------------------------------------------------------------------===//<br>><br>> Modified: cfe/trunk/test/SemaObjC/atomoic-property-synnthesis-rules.m<br>> URL:<span> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/atomoic-property-synnthesis-rules.m?rev=251874&r1=251873&r2=251874&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/atomoic-property-synnthesis-rules.m?rev=251874&r1=251873&r2=251874&view=diff</a><br>> ==============================================================================<br>> --- cfe/trunk/test/SemaObjC/atomoic-property-synnthesis-rules.m (original)<br>> +++ cfe/trunk/test/SemaObjC/atomoic-property-synnthesis-rules.m Mon Nov  2 19:15:46 2015<br>> @@ -129,10 +129,8 @@<br>><br>> // read-only in class, read-write in class extension - might warn<br>> @property(readonly) int GetSet_ReadWriteInExt;<br>> -@property(readonly) int Get_ReadWriteInExt;  // expected-note {{property declared here}} \<br>> -                                                // expected-note {{setter and getter must both be synthesized}}<br>> -@property(readonly) int Set_ReadWriteInExt;  // expected-note {{property declared here}} \<br>> -                                                // expected-note {{setter and getter must both be synthesized}}<br>> +@property(readonly) int Get_ReadWriteInExt;<br>> +@property(readonly) int Set_ReadWriteInExt;<br>> @property(readonly) int None_ReadWriteInExt;<br>> @property(nonatomic,readonly) int GetSet_Nonatomic_ReadWriteInExt;<br>> @property(nonatomic,readonly) int Get_Nonatomic_ReadWriteInExt;<br>> @@ -162,10 +160,8 @@<br>> @property(nonatomic,readonly) int None_Nonatomic_ReadOnly_LateSynthesize;<br>><br>> @property(readonly) int GetSet_ReadWriteInExt_LateSynthesize;<br>> -@property(readonly) int Get_ReadWriteInExt_LateSynthesize;   // expected-note {{property declared here}} \<br>> -                                                                // expected-note {{setter and getter must both be synthesized}}<br>> -@property(readonly) int Set_ReadWriteInExt_LateSynthesize;   // expected-note {{property declared here}} \<br>> -                                                                // expected-note {{setter and getter must both be synthesized}}<br>> +@property(readonly) int Get_ReadWriteInExt_LateSynthesize;<br>> +@property(readonly) int Set_ReadWriteInExt_LateSynthesize;<br>> @property(readonly) int None_ReadWriteInExt_LateSynthesize;<br>> @property(nonatomic,readonly) int GetSet_Nonatomic_ReadWriteInExt_LateSynthesize;<br>> @property(nonatomic,readonly) int Get_Nonatomic_ReadWriteInExt_LateSynthesize;<br>> @@ -207,8 +203,10 @@<br>> @interface Foo ()<br>><br>> @property(readwrite) int GetSet_ReadWriteInExt;<br>> -@property(readwrite) int Get_ReadWriteInExt;<br>> -@property(readwrite) int Set_ReadWriteInExt;<br>> +@property(readwrite) int Get_ReadWriteInExt; // expected-note {{property declared here}} \<br>> +                                             // expected-note {{setter and getter must both be synthesized}}<br>> +@property(readwrite) int Set_ReadWriteInExt; // expected-note {{property declared here}} \<br>> +                                             // expected-note {{setter and getter must both be synthesized}}<br>> @property(readwrite) int None_ReadWriteInExt;<br>> @property(nonatomic,readwrite) int GetSet_Nonatomic_ReadWriteInExt;<br>> @property(nonatomic,readwrite) int Get_Nonatomic_ReadWriteInExt;<br>> @@ -216,8 +214,10 @@<br>> @property(nonatomic,readwrite) int None_Nonatomic_ReadWriteInExt;<br>><br>> @property(readwrite) int GetSet_ReadWriteInExt_LateSynthesize;<br>> -@property(readwrite) int Get_ReadWriteInExt_LateSynthesize;<br>> -@property(readwrite) int Set_ReadWriteInExt_LateSynthesize;<br>> +@property(readwrite) int Get_ReadWriteInExt_LateSynthesize;  // expected-note {{property declared here}} \<br>> +                                                             // expected-note {{setter and getter must both be synthesized}}<br>> +@property(readwrite) int Set_ReadWriteInExt_LateSynthesize; // expected-note {{property declared here}} \<br>> +                                                            // expected-note {{setter and getter must both be synthesized}}<br>> @property(readwrite) int None_ReadWriteInExt_LateSynthesize;<br>> @property(nonatomic,readwrite) int GetSet_Nonatomic_ReadWriteInExt_LateSynthesize;<br>> @property(nonatomic,readwrite) int Get_Nonatomic_ReadWriteInExt_LateSynthesize;<br>><br>> Modified: cfe/trunk/test/SemaObjC/property-3.m<br>> URL:<span> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/property-3.m?rev=251874&r1=251873&r2=251874&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/property-3.m?rev=251874&r1=251873&r2=251874&view=diff</a><br>> ==============================================================================<br>> --- cfe/trunk/test/SemaObjC/property-3.m (original)<br>> +++ cfe/trunk/test/SemaObjC/property-3.m Mon Nov  2 19:15:46 2015<br>> @@ -29,5 +29,5 @@ typedef signed char BOOL;<br>><br>> @interface EKCalendar ()  <EKProtocolMutableCalendar><br>> @property (nonatomic, assign) BOOL allowReminders;<br>> -@property (nonatomic, assign) BOOL allowNonatomicProperty; // expected-warning {{'atomic' attribute on property 'allowNonatomicProperty' does not match the property inherited from 'EKProtocolCalendar'}}<br>> +@property (nonatomic, assign) BOOL allowNonatomicProperty; // expected-warning {{'atomic' attribute on property 'allowNonatomicProperty' does not match the property inherited from EKProtocolCalendar}}<br>> @end<br>><br>> Modified: cfe/trunk/test/SemaObjC/property-in-class-extension-1.m<br>> URL:<span> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/property-in-class-extension-1.m?rev=251874&r1=251873&r2=251874&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/property-in-class-extension-1.m?rev=251874&r1=251873&r2=251874&view=diff</a><br>> ==============================================================================<br>> --- cfe/trunk/test/SemaObjC/property-in-class-extension-1.m (original)<br>> +++ cfe/trunk/test/SemaObjC/property-in-class-extension-1.m Mon Nov  2 19:15:46 2015<br>> @@ -10,7 +10,7 @@<br>><br>> @property (nonatomic, copy, readonly) NSString* matchingMemoryModel;<br>><br>> -@property (nonatomic, retain, readonly) NSString* addingNoNewMemoryModel;<br>> +@property (atomic, retain, readonly) NSString* addingNoNewMemoryModel;<br>><br>> @property (readonly) NSString* none;<br>> @property (readonly) NSString* none1;<br>> @@ -50,10 +50,14 @@<br>> //<span> </span><a>rdar://12214070</a><br>> @interface radar12214070<br>> @property (nonatomic, atomic, readonly) float propertyName; // expected-error {{property attributes 'atomic' and 'nonatomic' are mutually exclusive}}<br>> +<br>> +@property (nonatomic, readonly) float propertyName2; // expected-note {{property declared here}}<br>> @end<br>><br>> @interface radar12214070 ()<br>> @property (atomic, nonatomic, readonly, readwrite) float propertyName; // expected-error {{property attributes 'readonly' and 'readwrite' are mutually exclusive}} \<br>>               // expected-error {{property attributes 'atomic' and 'nonatomic' are mutually exclusive}}<br>> +<br>> +@property (atomic, readwrite) float propertyName2; // expected-warning {{'atomic' attribute on property 'propertyName2' does not match the property inherited from radar12214070}}<br>> @end<br>><br>><br>> Modified: cfe/trunk/test/SemaObjCXX/<a href="http://property-invalid-type.mm/" rel="noreferrer" target="_blank">property-invalid-type.mm</a><br>> URL:<span> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/property-invalid-type.mm?rev=251874&r1=251873&r2=251874&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/property-invalid-type.mm?rev=251874&r1=251873&r2=251874&view=diff</a><br>> ==============================================================================<br>> --- cfe/trunk/test/SemaObjCXX/<a href="http://property-invalid-type.mm/" rel="noreferrer" target="_blank">property-invalid-type.mm</a><span> </span>(original)<br>> +++ cfe/trunk/test/SemaObjCXX/<a href="http://property-invalid-type.mm/" rel="noreferrer" target="_blank">property-invalid-type.mm</a><span> </span>Mon Nov  2 19:15:46 2015<br>> @@ -13,11 +13,11 @@<br>> @synthesize response;<br>> - (void) foo :(A*) a   // expected-error {{expected a type}}<br>> {<br>> -  self.response = a;<br>> +  self.response = a; // expected-error{{assigning to 'int *' from incompatible type 'id'}}<br>> }<br>> @end<br>><br>> void foo(I *i)<br>> {<br>> -  i.helper;<br>> +  i.helper; // expected-warning{{property access result unused - getters should not be used for side effects}}<br>> }<br>><br>><br>> _______________________________________________<br>> cfe-commits mailing list<br>><span> </span><a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>><span> </span><a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br><br>_______________________________________________<br>cfe-commits mailing list<br><a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br><a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br></div></div></blockquote></div><br></div></div></div></blockquote></div><br></div></div></div></blockquote></div><br></div></div></div><span><propregression.patch></span></div></blockquote></div><br></div></blockquote></div><br></div></div></div><span><prop.diff></span></div></blockquote></div><br></div></div></blockquote></div><br></div>