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
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 5d655e2..994b212 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -10472,11 +10472,12 @@
Diag(ClsIvar->getLocation(), diag::note_previous_definition);
continue;
}
- for (const ObjCCategoryDecl *ClsExtDecl =
- IDecl->getFirstClassExtension();
- ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) {
- if (const ObjCIvarDecl *ClsExtIvar =
- ClsExtDecl->getIvarDecl(ClsFields[i]->getIdentifier())) {
+ for (ObjCInterfaceDecl::known_extensions_iterator
+ Ext = IDecl->known_extensions_begin(),
+ ExtEnd = IDecl->known_extensions_end();
+ Ext != ExtEnd; ++Ext) {
+ if (const ObjCIvarDecl *ClsExtIvar
+ = Ext->getIvarDecl(ClsFields[i]->getIdentifier())) {
Diag(ClsFields[i]->getLocation(),
diag::err_duplicate_ivar_declaration);
Diag(ClsExtIvar->getLocation(), diag::note_previous_definition);