diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2007-09-18 20:26:58 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2007-09-18 20:26:58 +0000 |
commit | fd225cc227143553898f2d3902242d25db9a4902 (patch) | |
tree | e012e139c6f745a8cda686eee6bca618d03478e4 | |
parent | 8e2806573e74465c887a23b1bb4a05769a59b564 (diff) |
Patch for object creation and handling of category declarations.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@42104 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | AST/Decl.cpp | 28 | ||||
-rw-r--r-- | Parse/ParseObjc.cpp | 10 | ||||
-rw-r--r-- | Sema/Sema.h | 5 | ||||
-rw-r--r-- | Sema/SemaDecl.cpp | 25 | ||||
-rw-r--r-- | include/clang/AST/Decl.h | 33 | ||||
-rw-r--r-- | include/clang/Parse/Action.h | 7 |
6 files changed, 101 insertions, 7 deletions
diff --git a/AST/Decl.cpp b/AST/Decl.cpp index 0cbadbf969..4b330eeeeb 100644 --- a/AST/Decl.cpp +++ b/AST/Decl.cpp @@ -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*)); + } +} + diff --git a/Parse/ParseObjc.cpp b/Parse/ParseObjc.cpp index dd9ab2e152..224b826374 100644 --- a/Parse/ParseObjc.cpp +++ b/Parse/ParseObjc.cpp @@ -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)) { diff --git a/Sema/Sema.h b/Sema/Sema.h index 4c50bf67eb..79fc111e64 100644 --- a/Sema/Sema.h +++ b/Sema/Sema.h @@ -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); diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp index d1ce0b4eda..3b7d8f3467 100644 --- a/Sema/SemaDecl.cpp +++ b/Sema/SemaDecl.cpp @@ -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; diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 6569b0657c..aea0dc822b 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -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 diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index c644e75b6e..f7a7809c7b 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -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 |