Author: mren Date: Wed Jan 27 14:10:32 2016 New Revision: 258980 URL: http://llvm.org/viewvc/llvm-project?rev=258980&view=rev Log: Class Property: create accessors (class methods) for class property.
Change a few places where we assume property accessors can only be instance methods. rdar://23891898 Added: cfe/trunk/test/SemaObjC/objc-class-property.m Modified: cfe/trunk/include/clang/AST/DeclObjC.h cfe/trunk/lib/Sema/SemaDeclObjC.cpp cfe/trunk/lib/Sema/SemaObjCProperty.cpp Modified: cfe/trunk/include/clang/AST/DeclObjC.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=258980&r1=258979&r2=258980&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/DeclObjC.h (original) +++ cfe/trunk/include/clang/AST/DeclObjC.h Wed Jan 27 14:10:32 2016 @@ -1754,8 +1754,9 @@ public: /// including in all categories except for category passed /// as argument. ObjCMethodDecl *lookupPropertyAccessor(const Selector Sel, - const ObjCCategoryDecl *Cat) const { - return lookupMethod(Sel, true/*isInstance*/, + const ObjCCategoryDecl *Cat, + bool IsClassProperty) const { + return lookupMethod(Sel, !IsClassProperty/*isInstance*/, false/*shallowCategoryLookup*/, true /* followsSuper */, Cat); Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=258980&r1=258979&r2=258980&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Wed Jan 27 14:10:32 2016 @@ -2734,7 +2734,8 @@ void Sema::MatchAllMethodDeclarations(co for (auto *I : CDecl->class_methods()) { if (!ClsMapSeen.insert(I->getSelector()).second) continue; - if (!ClsMap.count(I->getSelector())) { + if (!I->isPropertyAccessor() && + !ClsMap.count(I->getSelector())) { if (ImmediateClass) WarnUndefinedMethod(*this, IMPDecl->getLocation(), I, IncompleteImpl, diag::warn_undef_method_impl); @@ -2743,12 +2744,14 @@ void Sema::MatchAllMethodDeclarations(co IMPDecl->getClassMethod(I->getSelector()); assert(CDecl->getClassMethod(I->getSelector()) && "Expected to find the method through lookup as well"); - if (!WarnCategoryMethodImpl) - WarnConflictingTypedMethods(ImpMethodDecl, I, - isa<ObjCProtocolDecl>(CDecl)); - else - WarnExactTypedMethods(ImpMethodDecl, I, - isa<ObjCProtocolDecl>(CDecl)); + // ImpMethodDecl may be null as in a @dynamic property. + if (ImpMethodDecl) { + if (!WarnCategoryMethodImpl) + WarnConflictingTypedMethods(ImpMethodDecl, I, + isa<ObjCProtocolDecl>(CDecl)); + else if (!I->isPropertyAccessor()) + WarnExactTypedMethods(ImpMethodDecl, I, isa<ObjCProtocolDecl>(CDecl)); + } } } Modified: cfe/trunk/lib/Sema/SemaObjCProperty.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaObjCProperty.cpp?rev=258980&r1=258979&r2=258980&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaObjCProperty.cpp (original) +++ cfe/trunk/lib/Sema/SemaObjCProperty.cpp Wed Jan 27 14:10:32 2016 @@ -1745,7 +1745,8 @@ static void DiagnoseUnimplementedAccesso // the class is going to implement them. if (!SMap.count(Method) && (PrimaryClass == nullptr || - !PrimaryClass->lookupPropertyAccessor(Method, C))) { + !PrimaryClass->lookupPropertyAccessor(Method, C, + Prop->isClassProperty()))) { S.Diag(IMPDecl->getLocation(), isa<ObjCCategoryDecl>(CDecl) ? diag::warn_setter_getter_impl_required_in_category : @@ -1916,8 +1917,12 @@ Sema::AtomicPropertySetterGetterRules (O if (!(AttributesAsWritten & ObjCPropertyDecl::OBJC_PR_atomic) && !(AttributesAsWritten & ObjCPropertyDecl::OBJC_PR_nonatomic)) { - GetterMethod = IMPDecl->getInstanceMethod(Property->getGetterName()); - SetterMethod = IMPDecl->getInstanceMethod(Property->getSetterName()); + GetterMethod = Property->isClassProperty() ? + IMPDecl->getClassMethod(Property->getGetterName()) : + IMPDecl->getInstanceMethod(Property->getGetterName()); + SetterMethod = Property->isClassProperty() ? + IMPDecl->getClassMethod(Property->getSetterName()) : + IMPDecl->getInstanceMethod(Property->getSetterName()); LookedUpGetterSetter = true; if (GetterMethod) { Diag(GetterMethod->getLocation(), @@ -1942,8 +1947,12 @@ Sema::AtomicPropertySetterGetterRules (O if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) continue; if (!LookedUpGetterSetter) { - GetterMethod = IMPDecl->getInstanceMethod(Property->getGetterName()); - SetterMethod = IMPDecl->getInstanceMethod(Property->getSetterName()); + GetterMethod = Property->isClassProperty() ? + IMPDecl->getClassMethod(Property->getGetterName()) : + IMPDecl->getInstanceMethod(Property->getGetterName()); + SetterMethod = Property->isClassProperty() ? + IMPDecl->getClassMethod(Property->getSetterName()) : + IMPDecl->getInstanceMethod(Property->getSetterName()); } if ((GetterMethod && !SetterMethod) || (!GetterMethod && SetterMethod)) { SourceLocation MethodLoc = @@ -1986,6 +1995,7 @@ void Sema::DiagnoseOwningPropertyGetterS for (const auto *PID : D->property_impls()) { const ObjCPropertyDecl *PD = PID->getPropertyDecl(); if (PD && !PD->hasAttr<NSReturnsNotRetainedAttr>() && + !PD->isClassProperty() && !D->getInstanceMethod(PD->getGetterName())) { ObjCMethodDecl *method = PD->getGetterMethodDecl(); if (!method) @@ -2091,20 +2101,30 @@ void Sema::ProcessPropertyDecl(ObjCPrope if (CD->isInvalidDecl()) return; - GetterMethod = CD->getInstanceMethod(property->getGetterName()); + bool IsClassProperty = property->isClassProperty(); + GetterMethod = IsClassProperty ? + CD->getClassMethod(property->getGetterName()) : + 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()-> + GetterMethod = IsClassProperty ? CatDecl->getClassInterface()-> + getClassMethod(property->getGetterName()) : + CatDecl->getClassInterface()-> getInstanceMethod(property->getGetterName()); - SetterMethod = CD->getInstanceMethod(property->getSetterName()); + SetterMethod = IsClassProperty ? + CD->getClassMethod(property->getSetterName()) : + CD->getInstanceMethod(property->getSetterName()); if (!SetterMethod) if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CD)) if (CatDecl->IsClassExtension()) - SetterMethod = CatDecl->getClassInterface()-> + SetterMethod = IsClassProperty ? CatDecl->getClassInterface()-> + getClassMethod(property->getSetterName()) : + CatDecl->getClassInterface()-> getInstanceMethod(property->getSetterName()); DiagnosePropertyAccessorMismatch(property, GetterMethod, property->getLocation()); @@ -2135,7 +2155,7 @@ void Sema::ProcessPropertyDecl(ObjCPrope // (which is odd, but allowed). Sema should be typechecking that the // declarations jive in that situation (which it is not currently). if (!GetterMethod) { - // No instance method of same name as property getter name was found. + // No instance/class 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 = property->getLocation(); @@ -2155,7 +2175,7 @@ void Sema::ProcessPropertyDecl(ObjCPrope GetterMethod = ObjCMethodDecl::Create(Context, Loc, Loc, property->getGetterName(), resultTy, nullptr, CD, - /*isInstance=*/true, /*isVariadic=*/false, + !IsClassProperty, /*isVariadic=*/false, /*isPropertyAccessor=*/true, /*isImplicitlyDeclared=*/true, /*isDefined=*/false, (property->getPropertyImplementation() == @@ -2191,7 +2211,8 @@ void Sema::ProcessPropertyDecl(ObjCPrope if (!property->isReadOnly()) { // Find the default setter and if one not found, add one. if (!SetterMethod) { - // No instance method of same name as property setter name was found. + // No instance/class 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 = property->getLocation(); @@ -2199,7 +2220,7 @@ void Sema::ProcessPropertyDecl(ObjCPrope SetterMethod = ObjCMethodDecl::Create(Context, Loc, Loc, property->getSetterName(), Context.VoidTy, - nullptr, CD, /*isInstance=*/true, + nullptr, CD, !IsClassProperty, /*isVariadic=*/false, /*isPropertyAccessor=*/true, /*isImplicitlyDeclared=*/true, @@ -2262,10 +2283,12 @@ void Sema::ProcessPropertyDecl(ObjCPrope // double bar = [foo bar]; // } // - if (GetterMethod) - AddInstanceMethodToGlobalPool(GetterMethod); - if (SetterMethod) - AddInstanceMethodToGlobalPool(SetterMethod); + if (!IsClassProperty) { + if (GetterMethod) + AddInstanceMethodToGlobalPool(GetterMethod); + if (SetterMethod) + AddInstanceMethodToGlobalPool(SetterMethod); + } ObjCInterfaceDecl *CurrentClass = dyn_cast<ObjCInterfaceDecl>(CD); if (!CurrentClass) { Added: cfe/trunk/test/SemaObjC/objc-class-property.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/objc-class-property.m?rev=258980&view=auto ============================================================================== --- cfe/trunk/test/SemaObjC/objc-class-property.m (added) +++ cfe/trunk/test/SemaObjC/objc-class-property.m Wed Jan 27 14:10:32 2016 @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// expected-no-diagnostics + +@interface Root +-(id) alloc; +-(id) init; +@end + +@interface A : Root { + int x; + int z; +} +@property int x; +@property int y; +@property int z; +@property(readonly) int ro, ro2; +@property (class) int c; +@property (class) int c2; +@end + +@implementation A +@dynamic x; +@synthesize z; +@dynamic c; +@end + +int test() { + A *a = [[A alloc] init]; + return a.x + A.c; +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits