Extend ExternalASTSource with the ability to lazily complete the
definition of an Objective-C class. Unlike with C/C++ classes, we
don't have a well-defined point in Sema where Objective-C classes are
checked for completeness, nor do we need to involve Sema when
completing a class. Therefore, we take the appropriate of having the
external AST source mark a particular Objective-C class as having an
external declaration; when using one of the accessors of an
Objective-C class that has an external declaration, we request that
the external AST source fill in the Objective-C class definition.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@120627 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp
index 5e57cf8..ea8fd4a 100644
--- a/lib/AST/DeclObjC.cpp
+++ b/lib/AST/DeclObjC.cpp
@@ -153,6 +153,9 @@
ObjCPropertyDecl *
ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass(
IdentifierInfo *PropertyId) const {
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
if (ObjCPropertyDecl *PD =
ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId))
return PD;
@@ -171,6 +174,9 @@
ObjCProtocolDecl *const* ExtList, unsigned ExtNum,
ASTContext &C)
{
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
if (AllReferencedProtocols.empty() && ReferencedProtocols.empty()) {
AllReferencedProtocols.set(ExtList, ExtNum, C);
return;
@@ -270,6 +276,9 @@
const ObjCInterfaceDecl* ClassDecl = this;
ObjCMethodDecl *MethodDecl = 0;
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
while (ClassDecl != NULL) {
if ((MethodDecl = ClassDecl->getMethod(Sel, isInstance)))
return MethodDecl;
@@ -443,11 +452,29 @@
: ObjCContainerDecl(ObjCInterface, DC, atLoc, Id),
TypeForDecl(0), SuperClass(0),
CategoryList(0), IvarList(0),
- ForwardDecl(FD), InternalInterface(isInternal),
+ ForwardDecl(FD), InternalInterface(isInternal), ExternallyCompleted(false),
ClassLoc(CLoc) {
}
+void ObjCInterfaceDecl::LoadExternalDefinition() const {
+ assert(ExternallyCompleted && "Class is not externally completed");
+ ExternallyCompleted = false;
+ getASTContext().getExternalSource()->CompleteType(
+ const_cast<ObjCInterfaceDecl *>(this));
+}
+
+void ObjCInterfaceDecl::setExternallyCompleted() {
+ assert(getASTContext().getExternalSource() &&
+ "Class can't be externally completed without an external source");
+ assert(!ForwardDecl &&
+ "Forward declarations can't be externally completed");
+ ExternallyCompleted = true;
+}
+
ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const {
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
return getASTContext().getObjCImplementation(
const_cast<ObjCInterfaceDecl*>(this));
}
@@ -506,6 +533,9 @@
///
ObjCCategoryDecl *
ObjCInterfaceDecl::FindCategoryDeclaration(IdentifierInfo *CategoryId) const {
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
for (ObjCCategoryDecl *Category = getCategoryList();
Category; Category = Category->getNextClassCategory())
if (Category->getIdentifier() == CategoryId)