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