[cfe-commits] r41275 - in /cfe/trunk: Parse/ParseObjc.cpp include/clang/Basic/DiagnosticKinds.def include/clang/Basic/TokenKinds.def include/clang/Parse/Parser.h

Steve Naroff snaroff at apple.com
Wed Aug 22 09:35:03 PDT 2007


Author: snaroff
Date: Wed Aug 22 11:35:03 2007
New Revision: 41275

URL: http://llvm.org/viewvc/llvm-project?rev=41275&view=rev
Log:

Add support for parsing method prototypes (and other stuff required by @interface).

Still need to finish Parser::ParseObjCMethodDecl(). Before I do, I need to do a minor
refactoring of ParseDeclarationOrFunctionDefinition(), to disallow function definitions.
At the moment, @inteface allows function defs (which is incorrect).

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

Modified: cfe/trunk/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Parse/ParseObjc.cpp?rev=41275&r1=41274&r2=41275&view=diff

==============================================================================
--- cfe/trunk/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/Parse/ParseObjc.cpp Wed Aug 22 11:35:03 2007
@@ -120,7 +120,7 @@
     return 0;
   }
   // We have a class or category name - consume it.
-  IdentifierInfo *nameId = Tok.getIdentifierInfo();
+  // IdentifierInfo *nameId = Tok.getIdentifierInfo();
   SourceLocation nameLoc = ConsumeToken();
   
   if (Tok.getKind() == tok::l_paren) { // we have a category
@@ -147,18 +147,15 @@
     if (attrList) // categories don't support attributes.
       Diag(Tok, diag::err_objc_no_attributes_on_category);
     
-    //ParseObjCInterfaceDeclList();
+    ParseObjCInterfaceDeclList(0/*FIXME*/);
 
-    if (Tok.getKind() != tok::at) { // check for @end
-      Diag(Tok, diag::err_objc_missing_end);
+    // The @ sign was already consumed by ParseObjCInterfaceDeclList().
+    if (Tok.getKind() == tok::identifier &&
+        Tok.getIdentifierInfo()->getObjCKeywordID() == tok::objc_end) {
+      ConsumeToken(); // the "end" identifier
       return 0;
     }
-    SourceLocation atEndLoc = ConsumeToken(); // eat the @ sign
-    if (Tok.getIdentifierInfo()->getObjCKeywordID() != tok::objc_end) {
-      Diag(Tok, diag::err_objc_missing_end);
-      return 0;
-    }
-    ConsumeToken(); // the "end" identifier
+    Diag(Tok, diag::err_objc_missing_end);
     return 0;
   }
   // Parse a class interface.
@@ -183,32 +180,173 @@
   if (Tok.getKind() == tok::l_brace)
     ParseObjCClassInstanceVariables(0/*FIXME*/);
 
-  //ParseObjCInterfaceDeclList();
-  
-  if (Tok.getKind() != tok::at) { // check for @end
-    Diag(Tok, diag::err_objc_missing_end);
-    return 0;
-  }
-  SourceLocation atEndLoc = ConsumeToken(); // eat the @ sign
-  if (Tok.getIdentifierInfo()->getObjCKeywordID() != tok::objc_end) {
-    Diag(Tok, diag::err_objc_missing_end);
+  ParseObjCInterfaceDeclList(0/*FIXME*/);
+
+  // The @ sign was already consumed by ParseObjCInterfaceDeclList().
+  if (Tok.getKind() == tok::identifier &&
+      Tok.getIdentifierInfo()->getObjCKeywordID() == tok::objc_end) {
+    ConsumeToken(); // the "end" identifier
     return 0;
   }
-  ConsumeToken(); // the "end" identifier
+  Diag(Tok, diag::err_objc_missing_end);
   return 0;
 }
 
 ///   objc-interface-decl-list:
 ///     empty
-///     objc-interface-decl-list objc-method-proto
 ///     objc-interface-decl-list objc-property-decl [OBJC2]
+///     objc-interface-decl-list objc-method-requirement [OBJC2]
+///     objc-interface-decl-list objc-method-proto
 ///     objc-interface-decl-list declaration
 ///     objc-interface-decl-list ';'
 ///
-void Parser::ParseObjCInterfaceDeclList() {
+///   objc-method-requirement: [OBJC2]
+///     @required
+///     @optional
+///
+void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl) {
+  while (1) {
+    if (Tok.getKind() == tok::at) {
+      SourceLocation AtLoc = ConsumeToken(); // the "@"
+      tok::ObjCKeywordKind ocKind = Tok.getIdentifierInfo()->getObjCKeywordID();
+      
+      if (ocKind == tok::objc_end) { // terminate list
+        return;
+      } else if (ocKind == tok::objc_required) { // protocols only
+        ConsumeToken();
+        continue;
+      } else if (ocKind == tok::objc_optional) { // protocols only
+        ConsumeToken();
+        continue;
+      } else if (ocKind == tok::objc_property) {
+        ParseObjCPropertyDecl(AtLoc);
+        continue;
+      } else {
+        Diag(Tok, diag::err_objc_illegal_interface_qual);
+        ConsumeToken();
+      }
+    }
+    if (Tok.getKind() == tok::minus || Tok.getKind() == tok::plus) {
+      ParseObjCMethodPrototype();
+      continue;
+    }
+    if (Tok.getKind() == tok::semi)
+      ConsumeToken();
+    else if (Tok.getKind() == tok::eof)
+      return;
+    else
+      ParseDeclarationOrFunctionDefinition();
+  }
+}
+
+void Parser::ParseObjCPropertyDecl(SourceLocation atLoc) {
   assert(0 && "Unimp");
 }
 
+///   objc-methodproto:
+///     objc-instance-method objc-method-decl ';'
+///     objc-class-method objc-method-decl ';'
+///
+///   objc-instance-method: '-'
+///   objc-class-method: '+'
+///
+void Parser::ParseObjCMethodPrototype() {
+  assert((Tok.getKind() == tok::minus || Tok.getKind() == tok::plus) && 
+         "expected +/-");
+
+  tok::TokenKind methodType = Tok.getKind();  
+  SourceLocation methodLoc = ConsumeToken();
+  
+  // FIXME: deal with "context sensitive" protocol qualifiers in prototypes
+  ParseObjCMethodDecl(methodType, methodLoc);
+  
+  // Consume the ';'.
+  ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "method proto");
+}
+
+///   objc-selector:
+///     identifier
+///     one of
+///       enum struct union if else while do for switch case default
+///       break continue return goto asm sizeof typeof __alignof
+///       unsigned long const short volatile signed restrict _Complex
+///       in out inout bycopy byref oneway int char float double void _Bool
+///
+IdentifierInfo *Parser::ParseObjCSelector() {
+  tok::TokenKind tKind = Tok.getKind();
+  IdentifierInfo *II = 0;
+  
+  if (tKind == tok::identifier || 
+      (tKind >= tok::kw_auto && tKind <= tok::kw__Complex)) {
+    // FIXME: make sure the list of keywords jives with gcc. For example,
+    // the above test does not include in/out/inout/bycopy/byref/oneway.
+    II = Tok.getIdentifierInfo();
+    ConsumeToken();
+  } 
+  return II;
+}
+
+///   objc-type-name:
+///     '(' objc-type-qualifiers[opt] type-name ')'
+///     '(' objc-type-qualifiers[opt] ')'
+///
+///   objc-type-qualifiers:
+///     objc-type-qualifier
+///     objc-type-qualifiers objc-type-qualifier
+///
+///   objc-type-qualifier: one of
+///     in out inout bycopy byref oneway
+///
+void Parser::ParseObjCTypeName() {
+  assert(Tok.getKind() == tok::l_paren && "expected (");
+  
+  SourceLocation LParenLoc = ConsumeParen(), RParenLoc;
+  
+  if (isTypeSpecifierQualifier()) {
+    TypeTy *Ty = ParseTypeName();
+
+    assert(Ty && "Parser::ParseObjCTypeName(): missing type");
+  }
+  if (Tok.getKind() != tok::r_paren) {
+    MatchRHSPunctuation(tok::r_paren, LParenLoc);
+    return;
+  }
+  RParenLoc = ConsumeParen();
+}
+
+///   objc-method-decl:
+///     objc-selector
+///     objc-keyword-selector objc-optparmlist
+///     objc-type-name objc-selector
+///     objc-type-name objc-keyword-selector objc-optparmlist
+///
+///   objc-keyword-selector:
+///     objc-keyword-decl
+///     objc-keyword-selector objc-keyword-decl
+///
+///   objc-keyword-decl:
+///     objc-selector ':' objc-type-name identifier
+///     objc-selector ':' identifier
+///     ':' objc-type-name identifier
+///     ':' identifier
+///
+///   objc-optparmlist:
+///     objc-optparms objc-optellipsis
+///
+///   objc-optparms:
+///     empty
+///     objc-opt-parms , parameter-declaration
+///
+///   objc-optellipsis:
+///     empty
+///     , ...
+///
+void Parser::ParseObjCMethodDecl(tok::TokenKind mType, SourceLocation mLoc) {
+  if (Tok.getKind() == tok::l_paren)
+    ParseObjCTypeName();
+  ParseObjCSelector();
+}
+
 ///   objc-protocol-refs:
 ///     '<' identifier-list '>'
 ///

Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=41275&r1=41274&r2=41275&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Aug 22 11:35:03 2007
@@ -384,6 +384,8 @@
      "missing @end")
 DIAG(err_objc_illegal_visibility_spec, ERROR,
      "illegal visibility specification")
+DIAG(err_objc_illegal_interface_qual, ERROR,
+     "illegal interface qualifier")
 
 //===----------------------------------------------------------------------===//
 // Semantic Analysis

Modified: cfe/trunk/include/clang/Basic/TokenKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TokenKinds.def?rev=41275&r1=41274&r2=41275&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/TokenKinds.def (original)
+++ cfe/trunk/include/clang/Basic/TokenKinds.def Wed Aug 22 11:35:03 2007
@@ -350,6 +350,8 @@
 // I'm guessing this is an objc2 keyword, what are the others?
 OBJC2_AT_KEYWORD(property)
 OBJC2_AT_KEYWORD(package)
+OBJC2_AT_KEYWORD(required)
+OBJC2_AT_KEYWORD(optional)
 
 // TODO: What to do about context-sensitive keywords like:
 //       bycopy/byref/in/inout/oneway/out?

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=41275&r1=41274&r2=41275&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Wed Aug 22 11:35:03 2007
@@ -260,12 +260,19 @@
                                           AttributeList *prefixAttrs = 0);
   void ParseObjCClassInstanceVariables(DeclTy *interfaceDecl);
   bool ParseObjCProtocolReferences();
-  void ParseObjCInterfaceDeclList();
+  void ParseObjCInterfaceDeclList(DeclTy *interfaceDecl);
   DeclTy *ParseObjCAtProtocolDeclaration();
   DeclTy *ParseObjCAtImplementationDeclaration();
   DeclTy *ParseObjCAtEndDeclaration();
   DeclTy *ParseObjCAtAliasDeclaration();
   
+  IdentifierInfo *ParseObjCSelector();
+  void ParseObjCTypeName();
+  void ParseObjCMethodRequirement();
+  void ParseObjCMethodPrototype();
+  void ParseObjCMethodDecl(tok::TokenKind mType, SourceLocation mLoc);
+  void ParseObjCPropertyDecl(SourceLocation atLoc);
+  
   void ParseObjCInstanceMethodDeclaration();
   void ParseObjCClassMethodDeclaration();
 





More information about the cfe-commits mailing list