]> granicus.if.org Git - clang/commitdiff
Early patch to collect objective-c methods inserts them in
authorFariborz Jahanian <fjahanian@apple.com>
Mon, 10 Sep 2007 20:33:04 +0000 (20:33 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Mon, 10 Sep 2007 20:33:04 +0000 (20:33 +0000)
class object.

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

AST/Decl.cpp
Parse/ParseObjc.cpp
Sema/Sema.h
Sema/SemaDecl.cpp
include/clang/AST/Decl.h
include/clang/Parse/Action.h
include/clang/Parse/Parser.h

index 5f87d93cbba61408a9133661290c991c68feaabc..0e6c218f2d5fef71491c544b4dcde818baf84ae7 100644 (file)
@@ -163,3 +163,23 @@ FieldDecl* RecordDecl::getMember(IdentifierInfo *name) {
   }
   return 0;
 }
+
+/// addObjcMethods - Insert instance and methods declarations into
+/// ObjcInterfaceDecl's InsMethods and ClsMethods fields.
+///
+void ObjcInterfaceDecl::ObjcAddMethods(ObjcMethodDecl **insMethods, 
+                                      unsigned numInsMembers,
+                                       ObjcMethodDecl **clsMethods,
+                                       unsigned numClsMembers) {
+  NumInsMethods = numInsMembers;
+  if (numInsMembers) {
+    InsMethods = new ObjcMethodDecl*[numInsMembers];
+    memcpy(InsMethods, insMethods, numInsMembers*sizeof(ObjcMethodDecl*));
+  }
+  NumClsMethods = numClsMembers;
+  if (numClsMembers) {
+    ClsMethods = new ObjcMethodDecl*[numClsMembers];
+    memcpy(ClsMethods, clsMethods, numClsMembers*sizeof(ObjcMethodDecl*));
+  }
+}
+
index 6557c4165289b1fa4afd5e071b48bfafed20339e..19594d89911a35dd8e21f717e5c84c21ec8de974 100644 (file)
@@ -214,13 +214,14 @@ Parser::DeclTy *Parser::ParseObjCAtInterfaceDeclaration(
 ///     @optional
 ///
 void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl) {
+  llvm::SmallVector<DeclTy*, 32>  allMethods;
   while (1) {
     if (Tok.getKind() == tok::at) {
       SourceLocation AtLoc = ConsumeToken(); // the "@"
       tok::ObjCKeywordKind ocKind = Tok.getObjCKeywordID();
       
       if (ocKind == tok::objc_end) { // terminate list
-        return;
+        break;
       } else if (ocKind == tok::objc_required) { // protocols only
         ConsumeToken();
         continue;
@@ -236,7 +237,7 @@ void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl) {
       }
     }
     if (Tok.getKind() == tok::minus || Tok.getKind() == tok::plus) {
-      ParseObjCMethodPrototype(interfaceDecl);
+      allMethods.push_back(ParseObjCMethodPrototype(interfaceDecl));
       // Consume the ';' here, since ParseObjCMethodPrototype() is re-used for
       // method definitions.
       ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "method proto");
@@ -245,13 +246,17 @@ void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl) {
     if (Tok.getKind() == tok::semi)
       ConsumeToken();
     else if (Tok.getKind() == tok::eof)
-      return;
+      break;
     else {
       // FIXME: as the name implies, this rule allows function definitions.
       // We could pass a flag or check for functions during semantic analysis.
       ParseDeclarationOrFunctionDefinition();
     }
   }
+  
+  /// Insert collected methods declarations into the @interface object.
+  Actions.ObjcAddMethodsToClass(interfaceDecl, &allMethods[0], allMethods.size());
+  return;
 }
 
 ///   Parse property attribute declarations.
@@ -364,15 +369,6 @@ Parser::DeclTy *Parser::ParseObjCMethodPrototype(DeclTy *CDecl) {
   SourceLocation methodLoc = ConsumeToken();
   
   DeclTy *MDecl = ParseObjCMethodDecl(methodType, methodLoc);
-
-  AttributeList *methodAttrs = 0;
-  // If attributes exist after the method, parse them.
-  if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute)
-    methodAttrs = ParseAttributes();
-
-  if (CDecl)
-    Actions.ObjcAddMethod(CDecl, MDecl, methodAttrs);
-  
   // Since this rule is used for both method declarations and definitions,
   // the caller is responsible for consuming the ';'.
   return MDecl;
@@ -484,6 +480,7 @@ Parser::TypeTy *Parser::ParseObjCTypeName() {
 Parser::DeclTy *Parser::ParseObjCMethodDecl(tok::TokenKind mType, SourceLocation mLoc) {
 
   TypeTy *ReturnType = 0;
+  AttributeList *methodAttrs = 0;
   
   // Parse the return type.
   if (Tok.getKind() == tok::l_paren)
@@ -491,42 +488,42 @@ Parser::DeclTy *Parser::ParseObjCMethodDecl(tok::TokenKind mType, SourceLocation
   IdentifierInfo *selIdent = ParseObjCSelector();
 
   llvm::SmallVector<ObjcKeywordInfo, 12> KeyInfo;
-  int KeySlot = 0;
   
   if (Tok.getKind() == tok::colon) {
     
     while (1) {
-      KeyInfo[KeySlot].SelectorName = selIdent;
+      ObjcKeywordInfo KeyInfoDecl;
+      KeyInfoDecl.SelectorName = selIdent;
       
       // Each iteration parses a single keyword argument.
       if (Tok.getKind() != tok::colon) {
         Diag(Tok, diag::err_expected_colon);
         break;
       }
-      KeyInfo[KeySlot].ColonLoc = ConsumeToken(); // Eat the ':'.
+      KeyInfoDecl.ColonLoc = ConsumeToken(); // Eat the ':'.
       if (Tok.getKind() == tok::l_paren) // Parse the argument type.
-        KeyInfo[KeySlot].TypeInfo = ParseObjCTypeName();
+        KeyInfoDecl.TypeInfo = ParseObjCTypeName();
 
       // If attributes exist before the argument name, parse them.
       if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute)
-        KeyInfo[KeySlot].AttrList = ParseAttributes();
+        KeyInfoDecl.AttrList = ParseAttributes();
 
       if (Tok.getKind() != tok::identifier) {
         Diag(Tok, diag::err_expected_ident); // missing argument name.
         break;
       }
-      KeyInfo[KeySlot].ArgumentName = Tok.getIdentifierInfo();
+      KeyInfoDecl.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()
       
+      KeyInfo.push_back(KeyInfoDecl);
       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) {
@@ -543,12 +540,21 @@ Parser::DeclTy *Parser::ParseObjCMethodDecl(tok::TokenKind mType, SourceLocation
       ParseDeclarator(ParmDecl);
     }
     // FIXME: Add support for optional parmameter list...
+    // If attributes exist after the method, parse them.
+    if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute) 
+      methodAttrs = ParseAttributes();
     return Actions.ObjcBuildMethodDeclaration(mLoc, mType, ReturnType, 
-                                              &KeyInfo[0], KeyInfo.size());
+                                              &KeyInfo[0], KeyInfo.size(), 
+                                             methodAttrs);
   } else if (!selIdent) {
     Diag(Tok, diag::err_expected_ident); // missing selector name.
   }
-  return Actions.ObjcBuildMethodDeclaration(mLoc, mType, ReturnType, selIdent);
+  // 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:
index cabaae92c082613ab0e119daa6b441da03fe0569..f0a072eb9b8747083f71b2087637d08036d33085 100644 (file)
@@ -156,6 +156,8 @@ private:
                              Declarator &D, ExprTy *BitfieldWidth);
   virtual void ParseRecordBody(SourceLocation RecLoc, DeclTy *TagDecl,
                                DeclTy **Fields, unsigned NumFields);
+  virtual void ObjcAddMethodsToClass(DeclTy *ClassDecl, 
+                                    DeclTy **allMethods, unsigned allNum); 
   virtual DeclTy *ParseEnumConstant(Scope *S, DeclTy *EnumDecl,
                                     DeclTy *LastEnumConstant,
                                     SourceLocation IdLoc, IdentifierInfo *Id,
index 50cde4e410dc71ee44154994feedd6322f1a9ab0..3315f38b0fa0e039c5513ab7807476610be64642 100644 (file)
@@ -1140,6 +1140,30 @@ void Sema::ParseRecordBody(SourceLocation RecLoc, DeclTy *RecDecl,
   Record->defineBody(&RecFields[0], RecFields.size());
 }
 
+void Sema::ObjcAddMethodsToClass(DeclTy *ClassDecl, 
+                                DeclTy **allMethods, unsigned allNum) { 
+  // FIXME: Add method insertion code here.
+#if 0
+  ObjcInterfaceDecl *Interface = cast<ObjcInterfaceDecl>(
+                                  static_cast<Decl*>(ClassDecl));
+  llvm::SmallVector<ObjcMethodDecl*, 32> insMethods;
+  llvm::SmallVector<ObjcMethodDecl*, 16> clsMethods;
+
+  for (unsigned i = 0; i < allNum; i++ ) {
+    ObjcMethodDecl *Method = 
+      cast_or_null<ObjcMethodDecl>(static_cast<Decl*>(allMethods[i]));
+    if (!Method) continue;  // Already issued a diagnostic.
+    if (Method->isInstance())
+      insMethods.push_back(Method);
+    else
+      clsMethods.push_back(Method);
+  }
+  Interface->ObjcAddMethods(&insMethods[0], insMethods.size(), 
+                           &clsMethods[0], clsMethods.size());
+#endif
+  return;
+}
+
 Sema::DeclTy *Sema::ParseEnumConstant(Scope *S, DeclTy *theEnumDecl,
                                       DeclTy *lastEnumConst,
                                       SourceLocation IdLoc, IdentifierInfo *Id,
index c588aba643a5ab632cd466a1765d9fa44af069ad..838bad4b5f81f6c61b5823e3574c16f1d46048c8 100644 (file)
@@ -23,6 +23,8 @@ class IdentifierInfo;
 class Expr;
 class Stmt;
 class FunctionDecl;
+class ObjcMethodDecl;
+class AttributeList;
 
 
 /// Decl - This represents one declaration (or definition), e.g. a variable, 
@@ -34,7 +36,7 @@ public:
     // Concrete sub-classes of ValueDecl
     Function, BlockVariable, FileVariable, ParmVariable, EnumConstant,
     // Concrete sub-classes of TypeDecl
-    Typedef, Struct, Union, Class, Enum, ObjcInterface, ObjcClass,
+    Typedef, Struct, Union, Class, Enum, ObjcInterface, ObjcClass, ObjcMethod,
     // Concrete sub-class of Decl
     Field
   };
@@ -508,13 +510,25 @@ class ObjcInterfaceDecl : public TypeDecl {
   FieldDecl **Ivars;   // Null if not defined.
   int NumIvars;   // -1 if not defined.
   
+  /// instance methods
+  ObjcMethodDecl **InsMethods;  // Null if not defined
+  int NumInsMethods;  // -1 if not defined
+  
+  /// class methods
+  ObjcMethodDecl **ClsMethods;  // Null if not defined
+  int NumClsMethods;  // -1 if not defined
+  
   bool isForwardDecl; // declared with @class.
 public:
   ObjcInterfaceDecl(SourceLocation L, IdentifierInfo *Id, bool FD = false)
-    : TypeDecl(ObjcInterface, L, Id, 0), Ivars(0), NumIvars(-1), 
+    : TypeDecl(ObjcInterface, L, Id, 0), Ivars(0), NumIvars(-1),
+      InsMethods(0), NumInsMethods(-1), ClsMethods(0), NumClsMethods(-1),
       isForwardDecl(FD) { }
      
   void addInstanceVariable(FieldDecl ivar);
+
+  void ObjcAddMethods(ObjcMethodDecl **insMethods, unsigned numInsMembers,
+                      ObjcMethodDecl **clsMethods, unsigned numClsMembers);
   
   static bool classof(const Decl *D) {
     return D->getKind() == ObjcInterface;
@@ -544,6 +558,43 @@ public:
   static bool classof(const ObjcClassDecl *D) { return true; }
 };
 
-}  // end namespace clang
+/// ObjcMethodDecl - An instance of this class is created to represent an instance
+/// or class method declaration.
+class ObjcMethodDecl : public ValueDecl {
+public:
+  ObjcMethodDecl(SourceLocation L, IdentifierInfo *Id, QualType T,
+                bool isInstance = true, Decl *PrevDecl = 0)
+    : ValueDecl(ObjcMethod, L, Id, T, PrevDecl), ParamInfo(0), 
+      MethodAttrs(0), IsInstance(isInstance) {}
+
+  virtual ~ObjcMethodDecl();
+  unsigned getNumParams() const;
+  ParmVarDecl *getParamDecl(unsigned i) {
+    assert(i < getNumParams() && "Illegal param #");
+    return ParamInfo[i];
+  }
+  void setParams(ParmVarDecl **NewParamInfo, unsigned NumParams);
 
+  bool isInstance() const { return IsInstance; }
+  QualType getResultType() const { return getType(); }
+  
+  void setMethodAttrs(AttributeList *attrs) {MethodAttrs = attrs;}
+  AttributeList *getMethodAttrs() const {return MethodAttrs;}
+
+  // Implement isa/cast/dyncast/etc.
+  static bool classof(const Decl *D) { return D->getKind() == ObjcMethod; }
+  static bool classof(const ObjcMethodDecl *D) { return true; }
+
+private:
+  /// ParamInfo - new[]'d array of pointers to VarDecls for the formal
+  /// parameters of this Method.  This is null if there are no formals.  
+  ParmVarDecl **ParamInfo;
+  
+  /// List of attributes for this method declaration.
+  AttributeList *MethodAttrs;
+
+  bool IsInstance : 1;
+};
+
+}  // end namespace clang
 #endif
index 5d0262fdb316bf260985f578a035f3bef2b9bcf9..1be6503a1130688b7a012061dceda743cfa91443 100644 (file)
@@ -174,6 +174,9 @@ public:
   virtual void ParseRecordBody(SourceLocation RecLoc, DeclTy *TagDecl,
                                DeclTy **Fields, unsigned NumFields) {}
 
+  virtual void ObjcAddMethodsToClass(DeclTy *ClassDecl,
+                                    DeclTy **allMethods, unsigned allNum) {}
+
   virtual DeclTy *ParseEnumConstant(Scope *S, DeclTy *EnumDecl,
                                     DeclTy *LastEnumConstant,
                                     SourceLocation IdLoc, IdentifierInfo *Id,
@@ -450,12 +453,13 @@ public:
   }
   virtual DeclTy *ObjcBuildMethodDeclaration(
     SourceLocation MethodLoc, tok::TokenKind MethodType, TypeTy *ReturnType,
-    ObjcKeywordInfo *Keywords, unsigned NumKeywords) {
+    ObjcKeywordInfo *Keywords, unsigned NumKeywords, 
+    AttributeList *AttrList) {
     return 0;
   }
   virtual DeclTy *ObjcBuildMethodDeclaration(
     SourceLocation MethodLoc, tok::TokenKind MethodType, TypeTy *ReturnType,
-    IdentifierInfo *SelectorName) {
+    IdentifierInfo *SelectorName, AttributeList *AttrList) {
     return 0;
   }
   virtual void ObjCStartCategoryInterface() { // FIXME
index 40e51bf75deb50b8e9b7485023c46d5b2d66294c..7d5cd1a6377d0fab4c7bcc6da47c691343bddd30 100644 (file)
@@ -288,7 +288,7 @@ private:
 
   TypeTy *ParseObjCTypeName();
   void ParseObjCMethodRequirement();
-  DeclTy *ParseObjCMethodPrototype(DeclTy *classOrCat);
+  DeclTy *ParseObjCMethodPrototype(DeclTy *classOrCat); 
   DeclTy *ParseObjCMethodDecl(tok::TokenKind mType, SourceLocation mLoc);
   void ParseObjCPropertyAttribute(DeclTy *interfaceDecl);
   void ParseObjCPropertyDecl(DeclTy *interfaceDecl);