[cfe-commits] r41732 - in /cfe/trunk: Parse/ParseDecl.cpp Parse/ParseObjc.cpp clang.xcodeproj/project.pbxproj include/clang/Parse/Action.h include/clang/Parse/DeclSpec.h include/clang/Parse/Parser.h

Steve Naroff snaroff at apple.com
Wed Sep 5 16:30:33 PDT 2007


Author: snaroff
Date: Wed Sep  5 18:30:30 2007
New Revision: 41732

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

Start implementing Actions interface for ObjC classes, instance variables, and methods.

Lot's of small changes to the parser.


Modified:
    cfe/trunk/Parse/ParseDecl.cpp
    cfe/trunk/Parse/ParseObjc.cpp
    cfe/trunk/clang.xcodeproj/project.pbxproj
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/include/clang/Parse/DeclSpec.h
    cfe/trunk/include/clang/Parse/Parser.h

Modified: cfe/trunk/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Parse/ParseDecl.cpp?rev=41732&r1=41731&r2=41732&view=diff

==============================================================================
--- cfe/trunk/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/Parse/ParseDecl.cpp Wed Sep  5 18:30:30 2007
@@ -406,8 +406,10 @@
           else { // FIXME: restrict this to "id" and ObjC classnames.
             DS.Range.setEnd(Tok.getLocation());
             ConsumeToken(); // The identifier
-            if (Tok.getKind() == tok::less)
-              ParseObjCProtocolReferences();
+            if (Tok.getKind() == tok::less) {
+              llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
+              ParseObjCProtocolReferences(ProtocolRefs);
+            }
             continue;
           }
         }

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

==============================================================================
--- cfe/trunk/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/Parse/ParseObjc.cpp Wed Sep  5 18:30:30 2007
@@ -147,13 +147,15 @@
     rparenLoc = ConsumeParen();
     // Next, we need to check for any protocol references.
     if (Tok.getKind() == tok::less) {
-      if (ParseObjCProtocolReferences())
+      llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
+      if (ParseObjCProtocolReferences(ProtocolRefs))
         return 0;
     }
     if (attrList) // categories don't support attributes.
       Diag(Tok, diag::err_objc_no_attributes_on_category);
     
-    ParseObjCInterfaceDeclList(0/*FIXME*/);
+    llvm::SmallVector<DeclTy*, 64> MethodDecls;
+    ParseObjCInterfaceDeclList(0/*FIXME*/, MethodDecls);
 
     // The @ sign was already consumed by ParseObjCInterfaceDeclList().
     if (Tok.isObjCAtKeyword(tok::objc_end)) {
@@ -182,15 +184,21 @@
     superClassLoc = ConsumeToken();
   }
   // Next, we need to check for any protocol references.
+  llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
   if (Tok.getKind() == tok::less) {
-    if (ParseObjCProtocolReferences())
+    if (ParseObjCProtocolReferences(ProtocolRefs))
       return 0;
   }
-  // FIXME: add Actions.StartObjCClassInterface(nameId, superClassId, ...)
+  DeclTy *ClsType = Actions.ObjcStartClassInterface(atLoc, nameId, nameLoc, 
+                      superClassId, superClassLoc, &ProtocolRefs[0], 
+                      ProtocolRefs.size(), attrList);
+            
+  llvm::SmallVector<DeclTy*, 32> IvarDecls;
   if (Tok.getKind() == tok::l_brace)
-    ParseObjCClassInstanceVariables(0/*FIXME*/);
+    ParseObjCClassInstanceVariables(ClsType, IvarDecls);
 
-  ParseObjCInterfaceDeclList(0/*FIXME*/);
+  llvm::SmallVector<DeclTy*, 64> MethodDecls;
+  ParseObjCInterfaceDeclList(ClsType, MethodDecls);
 
   // The @ sign was already consumed by ParseObjCInterfaceDeclList().
   if (Tok.isObjCAtKeyword(tok::objc_end)) {
@@ -213,7 +221,9 @@
 ///     @required
 ///     @optional
 ///
-void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl) {
+void Parser::ParseObjCInterfaceDeclList(
+  DeclTy *interfaceDecl, llvm::SmallVectorImpl<DeclTy*> &MethodDecls) {
+  DeclTy *IDecl = 0;
   while (1) {
     if (Tok.getKind() == tok::at) {
       SourceLocation AtLoc = ConsumeToken(); // the "@"
@@ -236,17 +246,20 @@
       }
     }
     if (Tok.getKind() == tok::minus || Tok.getKind() == tok::plus) {
-      ParseObjCMethodPrototype(true);
+      IDecl = ParseObjCMethodPrototype(true);
+      MethodDecls.push_back(IDecl);
       continue;
     }
     if (Tok.getKind() == tok::semi)
       ConsumeToken();
     else if (Tok.getKind() == tok::eof)
       return;
-    else 
+    else {
       // FIXME: as the name implies, this rule allows function definitions.
       // We could pass a flag or check for functions during semantic analysis.
-      ParseDeclarationOrFunctionDefinition();
+      IDecl = ParseDeclarationOrFunctionDefinition();
+      MethodDecls.push_back(IDecl);
+    }
   }
 }
 
@@ -353,7 +366,7 @@
 ///   objc-method-attributes:         [OBJC2]
 ///     __attribute__((deprecated))
 ///
-void Parser::ParseObjCMethodPrototype(bool decl) {
+Parser::DeclTy *Parser::ParseObjCMethodPrototype(bool decl) {
   assert((Tok.getKind() == tok::minus || Tok.getKind() == tok::plus) && 
          "expected +/-");
 
@@ -361,15 +374,12 @@
   SourceLocation methodLoc = ConsumeToken();
   
   // FIXME: deal with "context sensitive" protocol qualifiers in prototypes
-  ParseObjCMethodDecl(methodType, methodLoc);
+  DeclTy *MDecl = ParseObjCMethodDecl(methodType, methodLoc);
   
-  // If attributes exist after the method, parse them.
-  if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute)
-    ParseAttributes();
-    
   if (decl)
     // Consume the ';'.
     ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "method proto");
+  return MDecl;
 }
 
 ///   objc-selector:
@@ -425,24 +435,26 @@
 ///     objc-type-qualifier
 ///     objc-type-qualifiers objc-type-qualifier
 ///
-void Parser::ParseObjCTypeName() {
+Parser::TypeTy *Parser::ParseObjCTypeName() {
   assert(Tok.getKind() == tok::l_paren && "expected (");
   
   SourceLocation LParenLoc = ConsumeParen(), RParenLoc;
+  TypeTy *Ty;
   
   while (isObjCTypeQualifier())
     ConsumeToken();
 
   if (isTypeSpecifierQualifier()) {
-    //TypeTy *Ty = ParseTypeName();
-    //assert(Ty && "Parser::ParseObjCTypeName(): missing type");
-    ParseTypeName(); // FIXME: when sema support is added.
+    Ty = ParseTypeName();
+    // FIXME: back when Sema support is in place...
+    // assert(Ty && "Parser::ParseObjCTypeName(): missing type");
   }
   if (Tok.getKind() != tok::r_paren) {
     MatchRHSPunctuation(tok::r_paren, LParenLoc);
-    return;
+    return 0; // FIXME: decide how we want to handle this error...
   }
   RParenLoc = ConsumeParen();
+  return Ty;
 }
 
 ///   objc-method-decl:
@@ -473,40 +485,52 @@
 ///   objc-keyword-attributes:         [OBJC2]
 ///     __attribute__((unused))
 ///
-void Parser::ParseObjCMethodDecl(tok::TokenKind mType, SourceLocation mLoc) {
+Parser::DeclTy *Parser::ParseObjCMethodDecl(tok::TokenKind mType, SourceLocation mLoc) {
 
+  TypeTy *ReturnType = 0;
+  
   // Parse the return type.
   if (Tok.getKind() == tok::l_paren)
-    ParseObjCTypeName();
+    ReturnType = ParseObjCTypeName();
   IdentifierInfo *selIdent = ParseObjCSelector();
+
+  llvm::SmallVector<ObjcKeywordInfo, 12> KeyInfo;
+  int KeySlot = 0;
   
   if (Tok.getKind() == tok::colon) {
-    IdentifierInfo *keywordSelector = selIdent;
+    
     while (1) {
+      KeyInfo[KeySlot].SelectorName = selIdent;
+      
       // Each iteration parses a single keyword argument.
       if (Tok.getKind() != tok::colon) {
         Diag(Tok, diag::err_expected_colon);
         break;
       }
-      ConsumeToken(); // Eat the ':'.
+      KeyInfo[KeySlot].ColonLoc = ConsumeToken(); // Eat the ':'.
       if (Tok.getKind() == tok::l_paren) // Parse the argument type.
-        ParseObjCTypeName();
+        KeyInfo[KeySlot].TypeInfo = ParseObjCTypeName();
 
       // If attributes exist before the argument name, parse them.
       if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute)
-        ParseAttributes();
+        KeyInfo[KeySlot].AttrList = ParseAttributes();
 
       if (Tok.getKind() != tok::identifier) {
         Diag(Tok, diag::err_expected_ident); // missing argument name.
         break;
       }
+      KeyInfo[KeySlot].ArgumentName = Tok.getIdentifierInfo();
       ConsumeToken(); // Eat the identifier.
+      
+      // Rather than call out to the actions, try packaging up the info
+      // locally, like we do for Declarator.
       // FIXME: add Actions.BuildObjCKeyword()
       
-      keywordSelector = ParseObjCSelector();
-      if (!keywordSelector && Tok.getKind() != tok::colon)
+      selIdent = ParseObjCSelector();
+      if (!selIdent && Tok.getKind() != tok::colon)
         break;
       // We have a selector or a colon, continue parsing.
+      KeySlot++;
     }
     // Parse the (optional) parameter list.
     while (Tok.getKind() == tok::comma) {
@@ -522,20 +546,34 @@
       Declarator ParmDecl(DS, Declarator::PrototypeContext);
       ParseDeclarator(ParmDecl);
     }
+    AttributeList *methodAttrs = 0;
+    // If attributes exist after the method, parse them.
+    if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute)
+      methodAttrs = ParseAttributes();
+
+    // FIXME: Add support for optional parmameter list...
+    return Actions.ObjcBuildMethodDeclaration(mLoc, mType, ReturnType, 
+                                              &KeyInfo[0], KeyInfo.size(),
+                                              methodAttrs);
   } else if (!selIdent) {
     Diag(Tok, diag::err_expected_ident); // missing selector name.
   }
-  // FIXME: add Actions.BuildMethodSignature().
+  AttributeList *methodAttrs = 0;
+  // If attributes exist after the method, parse them.
+  if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute)
+    methodAttrs = ParseAttributes();
+  return Actions.ObjcBuildMethodDeclaration(mLoc, mType, ReturnType, selIdent,
+                                            methodAttrs);
 }
 
 ///   objc-protocol-refs:
 ///     '<' identifier-list '>'
 ///
-bool Parser::ParseObjCProtocolReferences() {
+bool Parser::ParseObjCProtocolReferences(
+  llvm::SmallVectorImpl<IdentifierInfo*> &ProtocolRefs) {
   assert(Tok.getKind() == tok::less && "expected <");
   
   ConsumeToken(); // the "<"
-  llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
   
   while (1) {
     if (Tok.getKind() != tok::identifier) {
@@ -574,11 +612,11 @@
 ///   objc-instance-variable-decl:
 ///     struct-declaration 
 ///
-void Parser::ParseObjCClassInstanceVariables(DeclTy *interfaceDecl) {
+void Parser::ParseObjCClassInstanceVariables(DeclTy *interfaceDecl,
+                              llvm::SmallVectorImpl<DeclTy*> &IvarDecls) {
   assert(Tok.getKind() == tok::l_brace && "expected {");
   
   SourceLocation LBraceLoc = ConsumeBrace(); // the "{"
-  llvm::SmallVector<DeclTy*, 32> IvarDecls;
   
   // While we still have something to read, read the instance variables.
   while (Tok.getKind() != tok::r_brace && 
@@ -685,10 +723,12 @@
   }
   // Last, and definitely not least, parse a protocol declaration.
   if (Tok.getKind() == tok::less) {
-    if (ParseObjCProtocolReferences())
+    llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
+    if (ParseObjCProtocolReferences(ProtocolRefs))
       return 0;
   }
-  ParseObjCInterfaceDeclList(0/*FIXME*/);
+  llvm::SmallVector<DeclTy*, 64> MethodDecls;
+  ParseObjCInterfaceDeclList(0/*FIXME*/, MethodDecls);
 
   // The @ sign was already consumed by ParseObjCInterfaceDeclList().
   if (Tok.isObjCAtKeyword(tok::objc_end)) {
@@ -754,8 +794,9 @@
     }
     ConsumeToken(); // Consume super class name
   }
+  llvm::SmallVector<DeclTy*, 32> IvarDecls;
   if (Tok.getKind() == tok::l_brace)
-    ParseObjCClassInstanceVariables(0/*FIXME*/); // we have ivars
+    ParseObjCClassInstanceVariables(0/*FIXME*/, IvarDecls); // we have ivars
   
   return 0;
 }

Modified: cfe/trunk/clang.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/clang.xcodeproj/project.pbxproj?rev=41732&r1=41731&r2=41732&view=diff

==============================================================================
--- cfe/trunk/clang.xcodeproj/project.pbxproj (original)
+++ cfe/trunk/clang.xcodeproj/project.pbxproj Wed Sep  5 18:30:30 2007
@@ -211,7 +211,7 @@
 		3547129D0C88881300B3E1D5 /* PrettyPrinter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PrettyPrinter.h; path = clang/AST/PrettyPrinter.h; sourceTree = "<group>"; };
 		84D9A8870C1A57E100AC7ABC /* AttributeList.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = AttributeList.cpp; path = Parse/AttributeList.cpp; sourceTree = "<group>"; };
 		84D9A88B0C1A581300AC7ABC /* AttributeList.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = AttributeList.h; path = clang/Parse/AttributeList.h; sourceTree = "<group>"; };
-		8DD76F6C0486A84900D96B5E /* clang */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "compiled.mach-o.executable"; path = clang; sourceTree = BUILT_PRODUCTS_DIR; };
+		8DD76F6C0486A84900D96B5E /* clang */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = clang; sourceTree = BUILT_PRODUCTS_DIR; };
 		DE01DA480B12ADA300AC22CE /* PPCallbacks.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PPCallbacks.h; sourceTree = "<group>"; };
 		DE06756B0C051CFE00EBBFD8 /* ParseExprCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ParseExprCXX.cpp; path = Parse/ParseExprCXX.cpp; sourceTree = "<group>"; };
 		DE06B73D0A8307640050E87E /* LangOptions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = LangOptions.h; sourceTree = "<group>"; };

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

==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Wed Sep  5 18:30:30 2007
@@ -21,6 +21,7 @@
   // Semantic.
   class DeclSpec;
   class Declarator;
+  class ObjcKeywordInfo;
   class AttributeList;
   // Parse.
   class Scope;
@@ -430,7 +431,35 @@
                                          tok::TokenKind Kind) {
     return 0;
   }
+  //===----------------------- Obj-C Declarations -------------------------===//
   
+  virtual DeclTy *ObjcStartClassInterface(SourceLocation AtInterafceLoc,
+                    IdentifierInfo *ClassName, SourceLocation ClassLoc,
+                    IdentifierInfo *SuperName, SourceLocation SuperLoc,
+                    IdentifierInfo **ProtocolNames, unsigned NumProtocols,
+                    AttributeList *AttrList) {
+    return 0;
+  }
+  virtual void ObjCContinueClassInterface(SourceLocation InterfaceLoc) {
+    return;
+  }
+  virtual void ObjCStartCategoryInterface() {
+    return;
+  }
+  virtual void ObjCFinishInterface() {
+    return;
+  }
+  virtual DeclTy *ObjcBuildMethodDeclaration(
+    SourceLocation MethodLoc, tok::TokenKind MethodType, TypeTy *ReturnType,
+    ObjcKeywordInfo *Keywords, unsigned NumKeywords, AttributeList *attrs) {
+    return 0;
+  }
+  virtual DeclTy *ObjcBuildMethodDeclaration(
+    SourceLocation MethodLoc, tok::TokenKind MethodType, TypeTy *ReturnType,
+    IdentifierInfo *SelectorName, AttributeList *attrs) {
+    return 0;
+  }
+    
   //===----------------------- Obj-C Expressions --------------------------===//
   virtual ExprResult ParseObjCStringLiteral(ExprTy *string) {
     return 0;

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

==============================================================================
--- cfe/trunk/include/clang/Parse/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Parse/DeclSpec.h Wed Sep  5 18:30:30 2007
@@ -562,7 +562,24 @@
   bool getInvalidType() { return InvalidType; }
 };
 
+struct ObjcKeywordInfo {
+  IdentifierInfo *SelectorName; // optional
+  SourceLocation SelectorLoc;
+  SourceLocation ColonLoc;
+  Action::TypeTy *TypeInfo; // optional
+  bool InvalidType;
+  IdentifierInfo *ArgumentName;
+  AttributeList *AttrList;
   
+  ObjcKeywordInfo() {}
+  ObjcKeywordInfo(IdentifierInfo *selName, SourceLocation sLoc, 
+                  SourceLocation cLoc, Action::TypeTy *tInfo,
+                  IdentifierInfo *argName, AttributeList *aList)
+    : SelectorName(selName), SelectorLoc(sLoc), ColonLoc(cLoc), TypeInfo(tInfo), 
+      ArgumentName(argName), AttrList(aList) {
+  }
+};
+
 }  // end namespace clang
 
 #endif

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

==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Wed Sep  5 18:30:30 2007
@@ -258,9 +258,11 @@
   DeclTy *ParseObjCAtClassDeclaration(SourceLocation atLoc);
   DeclTy *ParseObjCAtInterfaceDeclaration(SourceLocation atLoc, 
                                           AttributeList *prefixAttrs = 0);
-  void ParseObjCClassInstanceVariables(DeclTy *interfaceDecl);
-  bool ParseObjCProtocolReferences();
-  void ParseObjCInterfaceDeclList(DeclTy *interfaceDecl);
+  void ParseObjCClassInstanceVariables(DeclTy *interfaceDecl,
+                              llvm::SmallVectorImpl<DeclTy*> &IvarDecls);
+  bool ParseObjCProtocolReferences(llvm::SmallVectorImpl<IdentifierInfo*> &);
+  void ParseObjCInterfaceDeclList(DeclTy *interfaceDecl,
+                                  llvm::SmallVectorImpl<DeclTy*> &MethodDecls);
   DeclTy *ParseObjCAtProtocolDeclaration(SourceLocation atLoc);
   DeclTy *ParseObjCAtImplementationDeclaration(SourceLocation atLoc);
   DeclTy *ParseObjCAtEndDeclaration(SourceLocation atLoc);
@@ -284,10 +286,10 @@
   IdentifierInfo *ObjcPropertyAttrs[objc_NumAttrs];
   bool isObjCPropertyAttribute();
 
-  void ParseObjCTypeName();
+  TypeTy *ParseObjCTypeName();
   void ParseObjCMethodRequirement();
-  void ParseObjCMethodPrototype(bool decl);
-  void ParseObjCMethodDecl(tok::TokenKind mType, SourceLocation mLoc);
+  DeclTy *ParseObjCMethodPrototype(bool decl);
+  DeclTy *ParseObjCMethodDecl(tok::TokenKind mType, SourceLocation mLoc);
   void ParseObjCPropertyAttribute(DeclTy *interfaceDecl);
   void ParseObjCPropertyDecl(DeclTy *interfaceDecl);
   





More information about the cfe-commits mailing list