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