From 337ac58fc055f4b91051cedb3a689636bcfbcffc Mon Sep 17 00:00:00 2001 From: Manman Ren Date: Tue, 26 Jan 2016 18:52:43 +0000 Subject: [PATCH] Class Property: parse property attribute (class). This is the third patch in a series of patches to support class properties in addition to instance properties in objective-c. rdar://23891898 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@258834 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/DeclObjC.h | 46 ++++++++++++++++++++++++++----- include/clang/Sema/DeclSpec.h | 5 ++-- lib/AST/ASTDumper.cpp | 2 ++ lib/AST/DeclPrinter.cpp | 5 ++++ lib/Parse/ParseObjc.cpp | 3 ++ lib/Sema/SemaObjCProperty.cpp | 5 ++++ test/Parser/objc-class-property.m | 30 ++++++++++++++++++++ 7 files changed, 87 insertions(+), 9 deletions(-) create mode 100644 test/Parser/objc-class-property.m diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index c5349d59c4..18f89e16ac 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -716,12 +716,13 @@ public: /// property attribute rather than a type qualifier. OBJC_PR_nullability = 0x1000, OBJC_PR_null_resettable = 0x2000, + OBJC_PR_class = 0x4000 // Adding a property should change NumPropertyAttrsBits }; enum { /// \brief Number of bits fitting all the property attributes. - NumPropertyAttrsBits = 14 + NumPropertyAttrsBits = 15 }; enum SetterKind { Assign, Retain, Copy, Weak }; @@ -823,6 +824,9 @@ public: (OBJC_PR_retain | OBJC_PR_strong | OBJC_PR_copy)); } + bool isInstanceProperty() const { return !isClassProperty(); } + bool isClassProperty() const { return PropertyAttributes & OBJC_PR_class; } + /// getSetterKind - Return the method used for doing assignment in /// the property setter. This is only valid if the property has been /// defined to have a setter. @@ -899,21 +903,49 @@ public: SourceLocation atStartLoc) : NamedDecl(DK, DC, nameLoc, Id), DeclContext(DK), AtStart(atStartLoc) {} - // Iterator access to properties. + // Iterator access to instance/class properties. typedef specific_decl_iterator prop_iterator; typedef llvm::iterator_range> prop_range; - prop_range instance_properties() const { - return prop_range(instprop_begin(), instprop_end()); - } - prop_iterator instprop_begin() const { + prop_range properties() const { return prop_range(prop_begin(), prop_end()); } + prop_iterator prop_begin() const { return prop_iterator(decls_begin()); } - prop_iterator instprop_end() const { + prop_iterator prop_end() const { return prop_iterator(decls_end()); } + typedef filtered_decl_iterator + instprop_iterator; + typedef llvm::iterator_range instprop_range; + + instprop_range instance_properties() const { + return instprop_range(instprop_begin(), instprop_end()); + } + instprop_iterator instprop_begin() const { + return instprop_iterator(decls_begin()); + } + instprop_iterator instprop_end() const { + return instprop_iterator(decls_end()); + } + + typedef filtered_decl_iterator + classprop_iterator; + typedef llvm::iterator_range classprop_range; + + classprop_range class_properties() const { + return classprop_range(classprop_begin(), classprop_end()); + } + classprop_iterator classprop_begin() const { + return classprop_iterator(decls_begin()); + } + classprop_iterator classprop_end() const { + return classprop_iterator(decls_end()); + } + // Iterator access to instance/class methods. typedef specific_decl_iterator method_iterator; typedef llvm::iterator_range> diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index 064d37b2a0..fd50f51811 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -800,7 +800,8 @@ public: DQ_PR_strong = 0x400, DQ_PR_unsafe_unretained = 0x800, DQ_PR_nullability = 0x1000, - DQ_PR_null_resettable = 0x2000 + DQ_PR_null_resettable = 0x2000, + DQ_PR_class = 0x4000 }; ObjCDeclSpec() @@ -860,7 +861,7 @@ private: ObjCDeclQualifier objcDeclQualifier : 7; // NOTE: VC++ treats enums as signed, avoid using ObjCPropertyAttributeKind - unsigned PropertyAttributes : 14; + unsigned PropertyAttributes : 15; unsigned Nullability : 2; diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index 4622a75ac2..9b7944271a 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -1597,6 +1597,8 @@ void ASTDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { OS << " strong"; if (Attrs & ObjCPropertyDecl::OBJC_PR_unsafe_unretained) OS << " unsafe_unretained"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_class) + OS << " class"; if (Attrs & ObjCPropertyDecl::OBJC_PR_getter) dumpDeclRef(D->getGetterMethodDecl(), "getter"); if (Attrs & ObjCPropertyDecl::OBJC_PR_setter) diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index 6a3e8e2ae1..19c7da3074 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -1301,6 +1301,11 @@ void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) { } } + if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_class) { + Out << (first ? ' ' : ',') << "class"; + first = false; + } + (void) first; // Silence dead store warning due to idiomatic code. Out << " )"; } diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index bb6344f90d..9c9822a3de 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -847,6 +847,7 @@ static void diagnoseRedundantPropertyNullability(Parser &P, /// nullable /// null_unspecified /// null_resettable +/// class /// void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) { assert(Tok.getKind() == tok::l_paren); @@ -962,6 +963,8 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) { // Also set the null_resettable bit. DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_null_resettable); + } else if (II->isStr("class")) { + DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_class); } else { Diag(AttrName, diag::err_objc_expected_property_attr) << II; SkipUntil(tok::r_paren, StopAtSemi); diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp index db37a75479..9a976e6e59 100644 --- a/lib/Sema/SemaObjCProperty.cpp +++ b/lib/Sema/SemaObjCProperty.cpp @@ -303,6 +303,8 @@ makePropertyAttributesAsWritten(unsigned Attributes) { attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_nonatomic; if (Attributes & ObjCDeclSpec::DQ_PR_atomic) attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_atomic; + if (Attributes & ObjCDeclSpec::DQ_PR_class) + attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_class; return (ObjCPropertyDecl::PropertyAttributeKind)attributesAsWritten; } @@ -691,6 +693,9 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, if (Attributes & ObjCDeclSpec::DQ_PR_null_resettable) PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_null_resettable); + if (Attributes & ObjCDeclSpec::DQ_PR_class) + PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_class); + return PDecl; } diff --git a/test/Parser/objc-class-property.m b/test/Parser/objc-class-property.m new file mode 100644 index 0000000000..202352c33b --- /dev/null +++ b/test/Parser/objc-class-property.m @@ -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; +} -- 2.40.0