Rework the traversal of Objective-C categories and extensions to

consider (sub)module visibility.

The bulk of this change replaces myriad hand-rolled loops over the
linked list of Objective-C categories/extensions attached to an
interface declaration with loops using one of the four new category
iterator kinds:

  visible_categories_iterator: Iterates over all visible categories
  and extensions, hiding any that have their "hidden" bit set. This is
  by far the most commonly used iterator.

  known_categories_iterator: Iterates over all categories and
  extensions, ignoring the "hidden" bit. This tends to be used for
  redeclaration-like traversals.

  visible_extensions_iterator: Iterates over all visible extensions,
  hiding any that have their "hidden" bit set.

  known_extensions_iterator: Iterates over all extensions, whether
  they are visible to normal name lookup or not.

The effect of this change is that any uses of the visible_ iterators
will respect module-import visibility. See the new tests for examples.

Note that the old accessors for categories and extensions are gone;
there are *Raw() forms for some of them, for those (few) areas of the
compiler that have to manipulate the linked list of categories
directly. This is generally discouraged.

Part two of <rdar://problem/10634711>.
 

llvm-svn: 172665
This commit is contained in:
Douglas Gregor
2013-01-16 23:00:23 +00:00
parent e8baf33712
commit 048fbfa302
23 changed files with 533 additions and 222 deletions

View File

@@ -3433,9 +3433,11 @@ static void AddObjCProperties(ObjCContainerDecl *Container,
} else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
if (AllowCategories) {
// Look through categories.
for (ObjCCategoryDecl *Category = IFace->getCategoryList();
Category; Category = Category->getNextClassCategory())
AddObjCProperties(Category, AllowCategories, AllowNullaryMethods,
for (ObjCInterfaceDecl::known_categories_iterator
Cat = IFace->known_categories_begin(),
CatEnd = IFace->known_categories_end();
Cat != CatEnd; ++Cat)
AddObjCProperties(*Cat, AllowCategories, AllowNullaryMethods,
CurContext, AddedProperties, Results);
}
@@ -4806,9 +4808,13 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
CurContext, Selectors, AllowSameLength, Results, false);
// Add methods in categories.
for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl;
CatDecl = CatDecl->getNextClassCategory()) {
AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
for (ObjCInterfaceDecl::known_categories_iterator
Cat = IFace->known_categories_begin(),
CatEnd = IFace->known_categories_end();
Cat != CatEnd; ++Cat) {
ObjCCategoryDecl *CatDecl = *Cat;
AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
NumSelIdents, CurContext, Selectors, AllowSameLength,
Results, InOriginalClass);
@@ -5076,11 +5082,14 @@ static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
// Check in categories or class extensions.
if (!SuperMethod) {
for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
Category = Category->getNextClassCategory())
if ((SuperMethod = Category->getMethod(CurMethod->getSelector(),
for (ObjCInterfaceDecl::known_categories_iterator
Cat = Class->known_categories_begin(),
CatEnd = Class->known_categories_end();
Cat != CatEnd; ++Cat) {
if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),
CurMethod->isInstanceMethod())))
break;
}
}
}
@@ -5807,11 +5816,15 @@ void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
NamedDecl *CurClass
= LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass))
for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
Category = Category->getNextClassCategory())
CategoryNames.insert(Category->getIdentifier());
if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)){
for (ObjCInterfaceDecl::visible_categories_iterator
Cat = Class->visible_categories_begin(),
CatEnd = Class->visible_categories_end();
Cat != CatEnd; ++Cat) {
CategoryNames.insert(Cat->getIdentifier());
}
}
// Add all of the categories we know about.
Results.EnterNewScope();
TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
@@ -5853,11 +5866,14 @@ void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Results.EnterNewScope();
bool IgnoreImplemented = true;
while (Class) {
for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
Category = Category->getNextClassCategory())
if ((!IgnoreImplemented || !Category->getImplementation()) &&
CategoryNames.insert(Category->getIdentifier()))
Results.AddResult(Result(Category, 0), CurContext, 0, false);
for (ObjCInterfaceDecl::visible_categories_iterator
Cat = Class->visible_categories_begin(),
CatEnd = Class->visible_categories_end();
Cat != CatEnd; ++Cat) {
if ((!IgnoreImplemented || !Cat->getImplementation()) &&
CategoryNames.insert(Cat->getIdentifier()))
Results.AddResult(Result(*Cat, 0), CurContext, 0, false);
}
Class = Class->getSuperClass();
IgnoreImplemented = false;
@@ -6033,12 +6049,14 @@ static void FindImplementableMethods(ASTContext &Context,
KnownMethods, InOriginalClass);
// Add methods from any class extensions and categories.
for (const ObjCCategoryDecl *Cat = IFace->getCategoryList(); Cat;
Cat = Cat->getNextClassCategory())
FindImplementableMethods(Context, const_cast<ObjCCategoryDecl*>(Cat),
WantInstanceMethods, ReturnType,
for (ObjCInterfaceDecl::visible_categories_iterator
Cat = IFace->visible_categories_begin(),
CatEnd = IFace->visible_categories_end();
Cat != CatEnd; ++Cat) {
FindImplementableMethods(Context, *Cat, WantInstanceMethods, ReturnType,
KnownMethods, false);
}
// Visit the superclass.
if (IFace->getSuperClass())
FindImplementableMethods(Context, IFace->getSuperClass(),
@@ -6898,9 +6916,12 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,
IFace = Category->getClassInterface();
if (IFace) {
for (ObjCCategoryDecl *Category = IFace->getCategoryList(); Category;
Category = Category->getNextClassCategory())
Containers.push_back(Category);
for (ObjCInterfaceDecl::visible_categories_iterator
Cat = IFace->visible_categories_begin(),
CatEnd = IFace->visible_categories_end();
Cat != CatEnd; ++Cat) {
Containers.push_back(*Cat);
}
}
for (unsigned I = 0, N = Containers.size(); I != N; ++I) {