forked from OSchip/llvm-project
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. llvm-svn: 120627
This commit is contained in:
parent
560befce38
commit
73693023f0
|
@ -459,7 +459,11 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
|
|||
|
||||
bool ForwardDecl:1; // declared with @class.
|
||||
bool InternalInterface:1; // true - no @interface for @implementation
|
||||
|
||||
|
||||
/// \brief Indicates that the contents of this Objective-C class will be
|
||||
/// completed by the external AST source when required.
|
||||
mutable bool ExternallyCompleted : 1;
|
||||
|
||||
SourceLocation ClassLoc; // location of the class identifier.
|
||||
SourceLocation SuperClassLoc; // location of the super class identifier.
|
||||
SourceLocation EndLoc; // marks the '>', '}', or identifier.
|
||||
|
@ -467,6 +471,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
|
|||
ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
|
||||
SourceLocation CLoc, bool FD, bool isInternal);
|
||||
|
||||
void LoadExternalDefinition() const;
|
||||
public:
|
||||
static ObjCInterfaceDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation atLoc,
|
||||
|
@ -474,7 +479,16 @@ public:
|
|||
SourceLocation ClassLoc = SourceLocation(),
|
||||
bool ForwardDecl = false,
|
||||
bool isInternal = false);
|
||||
|
||||
/// \brief Indicate that this Objective-C class is complete, but that
|
||||
/// the external AST source will be responsible for filling in its contents
|
||||
/// when a complete class is required.
|
||||
void setExternallyCompleted();
|
||||
|
||||
const ObjCProtocolList &getReferencedProtocols() const {
|
||||
if (ExternallyCompleted)
|
||||
LoadExternalDefinition();
|
||||
|
||||
return ReferencedProtocols;
|
||||
}
|
||||
|
||||
|
@ -494,29 +508,47 @@ public:
|
|||
typedef ObjCProtocolList::iterator protocol_iterator;
|
||||
|
||||
protocol_iterator protocol_begin() const {
|
||||
if (ExternallyCompleted)
|
||||
LoadExternalDefinition();
|
||||
|
||||
return ReferencedProtocols.begin();
|
||||
}
|
||||
protocol_iterator protocol_end() const {
|
||||
if (ExternallyCompleted)
|
||||
LoadExternalDefinition();
|
||||
|
||||
return ReferencedProtocols.end();
|
||||
}
|
||||
|
||||
typedef ObjCProtocolList::loc_iterator protocol_loc_iterator;
|
||||
|
||||
protocol_loc_iterator protocol_loc_begin() const {
|
||||
if (ExternallyCompleted)
|
||||
LoadExternalDefinition();
|
||||
|
||||
return ReferencedProtocols.loc_begin();
|
||||
}
|
||||
|
||||
protocol_loc_iterator protocol_loc_end() const {
|
||||
if (ExternallyCompleted)
|
||||
LoadExternalDefinition();
|
||||
|
||||
return ReferencedProtocols.loc_end();
|
||||
}
|
||||
|
||||
typedef ObjCList<ObjCProtocolDecl>::iterator all_protocol_iterator;
|
||||
|
||||
all_protocol_iterator all_referenced_protocol_begin() const {
|
||||
if (ExternallyCompleted)
|
||||
LoadExternalDefinition();
|
||||
|
||||
return AllReferencedProtocols.empty() ? protocol_begin()
|
||||
: AllReferencedProtocols.begin();
|
||||
}
|
||||
all_protocol_iterator all_referenced_protocol_end() const {
|
||||
if (ExternallyCompleted)
|
||||
LoadExternalDefinition();
|
||||
|
||||
return AllReferencedProtocols.empty() ? protocol_end()
|
||||
: AllReferencedProtocols.end();
|
||||
}
|
||||
|
@ -551,10 +583,22 @@ public:
|
|||
bool isForwardDecl() const { return ForwardDecl; }
|
||||
void setForwardDecl(bool val) { ForwardDecl = val; }
|
||||
|
||||
ObjCInterfaceDecl *getSuperClass() const { return SuperClass; }
|
||||
ObjCInterfaceDecl *getSuperClass() const {
|
||||
if (ExternallyCompleted)
|
||||
LoadExternalDefinition();
|
||||
|
||||
return SuperClass;
|
||||
}
|
||||
|
||||
void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; }
|
||||
|
||||
ObjCCategoryDecl* getCategoryList() const { return CategoryList; }
|
||||
ObjCCategoryDecl* getCategoryList() const {
|
||||
if (ExternallyCompleted)
|
||||
LoadExternalDefinition();
|
||||
|
||||
return CategoryList;
|
||||
}
|
||||
|
||||
void setCategoryList(ObjCCategoryDecl *category) {
|
||||
CategoryList = category;
|
||||
}
|
||||
|
|
|
@ -147,6 +147,14 @@ public:
|
|||
/// an incomplete type.
|
||||
virtual void CompleteType(TagDecl *Tag) {}
|
||||
|
||||
/// \brief Gives the external AST source an opportunity to complete an
|
||||
/// incomplete Objective-C class.
|
||||
///
|
||||
/// This routine will only be invoked if the "externally completed" bit is
|
||||
/// set on the ObjCInterfaceDecl via the function
|
||||
/// \c ObjCInterfaceDecl::setExternallyCompleted().
|
||||
virtual void CompleteType(ObjCInterfaceDecl *Class) { }
|
||||
|
||||
/// \brief Notify ExternalASTSource that we started deserialization of
|
||||
/// a decl or type so until FinishedDeserializing is called there may be
|
||||
/// decls that are initializing. Must be paired with FinishedDeserializing.
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue