From: Argyrios Kyrtzidis Date: Mon, 15 Apr 2013 18:47:22 +0000 (+0000) Subject: Revert "Speed-up ObjCMethodDecl::getOverriddenMethods()." X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=77670f17ae3a5c3188149c19a7e386c01d0aa7c0;p=clang Revert "Speed-up ObjCMethodDecl::getOverriddenMethods()." 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 --- diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 6a03eefbba..d4878a99a6 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -328,10 +328,6 @@ class ASTContext : public RefCountedBase { typedef llvm::TinyPtrVector CXXMethodVector; llvm::DenseMap OverriddenMethods; - /// \brief Used to cache results from \c getBaseObjCCategoriesAfterInterface. - mutable llvm::DenseMap > CatsAfterInterface; - /// \brief Mapping from each declaration context to its corresponding lambda /// mangling context. llvm::DenseMap LambdaMangleContexts; @@ -686,12 +682,7 @@ public: void getOverriddenMethods( const NamedDecl *Method, SmallVectorImpl &Overridden) const; - - /// \brief Returns the ObjC categories of base classes, that were declared - /// after the given interface declaration. - void getBaseObjCCategoriesAfterInterface(const ObjCInterfaceDecl *D, - SmallVectorImpl &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); diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 8ede90dede..170cc0298b 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1127,8 +1127,8 @@ void ASTContext::getOverriddenMethods( assert(D); if (const CXXMethodDecl *CXXMethod = dyn_cast(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 &Cats) const { - if (!D) - return; - - typedef llvm::SmallVector VecTy; - typedef llvm::DenseMap MapTy; - - std::pair - 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"); diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 1fe262cc0c..5f5ba52947 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -959,6 +959,26 @@ static void collectOverriddenMethodsSlow(const ObjCMethodDecl *Method, } } +static void collectOnCategoriesAfterLocation(SourceLocation Loc, + const ObjCInterfaceDecl *Class, + SourceManager &SM, + const ObjCMethodDecl *Method, + SmallVectorImpl &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 &Methods) { assert(!Method->isOverriding()); @@ -981,11 +1001,8 @@ static void collectOverriddenMethodsFast(ASTContext &Ctx, if (!Class) return; - SmallVector Cats; - Ctx.getBaseObjCCategoriesAfterInterface(Class, Cats); - for (SmallVectorImpl::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() && diff --git a/test/SemaObjC/arc-repeated-weak.mm b/test/SemaObjC/arc-repeated-weak.mm index e652bee82d..eb818a8737 100644 --- a/test/SemaObjC/arc-repeated-weak.mm +++ b/test/SemaObjC/arc-repeated-weak.mm @@ -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;