]> granicus.if.org Git - clang/commitdiff
Revert "Speed-up ObjCMethodDecl::getOverriddenMethods()."
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Mon, 15 Apr 2013 18:47:22 +0000 (18:47 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Mon, 15 Apr 2013 18:47:22 +0000 (18:47 +0000)
This reverts commit r179436.

Due to caching, it was possible that we could miss overridden methods that
were introduced by categories later on.

Along with reverting the commit I also included a test case that would have caught this.

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

include/clang/AST/ASTContext.h
lib/AST/ASTContext.cpp
lib/AST/DeclObjC.cpp
test/SemaObjC/arc-repeated-weak.mm

index 6a03eefbba37b9d9ca24e9bfc11a40aed7babbef..d4878a99a6fe8168cc7ac50561a1af22ba602d40 100644 (file)
@@ -328,10 +328,6 @@ class ASTContext : public RefCountedBase<ASTContext> {
   typedef llvm::TinyPtrVector<const CXXMethodDecl*> CXXMethodVector;
   llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector> OverriddenMethods;
 
-  /// \brief Used to cache results from \c getBaseObjCCategoriesAfterInterface.
-  mutable llvm::DenseMap<const ObjCInterfaceDecl *,
-            llvm::SmallVector<const ObjCCategoryDecl *, 2> > CatsAfterInterface;
-
   /// \brief Mapping from each declaration context to its corresponding lambda 
   /// mangling context.
   llvm::DenseMap<const DeclContext *, LambdaMangleContext> LambdaMangleContexts;
@@ -686,12 +682,7 @@ public:
   void getOverriddenMethods(
                         const NamedDecl *Method,
                         SmallVectorImpl<const NamedDecl *> &Overridden) const;
-
-  /// \brief Returns the ObjC categories of base classes, that were declared
-  /// after the given interface declaration.
-  void getBaseObjCCategoriesAfterInterface(const ObjCInterfaceDecl *D,
-                         SmallVectorImpl<const ObjCCategoryDecl *> &Cats) const;
-
+  
   /// \brief Notify the AST context that a new import declaration has been
   /// parsed or implicitly created within this translation unit.
   void addedLocalImportDecl(ImportDecl *Import);
index 8ede90dede4b814977e9e77f8d1bde5ebed95a1b..170cc0298b3a716c368ce418d5516c54b87fb120 100644 (file)
@@ -1127,8 +1127,8 @@ void ASTContext::getOverriddenMethods(
   assert(D);
 
   if (const CXXMethodDecl *CXXMethod = dyn_cast<CXXMethodDecl>(D)) {
-    Overridden.append(overridden_methods_begin(CXXMethod),
-                      overridden_methods_end(CXXMethod));
+    Overridden.append(CXXMethod->begin_overridden_methods(),
+                      CXXMethod->end_overridden_methods());
     return;
   }
 
@@ -1141,39 +1141,6 @@ void ASTContext::getOverriddenMethods(
   Overridden.append(OverDecls.begin(), OverDecls.end());
 }
 
-void ASTContext::getBaseObjCCategoriesAfterInterface(
-                        const ObjCInterfaceDecl *D,
-                        SmallVectorImpl<const ObjCCategoryDecl *> &Cats) const {
-  if (!D)
-    return;
-  
-  typedef llvm::SmallVector<const ObjCCategoryDecl *, 2> VecTy;
-  typedef llvm::DenseMap<const ObjCInterfaceDecl *, VecTy> MapTy;
-  
-  std::pair<MapTy::iterator, bool>
-    InsertOp = CatsAfterInterface.insert(std::make_pair(D, VecTy()));
-  VecTy &Vec = InsertOp.first->second;
-  if (!InsertOp.second) {
-    // already in map.
-    Cats.append(Vec.begin(), Vec.end());
-    return;
-  }
-  
-  SourceLocation Loc = D->getLocation();
-  for (const ObjCInterfaceDecl *
-         Class = D->getSuperClass(); Class; Class = Class->getSuperClass()) {
-    for (ObjCInterfaceDecl::known_categories_iterator
-           CatI = Class->known_categories_begin(),
-           CatEnd = Class->known_categories_end();
-         CatI != CatEnd; ++CatI) {
-      if (SourceMgr.isBeforeInTranslationUnit(Loc, CatI->getLocation()))
-        Vec.push_back(*CatI);
-    }
-  }
-
-  Cats.append(Vec.begin(), Vec.end());
-}
-
 void ASTContext::addedLocalImportDecl(ImportDecl *Import) {
   assert(!Import->NextLocalImport && "Import declaration already in the chain");
   assert(!Import->isFromASTFile() && "Non-local import declaration");
index 1fe262cc0c8ceed3a57f62a8c4b80845b90e39cf..5f5ba52947d6f4da23f5c889d6cffa00a528a486 100644 (file)
@@ -959,6 +959,26 @@ static void collectOverriddenMethodsSlow(const ObjCMethodDecl *Method,
   }
 }
 
+static void collectOnCategoriesAfterLocation(SourceLocation Loc,
+                                             const ObjCInterfaceDecl *Class,
+                                             SourceManager &SM,
+                                             const ObjCMethodDecl *Method,
+                             SmallVectorImpl<const ObjCMethodDecl *> &Methods) {
+  if (!Class)
+    return;
+
+  for (ObjCInterfaceDecl::known_categories_iterator
+         Cat = Class->known_categories_begin(),
+         CatEnd = Class->known_categories_end();
+       Cat != CatEnd; ++Cat) {
+    if (SM.isBeforeInTranslationUnit(Loc, Cat->getLocation()))
+      CollectOverriddenMethodsRecurse(*Cat, Method, Methods, true);
+  }
+  
+  collectOnCategoriesAfterLocation(Loc, Class->getSuperClass(), SM,
+                                   Method, Methods);
+}
+
 /// \brief Faster collection that is enabled when ObjCMethodDecl::isOverriding()
 /// returns false.
 /// You'd think that in that case there are no overrides but categories can
@@ -968,7 +988,7 @@ static void collectOverriddenMethodsSlow(const ObjCMethodDecl *Method,
 /// further in super classes.
 /// Methods in an implementation can overide methods in super class's category
 /// but not in current class's category. But, such methods
-static void collectOverriddenMethodsFast(ASTContext &Ctx,
+static void collectOverriddenMethodsFast(SourceManager &SM,
                                          const ObjCMethodDecl *Method,
                              SmallVectorImpl<const ObjCMethodDecl *> &Methods) {
   assert(!Method->isOverriding());
@@ -981,11 +1001,8 @@ static void collectOverriddenMethodsFast(ASTContext &Ctx,
   if (!Class)
     return;
 
-  SmallVector<const ObjCCategoryDecl *, 32> Cats;
-  Ctx.getBaseObjCCategoriesAfterInterface(Class, Cats);
-  for (SmallVectorImpl<const ObjCCategoryDecl *>::iterator
-         I = Cats.begin(), E = Cats.end(); I != E; ++I)
-    CollectOverriddenMethodsRecurse(*I, Method, Methods, true);
+  collectOnCategoriesAfterLocation(Class->getLocation(), Class->getSuperClass(),
+                                   SM, Method, Methods);
 }
 
 void ObjCMethodDecl::getOverriddenMethods(
@@ -998,7 +1015,8 @@ void ObjCMethodDecl::getOverriddenMethods(
   }
 
   if (!Method->isOverriding()) {
-    collectOverriddenMethodsFast(getASTContext(), Method, Overridden);
+    collectOverriddenMethodsFast(getASTContext().getSourceManager(),
+                                 Method, Overridden);
   } else {
     collectOverriddenMethodsSlow(Method, Overridden);
     assert(!Overridden.empty() &&
index e652bee82d535f0b6c926a3a0cf3220d26e7541c..eb818a87376dd890fb889e2ef5b581639ed5b2f2 100644 (file)
@@ -327,6 +327,28 @@ void doWhileLoop(Test *a) {
 }
 @end
 
+@interface Base1
+@end
+@interface Sub1 : Base1
+@end
+@interface Sub1(cat)
+-(id)prop;
+@end
+
+void test1(Sub1 *s) {
+  use([s prop]);
+  use([s prop]);
+}
+
+@interface Base1(cat)
+@property (weak) id prop;
+@end
+
+void test2(Sub1 *s) {
+  use([s prop]); // expected-warning{{weak property 'prop' is accessed multiple times}}
+  use([s prop]); // expected-note{{also accessed here}}
+}
+
 
 class Wrapper {
   Test *a;