[cfe-commits] r42412 - in /cfe/trunk: AST/Decl.cpp Parse/ParseObjc.cpp Parse/Parser.cpp Sema/Sema.h Sema/SemaDecl.cpp clang.xcodeproj/project.pbxproj include/clang/AST/Decl.h include/clang/Basic/DiagnosticKinds.def include/clang/Parse/Action.h include/clang/Parse/Parser.h test/Sema/method-undefined-warn-1.m
Fariborz Jahanian
fjahanian at apple.com
Thu Sep 27 11:57:04 PDT 2007
Author: fjahanian
Date: Thu Sep 27 13:57:03 2007
New Revision: 42412
URL: http://llvm.org/viewvc/llvm-project?rev=42412&view=rev
Log:
Patch for method implementation. It populates ObjcImplementationDecl object with method implementation declarations .
It checks and warns on those methods declared in class interface and not implemented.
Added:
cfe/trunk/test/Sema/method-undefined-warn-1.m
Modified:
cfe/trunk/AST/Decl.cpp
cfe/trunk/Parse/ParseObjc.cpp
cfe/trunk/Parse/Parser.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/Basic/DiagnosticKinds.def
cfe/trunk/include/clang/Parse/Action.h
cfe/trunk/include/clang/Parse/Parser.h
Modified: cfe/trunk/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/Decl.cpp?rev=42412&r1=42411&r2=42412&view=diff
==============================================================================
--- cfe/trunk/AST/Decl.cpp (original)
+++ cfe/trunk/AST/Decl.cpp Thu Sep 27 13:57:03 2007
@@ -364,4 +364,23 @@
}
}
+/// ObjcAddImplMethods - Insert instance and methods declarations into
+/// ObjcImplementationDecl's InsMethods and ClsMethods fields.
+///
+void ObjcImplementationDecl::ObjcAddImplMethods(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*));
+ }
+}
+
Modified: cfe/trunk/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Parse/ParseObjc.cpp?rev=42412&r1=42411&r2=42412&view=diff
==============================================================================
--- cfe/trunk/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/Parse/ParseObjc.cpp Thu Sep 27 13:57:03 2007
@@ -882,12 +882,22 @@
if (Tok.getKind() == tok::l_brace)
ParseObjCClassInstanceVariables(ImplClsType/*FIXME*/); // we have ivars
- return 0;
+ return ImplClsType;
}
Parser::DeclTy *Parser::ParseObjCAtEndDeclaration(SourceLocation atLoc) {
assert(Tok.isObjCAtKeyword(tok::objc_end) &&
"ParseObjCAtEndDeclaration(): Expected @end");
ConsumeToken(); // the "end" identifier
+ if (ObjcImpDecl) {
+ // Checking is not necessary except that a parse error might have caused
+ // @implementation not to have been parsed to completion and ObjcImpDecl
+ // could be 0.
+ /// Insert collected methods declarations into the @interface object.
+ Actions.ObjcAddMethodsToClass(ObjcImpDecl,
+ &AllImplMethods[0],AllImplMethods.size());
+ ObjcImpDecl = 0;
+ AllImplMethods.clear();
+ }
return 0;
}
@@ -1056,7 +1066,7 @@
assert(Tok.getKind() == tok::minus &&
"ParseObjCInstanceMethodDefinition(): Expected '-'");
// FIXME: @optional/@protocol??
- ParseObjCMethodPrototype(ObjcImpDecl);
+ AllImplMethods.push_back(ParseObjCMethodPrototype(ObjcImpDecl));
// parse optional ';'
if (Tok.getKind() == tok::semi)
ConsumeToken();
@@ -1075,7 +1085,7 @@
assert(Tok.getKind() == tok::plus &&
"ParseObjCClassMethodDefinition(): Expected '+'");
// FIXME: @optional/@protocol??
- ParseObjCMethodPrototype(ObjcImpDecl);
+ AllImplMethods.push_back(ParseObjCMethodPrototype(ObjcImpDecl));
// parse optional ';'
if (Tok.getKind() == tok::semi)
ConsumeToken();
Modified: cfe/trunk/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Parse/Parser.cpp?rev=42412&r1=42411&r2=42412&view=diff
==============================================================================
--- cfe/trunk/Parse/Parser.cpp (original)
+++ cfe/trunk/Parse/Parser.cpp Thu Sep 27 13:57:03 2007
@@ -23,6 +23,7 @@
NumCachedScopes = 0;
ParenCount = BracketCount = BraceCount = 0;
ObjcImpDecl = 0;
+ AllImplMethods.clear();
}
/// Out-of-line virtual destructor to provide home for Action class.
Modified: cfe/trunk/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/Sema.h?rev=42412&r1=42411&r2=42412&view=diff
==============================================================================
--- cfe/trunk/Sema/Sema.h (original)
+++ cfe/trunk/Sema/Sema.h Thu Sep 27 13:57:03 2007
@@ -390,6 +390,8 @@
virtual void ActOnImpleIvarVsClassIvars(DeclTy *ClassDecl,
DeclTy **Fields, unsigned NumFields);
+ virtual void ActOnImplMethodsVsClassMethods(DeclTy *ImplClass, DeclTy *Class);
+
virtual DeclTy *ObjcBuildMethodDeclaration(SourceLocation MethodLoc,
tok::TokenKind MethodType, TypeTy *ReturnType, SelectorInfo *Sel,
// optional arguments. The number of types/arguments is obtained
Modified: cfe/trunk/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaDecl.cpp?rev=42412&r1=42411&r2=42412&view=diff
==============================================================================
--- cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/Sema/SemaDecl.cpp Thu Sep 27 13:57:03 2007
@@ -1174,6 +1174,49 @@
}
+void Sema::ActOnImplMethodsVsClassMethods(DeclTy* ImplClassDecl,
+ DeclTy* ClassDecl) {
+ ObjcImplementationDecl* IMPDecl =
+ cast<ObjcImplementationDecl>(static_cast<Decl*>(ImplClassDecl));
+ assert(IMPDecl && "missing implmentation class decl");
+
+ ObjcInterfaceDecl* IDecl =
+ cast<ObjcInterfaceDecl>(static_cast<Decl*>(ClassDecl));
+ assert(IDecl && "missing interface class decl");
+
+ llvm::DenseMap<const SelectorInfo*, char> Map;
+ // Check and see if instance methods in class interface have been
+ // implemented in the implementation class.
+ ObjcMethodDecl **methods = IMPDecl->getInsMethods();
+ for (int i=0; i < IMPDecl->getNumInsMethods(); i++) {
+ Map[methods[i]->getSelector()] = 'a';
+ }
+
+ methods = IDecl->getInsMethods();
+ for (int j = 0; j < IDecl->getNumInsMethods(); j++)
+ if (!Map.count(methods[j]->getSelector())) {
+ llvm::SmallString<128> buf;
+ Diag(methods[j]->getLocation(), diag::warn_undef_method_impl,
+ methods[j]->getSelector()->getName(buf));
+ }
+ Map.clear();
+ // Check and see if class methods in class interface have been
+ // implemented in the implementation class.
+ methods = IMPDecl->getClsMethods();
+ for (int i=0; i < IMPDecl->getNumClsMethods(); i++) {
+ Map[methods[i]->getSelector()] = 'a';
+ }
+
+ methods = IDecl->getClsMethods();
+ for (int j = 0; j < IDecl->getNumClsMethods(); j++)
+ if (!Map.count(methods[j]->getSelector())) {
+ llvm::SmallString<128> buf;
+ Diag(methods[j]->getLocation(), diag::warn_undef_method_impl,
+ methods[j]->getSelector()->getName(buf));
+ }
+ return;
+}
+
/// ObjcClassDeclaration -
/// Scope will always be top level file scope.
Action::DeclTy *
@@ -1560,7 +1603,17 @@
static_cast<Decl*>(ClassDecl));
Category->ObjcAddCatMethods(&insMethods[0], insMethods.size(),
&clsMethods[0], clsMethods.size());
- }
+ }
+ else if (isa<ObjcImplementationDecl>(static_cast<Decl *>(ClassDecl))) {
+ ObjcImplementationDecl* ImplClass = cast<ObjcImplementationDecl>(
+ static_cast<Decl*>(ClassDecl));
+ ImplClass->ObjcAddImplMethods(&insMethods[0], insMethods.size(),
+ &clsMethods[0], clsMethods.size());
+ ObjcInterfaceDecl* IDecl =
+ Context.getObjCInterfaceDecl(ImplClass->getIdentifier());
+ if (IDecl)
+ ActOnImplMethodsVsClassMethods(ImplClass, IDecl);
+ }
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=42412&r1=42411&r2=42412&view=diff
==============================================================================
--- cfe/trunk/clang.xcodeproj/project.pbxproj (original)
+++ cfe/trunk/clang.xcodeproj/project.pbxproj Thu Sep 27 13:57:03 2007
@@ -733,6 +733,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=42412&r1=42411&r2=42412&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Thu Sep 27 13:57:03 2007
@@ -591,6 +591,12 @@
ObjcIvarDecl **getIntfDeclIvars() const { return Ivars; }
int getIntfDeclNumIvars() const { return NumIvars; }
+ ObjcMethodDecl** getInsMethods() const { return InsMethods; }
+ int getNumInsMethods() const { return NumInsMethods; }
+
+ ObjcMethodDecl** getClsMethods() const { return ClsMethods; }
+ int getNumClsMethods() const { return NumClsMethods; }
+
void ObjcAddInstanceVariablesToClass(ObjcIvarDecl **ivars,
unsigned numIvars);
@@ -677,6 +683,9 @@
/// List of attributes for this method declaration.
AttributeList *MethodAttrs;
+
+ /// Loc - location of this declaration.
+ SourceLocation Loc;
/// instance (true) or class (false) method.
bool IsInstance : 1;
@@ -690,7 +699,7 @@
Decl *PrevDecl = 0)
: Decl(ObjcMethod), Selector(SelInfo), MethodDeclType(T),
ParamInfo(paramInfo), NumMethodParams(numParams),
- MethodAttrs(M), IsInstance(isInstance) {}
+ MethodAttrs(M), Loc(L), IsInstance(isInstance) {}
#if 0
ObjcMethodDecl(Kind DK, SourceLocation L, IdentifierInfo &SelId, QualType T,
ParmVarDecl **paramInfo = 0, int numParams=-1,
@@ -701,6 +710,7 @@
MethodAttrs(M), IsInstance(isInstance) {}
#endif
virtual ~ObjcMethodDecl();
+ SelectorInfo *getSelector() const { return Selector; }
QualType getMethodType() const { return MethodDeclType; }
unsigned getNumMethodParams() const { return NumMethodParams; }
ParmVarDecl *getMethodParamDecl(unsigned i) {
@@ -710,6 +720,7 @@
void setMethodParams(ParmVarDecl **NewParamInfo, unsigned NumParams);
AttributeList *getMethodAttrs() const {return MethodAttrs;}
+ SourceLocation getLocation() const { return Loc; }
bool isInstance() const { return IsInstance; }
// Related to protocols declared in @protocol
void setDeclImplementation(ImplementationControl ic)
@@ -890,13 +901,19 @@
void ObjcAddInstanceVariablesToClassImpl(ObjcIvarDecl **ivars,
unsigned numIvars);
- void ObjcAddMethods(ObjcMethodDecl **insMethods, unsigned numInsMembers,
- ObjcMethodDecl **clsMethods, unsigned numClsMembers);
+ void ObjcAddImplMethods(ObjcMethodDecl **insMethods, unsigned numInsMembers,
+ ObjcMethodDecl **clsMethods, unsigned numClsMembers);
ObjcInterfaceDecl *getImplSuperClass() const { return SuperClass; }
void setImplSuperClass(ObjcInterfaceDecl * superCls)
{ SuperClass = superCls; }
+
+ ObjcMethodDecl **getInsMethods() const { return InsMethods; }
+ int getNumInsMethods() const { return NumInsMethods; }
+
+ ObjcMethodDecl **getClsMethods() const { return ClsMethods; }
+ int getNumClsMethods() const { return NumClsMethods; }
static bool classof(const Decl *D) {
return D->getKind() == ObjcImplementation;
Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=42412&r1=42411&r2=42412&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Thu Sep 27 13:57:03 2007
@@ -432,7 +432,8 @@
"inconsistent instance variable specification")
DIAG(err_conflicting_ivar_type, ERROR,
"conflicting instance variable type")
-
+DIAG(warn_undef_method_impl, WARNING,
+ "method definition for '%0' not found")
//===----------------------------------------------------------------------===//
// Semantic Analysis
Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=42412&r1=42411&r2=42412&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Thu Sep 27 13:57:03 2007
@@ -451,6 +451,10 @@
DeclTy **Fields, unsigned NumFields) {
return;
}
+ virtual void ActOnImplMethodsVsClassMethods(DeclTy *ImplClassDecl,
+ DeclTy *ClassDecl) {
+ return;
+ }
virtual DeclTy *ObjcStartProtoInterface(Scope* S,
SourceLocation AtProtoInterfaceLoc,
IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc,
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=42412&r1=42411&r2=42412&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Thu Sep 27 13:57:03 2007
@@ -265,6 +265,8 @@
DeclTy *ParseObjCAtProtocolDeclaration(SourceLocation atLoc);
DeclTy *ObjcImpDecl;
+ /// Vector is used to collect method decls for each @implementation
+ llvm::SmallVector<DeclTy*, 32> AllImplMethods;
DeclTy *ParseObjCAtImplementationDeclaration(SourceLocation atLoc);
DeclTy *ParseObjCAtEndDeclaration(SourceLocation atLoc);
DeclTy *ParseObjCAtAliasDeclaration(SourceLocation atLoc);
Added: cfe/trunk/test/Sema/method-undefined-warn-1.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/method-undefined-warn-1.m?rev=42412&view=auto
==============================================================================
--- cfe/trunk/test/Sema/method-undefined-warn-1.m (added)
+++ cfe/trunk/test/Sema/method-undefined-warn-1.m Thu Sep 27 13:57:03 2007
@@ -0,0 +1,42 @@
+ at interface INTF
+- (void) meth;
+- (void) meth : (int) arg1;
+- (int) int_meth; // expected-warning {{method definition for 'int_meth' not found}}
++ (int) cls_meth; // expected-warning {{method definition for 'cls_meth' not found}}
++ (void) cls_meth1 : (int) arg1; // expected-warning {{method definition for 'cls_meth1:' not found}}
+ at end
+
+ at implementation INTF
+- (void) meth {}
+- (void) meth : (int) arg2{}
+- (void) cls_meth1 : (int) arg2{}
+ at end
+
+
+ at interface INTF1
+- (void) meth;
+- (void) meth : (int) arg1;
+- (int) int_meth; // expected-warning {{method definition for 'int_meth' not found}}
++ (int) cls_meth; // expected-warning {{method definition for 'cls_meth' not found}}
++ (void) cls_meth1 : (int) arg1; // expected-warning {{method definition for 'cls_meth1:' not found}}
+ at end
+
+ at implementation INTF1
+- (void) meth {}
+- (void) meth : (int) arg2{}
+- (void) cls_meth1 : (int) arg2{}
+ at end
+
+
+ at interface INTF2
+- (void) meth;
+- (void) meth : (int) arg1;
+- (void) cls_meth1 : (int) arg1;
+ at end
+
+ at implementation INTF2
+- (void) meth {}
+- (void) meth : (int) arg2{}
+- (void) cls_meth1 : (int) arg2{}
+ at end
+
More information about the cfe-commits
mailing list