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

Steve Naroff snaroff at apple.com
Mon Aug 20 14:31:49 PDT 2007


Author: snaroff
Date: Mon Aug 20 16:31:48 2007
New Revision: 41200

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

Start parsing ObjC classes/categories!

Next step, refactor Parser::ParseStructUnionBody() so that struct declarations can
be shared with Objective-C (for declaring instance variables).

Modified:
    cfe/trunk/Parse/ParseObjc.cpp
    cfe/trunk/Parse/Parser.cpp
    cfe/trunk/include/clang/Basic/DiagnosticKinds.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=41200&r1=41199&r2=41200&view=diff

==============================================================================
--- cfe/trunk/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/Parse/ParseObjc.cpp Mon Aug 20 16:31:48 2007
@@ -25,7 +25,7 @@
 /// [OBJC]  objc-protocol-definition   [TODO]
 /// [OBJC]  objc-method-definition     [TODO]
 /// [OBJC]  '@' 'end'                  [TODO]
-void Parser::ParseObjCAtDirectives() {
+Parser::DeclTy *Parser::ParseObjCAtDirectives() {
   SourceLocation AtLoc = ConsumeToken(); // the "@"
   
   IdentifierInfo *II = Tok.getIdentifierInfo();
@@ -33,7 +33,7 @@
     case tok::objc_class:
       return ParseObjCAtClassDeclaration(AtLoc);
     case tok::objc_interface:
-      return ParseObjCAtInterfaceDeclaration();
+      return ParseObjCAtInterfaceDeclaration(AtLoc);
     case tok::objc_protocol:
       return ParseObjCAtProtocolDeclaration();
     case tok::objc_implementation:
@@ -45,6 +45,7 @@
     default:
       Diag(AtLoc, diag::err_unexpected_at);
       SkipUntil(tok::semi);
+      return 0;
   }
 }
 
@@ -52,7 +53,7 @@
 /// objc-class-declaration: 
 ///    '@' 'class' identifier-list ';'
 ///  
-void Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
+Parser::DeclTy *Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
   ConsumeToken(); // the identifier "class"
   llvm::SmallVector<IdentifierInfo *, 8> ClassNames;
   
@@ -60,7 +61,7 @@
     if (Tok.getKind() != tok::identifier) {
       Diag(Tok, diag::err_expected_ident);
       SkipUntil(tok::semi);
-      return;
+      return 0;
     }
     
     ClassNames.push_back(Tok.getIdentifierInfo());
@@ -74,26 +75,232 @@
   
   // Consume the ';'.
   if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@class"))
-    return;
+    return 0;
   
-  Actions.ParsedObjcClassDeclaration(CurScope,
-                                     &ClassNames[0], ClassNames.size());
+  return Actions.ParsedObjcClassDeclaration(CurScope,
+                                            &ClassNames[0], ClassNames.size());
 }
 
-void Parser::ParseObjCAtInterfaceDeclaration() {
+///
+///   objc-interface:
+///     objc-class-interface-attributes[opt] objc-class-interface
+///     objc-category-interface
+///
+///   objc-class-interface:
+///     '@' 'interface' identifier objc-superclass[opt] 
+///       objc-protocol-refs[opt]
+///       objc-class-instance-variables[opt] 
+///       objc-interface-decl-list
+///     @end
+///
+///   objc-category-interface:
+///     '@' 'interface' identifier '(' identifier[opt] ')' 
+///       objc-protocol-refs[opt]
+///       objc-interface-decl-list
+///     @end
+///
+///   objc-superclass:
+///     ':' identifier
+///
+///   objc-class-interface-attributes:
+///     __attribute__((visibility("default")))
+///     __attribute__((visibility("hidden")))
+///     __attribute__((deprecated))
+///     __attribute__((unavailable))
+///     __attribute__((objc_exception)) - used by NSException on 64-bit
+///
+Parser::DeclTy *Parser::ParseObjCAtInterfaceDeclaration(
+  SourceLocation atLoc, AttributeList *attrList) {
+  assert(Tok.getIdentifierInfo()->getObjCKeywordID() == tok::objc_interface &&
+         "ParseObjCAtInterfaceDeclaration(): Expected @interface");
+  ConsumeToken(); // the "interface" identifier
+  
+  if (Tok.getKind() != tok::identifier) {
+    Diag(Tok, diag::err_expected_ident); // missing class or category name.
+    return 0;
+  }
+  // We have a class or category name - consume it.
+  IdentifierInfo *nameId = Tok.getIdentifierInfo();
+  SourceLocation nameLoc = ConsumeToken();
+  
+  if (Tok.getKind() == tok::l_paren) { // we have a category
+    SourceLocation lparenLoc = ConsumeParen();
+    SourceLocation categoryLoc, rparenLoc;
+    IdentifierInfo *categoryId = 0;
+    
+    // OBJC2: The cateogry name is optional (not an error).
+    if (Tok.getKind() == tok::identifier) {
+      categoryId = Tok.getIdentifierInfo();
+      categoryLoc = ConsumeToken();
+    }
+    if (Tok.getKind() != tok::r_paren) {
+      Diag(Tok, diag::err_expected_rparen);
+      SkipUntil(tok::r_paren, false); // don't stop at ';'
+      return 0;
+    }
+    rparenLoc = ConsumeParen();
+    // Next, we need to check for any protocol references.
+    if (Tok.getKind() == tok::less) {
+      if (ParseObjCProtocolReferences())
+        return 0;
+    }
+    if (attrList) // categories don't support attributes.
+      Diag(Tok, diag::err_objc_no_attributes_on_category);
+    
+    //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);
+      return 0;
+    }
+    ConsumeToken(); // the "end" identifier
+    return 0;
+  }
+  // Parse a class interface.
+  IdentifierInfo *superClassId = 0;
+  SourceLocation superClassLoc;
+  
+  if (Tok.getKind() == tok::colon) { // a super class is specified.
+    ConsumeToken();
+    if (Tok.getKind() != tok::identifier) {
+      Diag(Tok, diag::err_expected_ident); // missing super class name.
+      return 0;
+    }
+    superClassId = Tok.getIdentifierInfo();
+    superClassLoc = ConsumeToken();
+  }
+  // Next, we need to check for any protocol references.
+  if (Tok.getKind() == tok::less) {
+    if (ParseObjCProtocolReferences())
+      return 0;
+  }
+  if (Tok.getKind() == tok::l_brace)
+    ParseObjCClassInstanceVariables();
+
+  //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);
+    return 0;
+  }
+  ConsumeToken(); // the "end" identifier
+  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 declaration
+///     objc-interface-decl-list ';'
+///
+void Parser::ParseObjCInterfaceDeclList() {
   assert(0 && "Unimp");
 }
-void Parser::ParseObjCAtProtocolDeclaration() {
+
+///   objc-protocol-refs:
+///     '<' identifier-list '>'
+///
+bool Parser::ParseObjCProtocolReferences() {
+  assert(Tok.getKind() == tok::less && "expected <");
+  
+  ConsumeToken(); // the "<"
+  llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
+  
+  while (1) {
+    if (Tok.getKind() != tok::identifier) {
+      Diag(Tok, diag::err_expected_ident);
+      SkipUntil(tok::greater);
+      return true;
+    }
+    ProtocolRefs.push_back(Tok.getIdentifierInfo());
+    ConsumeToken();
+    
+    if (Tok.getKind() != tok::comma)
+      break;
+    ConsumeToken();
+  }
+  // Consume the '>'.
+  return ExpectAndConsume(tok::greater, diag::err_expected_greater);
+}
+
+///   objc-class-instance-variables:
+///     '{' objc-instance-variable-decl-list[opt] '}'
+///
+///   objc-instance-variable-decl-list:
+///     objc-visibility-spec
+///     objc-instance-variable-decl ';'
+///     ';'
+///     objc-instance-variable-decl-list objc-visibility-spec
+///     objc-instance-variable-decl-list objc-instance-variable-decl ';'
+///     objc-instance-variable-decl-list ';'
+///
+///   objc-visibility-spec:
+///     @private
+///     @protected
+///     @public
+///
+///   objc-instance-variable-decl:
+///     struct-declaration 
+///
+void Parser::ParseObjCClassInstanceVariables() {
   assert(0 && "Unimp");
 }
-void Parser::ParseObjCAtImplementationDeclaration() {
+
+///   objc-protocol-declaration:
+///     objc-protocol-definition
+///     objc-protocol-forward-reference
+///
+///   objc-protocol-definition:
+///     @protocol identifier 
+///       objc-protocol-refs[opt] 
+///       objc-methodprotolist 
+///     @end
+///
+///   objc-protocol-forward-reference:
+///     @protocol identifier-list ';'
+///
+///   "@protocol identifier ;" should be resolved as "@protocol
+///   identifier-list ;": objc-methodprotolist may not start with a
+///   semicolon in the first alternative if objc-protocol-refs are omitted.
+
+Parser::DeclTy *Parser::ParseObjCAtProtocolDeclaration() {
+  assert(0 && "Unimp");
+  return 0;
+}
+
+///   objc-implementation:
+///     objc-class-implementation-prologue
+///     objc-category-implementation-prologue
+///
+///   objc-class-implementation-prologue:
+///     @implementation identifier objc-superclass[opt]
+///       objc-class-instance-variables[opt]
+///
+///   objc-category-implementation-prologue:
+///     @implementation identifier ( identifier )
+
+Parser::DeclTy *Parser::ParseObjCAtImplementationDeclaration() {
   assert(0 && "Unimp");
+  return 0;
 }
-void Parser::ParseObjCAtEndDeclaration() {
+Parser::DeclTy *Parser::ParseObjCAtEndDeclaration() {
   assert(0 && "Unimp");
+  return 0;
 }
-void Parser::ParseObjCAtAliasDeclaration() {
+Parser::DeclTy *Parser::ParseObjCAtAliasDeclaration() {
   assert(0 && "Unimp");
+  return 0;
 }
 
 void Parser::ParseObjCInstanceMethodDeclaration() {

Modified: cfe/trunk/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Parse/Parser.cpp?rev=41200&r1=41199&r2=41200&view=diff

==============================================================================
--- cfe/trunk/Parse/Parser.cpp (original)
+++ cfe/trunk/Parse/Parser.cpp Mon Aug 20 16:31:48 2007
@@ -370,6 +370,13 @@
     return Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
   }
   
+  // OBJC: This grammar hack allows prefix attributes on class interfaces.
+  if (Tok.getKind() == tok::at) {
+    SourceLocation AtLoc = ConsumeToken(); // the "@"
+    if (Tok.getIdentifierInfo()->getObjCKeywordID() == tok::objc_interface)
+      return ParseObjCAtInterfaceDeclaration(AtLoc, DS.getAttributes()); 
+  }
+  
   // Parse the first declarator.
   Declarator DeclaratorInfo(DS, Declarator::FileContext);
   ParseDeclarator(DeclaratorInfo);

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

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Mon Aug 20 16:31:48 2007
@@ -377,6 +377,12 @@
 DIAG(err_matching, ERROR,
      "to match this '%0'")
 
+/// Objective-C parser diagnostics
+DIAG(err_objc_no_attributes_on_category, ERROR,
+     "attributes may not be specified on a category")
+DIAG(err_objc_missing_end, ERROR,
+     "missing @end")
+
 //===----------------------------------------------------------------------===//
 // Semantic Analysis
 //===----------------------------------------------------------------------===//

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

==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Mon Aug 20 16:31:48 2007
@@ -254,13 +254,17 @@
   void ParseAsmStringLiteral();
 
   // Objective-C External Declarations 
-  void ParseObjCAtDirectives(); 
-  void ParseObjCAtClassDeclaration(SourceLocation atLoc);
-  void ParseObjCAtInterfaceDeclaration();
-  void ParseObjCAtProtocolDeclaration();
-  void ParseObjCAtImplementationDeclaration();
-  void ParseObjCAtEndDeclaration();
-  void ParseObjCAtAliasDeclaration();
+  DeclTy *ParseObjCAtDirectives(); 
+  DeclTy *ParseObjCAtClassDeclaration(SourceLocation atLoc);
+  DeclTy *ParseObjCAtInterfaceDeclaration(SourceLocation atLoc, 
+                                          AttributeList *prefixAttrs = 0);
+  void ParseObjCClassInstanceVariables();
+  bool ParseObjCProtocolReferences();
+  void ParseObjCInterfaceDeclList();
+  DeclTy *ParseObjCAtProtocolDeclaration();
+  DeclTy *ParseObjCAtImplementationDeclaration();
+  DeclTy *ParseObjCAtEndDeclaration();
+  DeclTy *ParseObjCAtAliasDeclaration();
   
   void ParseObjCInstanceMethodDeclaration();
   void ParseObjCClassMethodDeclaration();





More information about the cfe-commits mailing list