Rework the way in which we (de-)serialize the declarations

corresponding to TagType and ObjCInterfaceType. Previously, we would
serialize the definition (if available) or the canonical declaration
(if no definition was available). However, this can end up forcing the
deserialization of the definition even through we might not want to
yet. 

Instead, always serialize the canonical declaration reference in the
TagType/ObjCInterfaceType entry, and as part of loading a pending
definition, update the "decl" pointer within the type node to point at
the definition. This is more robust in hard-to-isolate cases
where the *Type gets built and filled in before we see the definition.

llvm-svn: 148323
This commit is contained in:
Douglas Gregor 2012-01-17 19:21:53 +00:00
parent 2ed6718616
commit f3bccd77fc
4 changed files with 28 additions and 10 deletions

View File

@ -2225,6 +2225,7 @@ class TypeDecl : public NamedDecl {
friend class TagDecl; friend class TagDecl;
friend class TemplateTypeParmDecl; friend class TemplateTypeParmDecl;
friend class TagType; friend class TagType;
friend class ASTReader;
protected: protected:
TypeDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, TypeDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id,

View File

@ -3070,6 +3070,8 @@ class TagType : public Type {
/// TagDecl that declares the entity. /// TagDecl that declares the entity.
TagDecl * decl; TagDecl * decl;
friend class ASTReader;
protected: protected:
TagType(TypeClass TC, const TagDecl *D, QualType can); TagType(TypeClass TC, const TagDecl *D, QualType can);
@ -4160,6 +4162,7 @@ class ObjCInterfaceType : public ObjCObjectType {
: ObjCObjectType(Nonce_ObjCInterface), : ObjCObjectType(Nonce_ObjCInterface),
Decl(const_cast<ObjCInterfaceDecl*>(D)) {} Decl(const_cast<ObjCInterfaceDecl*>(D)) {}
friend class ASTContext; // ASTContext creates these. friend class ASTContext; // ASTContext creates these.
friend class ASTReader;
friend class ObjCInterfaceDecl; friend class ObjCInterfaceDecl;
public: public:

View File

@ -3901,8 +3901,9 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
} }
unsigned Idx = 0; unsigned Idx = 0;
bool IsDependent = Record[Idx++]; bool IsDependent = Record[Idx++];
QualType T RecordDecl *RD = ReadDeclAs<RecordDecl>(*Loc.F, Record, Idx);
= Context.getRecordType(ReadDeclAs<RecordDecl>(*Loc.F, Record, Idx)); RD = cast_or_null<RecordDecl>(RD->getCanonicalDecl());
QualType T = Context.getRecordType(RD);
const_cast<Type*>(T.getTypePtr())->setDependent(IsDependent); const_cast<Type*>(T.getTypePtr())->setDependent(IsDependent);
return T; return T;
} }
@ -3966,7 +3967,7 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
unsigned Idx = 0; unsigned Idx = 0;
ObjCInterfaceDecl *ItfD ObjCInterfaceDecl *ItfD
= ReadDeclAs<ObjCInterfaceDecl>(*Loc.F, Record, Idx); = ReadDeclAs<ObjCInterfaceDecl>(*Loc.F, Record, Idx);
return Context.getObjCInterfaceType(ItfD); return Context.getObjCInterfaceType(ItfD->getCanonicalDecl());
} }
case TYPE_OBJC_OBJECT: { case TYPE_OBJC_OBJECT: {
@ -6124,6 +6125,7 @@ void ASTReader::finishPendingActions() {
// Load pending declaration chains. // Load pending declaration chains.
for (unsigned I = 0; I != PendingDeclChains.size(); ++I) { for (unsigned I = 0; I != PendingDeclChains.size(); ++I) {
loadPendingDeclChain(PendingDeclChains[I]); loadPendingDeclChain(PendingDeclChains[I]);
PendingDeclChainsKnown.erase(PendingDeclChains[I]);
} }
PendingDeclChains.clear(); PendingDeclChains.clear();
@ -6143,16 +6145,28 @@ void ASTReader::finishPendingActions() {
for (llvm::SmallPtrSet<Decl *, 4>::iterator D = PendingDefinitions.begin(), for (llvm::SmallPtrSet<Decl *, 4>::iterator D = PendingDefinitions.begin(),
DEnd = PendingDefinitions.end(); DEnd = PendingDefinitions.end();
D != DEnd; ++D) { D != DEnd; ++D) {
if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(*D)) { if (TagDecl *TD = dyn_cast<TagDecl>(*D)) {
for (CXXRecordDecl::redecl_iterator R = RD->redecls_begin(), if (const TagType *TagT = dyn_cast<TagType>(TD->TypeForDecl)) {
REnd = RD->redecls_end(); // Make sure that the TagType points at the definition.
R != REnd; ++R) const_cast<TagType*>(TagT)->decl = TD;
cast<CXXRecordDecl>(*R)->DefinitionData = RD->DefinitionData; }
if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(*D)) {
for (CXXRecordDecl::redecl_iterator R = RD->redecls_begin(),
REnd = RD->redecls_end();
R != REnd; ++R)
cast<CXXRecordDecl>(*R)->DefinitionData = RD->DefinitionData;
}
continue; continue;
} }
if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(*D)) { if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(*D)) {
// Make sure that the ObjCInterfaceType points at the definition.
const_cast<ObjCInterfaceType *>(cast<ObjCInterfaceType>(ID->TypeForDecl))
->Decl = ID;
for (ObjCInterfaceDecl::redecl_iterator R = ID->redecls_begin(), for (ObjCInterfaceDecl::redecl_iterator R = ID->redecls_begin(),
REnd = ID->redecls_end(); REnd = ID->redecls_end();
R != REnd; ++R) R != REnd; ++R)

View File

@ -239,7 +239,7 @@ void ASTTypeWriter::VisitAutoType(const AutoType *T) {
void ASTTypeWriter::VisitTagType(const TagType *T) { void ASTTypeWriter::VisitTagType(const TagType *T) {
Record.push_back(T->isDependentType()); Record.push_back(T->isDependentType());
Writer.AddDeclRef(T->getDecl(), Record); Writer.AddDeclRef(T->getDecl()->getCanonicalDecl(), Record);
assert(!T->isBeingDefined() && assert(!T->isBeingDefined() &&
"Cannot serialize in the middle of a type definition"); "Cannot serialize in the middle of a type definition");
} }
@ -369,7 +369,7 @@ void ASTTypeWriter::VisitInjectedClassNameType(const InjectedClassNameType *T) {
} }
void ASTTypeWriter::VisitObjCInterfaceType(const ObjCInterfaceType *T) { void ASTTypeWriter::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
Writer.AddDeclRef(T->getDecl(), Record); Writer.AddDeclRef(T->getDecl()->getCanonicalDecl(), Record);
Code = TYPE_OBJC_INTERFACE; Code = TYPE_OBJC_INTERFACE;
} }