]> granicus.if.org Git - clang/commitdiff
Patch for object creation and handling of category declarations.
authorFariborz Jahanian <fjahanian@apple.com>
Tue, 18 Sep 2007 20:26:58 +0000 (20:26 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Tue, 18 Sep 2007 20:26:58 +0000 (20:26 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@42104 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

index 0cbadbf9692d8a377806e2055f0b26ea81569fae..4b330eeeebe6399686bfff6c9c2ac9eba067d8be 100644 (file)
@@ -29,6 +29,7 @@ static unsigned nInterfaceDecls = 0;
 static unsigned nClassDecls = 0;
 static unsigned nMethodDecls = 0;
 static unsigned nProtocolDecls = 0;
+static unsigned nCategoryDecls = 0;
 static unsigned nIvarDecls = 0;
 
 static bool StatSwitch = false;
@@ -79,7 +80,7 @@ void Decl::PrintStats() {
   fprintf(stderr, "  %d decls total.\n", 
          int(nFuncs+nBlockVars+nFileVars+nParmVars+nFieldDecls+nSUC+
              nEnumDecls+nEnumConst+nTypedef+nInterfaceDecls+nClassDecls+
-             nMethodDecls+nProtocolDecls+nIvarDecls));
+             nMethodDecls+nProtocolDecls+nCategoryDecls+nIvarDecls));
   fprintf(stderr, "    %d function decls, %d each (%d bytes)\n", 
          nFuncs, (int)sizeof(FunctionDecl), int(nFuncs*sizeof(FunctionDecl)));
   fprintf(stderr, "    %d block variable decls, %d each (%d bytes)\n", 
@@ -121,6 +122,9 @@ void Decl::PrintStats() {
   fprintf(stderr, "    %d protocol decls, %d each (%d bytes)\n", 
          nProtocolDecls, (int)sizeof(ObjcProtocolDecl),
          int(nProtocolDecls*sizeof(ObjcProtocolDecl)));
+  fprintf(stderr, "    %d category decls, %d each (%d bytes)\n", 
+         nCategoryDecls, (int)sizeof(ObjcCategoryDecl),
+         int(nCategoryDecls*sizeof(ObjcCategoryDecl)));
 
   fprintf(stderr, "Total bytes = %d\n", 
          int(nFuncs*sizeof(FunctionDecl)+nBlockVars*sizeof(BlockVarDecl)+
@@ -174,6 +178,9 @@ void Decl::addDeclKind(const Kind k) {
     case ObjcProtocol:
       nProtocolDecls++;
       break;
+    case ObjcCategory:
+     nCategoryDecls++;
+     break;
     case ObjcIvar:
       nIvarDecls++;
       break;
@@ -308,4 +315,23 @@ void ObjcProtocolDecl::ObjcAddProtoMethods(ObjcMethodDecl **insMethods,
   }
 }
 
+/// ObjcAddCat - Insert instance and methods declarations into
+/// ObjcProtocolDecl's CatInsMethods and CatClsMethods fields.
+///
+void ObjcCategoryDecl::ObjcAddCatMethods(ObjcMethodDecl **insMethods, 
+                                        unsigned numInsMembers,
+                                        ObjcMethodDecl **clsMethods,
+                                        unsigned numClsMembers) {
+  NumCatInsMethods = numInsMembers;
+  if (numInsMembers) {
+    CatInsMethods = new ObjcMethodDecl*[numInsMembers];
+    memcpy(CatInsMethods, insMethods, numInsMembers*sizeof(ObjcMethodDecl*));
+  }
+  NumCatClsMethods = numClsMembers;
+  if (numClsMembers) {
+    CatClsMethods = new ObjcMethodDecl*[numClsMembers];
+    memcpy(CatClsMethods, clsMethods, numClsMembers*sizeof(ObjcMethodDecl*));
+  }
+}
+
 
index dd9ab2e152ee05b07b9df54730e028fd2825d2d8..224b8263745649a61abfdf89d439a7ce7f206d56 100644 (file)
@@ -130,6 +130,7 @@ Parser::DeclTy *Parser::ParseObjCAtInterfaceDeclaration(
     SourceLocation lparenLoc = ConsumeParen();
     SourceLocation categoryLoc, rparenLoc;
     IdentifierInfo *categoryId = 0;
+    llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
     
     // For ObjC2, the category name is optional (not an error).
     if (Tok.getKind() == tok::identifier) {
@@ -147,14 +148,19 @@ Parser::DeclTy *Parser::ParseObjCAtInterfaceDeclaration(
     rparenLoc = ConsumeParen();
     // Next, we need to check for any protocol references.
     if (Tok.getKind() == tok::less) {
-      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, tok::objc_not_keyword/*FIXME*/);
+    DeclTy *CategoryType = Actions.ObjcStartCatInterface(atLoc, 
+                                     nameId, nameLoc,
+                                     categoryId, categoryLoc,
+                                     &ProtocolRefs[0],
+                                      ProtocolRefs.size());
+    
+    ParseObjCInterfaceDeclList(CategoryType, tok::objc_not_keyword);
 
     // The @ sign was already consumed by ParseObjCInterfaceDeclList().
     if (Tok.isObjCAtKeyword(tok::objc_end)) {
index 4c50bf67ebce53ca121a96e809ac58bebb3bab34..79fc111e6497143333497734d2d7fe4c55c1d0b3 100644 (file)
@@ -362,6 +362,11 @@ public:
                     IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc,
                     IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs);
   
+  virtual DeclTy *ObjcStartCatInterface(SourceLocation AtInterfaceLoc,
+                    IdentifierInfo *ClassName, SourceLocation ClassLoc,
+                    IdentifierInfo *CategoryName, SourceLocation CategoryLoc,
+                    IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs);
+  
   virtual DeclTy *ObjcClassDeclaration(Scope *S, SourceLocation AtClassLoc,
                                        IdentifierInfo **IdentList,
                                        unsigned NumElts);
index d1ce0b4eda97e950a350ce6beeb97481d2441a8a..3b7d8f3467ee72bdde325ff4f965015594388eb9 100644 (file)
@@ -32,8 +32,7 @@ using namespace clang;
 Sema::DeclTy *Sema::isTypeName(const IdentifierInfo &II, Scope *S) const {
   Decl *IIDecl = II.getFETokenInfo<Decl>();
   if (dyn_cast_or_null<TypedefDecl>(IIDecl) || 
-      dyn_cast_or_null<ObjcInterfaceDecl>(IIDecl) ||
-      dyn_cast_or_null<ObjcProtocolDecl>(IIDecl))
+      dyn_cast_or_null<ObjcInterfaceDecl>(IIDecl))
     return IIDecl;
   return 0;
 }
@@ -896,6 +895,22 @@ Sema::DeclTy *Sema::ObjcStartProtoInterface(SourceLocation AtProtoInterfaceLoc,
   return PDecl;
 }
 
+Sema::DeclTy *Sema::ObjcStartCatInterface(SourceLocation AtInterfaceLoc,
+                      IdentifierInfo *ClassName, SourceLocation ClassLoc,
+                      IdentifierInfo *CategoryName, SourceLocation CategoryLoc,
+                      IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs) {
+  ObjcCategoryDecl *CDecl;
+  CDecl = new ObjcCategoryDecl(AtInterfaceLoc, ClassName);
+  assert (ClassName->getFETokenInfo<ScopedDecl>() && "Missing @interface decl");
+  Decl *D = static_cast<Decl *>(ClassName->getFETokenInfo<ScopedDecl>());
+  assert(isa<ObjcInterfaceDecl>(D) && "Missing @interface decl");
+    
+  // Chain & install the category decl into the identifier.
+  // Note that head of the chain is the @interface class type and follow up
+  // nodes in the chain are the protocol decl nodes.
+  cast<ObjcInterfaceDecl>(D)->setNext(CDecl);
+  return CDecl;
+}
 /// ObjcClassDeclaration - 
 /// Scope will always be top level file scope. 
 Action::DeclTy *
@@ -1263,6 +1278,12 @@ void Sema::ObjcAddMethodsToClass(DeclTy *ClassDecl,
     Protocol->ObjcAddProtoMethods(&insMethods[0], insMethods.size(),
                                   &clsMethods[0], clsMethods.size());
   }
+  else if (isa<ObjcCategoryDecl>(static_cast<Decl *>(ClassDecl))) {
+    ObjcCategoryDecl *Category = cast<ObjcCategoryDecl>(
+                                        static_cast<Decl*>(ClassDecl));
+    Category->ObjcAddCatMethods(&insMethods[0], insMethods.size(),
+                                &clsMethods[0], clsMethods.size());
+  }  
   else
     assert(0 && "Sema::ObjcAddMethodsToClass(): Unknown DeclTy");
   return;
index 6569b0657c2e7a7961616d0756b2c3432c543ddb..aea0dc822b859756825f4a75fb9533082e61dbda 100644 (file)
@@ -39,7 +39,7 @@ public:
     Function, BlockVariable, FileVariable, ParmVariable, EnumConstant,
     // Concrete sub-classes of TypeDecl
     Typedef, Struct, Union, Class, Enum, ObjcInterface, ObjcClass, ObjcMethod,
-    ObjcProtoMethod, ObjcProtocol,
+    ObjcProtoMethod, ObjcProtocol, ObjcCategory,
     // Concrete sub-class of Decl
     Field, ObjcIvar
   };
@@ -703,5 +703,36 @@ public:
   static bool classof(const ObjcProtocolDecl *D) { return true; }
 };
 
+class ObjcCategoryDecl : public ScopedDecl {
+  /// category instance methods
+  ObjcMethodDecl **CatInsMethods;  // Null if not defined
+  int NumCatInsMethods;  // -1 if not defined
+
+  /// category class methods
+  ObjcMethodDecl **CatClsMethods;  // Null if not defined
+  int NumCatClsMethods;  // -1 if not defined
+  
+  /// Category name
+  IdentifierInfo *ObjcCatName;
+
+public:
+  ObjcCategoryDecl(SourceLocation L, IdentifierInfo *Id)
+    : ScopedDecl(ObjcCategory, L, Id, 0),
+      CatInsMethods(0), NumCatInsMethods(-1),
+      CatClsMethods(0), NumCatClsMethods(-1),
+      ObjcCatName(0) {}
+
+  void ObjcAddCatMethods(ObjcMethodDecl **insMethods, unsigned numInsMembers,
+                         ObjcMethodDecl **clsMethods, unsigned numClsMembers);
+  
+  IdentifierInfo *getCatName() const { return ObjcCatName; }
+  void setCatName(IdentifierInfo *catName) { ObjcCatName = catName; }
+
+  static bool classof(const Decl *D) {
+    return D->getKind() == ObjcCategory;
+  }
+  static bool classof(const ObjcCategoryDecl *D) { return true; }
+};
+
 }  // end namespace clang
 #endif
index c644e75b6e08cae4eae36f5d18776654980f89c9..f7a7809c7b278528481579ca7056593b03408848 100644 (file)
@@ -453,6 +453,12 @@ public:
                     IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs) {
     return 0;
   }
+  virtual DeclTy *ObjcStartCatInterface(SourceLocation AtInterfaceLoc,
+                    IdentifierInfo *ClassName, SourceLocation ClassLoc,
+                    IdentifierInfo *CategoryName, SourceLocation CategoryLoc,
+                    IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs) {
+    return 0;
+  }
   virtual DeclTy *ObjcBuildMethodDeclaration(SourceLocation MethodLoc, 
     tok::TokenKind MethodType, TypeTy *ReturnType,
     ObjcKeywordDecl *Keywords, unsigned NumKeywords, 
@@ -544,7 +550,6 @@ public:
   virtual DeclTy *ObjcStartProtoInterface(SourceLocation AtProtoInterfaceLoc,
                     IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc,
                     IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs);
-
 };
 
 }  // end namespace clang