]> granicus.if.org Git - clang/commitdiff
Class Property: parse property attribute (class).
authorManman Ren <manman.ren@gmail.com>
Tue, 26 Jan 2016 18:52:43 +0000 (18:52 +0000)
committerManman Ren <manman.ren@gmail.com>
Tue, 26 Jan 2016 18:52:43 +0000 (18:52 +0000)
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
include/clang/Sema/DeclSpec.h
lib/AST/ASTDumper.cpp
lib/AST/DeclPrinter.cpp
lib/Parse/ParseObjc.cpp
lib/Sema/SemaObjCProperty.cpp
test/Parser/objc-class-property.m [new file with mode: 0644]

index c5349d59c482a2dff1e5fca8706695bedb1270c1..18f89e16acb7da2cb17ee4c7a619c23ddb95c5fd 100644 (file)
@@ -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>>
index 064d37b2a02bfe4cfbc1d5543009c094295a1640..fd50f51811eceae29e69924c237171a5d55cb9e4 100644 (file)
@@ -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;
 
index 4622a75ac2c64fcf20b76c473c81be0aa40510b1..9b7944271af8fe6e421c32fe2ed1fe3172002237 100644 (file)
@@ -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)
index 6a3e8e2ae1a016110162576a89340df872422ac3..19c7da3074b740468b94e7d8db96aa64cbb4729d 100644 (file)
@@ -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 << " )";
   }
index bb6344f90d5e254e9145ce6baaa701b55171d3df..9c9822a3de477d729f8e01548a23ed3b5bb285ec 100644 (file)
@@ -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);
index db37a7547917769f5c539837a65a5009861f3a81..9a976e6e590dfdb040cb30218523c3d8799670df 100644 (file)
@@ -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 (file)
index 0000000..202352c
--- /dev/null
@@ -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;
+}