]> granicus.if.org Git - clang/commitdiff
Author: F. Jahanian
authorFariborz Jahanian <fjahanian@apple.com>
Fri, 31 Aug 2007 16:11:31 +0000 (16:11 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Fri, 31 Aug 2007 16:11:31 +0000 (16:11 +0000)
Log:
Implement parsing of objective-c's new @property declaration.

Modified:
include/clang/Basic/DiagnosticKinds.def
include/clang/Parse/Parser.h
Parse/ParseObjc.cpp
Parse/Parser.cpp

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41644 91177308-0d34-0410-b5e6-96231b3b80d8

Parse/ParseObjc.cpp
Parse/Parser.cpp
include/clang/Basic/DiagnosticKinds.def
include/clang/Parse/Parser.h

index 7c0f84257eb973a2fa4bcf9d55c59aa2f8013414..83dba037fa94764ba269e8de1028687cd08ddac9 100644 (file)
@@ -224,7 +224,7 @@ void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl) {
         ConsumeToken();
         continue;
       } else if (ocKind == tok::objc_property) {
-        ParseObjCPropertyDecl(AtLoc);
+        ParseObjCPropertyDecl(0/*FIXME*/);
         continue;
       } else {
         Diag(Tok, diag::err_objc_illegal_interface_qual);
@@ -246,8 +246,96 @@ void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl) {
   }
 }
 
-void Parser::ParseObjCPropertyDecl(SourceLocation atLoc) {
-  assert(0 && "Unimp");
+///   Parse property attribute declarations.
+///
+///   property-attr-decl: '(' property-attrlist ')'
+///   property-attrlist:
+///     property-attribute
+///     property-attrlist ',' property-attribute
+///   property-attribute:
+///     getter '=' identifier
+///     setter '=' identifier ':'
+///     readonly
+///     readwrite
+///     assign
+///     retain
+///     copy
+///     nonatomic
+///
+void Parser::ParseObjCPropertyAttribute (DeclTy *interfaceDecl) {
+  SourceLocation loc = ConsumeParen(); // consume '('
+  while (isObjCPropertyAttribute()) {
+    const IdentifierInfo *II = Tok.getIdentifierInfo();
+    // getter/setter require extra treatment.
+    if (II == ObjcPropertyAttrs[objc_getter] || 
+        II == ObjcPropertyAttrs[objc_setter]) {
+      // skip getter/setter part.
+      SourceLocation loc = ConsumeToken();
+      if (Tok.getKind() == tok::equal) {
+        loc = ConsumeToken();
+        if (Tok.getKind() == tok::identifier) {
+          if (II == ObjcPropertyAttrs[objc_setter]) {
+            loc = ConsumeToken();  // consume method name
+            if (Tok.getKind() != tok::colon) {
+              Diag(loc, diag::err_expected_colon);
+              SkipUntil(tok::r_paren,true,true);
+              break;
+            }
+          }
+        }
+        else {
+          Diag(loc, diag::err_expected_ident);
+         SkipUntil(tok::r_paren,true,true);
+         break;
+       }
+      }
+      else {
+        Diag(loc, diag::err_objc_expected_equal);    
+        SkipUntil(tok::r_paren,true,true);
+        break;
+      }
+    }
+    ConsumeToken(); // consume last attribute token
+    if (Tok.getKind() == tok::comma) {
+      loc = ConsumeToken();
+      continue;
+    }
+    if (Tok.getKind() == tok::r_paren)
+      break;
+    Diag(loc, diag::err_expected_rparen);
+    SkipUntil(tok::semi);
+    return;
+  }
+  if (Tok.getKind() == tok::r_paren)
+    ConsumeParen();
+  else {
+    Diag(loc, diag::err_objc_expected_property_attr);
+    SkipUntil(tok::r_paren); // recover from error inside attribute list
+  }
+}
+
+///   Main routine to parse property declaration.
+///
+///   @property property-attr-decl[opt] property-component-decl ';'
+///
+void Parser::ParseObjCPropertyDecl(DeclTy *interfaceDecl) {
+  assert(Tok.isObjCAtKeyword(tok::objc_property) &&
+         "ParseObjCPropertyDecl(): Expected @property");
+  ConsumeToken(); // the "property" identifier
+  // Parse property attribute list, if any. 
+  if (Tok.getKind() == tok::l_paren) {
+    // property has attribute list.
+    ParseObjCPropertyAttribute(0/*FIXME*/);
+  }
+  // Parse declaration portion of @property.
+  llvm::SmallVector<DeclTy*, 32> PropertyDecls;
+  ParseStructDeclaration(interfaceDecl, PropertyDecls);
+  if (Tok.getKind() == tok::semi) 
+    ConsumeToken();
+  else {
+    Diag(Tok, diag::err_expected_semi_decl_list);
+    SkipUntil(tok::r_brace, true, true);
+  }
 }
 
 ///   objc-methodproto:
@@ -312,6 +400,18 @@ bool Parser::isObjCTypeQualifier() {
   return false;
 }
 
+///  property-attrlist: one of
+///    readonly getter setter assign retain copy nonatomic
+///
+bool Parser::isObjCPropertyAttribute() {
+  if (Tok.getKind() == tok::identifier) {
+    const IdentifierInfo *II = Tok.getIdentifierInfo();
+    for (unsigned i = 0; i < objc_NumAttrs; ++i)
+      if (II == ObjcPropertyAttrs[i]) return true;
+  }
+  return false;
+} 
+
 ///   objc-type-name:
 ///     '(' objc-type-qualifiers[opt] type-name ')'
 ///     '(' objc-type-qualifiers[opt] ')'
index 581d585a82af4585649e0ab406cbf26662d98e2f..0a7ea58b0459a15ffbeea232af3449aaac2cabe8 100644 (file)
@@ -258,6 +258,18 @@ void Parser::Initialize() {
     ObjcTypeQuals[objc_bycopy] = &PP.getIdentifierTable().get("bycopy");
     ObjcTypeQuals[objc_byref] = &PP.getIdentifierTable().get("byref");
   }
+  if (getLang().ObjC2) {
+    ObjcPropertyAttrs[objc_readonly] = &PP.getIdentifierTable().get("readonly");
+    ObjcPropertyAttrs[objc_getter] = &PP.getIdentifierTable().get("getter");
+    ObjcPropertyAttrs[objc_setter] = &PP.getIdentifierTable().get("setter");
+    ObjcPropertyAttrs[objc_assign] = &PP.getIdentifierTable().get("assign");
+    ObjcPropertyAttrs[objc_readwrite] = 
+                                  &PP.getIdentifierTable().get("readwrite");
+    ObjcPropertyAttrs[objc_retain] = &PP.getIdentifierTable().get("retain");
+    ObjcPropertyAttrs[objc_copy] = &PP.getIdentifierTable().get("copy");
+    ObjcPropertyAttrs[objc_nonatomic] = 
+                                  &PP.getIdentifierTable().get("nonatomic");
+  }
 }
 
 /// ParseTopLevelDecl - Parse one top-level declaration, return whatever the
index 9eaf4d40616a21f1f26e2831d2107bd2b9069dad..a5d276d33e99ebb585549f3ea301317d609c5818 100644 (file)
@@ -399,6 +399,10 @@ DIAG(err_objc_illegal_visibility_spec, ERROR,
      "illegal visibility specification")
 DIAG(err_objc_illegal_interface_qual, ERROR,
      "illegal interface qualifier")
+DIAG(err_objc_expected_equal, ERROR,
+     "setter/getter expects '=' followed by name")
+DIAG(err_objc_expected_property_attr, ERROR,
+     "unknown property attribute detected")
 
 //===----------------------------------------------------------------------===//
 // Semantic Analysis
index ab6f84fb3139c2af56112ed690dc550844b7ffcd..65d1ff6431e864bd1198176f417b46b9e90e918d 100644 (file)
@@ -274,11 +274,20 @@ private:
   };
   IdentifierInfo *ObjcTypeQuals[objc_NumQuals];
   bool isObjCTypeQualifier();
+  // Definitions for ObjC2's @property attributes.
+  enum ObjCPropertyAttr {
+    objc_readonly=0, objc_getter, objc_setter, objc_assign, 
+    objc_readwrite, objc_retain, objc_copy, objc_nonatomic, objc_NumAttrs
+  };
+  IdentifierInfo *ObjcPropertyAttrs[objc_NumAttrs];
+  bool isObjCPropertyAttribute();
+
   void ParseObjCTypeName();
   void ParseObjCMethodRequirement();
   void ParseObjCMethodPrototype();
   void ParseObjCMethodDecl(tok::TokenKind mType, SourceLocation mLoc);
-  void ParseObjCPropertyDecl(SourceLocation atLoc);
+  void ParseObjCPropertyAttribute(DeclTy *interfaceDecl);
+  void ParseObjCPropertyDecl(DeclTy *interfaceDecl);
   
   void ParseObjCInstanceMethodDefinition();
   void ParseObjCClassMethodDefinition();