r251874 - Stop back-patching 'readonly' Objective-C properties with 'readwrite' ones.
Douglas Gregor via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 2 17:22:03 PST 2015
… 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 at 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
>
> + at interface NSObject (Properties)
> + at property (readonly,nonatomic) int intProp;
> + at end
> +
> //===----------------------------------------------------------------------===//
> #elif !defined(HEADER2)
> #define HEADER2
> @@ -34,6 +38,12 @@
> -(void)extMeth;
> @end
>
> + at interface NSObject ()
> + at property (readwrite,nonatomic) int intProp;
> + at end
> +
> + at class NSObject;
> +
> //===----------------------------------------------------------------------===//
> #else
> //===----------------------------------------------------------------------===//
> @@ -47,6 +57,9 @@
>
> void test(NSObject *o) {
> [o extMeth];
> +
> + // Make sure the property is treated as read-write.
> + o.intProp = 17;
> }
>
> //===----------------------------------------------------------------------===//
>
> Modified: cfe/trunk/test/SemaObjC/atomoic-property-synnthesis-rules.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/atomoic-property-synnthesis-rules.m?rev=251874&r1=251873&r2=251874&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/atomoic-property-synnthesis-rules.m (original)
> +++ cfe/trunk/test/SemaObjC/atomoic-property-synnthesis-rules.m Mon Nov 2 19:15:46 2015
> @@ -129,10 +129,8 @@
>
> // read-only in class, read-write in class extension - might warn
> @property(readonly) int GetSet_ReadWriteInExt;
> - at property(readonly) int Get_ReadWriteInExt; // expected-note {{property declared here}} \
> - // expected-note {{setter and getter must both be synthesized}}
> - at property(readonly) int Set_ReadWriteInExt; // expected-note {{property declared here}} \
> - // expected-note {{setter and getter must both be synthesized}}
> + at property(readonly) int Get_ReadWriteInExt;
> + at property(readonly) int Set_ReadWriteInExt;
> @property(readonly) int None_ReadWriteInExt;
> @property(nonatomic,readonly) int GetSet_Nonatomic_ReadWriteInExt;
> @property(nonatomic,readonly) int Get_Nonatomic_ReadWriteInExt;
> @@ -162,10 +160,8 @@
> @property(nonatomic,readonly) int None_Nonatomic_ReadOnly_LateSynthesize;
>
> @property(readonly) int GetSet_ReadWriteInExt_LateSynthesize;
> - at property(readonly) int Get_ReadWriteInExt_LateSynthesize; // expected-note {{property declared here}} \
> - // expected-note {{setter and getter must both be synthesized}}
> - at property(readonly) int Set_ReadWriteInExt_LateSynthesize; // expected-note {{property declared here}} \
> - // expected-note {{setter and getter must both be synthesized}}
> + at property(readonly) int Get_ReadWriteInExt_LateSynthesize;
> + at property(readonly) int Set_ReadWriteInExt_LateSynthesize;
> @property(readonly) int None_ReadWriteInExt_LateSynthesize;
> @property(nonatomic,readonly) int GetSet_Nonatomic_ReadWriteInExt_LateSynthesize;
> @property(nonatomic,readonly) int Get_Nonatomic_ReadWriteInExt_LateSynthesize;
> @@ -207,8 +203,10 @@
> @interface Foo ()
>
> @property(readwrite) int GetSet_ReadWriteInExt;
> - at property(readwrite) int Get_ReadWriteInExt;
> - at property(readwrite) int Set_ReadWriteInExt;
> + at property(readwrite) int Get_ReadWriteInExt; // expected-note {{property declared here}} \
> + // expected-note {{setter and getter must both be synthesized}}
> + at property(readwrite) int Set_ReadWriteInExt; // expected-note {{property declared here}} \
> + // expected-note {{setter and getter must both be synthesized}}
> @property(readwrite) int None_ReadWriteInExt;
> @property(nonatomic,readwrite) int GetSet_Nonatomic_ReadWriteInExt;
> @property(nonatomic,readwrite) int Get_Nonatomic_ReadWriteInExt;
> @@ -216,8 +214,10 @@
> @property(nonatomic,readwrite) int None_Nonatomic_ReadWriteInExt;
>
> @property(readwrite) int GetSet_ReadWriteInExt_LateSynthesize;
> - at property(readwrite) int Get_ReadWriteInExt_LateSynthesize;
> - at property(readwrite) int Set_ReadWriteInExt_LateSynthesize;
> + at property(readwrite) int Get_ReadWriteInExt_LateSynthesize; // expected-note {{property declared here}} \
> + // expected-note {{setter and getter must both be synthesized}}
> + at property(readwrite) int Set_ReadWriteInExt_LateSynthesize; // expected-note {{property declared here}} \
> + // expected-note {{setter and getter must both be synthesized}}
> @property(readwrite) int None_ReadWriteInExt_LateSynthesize;
> @property(nonatomic,readwrite) int GetSet_Nonatomic_ReadWriteInExt_LateSynthesize;
> @property(nonatomic,readwrite) int Get_Nonatomic_ReadWriteInExt_LateSynthesize;
>
> Modified: cfe/trunk/test/SemaObjC/property-3.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/property-3.m?rev=251874&r1=251873&r2=251874&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/property-3.m (original)
> +++ cfe/trunk/test/SemaObjC/property-3.m Mon Nov 2 19:15:46 2015
> @@ -29,5 +29,5 @@ typedef signed char BOOL;
>
> @interface EKCalendar () <EKProtocolMutableCalendar>
> @property (nonatomic, assign) BOOL allowReminders;
> - at property (nonatomic, assign) BOOL allowNonatomicProperty; // expected-warning {{'atomic' attribute on property 'allowNonatomicProperty' does not match the property inherited from 'EKProtocolCalendar'}}
> + at property (nonatomic, assign) BOOL allowNonatomicProperty; // expected-warning {{'atomic' attribute on property 'allowNonatomicProperty' does not match the property inherited from EKProtocolCalendar}}
> @end
>
> Modified: cfe/trunk/test/SemaObjC/property-in-class-extension-1.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/property-in-class-extension-1.m?rev=251874&r1=251873&r2=251874&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/property-in-class-extension-1.m (original)
> +++ cfe/trunk/test/SemaObjC/property-in-class-extension-1.m Mon Nov 2 19:15:46 2015
> @@ -10,7 +10,7 @@
>
> @property (nonatomic, copy, readonly) NSString* matchingMemoryModel;
>
> - at property (nonatomic, retain, readonly) NSString* addingNoNewMemoryModel;
> + at property (atomic, retain, readonly) NSString* addingNoNewMemoryModel;
>
> @property (readonly) NSString* none;
> @property (readonly) NSString* none1;
> @@ -50,10 +50,14 @@
> // rdar://12214070
> @interface radar12214070
> @property (nonatomic, atomic, readonly) float propertyName; // expected-error {{property attributes 'atomic' and 'nonatomic' are mutually exclusive}}
> +
> + at property (nonatomic, readonly) float propertyName2; // expected-note {{property declared here}}
> @end
>
> @interface radar12214070 ()
> @property (atomic, nonatomic, readonly, readwrite) float propertyName; // expected-error {{property attributes 'readonly' and 'readwrite' are mutually exclusive}} \
> // expected-error {{property attributes 'atomic' and 'nonatomic' are mutually exclusive}}
> +
> + at property (atomic, readwrite) float propertyName2; // expected-warning {{'atomic' attribute on property 'propertyName2' does not match the property inherited from radar12214070}}
> @end
>
>
> Modified: cfe/trunk/test/SemaObjCXX/property-invalid-type.mm
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/property-invalid-type.mm?rev=251874&r1=251873&r2=251874&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaObjCXX/property-invalid-type.mm (original)
> +++ cfe/trunk/test/SemaObjCXX/property-invalid-type.mm Mon Nov 2 19:15:46 2015
> @@ -13,11 +13,11 @@
> @synthesize response;
> - (void) foo :(A*) a // expected-error {{expected a type}}
> {
> - self.response = a;
> + self.response = a; // expected-error{{assigning to 'int *' from incompatible type 'id'}}
> }
> @end
>
> void foo(I *i)
> {
> - i.helper;
> + i.helper; // expected-warning{{property access result unused - getters should not be used for side effects}}
> }
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list