[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