From 418381e0b226058d16e8c3dbc33abcf8b7893d75 Mon Sep 17 00:00:00 2001 From: Manman Ren Date: Thu, 28 Jan 2016 18:49:28 +0000 Subject: [PATCH] Class Property: class property and instance property can have the same name. Add "enum ObjCPropertyQueryKind" to a few APIs that used to only take the name of the property: ObjCPropertyDecl::findPropertyDecl, ObjCContainerDecl::FindPropertyDeclaration, ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass, ObjCImplDecl::FindPropertyImplDecl, and Sema::ActOnPropertyImplDecl. ObjCPropertyQueryKind currently has 3 values: OBJC_PR_query_unknown, OBJC_PR_query_instance, OBJC_PR_query_class This extra parameter specifies that we are looking for an instance property with the given name, or a class property with the given name, or any property with the given name (if both exist, the instance property will be returned). rdar://23891898 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@259070 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/DeclObjC.h | 26 +++++++-- include/clang/Sema/Sema.h | 3 +- lib/ARCMigrate/ObjCMT.cpp | 3 +- lib/AST/ASTImporter.cpp | 3 +- lib/AST/DeclObjC.cpp | 83 ++++++++++++++++++++++------- lib/Analysis/BodyFarm.cpp | 2 +- lib/Parse/ParseObjc.cpp | 12 +++-- lib/Sema/SemaCodeComplete.cpp | 6 +-- lib/Sema/SemaDeclObjC.cpp | 3 +- lib/Sema/SemaExprMember.cpp | 10 ++-- lib/Sema/SemaExprObjC.cpp | 11 ++-- lib/Sema/SemaLookup.cpp | 3 +- lib/Sema/SemaObjCProperty.cpp | 43 +++++++++------ lib/Sema/SemaPseudoObject.cpp | 3 +- test/SemaObjC/objc-class-property.m | 1 + tools/libclang/CIndex.cpp | 3 +- 16 files changed, 154 insertions(+), 61 deletions(-) diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index f9f47cd3db..def08daf7f 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -689,6 +689,12 @@ public: friend TrailingObjects; }; +enum class ObjCPropertyQueryKind : uint8_t { + OBJC_PR_query_unknown = 0x00, + OBJC_PR_query_instance, + OBJC_PR_query_class +}; + /// \brief Represents one property declaration in an Objective-C interface. /// /// For example: @@ -826,6 +832,14 @@ public: bool isInstanceProperty() const { return !isClassProperty(); } bool isClassProperty() const { return PropertyAttributes & OBJC_PR_class; } + ObjCPropertyQueryKind getQueryKind() const { + return isClassProperty() ? ObjCPropertyQueryKind::OBJC_PR_query_class : + ObjCPropertyQueryKind::OBJC_PR_query_instance; + } + static ObjCPropertyQueryKind getQueryKind(bool isClassProperty) { + return isClassProperty ? ObjCPropertyQueryKind::OBJC_PR_query_class : + ObjCPropertyQueryKind::OBJC_PR_query_instance; + } /// getSetterKind - Return the method used for doing assignment in /// the property setter. This is only valid if the property has been @@ -878,7 +892,8 @@ public: /// Lookup a property by name in the specified DeclContext. static ObjCPropertyDecl *findPropertyDecl(const DeclContext *DC, - const IdentifierInfo *propertyID); + const IdentifierInfo *propertyID, + ObjCPropertyQueryKind queryKind); static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == ObjCProperty; } @@ -1005,7 +1020,8 @@ public: ObjCIvarDecl *getIvarDecl(IdentifierInfo *Id) const; ObjCPropertyDecl * - FindPropertyDeclaration(const IdentifierInfo *PropertyId) const; + FindPropertyDeclaration(const IdentifierInfo *PropertyId, + ObjCPropertyQueryKind QueryKind) const; typedef llvm::DenseMap PropertyMap; @@ -1688,7 +1704,8 @@ public: } ObjCPropertyDecl - *FindPropertyVisibleInPrimaryClass(IdentifierInfo *PropertyId) const; + *FindPropertyVisibleInPrimaryClass(IdentifierInfo *PropertyId, + ObjCPropertyQueryKind QueryKind) const; void collectPropertiesToImplement(PropertyMap &PM, PropertyDeclOrder &PO) const override; @@ -2325,7 +2342,8 @@ public: void addPropertyImplementation(ObjCPropertyImplDecl *property); - ObjCPropertyImplDecl *FindPropertyImplDecl(IdentifierInfo *propertyId) const; + ObjCPropertyImplDecl *FindPropertyImplDecl(IdentifierInfo *propertyId, + ObjCPropertyQueryKind queryKind) const; ObjCPropertyImplDecl *FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const; // Iterator access to properties. diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index e358d232d4..c55c41f1eb 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -7351,7 +7351,8 @@ public: bool ImplKind, IdentifierInfo *PropertyId, IdentifierInfo *PropertyIvar, - SourceLocation PropertyIvarLoc); + SourceLocation PropertyIvarLoc, + ObjCPropertyQueryKind QueryKind); enum ObjCSpecialMethodKind { OSMK_None, diff --git a/lib/ARCMigrate/ObjCMT.cpp b/lib/ARCMigrate/ObjCMT.cpp index 10996e8320..1be724c38a 100644 --- a/lib/ARCMigrate/ObjCMT.cpp +++ b/lib/ARCMigrate/ObjCMT.cpp @@ -615,7 +615,8 @@ ClassImplementsAllMethodsAndProperties(ASTContext &Ctx, // or dynamic declaration. Class is implementing a property coming from // another protocol. This still makes the target protocol as conforming. if (!ImpDecl->FindPropertyImplDecl( - Property->getDeclName().getAsIdentifierInfo())) + Property->getDeclName().getAsIdentifierInfo(), + Property->getQueryKind())) return false; } else if (ObjCPropertyDecl *ClassProperty = dyn_cast(R[0])) { diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 916f108179..018fafff9c 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -4061,7 +4061,8 @@ Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { } ObjCPropertyImplDecl *ToImpl - = InImpl->FindPropertyImplDecl(Property->getIdentifier()); + = InImpl->FindPropertyImplDecl(Property->getIdentifier(), + Property->getQueryKind()); if (!ToImpl) { ToImpl = ObjCPropertyImplDecl::Create(Importer.getToContext(), DC, Importer.Import(D->getLocStart()), diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index e804fef243..230c2cfd50 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -152,7 +152,8 @@ bool ObjCContainerDecl::HasUserDeclaredSetterMethod( ObjCPropertyDecl * ObjCPropertyDecl::findPropertyDecl(const DeclContext *DC, - const IdentifierInfo *propertyID) { + const IdentifierInfo *propertyID, + ObjCPropertyQueryKind queryKind) { // If this context is a hidden protocol definition, don't find any // property. if (const ObjCProtocolDecl *Proto = dyn_cast(DC)) { @@ -166,15 +167,33 @@ ObjCPropertyDecl::findPropertyDecl(const DeclContext *DC, if (auto *IDecl = dyn_cast(DC)) { for (const auto *Ext : IDecl->known_extensions()) if (ObjCPropertyDecl *PD = ObjCPropertyDecl::findPropertyDecl(Ext, - propertyID)) + propertyID, + queryKind)) return PD; } DeclContext::lookup_result R = DC->lookup(propertyID); + ObjCPropertyDecl *classProp = nullptr; for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) - if (ObjCPropertyDecl *PD = dyn_cast(*I)) - return PD; + if (ObjCPropertyDecl *PD = dyn_cast(*I)) { + // If queryKind is unknown, we return the instance property if one + // exists; otherwise we return the class property. + if ((queryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown && + !PD->isClassProperty()) || + (queryKind == ObjCPropertyQueryKind::OBJC_PR_query_class && + PD->isClassProperty()) || + (queryKind == ObjCPropertyQueryKind::OBJC_PR_query_instance && + !PD->isClassProperty())) + return PD; + + if (PD->isClassProperty()) + classProp = PD; + } + + if (queryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown) + // We can't find the instance property, return the class property. + return classProp; return nullptr; } @@ -192,7 +211,8 @@ ObjCPropertyDecl::getDefaultSynthIvarName(ASTContext &Ctx) const { /// FindPropertyDeclaration - Finds declaration of the property given its name /// in 'PropertyId' and returns it. It returns 0, if not found. ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration( - const IdentifierInfo *PropertyId) const { + const IdentifierInfo *PropertyId, + ObjCPropertyQueryKind QueryKind) const { // Don't find properties within hidden protocol definitions. if (const ObjCProtocolDecl *Proto = dyn_cast(this)) { if (const ObjCProtocolDecl *Def = Proto->getDefinition()) @@ -204,13 +224,14 @@ ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration( // the class itself. if (const auto *ClassDecl = dyn_cast(this)) { for (const auto *Ext : ClassDecl->visible_extensions()) { - if (auto *P = Ext->FindPropertyDeclaration(PropertyId)) + if (auto *P = Ext->FindPropertyDeclaration(PropertyId, QueryKind)) return P; } } if (ObjCPropertyDecl *PD = - ObjCPropertyDecl::findPropertyDecl(cast(this), PropertyId)) + ObjCPropertyDecl::findPropertyDecl(cast(this), PropertyId, + QueryKind)) return PD; switch (getKind()) { @@ -219,7 +240,8 @@ ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration( case Decl::ObjCProtocol: { const ObjCProtocolDecl *PID = cast(this); for (const auto *I : PID->protocols()) - if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId)) + if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId, + QueryKind)) return P; break; } @@ -228,18 +250,20 @@ ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration( // 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)) + if (ObjCPropertyDecl *P = Cat->FindPropertyDeclaration( + PropertyId, QueryKind)) return P; } // Look through protocols. for (const auto *I : OID->all_referenced_protocols()) - if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId)) + if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId, + QueryKind)) return P; // Finally, check the super class. if (const ObjCInterfaceDecl *superClass = OID->getSuperClass()) - return superClass->FindPropertyDeclaration(PropertyId); + return superClass->FindPropertyDeclaration(PropertyId, QueryKind); break; } case Decl::ObjCCategory: { @@ -247,7 +271,8 @@ ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration( // Look through protocols. if (!OCD->IsClassExtension()) for (const auto *I : OCD->protocols()) - if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId)) + if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId, + QueryKind)) return P; break; } @@ -319,7 +344,8 @@ SourceLocation ObjCInterfaceDecl::getSuperClassLoc() const { /// ObjCPropertyDecl * ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass( - IdentifierInfo *PropertyId) const { + IdentifierInfo *PropertyId, + ObjCPropertyQueryKind QueryKind) const { // FIXME: Should make sure no callers ever do this. if (!hasDefinition()) return nullptr; @@ -328,12 +354,14 @@ ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass( LoadExternalDefinition(); if (ObjCPropertyDecl *PD = - ObjCPropertyDecl::findPropertyDecl(cast(this), PropertyId)) + ObjCPropertyDecl::findPropertyDecl(cast(this), PropertyId, + QueryKind)) return PD; // Look through protocols. for (const auto *I : all_referenced_protocols()) - if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId)) + if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId, + QueryKind)) return P; return nullptr; @@ -2011,10 +2039,29 @@ FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const { /// category \@implementation block. /// ObjCPropertyImplDecl *ObjCImplDecl:: -FindPropertyImplDecl(IdentifierInfo *Id) const { +FindPropertyImplDecl(IdentifierInfo *Id, + ObjCPropertyQueryKind QueryKind) const { + ObjCPropertyImplDecl *ClassPropImpl = nullptr; for (auto *PID : property_impls()) - if (PID->getPropertyDecl()->getIdentifier() == Id) - return PID; + // If queryKind is unknown, we return the instance property if one + // exists; otherwise we return the class property. + if (PID->getPropertyDecl()->getIdentifier() == Id) { + if ((QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown && + !PID->getPropertyDecl()->isClassProperty()) || + (QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_class && + PID->getPropertyDecl()->isClassProperty()) || + (QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_instance && + !PID->getPropertyDecl()->isClassProperty())) + return PID; + + if (PID->getPropertyDecl()->isClassProperty()) + ClassPropImpl = PID; + } + + if (QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown) + // We can't find the instance property, return the class property. + return ClassPropImpl; + return nullptr; } diff --git a/lib/Analysis/BodyFarm.cpp b/lib/Analysis/BodyFarm.cpp index 325c326137..2118301362 100644 --- a/lib/Analysis/BodyFarm.cpp +++ b/lib/Analysis/BodyFarm.cpp @@ -414,7 +414,7 @@ static const ObjCIvarDecl *findBackingIvar(const ObjCPropertyDecl *Prop) { // is guaranteed to find the shadowing property, if it exists, rather than // the shadowed property. auto *ShadowingProp = PrimaryInterface->FindPropertyVisibleInPrimaryClass( - Prop->getIdentifier()); + Prop->getIdentifier(), Prop->getQueryKind()); if (ShadowingProp && ShadowingProp != Prop) { IVar = ShadowingProp->getPropertyIvarDecl(); } diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index 9c9822a3de..0f2c3a4367 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -2330,8 +2330,10 @@ Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) { propertyIvar = Tok.getIdentifierInfo(); propertyIvarLoc = ConsumeToken(); // consume ivar-name } - Actions.ActOnPropertyImplDecl(getCurScope(), atLoc, propertyLoc, true, - propertyId, propertyIvar, propertyIvarLoc); + Actions.ActOnPropertyImplDecl( + getCurScope(), atLoc, propertyLoc, true, + propertyId, propertyIvar, propertyIvarLoc, + ObjCPropertyQueryKind::OBJC_PR_query_unknown); if (Tok.isNot(tok::comma)) break; ConsumeToken(); // consume ',' @@ -2366,8 +2368,10 @@ Decl *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) { IdentifierInfo *propertyId = Tok.getIdentifierInfo(); SourceLocation propertyLoc = ConsumeToken(); // consume property name - Actions.ActOnPropertyImplDecl(getCurScope(), atLoc, propertyLoc, false, - propertyId, nullptr, SourceLocation()); + Actions.ActOnPropertyImplDecl( + getCurScope(), atLoc, propertyLoc, false, + propertyId, nullptr, SourceLocation(), + ObjCPropertyQueryKind::OBJC_PR_query_unknown); if (Tok.isNot(tok::comma)) break; diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 59ab0ba618..12aec6caba 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -6189,7 +6189,7 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, // Figure out which interface we're looking into. ObjCInterfaceDecl *Class = nullptr; if (ObjCImplementationDecl *ClassImpl - = dyn_cast(Container)) + = dyn_cast(Container)) Class = ClassImpl->getClassInterface(); else Class = cast(Container)->getCategoryDecl() @@ -6198,8 +6198,8 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, // Determine the type of the property we're synthesizing. QualType PropertyType = Context.getObjCIdType(); if (Class) { - if (ObjCPropertyDecl *Property - = Class->FindPropertyDeclaration(PropertyName)) { + if (ObjCPropertyDecl *Property = Class->FindPropertyDeclaration( + PropertyName, ObjCPropertyQueryKind::OBJC_PR_query_instance)) { PropertyType = Property->getType().getNonReferenceType().getUnqualifiedType(); diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index cf45e916af..7b1bc2f490 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -3656,7 +3656,8 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef allMethods, for (const auto *Property : Ext->instance_properties()) { // Skip over properties declared @dynamic if (const ObjCPropertyImplDecl *PIDecl - = IC->FindPropertyImplDecl(Property->getIdentifier())) + = IC->FindPropertyImplDecl(Property->getIdentifier(), + Property->getQueryKind())) if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) continue; diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp index 9c345f8a69..f62b5a58e8 100644 --- a/lib/Sema/SemaExprMember.cpp +++ b/lib/Sema/SemaExprMember.cpp @@ -380,7 +380,8 @@ static Decl *FindGetterSetterNameDeclFromProtocolList(const ObjCProtocolDecl*PDe const Selector &Sel, ASTContext &Context) { if (Member) - if (ObjCPropertyDecl *PD = PDecl->FindPropertyDeclaration(Member)) + if (ObjCPropertyDecl *PD = PDecl->FindPropertyDeclaration( + Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) return PD; if (ObjCMethodDecl *OMD = PDecl->getInstanceMethod(Sel)) return OMD; @@ -401,7 +402,8 @@ static Decl *FindGetterSetterNameDecl(const ObjCObjectPointerType *QIdTy, Decl *GDecl = nullptr; for (const auto *I : QIdTy->quals()) { if (Member) - if (ObjCPropertyDecl *PD = I->FindPropertyDeclaration(Member)) { + if (ObjCPropertyDecl *PD = I->FindPropertyDeclaration( + Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) { GDecl = PD; break; } @@ -1324,7 +1326,9 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R, D = CAT->getClassInterface(); ClassDeclared = cast(D); } else { - if (IsArrow && IDecl->FindPropertyDeclaration(Member)) { + if (IsArrow && + IDecl->FindPropertyDeclaration( + Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) { S.Diag(MemberLoc, diag::err_property_found_suggest) << Member << BaseExpr.get()->getType() << FixItHint::CreateReplacement(OpLoc, "."); diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index b14ca4b64b..53f39e3b2a 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -1778,7 +1778,8 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, MemberName, BaseRange)) return ExprError(); - if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(Member)) { + if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration( + Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) { // Check whether we can reference this property. if (DiagnoseUseOfDecl(PD, MemberLoc)) return ExprError(); @@ -1793,7 +1794,8 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, } // Check protocols on qualified interfaces. for (const auto *I : OPT->quals()) - if (ObjCPropertyDecl *PD = I->FindPropertyDeclaration(Member)) { + if (ObjCPropertyDecl *PD = I->FindPropertyDeclaration( + Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) { // Check whether we can reference this property. if (DiagnoseUseOfDecl(PD, MemberLoc)) return ExprError(); @@ -1852,8 +1854,9 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, // Special warning if member name used in a property-dot for a setter accessor // does not use a property with same name; e.g. obj.X = ... for a property with // name 'x'. - if (Setter && Setter->isImplicit() && Setter->isPropertyAccessor() - && !IFace->FindPropertyDeclaration(Member)) { + if (Setter && Setter->isImplicit() && Setter->isPropertyAccessor() && + !IFace->FindPropertyDeclaration( + Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) { if (const ObjCPropertyDecl *PDecl = Setter->findPropertyDecl()) { // Do not warn if user is using property-dot syntax to make call to // user named setter. diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 45dc2e33da..f28cd27e85 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -4207,7 +4207,8 @@ static void LookupPotentialTypoResult(Sema &SemaRef, } } - if (ObjCPropertyDecl *Prop = Class->FindPropertyDeclaration(Name)) { + if (ObjCPropertyDecl *Prop = Class->FindPropertyDeclaration( + Name, ObjCPropertyQueryKind::OBJC_PR_query_instance)) { Res.addDecl(Prop); Res.resolveKind(); return; diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp index 4c5a0616f3..35f79b2a3e 100644 --- a/lib/Sema/SemaObjCProperty.cpp +++ b/lib/Sema/SemaObjCProperty.cpp @@ -433,10 +433,13 @@ Sema::HandlePropertyInClassExtension(Scope *S, return nullptr; } + bool isClassProperty = (AttributesAsWritten & ObjCDeclSpec::DQ_PR_class) || + (Attributes & ObjCDeclSpec::DQ_PR_class); + // Find the property in the extended class's primary class or // extensions. - ObjCPropertyDecl *PIDecl = - CCPrimary->FindPropertyVisibleInPrimaryClass(PropertyId); + ObjCPropertyDecl *PIDecl = CCPrimary->FindPropertyVisibleInPrimaryClass( + PropertyId, ObjCPropertyDecl::getQueryKind(isClassProperty)); // If we found a property in an extension, complain. if (PIDecl && isa(PIDecl->getDeclContext())) { @@ -614,8 +617,11 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, PropertyId, AtLoc, LParenLoc, T, TInfo); - if (ObjCPropertyDecl *prevDecl = - ObjCPropertyDecl::findPropertyDecl(DC, PropertyId)) { + bool isClassProperty = (AttributesAsWritten & ObjCDeclSpec::DQ_PR_class) || + (Attributes & ObjCDeclSpec::DQ_PR_class); + // Class property and instance property can have the same name. + if (ObjCPropertyDecl *prevDecl = ObjCPropertyDecl::findPropertyDecl( + DC, PropertyId, ObjCPropertyDecl::getQueryKind(isClassProperty))) { Diag(PDecl->getLocation(), diag::err_duplicate_property); Diag(prevDecl->getLocation(), diag::note_property_declare); PDecl->setInvalidDecl(); @@ -852,7 +858,8 @@ DiagnosePropertyMismatchDeclInProtocols(Sema &S, SourceLocation AtLoc, } /// Determine whether any storage attributes were written on the property. -static bool hasWrittenStorageAttribute(ObjCPropertyDecl *Prop) { +static bool hasWrittenStorageAttribute(ObjCPropertyDecl *Prop, + ObjCPropertyQueryKind QueryKind) { if (Prop->getPropertyAttributesAsWritten() & OwnershipMask) return true; // If this is a readwrite property in a class extension that refines @@ -875,8 +882,8 @@ static bool hasWrittenStorageAttribute(ObjCPropertyDecl *Prop) { // Look through all of the protocols. for (const auto *Proto : OrigClass->all_referenced_protocols()) { - if (ObjCPropertyDecl *OrigProp = - Proto->FindPropertyDeclaration(Prop->getIdentifier())) + if (ObjCPropertyDecl *OrigProp = Proto->FindPropertyDeclaration( + Prop->getIdentifier(), QueryKind)) return OrigProp->getPropertyAttributesAsWritten() & OwnershipMask; } @@ -893,7 +900,8 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, bool Synthesize, IdentifierInfo *PropertyId, IdentifierInfo *PropertyIvar, - SourceLocation PropertyIvarLoc) { + SourceLocation PropertyIvarLoc, + ObjCPropertyQueryKind QueryKind) { ObjCContainerDecl *ClassImpDecl = dyn_cast(CurContext); // Make sure we have a context for the property implementation declaration. @@ -920,7 +928,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, "ActOnPropertyImplDecl - @implementation without @interface"); // Look for this property declaration in the @implementation's @interface - property = IDecl->FindPropertyDeclaration(PropertyId); + property = IDecl->FindPropertyDeclaration(PropertyId, QueryKind); if (!property) { Diag(PropertyLoc, diag::error_bad_property_decl) << IDecl->getDeclName(); return nullptr; @@ -998,7 +1006,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, if (!Category) return nullptr; // Look for this property declaration in @implementation's category - property = Category->FindPropertyDeclaration(PropertyId); + property = Category->FindPropertyDeclaration(PropertyId, QueryKind); if (!property) { Diag(PropertyLoc, diag::error_bad_category_property_decl) << Category->getDeclName(); @@ -1110,7 +1118,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, // It's an error if we have to do this and the user didn't // explicitly write an ownership attribute on the property. - if (!hasWrittenStorageAttribute(property) && + if (!hasWrittenStorageAttribute(property, QueryKind) && !(kind & ObjCPropertyDecl::OBJC_PR_strong)) { Diag(PropertyDiagLoc, diag::err_arc_objc_property_default_assign_on_object); @@ -1345,7 +1353,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, } if (ObjCPropertyImplDecl *PPIDecl - = IC->FindPropertyImplDecl(PropertyId)) { + = IC->FindPropertyImplDecl(PropertyId, QueryKind)) { Diag(PropertyLoc, diag::error_property_implemented) << PropertyId; Diag(PPIDecl->getLocation(), diag::note_previous_declaration); return nullptr; @@ -1384,7 +1392,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, } if (ObjCPropertyImplDecl *PPIDecl = - CatImplClass->FindPropertyImplDecl(PropertyId)) { + CatImplClass->FindPropertyImplDecl(PropertyId, QueryKind)) { Diag(PropertyDiagLoc, diag::error_property_implemented) << PropertyId; Diag(PPIDecl->getLocation(), diag::note_previous_declaration); return nullptr; @@ -1653,7 +1661,8 @@ void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl* IMPDecl, Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional) continue; // Property may have been synthesized by user. - if (IMPDecl->FindPropertyImplDecl(Prop->getIdentifier())) + if (IMPDecl->FindPropertyImplDecl( + Prop->getIdentifier(), Prop->getQueryKind())) continue; if (IMPDecl->getInstanceMethod(Prop->getGetterName())) { if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readonly) @@ -1712,7 +1721,7 @@ void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl* IMPDecl, true, /* property = */ Prop->getIdentifier(), /* ivar = */ Prop->getDefaultSynthIvarName(Context), - Prop->getLocation())); + Prop->getLocation(), Prop->getQueryKind())); if (PIDecl) { Diag(Prop->getLocation(), diag::warn_missing_explicit_synthesis); Diag(IMPDecl->getLocation(), diag::note_while_in_implementation); @@ -1942,8 +1951,8 @@ Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl, if ((Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) || !(Attributes & ObjCPropertyDecl::OBJC_PR_readwrite)) continue; - if (const ObjCPropertyImplDecl *PIDecl - = IMPDecl->FindPropertyImplDecl(Property->getIdentifier())) { + if (const ObjCPropertyImplDecl *PIDecl = IMPDecl->FindPropertyImplDecl( + Property->getIdentifier(), Property->getQueryKind())) { if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) continue; if (!LookedUpGetterSetter) { diff --git a/lib/Sema/SemaPseudoObject.cpp b/lib/Sema/SemaPseudoObject.cpp index e5d51f173c..62c823b363 100644 --- a/lib/Sema/SemaPseudoObject.cpp +++ b/lib/Sema/SemaPseudoObject.cpp @@ -658,7 +658,8 @@ bool ObjCPropertyOpBuilder::findSetter(bool warn) { SmallString<100> PropertyName = thisPropertyName; PropertyName[0] = front; IdentifierInfo *AltMember = &S.PP.getIdentifierTable().get(PropertyName); - if (ObjCPropertyDecl *prop1 = IFace->FindPropertyDeclaration(AltMember)) + if (ObjCPropertyDecl *prop1 = IFace->FindPropertyDeclaration( + AltMember, prop->getQueryKind())) if (prop != prop1 && (prop1->getSetterMethodDecl() == setter)) { S.Diag(RefExpr->getExprLoc(), diag::error_property_setter_ambiguous_use) << prop << prop1 << setter->getSelector(); diff --git a/test/SemaObjC/objc-class-property.m b/test/SemaObjC/objc-class-property.m index f24e86b635..bc2bf25193 100644 --- a/test/SemaObjC/objc-class-property.m +++ b/test/SemaObjC/objc-class-property.m @@ -16,6 +16,7 @@ @property(readonly) int ro, ro2; @property (class) int c; @property (class) int c2; +@property (class) int x; @end @implementation A diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 6f1b366aa3..b2a9ab88e9 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -1077,7 +1077,8 @@ bool CursorVisitor::VisitObjCPropertyDecl(ObjCPropertyDecl *PD) { IdentifierInfo *PropertyId = PD->getIdentifier(); ObjCPropertyDecl *prevDecl = - ObjCPropertyDecl::findPropertyDecl(cast(ID), PropertyId); + ObjCPropertyDecl::findPropertyDecl(cast(ID), PropertyId, + PD->getQueryKind()); if (!prevDecl) return false; -- 2.40.0