diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-12-01 23:49:52 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-12-01 23:49:52 +0000 |
commit | 26ac3f30ecef21749c00a4b1a08dd15d772dd5aa (patch) | |
tree | 26f58f160501bd478a14058ed0e2981880afc1ba /lib/AST/DeclObjC.cpp | |
parent | 1ceee5c42d5c410217f67d384eecc6ea4a2bba9b (diff) |
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
Diffstat (limited to 'lib/AST/DeclObjC.cpp')
-rw-r--r-- | lib/AST/DeclObjC.cpp | 32 |
1 files changed, 31 insertions, 1 deletions
diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 5e57cf87b9..ea8fd4ae89 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -153,6 +153,9 @@ ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const { ObjCPropertyDecl * ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass( IdentifierInfo *PropertyId) const { + if (ExternallyCompleted) + LoadExternalDefinition(); + if (ObjCPropertyDecl *PD = ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId)) return PD; @@ -171,6 +174,9 @@ void ObjCInterfaceDecl::mergeClassExtensionProtocolList( 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 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel, 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 @@ ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id, : 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 @@ ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() { /// ObjCCategoryDecl * ObjCInterfaceDecl::FindCategoryDeclaration(IdentifierInfo *CategoryId) const { + if (ExternallyCompleted) + LoadExternalDefinition(); + for (ObjCCategoryDecl *Category = getCategoryList(); Category; Category = Category->getNextClassCategory()) if (Category->getIdentifier() == CategoryId) |