]> granicus.if.org Git - clang/commitdiff
- Added Sema::AddFactoryMethodToGlobalPool and Sema::AddInstanceMethodToGlobalPool...
authorSteve Naroff <snaroff@apple.com>
Sun, 14 Oct 2007 00:58:41 +0000 (00:58 +0000)
committerSteve Naroff <snaroff@apple.com>
Sun, 14 Oct 2007 00:58:41 +0000 (00:58 +0000)
- Fixed some funky "}
                    else {" indentation in Sema::ActOnAddMethodsToObjcDecl(). I'd prefer we stay away from this style...it wastes space and isn't any easier to read (from my perspective, at least:-)

- Changed Parser::ParseObjCInterfaceDeclList() to only call Action::ActOnAddMethodsToObjcDecl() when it actually has methods to add (since most interface have methods, this is a very minor cleanup).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@42957 91177308-0d34-0410-b5e6-96231b3b80d8

Parse/ParseObjc.cpp
Sema/ASTStreamer.cpp
Sema/Sema.h
Sema/SemaDecl.cpp
include/clang/Parse/Action.h

index bfd6797c964c95db6d279b9aea8cd3dcdd37c25c..4236314fdf91dcfa6c857b14821fa72924850e25 100644 (file)
@@ -266,9 +266,10 @@ void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl,
       ParseDeclarationOrFunctionDefinition();
     }
   }
-  /// Insert collected methods declarations into the @interface object.
-  Actions.ActOnAddMethodsToObjcDecl(CurScope, interfaceDecl,
-                                    &allMethods[0], allMethods.size());
+  if (allMethods.size())
+    /// Insert collected methods declarations into the @interface object.
+    Actions.ActOnAddMethodsToObjcDecl(CurScope, interfaceDecl,
+                                      &allMethods[0], allMethods.size());
 }
 
 ///   Parse property attribute declarations.
index b622d2887a54ffc6c2c93cd8a6aba2adf636c58b..facd5bccaa9b9a20a14d31b7177f266c90c55520 100644 (file)
@@ -81,6 +81,7 @@ Decl *ASTStreamer::ReadTopLevelDecl() {
 }
 
 void ASTStreamer::PrintStats() const {
+  P.getActions().PrintStats();
 }
 
 //===----------------------------------------------------------------------===//
index 511b43a1bb734083dddfe9911f6d596adbd5a208..94d22f074211b4169ea143948f7a2456f9ad79a0 100644 (file)
@@ -120,6 +120,27 @@ class Sema : public Action {
   
   /// ObjcIdTypedef - built-in typedef for "id".
   TypedefDecl *ObjcIdTypedef;
+
+  /// ObjCMethodList - a linked list of methods with different signatures.
+  struct ObjcMethodList {
+    ObjcMethodDecl *Method;
+    ObjcMethodList *Next;
+    
+    ObjcMethodList() {
+      Method = 0; 
+      Next = 0;
+    }
+    ObjcMethodList(ObjcMethodDecl *M, ObjcMethodList *C) {
+      Method = M;
+      Next = C;
+    }
+  };
+  /// Instance/Factory Method Pools - allows efficient lookup when typechecking
+  /// messages to "id". We need to maintain a list, since selectors can have
+  /// differing signatures across classes. In Cocoa, this happens to be 
+  /// extremely uncommon (only 1% of selectors are "overloaded").
+  llvm::DenseMap<Selector, ObjcMethodList> InstanceMethodPool;
+  llvm::DenseMap<Selector, ObjcMethodList> FactoryMethodPool;
 public:
   Sema(Preprocessor &pp, ASTContext &ctxt, std::vector<Decl*> &prevInGroup);
   
@@ -259,6 +280,14 @@ private:
   /// GetObjcIdType - Getter for the build-in "id" type.
   QualType GetObjcIdType(SourceLocation Loc = SourceLocation());
   
+  /// AddInstanceMethodToGlobalPool - All instance methods in a translation
+  /// unit are added to a global pool. This allows us to efficiently associate
+  /// a selector with a method declaraation for purposes of typechecking
+  /// messages sent to "id" (where the class of the object is unknown).
+  void AddInstanceMethodToGlobalPool(ObjcMethodDecl *Method);
+  
+  /// AddFactoryMethodToGlobalPool - Same as above, but for factory methods.
+  void AddFactoryMethodToGlobalPool(ObjcMethodDecl *Method);
   //===--------------------------------------------------------------------===//
   // Statement Parsing Callbacks: SemaStmt.cpp.
 public:
index 472df150e8b5965beabf81547e3167cdb65d4570..ef99564dac5cf75c2d9b12e73027f8b8753ea32e 100644 (file)
@@ -1754,6 +1754,52 @@ bool Sema:: MatchTwoMethodDeclarations(const ObjcMethodDecl *Method,
   return true;
 }
 
+void Sema::AddInstanceMethodToGlobalPool(ObjcMethodDecl *Method) {
+  ObjcMethodList &FirstMethod = InstanceMethodPool[Method->getSelector()];
+  if (!FirstMethod.Method) {
+    // Haven't seen a method with this selector name yet - add it.
+    FirstMethod.Method = Method;
+    FirstMethod.Next = 0;
+  } else {
+    // We've seen a method with this name, now check the type signature(s).
+    bool match = MatchTwoMethodDeclarations(Method, FirstMethod.Method);
+    
+    for (ObjcMethodList *Next = FirstMethod.Next; !match && Next; 
+         Next = Next->Next)
+      match = MatchTwoMethodDeclarations(Method, Next->Method);
+      
+    if (!match) {
+      // We have a new signature for an existing method - add it.
+      // This is extremely rare. Only 1% of Cocoa selectors are "overloaded".
+      struct ObjcMethodList *OMI = new ObjcMethodList(Method, FirstMethod.Next);
+      FirstMethod.Next = OMI;
+    }
+  }
+}
+
+void Sema::AddFactoryMethodToGlobalPool(ObjcMethodDecl *Method) {
+  ObjcMethodList &FirstMethod = FactoryMethodPool[Method->getSelector()];
+  if (!FirstMethod.Method) {
+    // Haven't seen a method with this selector name yet - add it.
+    FirstMethod.Method = Method;
+    FirstMethod.Next = 0;
+  } else {
+    // We've seen a method with this name, now check the type signature(s).
+    bool match = MatchTwoMethodDeclarations(Method, FirstMethod.Method);
+    
+    for (ObjcMethodList *Next = FirstMethod.Next; !match && Next; 
+         Next = Next->Next)
+      match = MatchTwoMethodDeclarations(Method, Next->Method);
+      
+    if (!match) {
+      // We have a new signature for an existing method - add it.
+      // This is extremely rare. Only 1% of Cocoa selectors are "overloaded".
+      struct ObjcMethodList *OMI = new ObjcMethodList(Method, FirstMethod.Next);
+      FirstMethod.Next = OMI;
+    }
+  }
+}
+
 void Sema::ActOnAddMethodsToObjcDecl(Scope* S, DeclTy *classDecl,
                                      DeclTy **allMethods, unsigned allNum) {
   Decl *ClassDecl = static_cast<Decl *>(classDecl);
@@ -1777,6 +1823,7 @@ void Sema::ActOnAddMethodsToObjcDecl(Scope* S, DeclTy *classDecl,
   for (unsigned i = 0; i < allNum; i++ ) {
     ObjcMethodDecl *Method =
       cast_or_null<ObjcMethodDecl>(static_cast<Decl*>(allMethods[i]));
+
     if (!Method) continue;  // Already issued a diagnostic.
     if (Method->isInstance()) {
       if (checkDuplicateMethods) {
@@ -1786,16 +1833,17 @@ void Sema::ActOnAddMethodsToObjcDecl(Scope* S, DeclTy *classDecl,
           Diag(Method->getLocation(), diag::error_duplicate_method_decl,
                Method->getSelector().getName());
           Diag(PrevMethod->getLocation(), diag::err_previous_declaration);
-        }
-        else {
+        } else {
           insMethods.push_back(Method);
           InsMap[Method->getSelector()] = Method;
         }
       }
       else
         insMethods.push_back(Method);
-    }
-    else {
+        
+      /// The following allows us to typecheck messages to "id".
+      AddInstanceMethodToGlobalPool(Method);
+    } else {
       if (checkDuplicateMethods) {
         /// Check for class method of the same name with incompatible types
         const ObjcMethodDecl *&PrevMethod = ClsMap[Method->getSelector()];
@@ -1803,14 +1851,16 @@ void Sema::ActOnAddMethodsToObjcDecl(Scope* S, DeclTy *classDecl,
           Diag(Method->getLocation(), diag::error_duplicate_method_decl,
                Method->getSelector().getName());
           Diag(PrevMethod->getLocation(), diag::err_previous_declaration);
-        }
-        else {        
+        } else {        
           clsMethods.push_back(Method);
           ClsMap[Method->getSelector()] = Method;
         }
       }
       else
         clsMethods.push_back(Method);
+        
+      /// The following allows us to typecheck messages to "id".
+      AddFactoryMethodToGlobalPool(Method);
     }
   }
   
index 509e0a28139f4461265431585db8e6258ad8ee98..2113871f39621e638f04a94ab54731a10eabf1c4 100644 (file)
@@ -85,6 +85,8 @@ public:
   virtual void DeleteExpr(ExprTy *E) {}
   virtual void DeleteStmt(StmtTy *E) {}
   
+  /// Statistics.
+  virtual void PrintStats() const {}
   //===--------------------------------------------------------------------===//
   // Declaration Tracking Callbacks.
   //===--------------------------------------------------------------------===//