static unsigned nCategoryDecls = 0;
static unsigned nIvarDecls = 0;
static unsigned nObjcImplementationDecls = 0;
+static unsigned nObjcCategoryImpl = 0;
static bool StatSwitch = false;
nObjcImplementationDecls, (int)sizeof(ObjcImplementationDecl),
int(nObjcImplementationDecls*sizeof(ObjcImplementationDecl)));
+ fprintf(stderr, " %d class implementation decls, %d each (%d bytes)\n",
+ nObjcCategoryImpl, (int)sizeof(ObjcCategoryImplDecl),
+ int(nObjcCategoryImpl*sizeof(ObjcCategoryImplDecl)));
+
fprintf(stderr, "Total bytes = %d\n",
int(nFuncs*sizeof(FunctionDecl)+nBlockVars*sizeof(BlockVarDecl)+
nFileVars*sizeof(FileVarDecl)+nParmVars*sizeof(ParmVarDecl)+
case ObjcImplementation:
nObjcImplementationDecls++;
break;
+ case ObjcCategoryImpl:
+ nObjcCategoryImpl++;
+ break;
}
}
}
/// ObjcAddCat - Insert instance and methods declarations into
-/// ObjcProtocolDecl's CatInsMethods and CatClsMethods fields.
+/// ObjcCategoryDecl's CatInsMethods and CatClsMethods fields.
///
void ObjcCategoryDecl::ObjcAddCatMethods(ObjcMethodDecl **insMethods,
unsigned numInsMembers,
}
}
+/// ObjcAddCatImplMethods - Insert instance and methods declarations into
+/// ObjcCategoryImplDecl's CatInsMethods and CatClsMethods fields.
+///
+void ObjcCategoryImplDecl::ObjcAddCatImplMethods(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*));
+ }
+}
+
/// ObjcAddImplMethods - Insert instance and methods declarations into
/// ObjcImplementationDecl's InsMethods and ClsMethods fields.
///
return 0;
}
rparenLoc = ConsumeParen();
- return 0;
+ DeclTy *ImplCatType = Actions.ObjcStartCategoryImplementation(CurScope,
+ atLoc, nameId, nameLoc, categoryId,
+ categoryLoc);
+ return ImplCatType;
}
// We have a class implementation
SourceLocation superClassLoc;
class ObjcInterfaceDecl;
class ObjcProtocolDecl;
class ObjcImplementationDecl;
+ class ObjcCategoryImplDecl;
+ class ObjcCategoryDecl;
/// Sema - This implements semantic analysis and AST building for C.
class Sema : public Action {
void ImplMethodsVsClassMethods(ObjcImplementationDecl* IMPDecl,
ObjcInterfaceDecl* IDecl);
+ /// ImplCategoryMethodsVsIntfMethods - Checks that methods declared in the
+ /// category interface is implemented in the category @implementation.
+ void ImplCategoryMethodsVsIntfMethods(ObjcCategoryImplDecl *CatImplDecl,
+ ObjcCategoryDecl *CatClassDecl);
+
//===--------------------------------------------------------------------===//
// Statement Parsing Callbacks: SemaStmt.cpp.
public:
IdentifierInfo *SuperClassname,
SourceLocation SuperClassLoc);
+ virtual DeclTy *ObjcStartCategoryImplementation(Scope* S,
+ SourceLocation AtCatImplLoc,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassLoc,
+ IdentifierInfo *CatName,
+ SourceLocation CatLoc);
+
virtual DeclTy *ObjcClassDeclaration(Scope *S, SourceLocation AtClassLoc,
IdentifierInfo **IdentList,
unsigned NumElts);
return CDecl;
}
+/// ObjcStartCategoryImplementation - Perform semantic checks on the
+/// category implementation declaration and build an ObjcCategoryImplDecl
+/// object.
+Sema::DeclTy *Sema::ObjcStartCategoryImplementation(Scope* S,
+ SourceLocation AtCatImplLoc,
+ IdentifierInfo *ClassName, SourceLocation ClassLoc,
+ IdentifierInfo *CatName, SourceLocation CatLoc) {
+ ObjcInterfaceDecl *IDecl = getObjCInterfaceDecl(S, ClassName, ClassLoc);
+ ObjcCategoryImplDecl *CDecl = new ObjcCategoryImplDecl(AtCatImplLoc,
+ ClassName, IDecl,
+ CatName);
+ /// Check that class of this category is already completely declared.
+ if (!IDecl || IDecl->getIsForwardDecl())
+ Diag(ClassLoc, diag::err_undef_interface, ClassName->getName());
+ /// TODO: Check that CatName, category name, is not used in another
+ // implementation.
+ return CDecl;
+}
+
Sema::DeclTy *Sema::ObjcStartClassImplementation(Scope *S,
SourceLocation AtClassImplLoc,
IdentifierInfo *ClassName, SourceLocation ClassLoc,
ObjcProtocolDecl* PDecl = protocols[i];
CheckProtocolMethodDefs(PDecl, InsMap, ClsMap);
}
- return;
+}
+
+/// ImplCategoryMethodsVsIntfMethods - Checks that methods declared in the
+/// category interface is implemented in the category @implementation.
+void Sema::ImplCategoryMethodsVsIntfMethods(ObjcCategoryImplDecl *CatImplDecl,
+ ObjcCategoryDecl *CatClassDecl) {
+ llvm::DenseMap<void *, char> InsMap;
+ // Check and see if instance methods in category interface have been
+ // implemented in its implementation class.
+ ObjcMethodDecl **methods = CatImplDecl->getCatInsMethods();
+ for (int i=0; i < CatImplDecl->getNumCatInsMethods(); i++) {
+ InsMap[methods[i]->getSelector().getAsOpaquePtr()] = 'a';
+ }
+
+ methods = CatClassDecl->getCatInsMethods();
+ for (int j = 0; j < CatClassDecl->getNumCatInsMethods(); j++)
+ if (!InsMap.count(methods[j]->getSelector().getAsOpaquePtr())) {
+ llvm::SmallString<128> buf;
+ Diag(methods[j]->getLocation(), diag::warn_undef_method_impl,
+ methods[j]->getSelector().getName(buf));
+ }
+ llvm::DenseMap<void *, char> ClsMap;
+ // Check and see if class methods in category interface have been
+ // implemented in its implementation class.
+ methods = CatImplDecl->getCatClsMethods();
+ for (int i=0; i < CatImplDecl->getNumCatClsMethods(); i++) {
+ ClsMap[methods[i]->getSelector().getAsOpaquePtr()] = 'a';
+ }
+
+ methods = CatClassDecl->getCatClsMethods();
+ for (int j = 0; j < CatClassDecl->getNumCatClsMethods(); j++)
+ if (!ClsMap.count(methods[j]->getSelector().getAsOpaquePtr())) {
+ llvm::SmallString<128> buf;
+ Diag(methods[j]->getLocation(), diag::warn_undef_method_impl,
+ methods[j]->getSelector().getName(buf));
+ }
+
+ // Check the protocol list for unimplemented methods in the @implementation
+ // class.
+ ObjcProtocolDecl** protocols = CatClassDecl->getCatReferencedProtocols();
+ for (int i = 0; i < CatClassDecl->getNumCatReferencedProtocols(); i++) {
+ ObjcProtocolDecl* PDecl = protocols[i];
+ CheckProtocolMethodDefs(PDecl, InsMap, ClsMap);
+ }
+
}
/// ObjcClassDeclaration -
if (IDecl)
ImplMethodsVsClassMethods(ImplClass, IDecl);
}
+ else if (isa<ObjcCategoryImplDecl>(static_cast<Decl *>(ClassDecl))) {
+ ObjcCategoryImplDecl* CatImplClass = cast<ObjcCategoryImplDecl>(
+ static_cast<Decl*>(ClassDecl));
+ CatImplClass->ObjcAddCatImplMethods(&insMethods[0], insMethods.size(),
+ &clsMethods[0], clsMethods.size());
+ ObjcInterfaceDecl* IDecl = CatImplClass->getClassInterface();
+ // Find category interface decl and then check that all methods declared
+ // in this interface is implemented in the category @implementation.
+ if (IDecl) {
+ for (ObjcCategoryDecl *Categories = IDecl->getListCategories();
+ Categories; Categories = Categories->getNextClassCategory()) {
+ if (Categories->getCatName() == CatImplClass->getObjcCatName()) {
+ ImplCategoryMethodsVsIntfMethods(CatImplClass, Categories);
+ break;
+ }
+ }
+ }
+ }
else
assert(0 && "Sema::ObjcAddMethodsToClass(): Unknown DeclTy");
return;
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */;
+ compatibilityVersion = "Xcode 2.4";
hasScannedForEncodings = 1;
mainGroup = 08FB7794FE84155DC02AAC07 /* clang */;
projectDirPath = "";
Function, BlockVariable, FileVariable, ParmVariable, EnumConstant,
// Concrete sub-classes of TypeDecl
Typedef, Struct, Union, Class, Enum, ObjcInterface, ObjcClass, ObjcMethod,
- ObjcProtocol, ObjcForwardProtocol, ObjcCategory,
+ ObjcProtocol, ObjcForwardProtocol, ObjcCategory, ObjcCategoryImpl,
ObjcImplementation,
// Concrete sub-class of Decl
Field, ObjcIvar
CatReferencedProtocols[idx] = OID;
}
+ ObjcProtocolDecl **getCatReferencedProtocols() const {
+ return CatReferencedProtocols;
+ }
+ int getNumCatReferencedProtocols() const { return NumCatReferencedProtocols; }
+
+ ObjcMethodDecl **getCatInsMethods() const { return CatInsMethods; }
+ int getNumCatInsMethods() const { return NumCatInsMethods; }
+
+ ObjcMethodDecl **getCatClsMethods() const { return CatClsMethods; }
+ int getNumCatClsMethods() const { return NumCatClsMethods; }
+
void ObjcAddCatMethods(ObjcMethodDecl **insMethods, unsigned numInsMembers,
ObjcMethodDecl **clsMethods, unsigned numClsMembers);
static bool classof(const ObjcCategoryDecl *D) { return true; }
};
+/// ObjcCategoryImplDecl - An object of this class encapsulates a category
+/// @implementation declaration.
+class ObjcCategoryImplDecl : public Decl {
+ /// Class interface for this category implementation
+ ObjcInterfaceDecl *ClassInterface;
+
+ /// Category name
+ IdentifierInfo *ObjcCatName;
+
+ /// category instance methods being implemented
+ ObjcMethodDecl **CatInsMethods; // Null if category is not implementing any
+ int NumCatInsMethods; // -1 if category is not implementing any
+
+ /// category class methods being implemented
+ ObjcMethodDecl **CatClsMethods; // Null if category is not implementing any
+ int NumCatClsMethods; // -1 if category is not implementing any
+
+ public:
+ ObjcCategoryImplDecl(SourceLocation L, IdentifierInfo *Id,
+ ObjcInterfaceDecl *classInterface,
+ IdentifierInfo *catName)
+ : Decl(ObjcCategoryImpl),
+ ClassInterface(classInterface),
+ ObjcCatName(catName),
+ CatInsMethods(0), NumCatInsMethods(-1),
+ CatClsMethods(0), NumCatClsMethods(-1) {}
+
+ ObjcInterfaceDecl *getClassInterface() const {
+ return ClassInterface;
+ }
+
+ IdentifierInfo *getObjcCatName() const { return ObjcCatName; }
+
+ ObjcMethodDecl **getCatInsMethods() const { return CatInsMethods; }
+ int getNumCatInsMethods() const { return NumCatInsMethods; }
+
+ ObjcMethodDecl **getCatClsMethods() const { return CatClsMethods; }
+ int getNumCatClsMethods() const { return NumCatClsMethods; }
+
+
+ void ObjcAddCatImplMethods(
+ ObjcMethodDecl **insMethods, unsigned numInsMembers,
+ ObjcMethodDecl **clsMethods, unsigned numClsMembers);
+
+ static bool classof(const Decl *D) {
+ return D->getKind() == ObjcCategoryImpl;
+ }
+ static bool classof(const ObjcCategoryImplDecl *D) { return true; }
+};
+
/// ObjcImplementationDecl - Represents a class definition - this is where
/// method definitions are specified. For example:
///
SourceLocation SuperClassLoc) {
return 0;
}
+ virtual DeclTy *ObjcStartCategoryImplementation(Scope* S,
+ SourceLocation AtCatImplLoc,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassLoc,
+ IdentifierInfo *CatName,
+ SourceLocation CatLoc) {
+ return 0;
+ }
virtual DeclTy *ObjcBuildMethodDeclaration(SourceLocation MethodLoc,
tok::TokenKind MethodType, TypeTy *ReturnType, Selector Sel,
// optional arguments. The number of types/arguments is obtained
--- /dev/null
+@interface MyClass1
+@end
+
+@protocol P
+- (void) Pmeth; // expected-warning {{method definition for 'Pmeth' not found}}
+- (void) Pmeth1; // expected-warning {{method definition for 'Pmeth1' not found}}
+@end
+
+@interface MyClass1(CAT) <P>
+- (void) meth2; // expected-warning {{method definition for 'meth2' not found}}
+@end
+
+@implementation MyClass1(CAT)
+- (void) Pmeth1{}
+@end
+
+@interface MyClass1(DOG) <P>
+- (void)ppp; // expected-warning {{method definition for 'ppp' not found}}
+@end
+
+@implementation MyClass1(DOG)
+- (void) Pmeth {}
+@end
+
+@implementation MyClass1(CAT1)
+@end