[cfe-commits] r42531 - in /cfe/trunk: AST/Decl.cpp Parse/ParseObjc.cpp Sema/Sema.h Sema/SemaDecl.cpp clang.xcodeproj/project.pbxproj include/clang/AST/Decl.h include/clang/AST/DeclObjC.h include/clang/Parse/Action.h test/Sema/method-undef-category-warn-1.m
Fariborz Jahanian
fjahanian at apple.com
Tue Oct 2 09:38:50 PDT 2007
Author: fjahanian
Date: Tue Oct 2 11:38:50 2007
New Revision: 42531
URL: http://llvm.org/viewvc/llvm-project?rev=42531&view=rev
Log:
This patch introduces the ObjcCategoryImplDecl class and does the checking related to
unimplemented methods in category implementation.
Added:
cfe/trunk/test/Sema/method-undef-category-warn-1.m
Modified:
cfe/trunk/AST/Decl.cpp
cfe/trunk/Parse/ParseObjc.cpp
cfe/trunk/Sema/Sema.h
cfe/trunk/Sema/SemaDecl.cpp
cfe/trunk/clang.xcodeproj/project.pbxproj
cfe/trunk/include/clang/AST/Decl.h
cfe/trunk/include/clang/AST/DeclObjC.h
cfe/trunk/include/clang/Parse/Action.h
Modified: cfe/trunk/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/Decl.cpp?rev=42531&r1=42530&r2=42531&view=diff
==============================================================================
--- cfe/trunk/AST/Decl.cpp (original)
+++ cfe/trunk/AST/Decl.cpp Tue Oct 2 11:38:50 2007
@@ -34,6 +34,7 @@
static unsigned nCategoryDecls = 0;
static unsigned nIvarDecls = 0;
static unsigned nObjcImplementationDecls = 0;
+static unsigned nObjcCategoryImpl = 0;
static bool StatSwitch = false;
@@ -136,6 +137,10 @@
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)+
@@ -199,6 +204,9 @@
case ObjcImplementation:
nObjcImplementationDecls++;
break;
+ case ObjcCategoryImpl:
+ nObjcCategoryImpl++;
+ break;
}
}
@@ -344,7 +352,7 @@
}
/// 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,
@@ -362,6 +370,25 @@
}
}
+/// 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.
///
Modified: cfe/trunk/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Parse/ParseObjc.cpp?rev=42531&r1=42530&r2=42531&view=diff
==============================================================================
--- cfe/trunk/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/Parse/ParseObjc.cpp Tue Oct 2 11:38:50 2007
@@ -934,7 +934,10 @@
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;
Modified: cfe/trunk/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/Sema.h?rev=42531&r1=42530&r2=42531&view=diff
==============================================================================
--- cfe/trunk/Sema/Sema.h (original)
+++ cfe/trunk/Sema/Sema.h Tue Oct 2 11:38:50 2007
@@ -49,6 +49,8 @@
class ObjcInterfaceDecl;
class ObjcProtocolDecl;
class ObjcImplementationDecl;
+ class ObjcCategoryImplDecl;
+ class ObjcCategoryDecl;
/// Sema - This implements semantic analysis and AST building for C.
class Sema : public Action {
@@ -219,6 +221,11 @@
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:
@@ -395,6 +402,13 @@
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);
Modified: cfe/trunk/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaDecl.cpp?rev=42531&r1=42530&r2=42531&view=diff
==============================================================================
--- cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/Sema/SemaDecl.cpp Tue Oct 2 11:38:50 2007
@@ -1068,6 +1068,25 @@
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,
@@ -1255,7 +1274,51 @@
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 -
@@ -1647,6 +1710,24 @@
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;
Modified: cfe/trunk/clang.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/clang.xcodeproj/project.pbxproj?rev=42531&r1=42530&r2=42531&view=diff
==============================================================================
--- cfe/trunk/clang.xcodeproj/project.pbxproj (original)
+++ cfe/trunk/clang.xcodeproj/project.pbxproj Tue Oct 2 11:38:50 2007
@@ -737,6 +737,7 @@
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */;
+ compatibilityVersion = "Xcode 2.4";
hasScannedForEncodings = 1;
mainGroup = 08FB7794FE84155DC02AAC07 /* clang */;
projectDirPath = "";
Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=42531&r1=42530&r2=42531&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Tue Oct 2 11:38:50 2007
@@ -35,7 +35,7 @@
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
Modified: cfe/trunk/include/clang/AST/DeclObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=42531&r1=42530&r2=42531&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Tue Oct 2 11:38:50 2007
@@ -448,6 +448,17 @@
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);
@@ -466,6 +477,56 @@
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:
///
Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=42531&r1=42530&r2=42531&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Tue Oct 2 11:38:50 2007
@@ -472,6 +472,14 @@
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
Added: cfe/trunk/test/Sema/method-undef-category-warn-1.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/method-undef-category-warn-1.m?rev=42531&view=auto
==============================================================================
--- cfe/trunk/test/Sema/method-undef-category-warn-1.m (added)
+++ cfe/trunk/test/Sema/method-undef-category-warn-1.m Tue Oct 2 11:38:50 2007
@@ -0,0 +1,26 @@
+ at interface MyClass1
+ at end
+
+ at protocol P
+- (void) Pmeth; // expected-warning {{method definition for 'Pmeth' not found}}
+- (void) Pmeth1; // expected-warning {{method definition for 'Pmeth1' not found}}
+ at end
+
+ at interface MyClass1(CAT) <P>
+- (void) meth2; // expected-warning {{method definition for 'meth2' not found}}
+ at end
+
+ at implementation MyClass1(CAT)
+- (void) Pmeth1{}
+ at end
+
+ at interface MyClass1(DOG) <P>
+- (void)ppp; // expected-warning {{method definition for 'ppp' not found}}
+ at end
+
+ at implementation MyClass1(DOG)
+- (void) Pmeth {}
+ at end
+
+ at implementation MyClass1(CAT1)
+ at end
More information about the cfe-commits
mailing list