Extend ObjCInterfaceDecl::DefinitionData to contain a pointer to the

definition, and implement ObjCInterfaceDecl::getDefinition()
efficiently based on that.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146669 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Douglas Gregor 2011-12-15 18:17:27 +00:00
Родитель 36370f58d8
Коммит 26fec63b14
3 изменённых файлов: 26 добавлений и 24 удалений

Просмотреть файл

@ -548,6 +548,10 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
friend class ASTContext; friend class ASTContext;
struct DefinitionData { struct DefinitionData {
/// \brief The definition of this class, for quick access from any
/// declaration.
ObjCInterfaceDecl *Definition;
/// Class's super class. /// Class's super class.
ObjCInterfaceDecl *SuperClass; ObjCInterfaceDecl *SuperClass;
@ -574,7 +578,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
SourceLocation SuperClassLoc; // location of the super class identifier. SourceLocation SuperClassLoc; // location of the super class identifier.
DefinitionData() : SuperClass(), CategoryList(), IvarList(), DefinitionData() : Definition(), SuperClass(), CategoryList(), IvarList(),
ExternallyCompleted() { } ExternallyCompleted() { }
}; };
@ -585,10 +589,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
/// \brief Contains a pointer to the data associated with this class, /// \brief Contains a pointer to the data associated with this class,
/// which will be NULL if this class has not yet been defined. /// which will be NULL if this class has not yet been defined.
/// DefinitionData *Data;
/// 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., /// \brief The location of the last location in this declaration, e.g.,
/// the '>', '}', or identifier. /// the '>', '}', or identifier.
@ -602,8 +603,8 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
bool InitiallyForwardDecl : 1; bool InitiallyForwardDecl : 1;
DefinitionData &data() const { DefinitionData &data() const {
assert(Definition.getPointer() != 0 && "Declaration is not a definition!"); assert(Data != 0 && "Declaration has no definition!");
return *Definition.getPointer(); return *Data;
} }
/// \brief Allocate the definition data for this class. /// \brief Allocate the definition data for this class.
@ -778,29 +779,30 @@ public:
return InitiallyForwardDecl; return InitiallyForwardDecl;
} }
/// \brief Determine whether this declaration is a forward declaration of /// \brief Determine whether this class has only ever been forward-declared.
/// the class. bool isForwardDecl() const { return Data == 0; }
bool isForwardDecl() const { return !Definition.getInt(); }
/// \brief Determine whether this particular declaration of this class is /// \brief Determine whether this particular declaration of this class is
/// actually also a definition. /// actually also a definition.
bool isThisDeclarationADefinition() const { return Definition.getInt(); } bool isThisDeclarationADefinition() const {
return Data == 0 || Data->Definition != this;
}
/// \brief Determine whether this class has been defined. /// \brief Determine whether this class has been defined.
bool hasDefinition() const { return Definition.getPointer() != 0; } bool hasDefinition() const { return Data; }
/// \brief Retrieve the definition of this class, or NULL if this class /// \brief Retrieve the definition of this class, or NULL if this class
/// has been forward-declared (with @class) but not yet defined (with /// has been forward-declared (with @class) but not yet defined (with
/// @interface). /// @interface).
ObjCInterfaceDecl *getDefinition() { ObjCInterfaceDecl *getDefinition() {
return hasDefinition()? this : 0; return hasDefinition()? Data->Definition : 0;
} }
/// \brief Retrieve the definition of this class, or NULL if this class /// \brief Retrieve the definition of this class, or NULL if this class
/// has been forward-declared (with @class) but not yet defined (with /// has been forward-declared (with @class) but not yet defined (with
/// @interface). /// @interface).
const ObjCInterfaceDecl *getDefinition() const { const ObjCInterfaceDecl *getDefinition() const {
return hasDefinition()? this : 0; return hasDefinition()? Data->Definition : 0;
} }
/// \brief Starts the definition of this Objective-C class, taking it from /// \brief Starts the definition of this Objective-C class, taking it from

Просмотреть файл

@ -224,14 +224,14 @@ void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
void ObjCInterfaceDecl::allocateDefinitionData() { void ObjCInterfaceDecl::allocateDefinitionData() {
assert(!hasDefinition() && "ObjC class already has a definition"); assert(!hasDefinition() && "ObjC class already has a definition");
Definition.setPointer(new (getASTContext()) DefinitionData()); Data = new (getASTContext()) DefinitionData();
Definition.setInt(true); Data->Definition = this;
// Update all of the declarations with a pointer to the definition. // Update all of the declarations with a pointer to the definition.
for (redecl_iterator RD = redecls_begin(), RDEnd = redecls_end(); for (redecl_iterator RD = redecls_begin(), RDEnd = redecls_end();
RD != RDEnd; ++RD) { RD != RDEnd; ++RD) {
if (*RD != this) if (*RD != this)
RD->Definition.setPointer(Definition.getPointer()); RD->Data = Data;
} }
} }
@ -684,7 +684,7 @@ ObjCInterfaceDecl::
ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id, ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
SourceLocation CLoc, bool FD, bool isInternal) SourceLocation CLoc, bool FD, bool isInternal)
: ObjCContainerDecl(ObjCInterface, DC, Id, CLoc, atLoc), : ObjCContainerDecl(ObjCInterface, DC, Id, CLoc, atLoc),
TypeForDecl(0), Definition(), InitiallyForwardDecl(FD) TypeForDecl(0), Data(), InitiallyForwardDecl(FD)
{ {
setImplicit(isInternal); setImplicit(isInternal);
} }

Просмотреть файл

@ -613,15 +613,15 @@ void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
for (ASTReader::ForwardRefs::iterator I = Refs.begin(), for (ASTReader::ForwardRefs::iterator I = Refs.begin(),
E = Refs.end(); E = Refs.end();
I != E; ++I) I != E; ++I)
cast<ObjCInterfaceDecl>(*I)->Definition = ID->Definition; cast<ObjCInterfaceDecl>(*I)->Data = ID->Data;
#ifndef NDEBUG #ifndef NDEBUG
// We later check whether PendingForwardRefs is empty to make sure all // We later check whether PendingForwardRefs is empty to make sure all
// pending references were linked. // pending references were linked.
Reader.PendingForwardRefs.erase(ID); Reader.PendingForwardRefs.erase(ID);
#endif #endif
} else if (Def) { } else if (Def) {
if (Def->Definition.getPointer()) { if (Def->Data) {
ID->Definition.setPointer(Def->Definition.getPointer()); ID->Data = Def->Data;
} else { } else {
// The definition is still initializing. // The definition is still initializing.
Reader.PendingForwardRefs[Def].push_back(ID); Reader.PendingForwardRefs[Def].push_back(ID);
@ -2072,8 +2072,8 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
ObjCInterfaceDecl *ID = cast<ObjCInterfaceDecl>(D); ObjCInterfaceDecl *ID = cast<ObjCInterfaceDecl>(D);
ObjCInterfaceDecl *Def ObjCInterfaceDecl *Def
= Reader.ReadDeclAs<ObjCInterfaceDecl>(ModuleFile, Record, Idx); = Reader.ReadDeclAs<ObjCInterfaceDecl>(ModuleFile, Record, Idx);
if (Def->Definition.getPointer()) { if (Def->Data) {
ID->Definition.setPointer(Def->Definition.getPointer()); ID->Data = Def->Data;
} else { } else {
// The definition is still initializing. // The definition is still initializing.
Reader.PendingForwardRefs[Def].push_back(ID); Reader.PendingForwardRefs[Def].push_back(ID);