[cfe-commits] r43995 - in /cfe/trunk: AST/Decl.cpp Driver/RewriteTest.cpp Parse/ParseObjc.cpp Parse/Parser.cpp Sema/Sema.h Sema/SemaDecl.cpp include/clang/AST/DeclObjC.h include/clang/Parse/Action.h include/clang/Parse/Parser.h test/Sema/message.m

Steve Naroff snaroff at apple.com
Sun Nov 11 09:19:15 PST 2007


Author: snaroff
Date: Sun Nov 11 11:19:15 2007
New Revision: 43995

URL: http://llvm.org/viewvc/llvm-project?rev=43995&view=rev
Log:

This is the last 5% of the solution to teaching Sema::ActOnInstanceMessage() about private methods (r43989).

While the diff is large, the idea is very simple. When we parse method definitions (in an @implementation), we need to add them incrementally (rather than wait until the @end).

Other details...

- Renamed Sema::ActOnAddMethodsToObjcDecl() to Sema::ActOnAtEnd(). The methods are now optional arguments.
- Removed Parser::AllImplMethods (a nice cleanup).
- Added location info to ObjcImplementationDecl (since we will need it very soon:-)
- Modified message.m test to no longer allow the bogus diagnostic.


Modified:
    cfe/trunk/AST/Decl.cpp
    cfe/trunk/Driver/RewriteTest.cpp
    cfe/trunk/Parse/ParseObjc.cpp
    cfe/trunk/Parse/Parser.cpp
    cfe/trunk/Sema/Sema.h
    cfe/trunk/Sema/SemaDecl.cpp
    cfe/trunk/include/clang/AST/DeclObjC.h
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/test/Sema/message.m

Modified: cfe/trunk/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/Decl.cpp?rev=43995&r1=43994&r2=43995&view=diff

==============================================================================
--- cfe/trunk/AST/Decl.cpp (original)
+++ cfe/trunk/AST/Decl.cpp Sun Nov 11 11:19:15 2007
@@ -408,26 +408,6 @@
   }
 }
 
-/// ObjcAddImplMethods - Insert instance and methods declarations into
-/// ObjcImplementationDecl's InsMethods and ClsMethods fields.
-///
-void ObjcImplementationDecl::addMethods(ObjcMethodDecl **insMethods, 
-                                        unsigned numInsMembers,
-                                        ObjcMethodDecl **clsMethods,
-                                        unsigned numClsMembers,
-                                        SourceLocation AtEndLoc) {
-  NumInstanceMethods = numInsMembers;
-  if (numInsMembers) {
-    InstanceMethods = new ObjcMethodDecl*[numInsMembers];
-    memcpy(InstanceMethods, insMethods, numInsMembers*sizeof(ObjcMethodDecl*));
-  }
-  NumClassMethods = numClsMembers;
-  if (numClsMembers) {
-    ClassMethods = new ObjcMethodDecl*[numClsMembers];
-    memcpy(ClassMethods, clsMethods, numClsMembers*sizeof(ObjcMethodDecl*));
-  }
-}
-
 // lookupInstanceMethod - This method returns an instance method by looking in
 // the class, it's categories, and it's super classes (using a linear search).
 ObjcMethodDecl *ObjcInterfaceDecl::lookupInstanceMethod(Selector &Sel) {
@@ -514,7 +494,7 @@
 // the class implementation. Unlike interfaces, we don't look outside the
 // implementation.
 ObjcMethodDecl *ObjcImplementationDecl::lookupInstanceMethod(Selector &Sel) {
-  ObjcMethodDecl **methods = getInstanceMethods();
+  ObjcMethodDecl *const*methods = getInstanceMethods();
   int methodCount = getNumInstanceMethods();
   for (int i = 0; i < methodCount; ++i) {
     if (methods[i]->getSelector() == Sel) {
@@ -528,7 +508,7 @@
 // the class implementation. Unlike interfaces, we don't look outside the
 // implementation.
 ObjcMethodDecl *ObjcImplementationDecl::lookupClassMethod(Selector &Sel) {
-  ObjcMethodDecl **methods = getClassMethods();
+  ObjcMethodDecl *const*methods = getClassMethods();
   int methodCount = getNumClassMethods();
   for (int i = 0; i < methodCount; ++i) {
     if (methods[i]->getSelector() == Sel) {

Modified: cfe/trunk/Driver/RewriteTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/RewriteTest.cpp?rev=43995&r1=43994&r2=43995&view=diff

==============================================================================
--- cfe/trunk/Driver/RewriteTest.cpp (original)
+++ cfe/trunk/Driver/RewriteTest.cpp Sun Nov 11 11:19:15 2007
@@ -118,7 +118,7 @@
     void RewriteObjcCategoryImplDecl(ObjcCategoryImplDecl *CDecl,
                                      std::string &Result);
     
-    void RewriteObjcMethodsMetaData(ObjcMethodDecl **Methods,
+    void RewriteObjcMethodsMetaData(ObjcMethodDecl *const*Methods,
                                     int NumMethods,
                                     bool IsInstanceMethod,
                                     const char *prefix,
@@ -1039,7 +1039,7 @@
 
 // RewriteObjcMethodsMetaData - Rewrite methods metadata for instance or
 /// class methods.
-void RewriteTest::RewriteObjcMethodsMetaData(ObjcMethodDecl **Methods,
+void RewriteTest::RewriteObjcMethodsMetaData(ObjcMethodDecl *const*Methods,
                                              int NumMethods,
                                              bool IsInstanceMethod,
                                              const char *prefix,

Modified: cfe/trunk/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Parse/ParseObjc.cpp?rev=43995&r1=43994&r2=43995&view=diff

==============================================================================
--- cfe/trunk/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/Parse/ParseObjc.cpp Sun Nov 11 11:19:15 2007
@@ -275,12 +275,8 @@
     }
   }
   /// Insert collected methods declarations into the @interface object.
-  /// This action is executed even if we don't have any methods (so the @end
-  /// can be recorded properly).
-  Actions.ActOnAddMethodsToObjcDecl(CurScope, interfaceDecl, &allMethods[0], 
-                                    allMethods.size(), 
-                                    &allProperties[0], allProperties.size(), 
-                                    AtEndLoc);
+  Actions.ActOnAtEnd(AtEndLoc, interfaceDecl, &allMethods[0], allMethods.size(), 
+                     &allProperties[0], allProperties.size());
 }
 
 ///   Parse property attribute declarations.
@@ -946,12 +942,7 @@
     // 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.ActOnAddMethodsToObjcDecl(CurScope, ObjcImpDecl,
-                                      &AllImplMethods[0], AllImplMethods.size(),
-                                      (DeclTy **)0, 0,
-                                      atLoc);
-    AllImplMethods.clear();
+    Actions.ActOnAtEnd(atLoc, ObjcImpDecl);
   }
 
   return ObjcImpDecl;
@@ -1151,8 +1142,6 @@
 void Parser::ParseObjCInstanceMethodDefinition() {
   assert(Tok.is(tok::minus) && "Method definitions should start with '-'");
   DeclTy *MDecl = ParseObjCMethodPrototype(ObjcImpDecl);
-  // FIXME: @optional/@protocol??
-  AllImplMethods.push_back(MDecl);
   // parse optional ';'
   if (Tok.is(tok::semi))
     ConsumeToken();
@@ -1169,8 +1158,6 @@
 void Parser::ParseObjCClassMethodDefinition() {
   assert(Tok.is(tok::plus) && "Class method definitions should start with '+'");
   DeclTy *MDecl = ParseObjCMethodPrototype(ObjcImpDecl);
-  // FIXME: @optional/@protocol??
-  AllImplMethods.push_back(MDecl);
   // parse optional ';'
   if (Tok.is(tok::semi))
     ConsumeToken();

Modified: cfe/trunk/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Parse/Parser.cpp?rev=43995&r1=43994&r2=43995&view=diff

==============================================================================
--- cfe/trunk/Parse/Parser.cpp (original)
+++ cfe/trunk/Parse/Parser.cpp Sun Nov 11 11:19:15 2007
@@ -23,7 +23,6 @@
   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=43995&r1=43994&r2=43995&view=diff

==============================================================================
--- cfe/trunk/Sema/Sema.h (original)
+++ cfe/trunk/Sema/Sema.h Sun Nov 11 11:19:15 2007
@@ -541,10 +541,9 @@
                                        llvm::SmallVector<DeclTy *, 8> & 
                                        Protocols);
 
-  virtual void ActOnAddMethodsToObjcDecl(Scope* S, DeclTy *ClassDecl, 
-				         DeclTy **allMethods, unsigned allNum,
-                                         DeclTy **allProperties, unsigned pNum,
-                                         SourceLocation AtEndLoc);
+  virtual void ActOnAtEnd(SourceLocation AtEndLoc, DeclTy *classDecl,
+                      DeclTy **allMethods = 0, unsigned allNum = 0,
+                      DeclTy **allProperties = 0, unsigned pNum = 0);
   
   virtual DeclTy *ActOnAddObjcProperties(SourceLocation AtLoc, 
                                          DeclTy **allProperties,

Modified: cfe/trunk/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaDecl.cpp?rev=43995&r1=43994&r2=43995&view=diff

==============================================================================
--- cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/Sema/SemaDecl.cpp Sun Nov 11 11:19:15 2007
@@ -1576,7 +1576,7 @@
   llvm::DenseSet<Selector> InsMap;
   // Check and see if instance methods in class interface have been
   // implemented in the implementation class.
-  ObjcMethodDecl **methods = IMPDecl->getInstanceMethods();
+  ObjcMethodDecl *const*methods = IMPDecl->getInstanceMethods();
   for (int i=0; i < IMPDecl->getNumInstanceMethods(); i++) 
     InsMap.insert(methods[i]->getSelector());
   
@@ -2079,10 +2079,9 @@
   }
 }
 
-void Sema::ActOnAddMethodsToObjcDecl(Scope* S, DeclTy *classDecl,
-                                     DeclTy **allMethods, unsigned allNum,
-                                     DeclTy **allProperties, unsigned pNum,
-                                     SourceLocation AtEndLoc) {
+void Sema::ActOnAtEnd(SourceLocation AtEndLoc, DeclTy *classDecl,
+                      DeclTy **allMethods, unsigned allNum,
+                      DeclTy **allProperties, unsigned pNum) {
   Decl *ClassDecl = static_cast<Decl *>(classDecl);
 
   // FIXME: If we don't have a ClassDecl, we have an error. I (snaroff) would
@@ -2164,8 +2163,7 @@
   }
   else if (ObjcImplementationDecl *IC = 
                 dyn_cast<ObjcImplementationDecl>(ClassDecl)) {
-    IC->addMethods(&insMethods[0], insMethods.size(),
-                   &clsMethods[0], clsMethods.size(), AtEndLoc);
+    IC->setLocEnd(AtEndLoc);
     if (ObjcInterfaceDecl* IDecl = getObjCInterfaceDecl(IC->getIdentifier()))
       ImplMethodsVsClassMethods(IC, IDecl);
   } else {
@@ -2242,14 +2240,15 @@
   
   Decl *CDecl = static_cast<Decl*>(ClassDecl);
   ObjcInterfaceDecl *IDecl = 0;
+  ObjcImplementationDecl *ImpDecl = 0;
   if (isa<ObjcInterfaceDecl>(CDecl))
     IDecl = cast<ObjcInterfaceDecl>(CDecl);
   else if (isa<ObjcCategoryDecl>(CDecl))
-    IDecl = cast<ObjcCategoryDecl>(CDecl)->getClassInterface();
-  else if (isa<ObjcImplementationDecl>(CDecl))
-    IDecl = cast<ObjcImplementationDecl>(CDecl)->getClassInterface();
+    IDecl = cast<ObjcCategoryDecl>(CDecl)->getClassInterface(); // FIXME: what is this? (talk to fariborz)
+  else if ((ImpDecl = dyn_cast<ObjcImplementationDecl>(CDecl)))
+    IDecl = ImpDecl->getClassInterface(); // FIXME: what is this? (talk to fariborz)
   else if (isa<ObjcCategoryImplDecl>(CDecl))
-    IDecl = cast<ObjcCategoryImplDecl>(CDecl)->getClassInterface();
+    IDecl = cast<ObjcCategoryImplDecl>(CDecl)->getClassInterface(); // FIXME: what is this? (talk to fariborz)
   
   ObjcMethodDecl* ObjcMethod =  new ObjcMethodDecl(MethodLoc, EndLoc, Sel,
                                       resultDeclType,
@@ -2262,6 +2261,27 @@
   ObjcMethod->setMethodParams(&Params[0], Sel.getNumArgs());
   ObjcMethod->setObjcDeclQualifier(
     CvtQTToAstBitMask(ReturnQT.getObjcDeclQualifier()));
+  if (ImpDecl) {
+    // For implementations (which can be very "coarse grain"), we add the 
+    // method now. This allows the AST to implement lookup methods that work 
+    // incrementally (without waiting until we parse the @end). It also allows 
+    // us to flag multiple declaration errors as they occur.
+    // FIXME: still need to do this for ObjcCategoryImplDecl.
+    const ObjcMethodDecl *PrevMethod = 0;
+    if (MethodType == tok::minus) {
+      PrevMethod = ImpDecl->lookupInstanceMethod(Sel);
+      ImpDecl->addInstanceMethod(ObjcMethod);
+    } else {
+      PrevMethod = ImpDecl->lookupClassMethod(Sel);
+      ImpDecl->addClassMethod(ObjcMethod);
+    }
+    if (PrevMethod) {
+      // You can never have two method definitions with the same name.
+      Diag(ObjcMethod->getLocation(), diag::error_duplicate_method_decl,
+          ObjcMethod->getSelector().getName());
+      Diag(PrevMethod->getLocation(), diag::err_previous_declaration);
+    } 
+  }
   return ObjcMethod;
 }
 

Modified: cfe/trunk/include/clang/AST/DeclObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=43995&r1=43994&r2=43995&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Sun Nov 11 11:19:15 2007
@@ -629,44 +629,53 @@
   /// Optional Ivars/NumIvars - This is a new[]'d array of pointers to Decls.
   ObjcIvarDecl **Ivars;   // Null if not specified
   int NumIvars;   // -1 if not defined.
-    
+
   /// implemented instance methods
-  ObjcMethodDecl **InstanceMethods;  // Null if not defined
-  int NumInstanceMethods;  // -1 if not defined
-    
+  llvm::SmallVector<ObjcMethodDecl*, 32> InstanceMethods;
+  
   /// implemented class methods
-  ObjcMethodDecl **ClassMethods;  // Null if not defined
-  int NumClassMethods;  // -1 if not defined
-    
+  llvm::SmallVector<ObjcMethodDecl*, 32> ClassMethods;
+
+  SourceLocation EndLoc;
 public:
   ObjcImplementationDecl(SourceLocation L, IdentifierInfo *Id,
                          ObjcInterfaceDecl *classInterface,
                          ObjcInterfaceDecl *superDecl)
     : NamedDecl(ObjcImplementation, L, Id),
-      ClassInterface(classInterface),
-      SuperClass(superDecl),
-      Ivars(0), NumIvars(-1),
-      InstanceMethods(0), NumInstanceMethods(-1), 
-      ClassMethods(0), NumClassMethods(-1) {}
+      ClassInterface(classInterface), SuperClass(superDecl),
+      Ivars(0), NumIvars(-1) {}
   
   void ObjcAddInstanceVariablesToClassImpl(ObjcIvarDecl **ivars, 
                                            unsigned numIvars);
     
-  void addMethods(ObjcMethodDecl **insMethods, unsigned numInsMembers,
-                  ObjcMethodDecl **clsMethods, unsigned numClsMembers,
-                  SourceLocation AtEndLoc);
-    
+  void addInstanceMethod(ObjcMethodDecl *method) {
+    InstanceMethods.push_back(method);
+  }
+  void addClassMethod(ObjcMethodDecl *method) {
+    ClassMethods.push_back(method);
+  }    
+  // Location information, modeled after the Stmt API. 
+  SourceLocation getLocStart() const { return getLocation(); }
+  SourceLocation getLocEnd() const { return EndLoc; }
+  void setLocEnd(SourceLocation LE) { EndLoc = LE; };
+  
   ObjcInterfaceDecl *getClassInterface() const { return ClassInterface; }
   ObjcInterfaceDecl *getSuperClass() const { return SuperClass; }
   
   void setSuperClass(ObjcInterfaceDecl * superCls) 
          { SuperClass = superCls; }
   
-  ObjcMethodDecl **getInstanceMethods() const { return InstanceMethods; }
-  int getNumInstanceMethods() const { return NumInstanceMethods; }
+  // FIXME: Figure out how to remove the const pointer below.
+  ObjcMethodDecl *const*getInstanceMethods() const {
+    return &InstanceMethods[0];
+  }
+  int getNumInstanceMethods() const { return InstanceMethods.size(); }
   
-  ObjcMethodDecl **getClassMethods() const { return ClassMethods; }
-  int getNumClassMethods() const { return NumClassMethods; }
+  // FIXME: Figure out how to remove the const pointer below.
+  ObjcMethodDecl *const*getClassMethods() const { 
+    return &ClassMethods[0];
+  }
+  int getNumClassMethods() const { return ClassMethods.size(); }
 
   ObjcMethodDecl *lookupInstanceMethod(Selector &Sel);
   ObjcMethodDecl *lookupClassMethod(Selector &Sel);

Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=43995&r1=43994&r2=43995&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Sun Nov 11 11:19:15 2007
@@ -576,19 +576,19 @@
     tok::ObjCKeywordKind impKind) {
     return 0;
   }
-  // ActOnAddMethodsToObjcDecl - called to associate methods with an interface,
-  // protocol, category, or implementation. 
-  virtual void ActOnAddMethodsToObjcDecl(
-    Scope* S, 
-    DeclTy *ClassDecl,
-    DeclTy **allMethods, 
-    unsigned allNum,
-    DeclTy **allProperties,
-    unsigned NumProperties,
-    SourceLocation AtEndLoc) {
+  // ActOnAtEnd - called to mark the @end. For declarations (interfaces,
+  // protocols, categories), the parser passes all methods/properties. 
+  // For class implementations, these values default to 0. For implementations,
+  // methods are processed incrementally (by ActOnMethodDeclaration above).
+  virtual void ActOnAtEnd(
+    SourceLocation AtEndLoc, 
+    DeclTy *classDecl,
+    DeclTy **allMethods = 0, 
+    unsigned allNum = 0,
+    DeclTy **allProperties = 0, 
+    unsigned pNum = 0) {
     return;
   }
-  
   // ActOnAddObjcProperties - called to build one property AST
   virtual DeclTy *ActOnAddObjcProperties (SourceLocation AtLoc,
     DeclTy **allProperties, unsigned NumProperties, ObjcDeclSpec &DS) {

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=43995&r1=43994&r2=43995&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Sun Nov 11 11:19:15 2007
@@ -269,8 +269,7 @@
   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);

Modified: cfe/trunk/test/Sema/message.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/message.m?rev=43995&r1=43994&r2=43995&view=diff

==============================================================================
--- cfe/trunk/test/Sema/message.m (original)
+++ cfe/trunk/test/Sema/message.m Sun Nov 11 11:19:15 2007
@@ -6,6 +6,6 @@
 
 @implementation foo
 - (void) contents {}			// No declaration in @interface!
-- (void) meth { [self contents]; } // expected-warning {{method '-contents' not found (return type defaults to 'id')}}
+- (void) meth { [self contents]; } 
 @end
 





More information about the cfe-commits mailing list