зеркало из https://github.com/microsoft/clang-1.git
Introduce the core infrastructure needed to model a complete
redeclaration chain for Objective-C classes, including: - Using the first declaration as the canonical declaration. - Using the definition as the primary DeclContext - Making sure that all declarations have a pointer to the definition data, and the definition knows that it is the definition. - Serialization support for when a definition gets added to a declaration that comes from an AST file. However, note that we're not taking advantage of much of this code yet, because we're still re-using ObjCInterfaceDecls. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146667 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
7ab8ef99e6
Коммит
53df7a1d34
|
@ -540,7 +540,8 @@ public:
|
|||
/// Unlike C++, ObjC is a single-rooted class model. In Cocoa, classes
|
||||
/// typically inherit from NSObject (an exception is NSProxy).
|
||||
///
|
||||
class ObjCInterfaceDecl : public ObjCContainerDecl {
|
||||
class ObjCInterfaceDecl : public ObjCContainerDecl
|
||||
, public Redeclarable<ObjCInterfaceDecl> {
|
||||
/// TypeForDecl - This indicates the Type object that represents this
|
||||
/// TypeDecl. It is a cache maintained by ASTContext::getObjCInterfaceType
|
||||
mutable const Type *TypeForDecl;
|
||||
|
@ -584,7 +585,10 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
|
|||
|
||||
/// \brief Contains a pointer to the data associated with this class,
|
||||
/// which will be NULL if this class has not yet been defined.
|
||||
DefinitionData *Definition;
|
||||
///
|
||||
/// The boolean value indicates whether this particular declaration is
|
||||
/// also the definition.
|
||||
llvm::PointerIntPair<DefinitionData *, 1, bool> Definition;
|
||||
|
||||
/// \brief The location of the last location in this declaration, e.g.,
|
||||
/// the '>', '}', or identifier.
|
||||
|
@ -598,13 +602,18 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
|
|||
bool InitiallyForwardDecl : 1;
|
||||
|
||||
DefinitionData &data() const {
|
||||
assert(Definition != 0 && "Declaration is not a definition!");
|
||||
return *Definition;
|
||||
assert(Definition.getPointer() != 0 && "Declaration is not a definition!");
|
||||
return *Definition.getPointer();
|
||||
}
|
||||
|
||||
/// \brief Allocate the definition data for this class.
|
||||
void allocateDefinitionData();
|
||||
|
||||
typedef Redeclarable<ObjCInterfaceDecl> redeclarable_base;
|
||||
virtual ObjCInterfaceDecl *getNextRedeclaration() {
|
||||
return RedeclLink.getNext();
|
||||
}
|
||||
|
||||
public:
|
||||
static ObjCInterfaceDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation atLoc,
|
||||
|
@ -771,11 +780,15 @@ public:
|
|||
|
||||
/// \brief Determine whether this declaration is a forward declaration of
|
||||
/// the class.
|
||||
bool isForwardDecl() const { return Definition == 0; }
|
||||
bool isForwardDecl() const { return !Definition.getInt(); }
|
||||
|
||||
/// \brief Determine whether this particular declaration of this class is
|
||||
/// actually also a definition.
|
||||
bool isThisDeclarationADefinition() const { return Definition.getInt(); }
|
||||
|
||||
/// \brief Determine whether this class has been defined.
|
||||
bool hasDefinition() const { return Definition != 0; }
|
||||
|
||||
bool hasDefinition() const { return Definition.getPointer() != 0; }
|
||||
|
||||
/// \brief Retrieve the definition of this class, or NULL if this class
|
||||
/// has been forward-declared (with @class) but not yet defined (with
|
||||
/// @interface).
|
||||
|
@ -896,6 +909,22 @@ public:
|
|||
bool lookupCategory,
|
||||
bool RHSIsQualifiedID = false);
|
||||
|
||||
typedef redeclarable_base::redecl_iterator redecl_iterator;
|
||||
redecl_iterator redecls_begin() const {
|
||||
return redeclarable_base::redecls_begin();
|
||||
}
|
||||
redecl_iterator redecls_end() const {
|
||||
return redeclarable_base::redecls_end();
|
||||
}
|
||||
|
||||
/// Retrieves the canonical declaration of this Objective-C class.
|
||||
ObjCInterfaceDecl *getCanonicalDecl() {
|
||||
return getFirstDeclaration();
|
||||
}
|
||||
const ObjCInterfaceDecl *getCanonicalDecl() const {
|
||||
return getFirstDeclaration();
|
||||
}
|
||||
|
||||
// Low-level accessor
|
||||
const Type *getTypeForDecl() const { return TypeForDecl; }
|
||||
void setTypeForDecl(const Type *TD) const { TypeForDecl = TD; }
|
||||
|
|
|
@ -779,9 +779,16 @@ DeclContext *DeclContext::getPrimaryContext() {
|
|||
return this;
|
||||
|
||||
case Decl::ObjCInterface:
|
||||
if (ObjCInterfaceDecl *Def = cast<ObjCInterfaceDecl>(this)->getDefinition())
|
||||
return Def;
|
||||
|
||||
return this;
|
||||
|
||||
case Decl::ObjCProtocol:
|
||||
// FIXME: Update when protocols properly model forward declarations.
|
||||
// For now, it's fine to fall through
|
||||
|
||||
case Decl::ObjCCategory:
|
||||
// FIXME: Can Objective-C interfaces be forward-declared?
|
||||
return this;
|
||||
|
||||
case Decl::ObjCImplementation:
|
||||
|
|
|
@ -224,7 +224,15 @@ void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
|
|||
|
||||
void ObjCInterfaceDecl::allocateDefinitionData() {
|
||||
assert(!hasDefinition() && "ObjC class already has a definition");
|
||||
Definition = new (getASTContext()) DefinitionData();
|
||||
Definition.setPointer(new (getASTContext()) DefinitionData());
|
||||
Definition.setInt(true);
|
||||
|
||||
// Update all of the declarations with a pointer to the definition.
|
||||
for (redecl_iterator RD = redecls_begin(), RDEnd = redecls_end();
|
||||
RD != RDEnd; ++RD) {
|
||||
if (*RD != this)
|
||||
RD->Definition.setPointer(Definition.getPointer());
|
||||
}
|
||||
}
|
||||
|
||||
void ObjCInterfaceDecl::startDefinition() {
|
||||
|
|
|
@ -26,7 +26,8 @@ enum DeclUpdateKind {
|
|||
UPD_CXX_ADDED_IMPLICIT_MEMBER,
|
||||
UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION,
|
||||
UPD_CXX_ADDED_ANONYMOUS_NAMESPACE,
|
||||
UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER
|
||||
UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER,
|
||||
UPD_OBJC_SET_CLASS_DEFINITIONDATA
|
||||
};
|
||||
|
||||
TypeIdx TypeIdxFromBuiltin(const BuiltinType *BT);
|
||||
|
|
|
@ -554,6 +554,7 @@ void ASTDeclReader::VisitObjCContainerDecl(ObjCContainerDecl *CD) {
|
|||
}
|
||||
|
||||
void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
|
||||
VisitRedeclarable(ID);
|
||||
VisitObjCContainerDecl(ID);
|
||||
ID->setTypeForDecl(Reader.readType(F, Record, Idx).getTypePtrOrNull());
|
||||
|
||||
|
@ -618,10 +619,9 @@ void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
|
|||
// pending references were linked.
|
||||
Reader.PendingForwardRefs.erase(ID);
|
||||
#endif
|
||||
|
||||
} else if (Def) {
|
||||
if (Def->Definition) {
|
||||
ID->Definition = Def->Definition;
|
||||
if (Def->Definition.getPointer()) {
|
||||
ID->Definition.setPointer(Def->Definition.getPointer());
|
||||
} else {
|
||||
// The definition is still initializing.
|
||||
Reader.PendingForwardRefs[Def].push_back(ID);
|
||||
|
@ -2067,6 +2067,19 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
|
|||
cast<VarDecl>(D)->getMemberSpecializationInfo()->setPointOfInstantiation(
|
||||
Reader.ReadSourceLocation(ModuleFile, Record, Idx));
|
||||
break;
|
||||
|
||||
case UPD_OBJC_SET_CLASS_DEFINITIONDATA: {
|
||||
ObjCInterfaceDecl *ID = cast<ObjCInterfaceDecl>(D);
|
||||
ObjCInterfaceDecl *Def
|
||||
= Reader.ReadDeclAs<ObjCInterfaceDecl>(ModuleFile, Record, Idx);
|
||||
if (Def->Definition.getPointer()) {
|
||||
ID->Definition.setPointer(Def->Definition.getPointer());
|
||||
} else {
|
||||
// The definition is still initializing.
|
||||
Reader.PendingForwardRefs[Def].push_back(ID);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3439,6 +3439,7 @@ void ASTWriter::ResolveDeclUpdatesBlocks() {
|
|||
case UPD_CXX_ADDED_IMPLICIT_MEMBER:
|
||||
case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION:
|
||||
case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE:
|
||||
case UPD_OBJC_SET_CLASS_DEFINITIONDATA:
|
||||
URec[Idx] = GetDeclRef(reinterpret_cast<Decl *>(URec[Idx]));
|
||||
++Idx;
|
||||
break;
|
||||
|
@ -4379,10 +4380,26 @@ void ASTWriter::AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
|
|||
|
||||
void ASTWriter::CompletedObjCForwardRef(const ObjCContainerDecl *D) {
|
||||
assert(!WritingAST && "Already writing the AST!");
|
||||
if (!D->isFromASTFile())
|
||||
return; // Declaration not imported from PCH.
|
||||
if (D->isFromASTFile())
|
||||
RewriteDecl(D);
|
||||
|
||||
RewriteDecl(D);
|
||||
if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
|
||||
for (ObjCInterfaceDecl::redecl_iterator I = ID->redecls_begin(),
|
||||
E = ID->redecls_end();
|
||||
I != E; ++I) {
|
||||
if (*I == ID)
|
||||
continue;
|
||||
|
||||
// We are interested when a PCH decl is modified.
|
||||
if (I->isFromASTFile()) {
|
||||
UpdateRecord &Record = DeclUpdates[*I];
|
||||
Record.push_back(UPD_OBJC_SET_CLASS_DEFINITIONDATA);
|
||||
assert((*I)->hasDefinition());
|
||||
assert((*I)->getDefinition() == D);
|
||||
Record.push_back(reinterpret_cast<uint64_t>(D)); // the DefinitionDecl
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ASTWriter::AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop,
|
||||
|
|
|
@ -447,6 +447,7 @@ void ASTDeclWriter::VisitObjCContainerDecl(ObjCContainerDecl *D) {
|
|||
}
|
||||
|
||||
void ASTDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
|
||||
VisitRedeclarable(D);
|
||||
VisitObjCContainerDecl(D);
|
||||
Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче