summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManman Ren <manman.ren@gmail.com>2016-01-26 18:52:43 +0000
committerManman Ren <manman.ren@gmail.com>2016-01-26 18:52:43 +0000
commit337ac58fc055f4b91051cedb3a689636bcfbcffc (patch)
tree02fe527a0667a09e6871d9826bb36d9aa5d7f3a7
parented30907f4a2352e40c8dfebbf615bd14607833fc (diff)
downloadclang-337ac58fc055f4b91051cedb3a689636bcfbcffc.tar.gz
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
-rw-r--r--include/clang/AST/DeclObjC.h46
-rw-r--r--include/clang/Sema/DeclSpec.h5
-rw-r--r--lib/AST/ASTDumper.cpp2
-rw-r--r--lib/AST/DeclPrinter.cpp5
-rw-r--r--lib/Parse/ParseObjc.cpp3
-rw-r--r--lib/Sema/SemaObjCProperty.cpp5
-rw-r--r--test/Parser/objc-class-property.m30
7 files changed, 87 insertions, 9 deletions
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<ObjCPropertyDecl> prop_iterator;
typedef llvm::iterator_range<specific_decl_iterator<ObjCPropertyDecl>>
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<ObjCPropertyDecl,
+ &ObjCPropertyDecl::isInstanceProperty>
+ instprop_iterator;
+ typedef llvm::iterator_range<instprop_iterator> 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<ObjCPropertyDecl,
+ &ObjCPropertyDecl::isClassProperty>
+ classprop_iterator;
+ typedef llvm::iterator_range<classprop_iterator> 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<ObjCMethodDecl> method_iterator;
typedef llvm::iterator_range<specific_decl_iterator<ObjCMethodDecl>>
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;
+}