From 181431cd91e3cfe9b8638866880516773e1d2915 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Tue, 6 Jul 2010 15:36:58 +0000 Subject: [PATCH] Allow a CXXRecordDecl to get a DefinitionData pointer even when its owner is still initializing. llvm-svn: 107663 --- clang/lib/Frontend/PCHReaderDecl.cpp | 102 ++++++++++++++++----------- clang/lib/Frontend/PCHWriterDecl.cpp | 87 +++++++++++++---------- 2 files changed, 110 insertions(+), 79 deletions(-) diff --git a/clang/lib/Frontend/PCHReaderDecl.cpp b/clang/lib/Frontend/PCHReaderDecl.cpp index 25d16f8ea247..698adf49b545 100644 --- a/clang/lib/Frontend/PCHReaderDecl.cpp +++ b/clang/lib/Frontend/PCHReaderDecl.cpp @@ -655,55 +655,71 @@ void PCHDeclReader::VisitUnresolvedUsingTypenameDecl( } void PCHDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) { - VisitRecordDecl(D); - ASTContext &C = *Reader.getContext(); - if (D->isFirstDeclaration()) { - if (Record[Idx++]) { // DefinitionData != 0 - D->DefinitionData = new (C) struct CXXRecordDecl::DefinitionData(0); - struct CXXRecordDecl::DefinitionData &Data = *D->DefinitionData; + // We need to allocate the DefinitionData struct ahead of VisitRecordDecl + // so that the other CXXRecordDecls can get a pointer even when the owner + // is still initializing. + bool OwnsDefinitionData = false; + enum DataOwnership { Data_NoDefData, Data_Owner, Data_NotOwner }; + switch ((DataOwnership)Record[Idx++]) { + default: + assert(0 && "Out of sync with PCHDeclWriter or messed up reading"); + case Data_NoDefData: + break; + case Data_Owner: + OwnsDefinitionData = true; + D->DefinitionData = new (C) struct CXXRecordDecl::DefinitionData(D); + break; + case Data_NotOwner: + D->DefinitionData + = cast(Reader.GetDecl(Record[Idx++]))->DefinitionData; + break; + } - Data.UserDeclaredConstructor = Record[Idx++]; - Data.UserDeclaredCopyConstructor = Record[Idx++]; - Data.UserDeclaredCopyAssignment = Record[Idx++]; - Data.UserDeclaredDestructor = Record[Idx++]; - Data.Aggregate = Record[Idx++]; - Data.PlainOldData = Record[Idx++]; - Data.Empty = Record[Idx++]; - Data.Polymorphic = Record[Idx++]; - Data.Abstract = Record[Idx++]; - Data.HasTrivialConstructor = Record[Idx++]; - Data.HasTrivialCopyConstructor = Record[Idx++]; - Data.HasTrivialCopyAssignment = Record[Idx++]; - Data.HasTrivialDestructor = Record[Idx++]; - Data.ComputedVisibleConversions = Record[Idx++]; - Data.DeclaredDefaultConstructor = Record[Idx++]; - Data.DeclaredCopyConstructor = Record[Idx++]; - Data.DeclaredCopyAssignment = Record[Idx++]; - Data.DeclaredDestructor = Record[Idx++]; + VisitRecordDecl(D); - // setBases() is unsuitable since it may try to iterate the bases of an - // unitialized base. - Data.NumBases = Record[Idx++]; - Data.Bases = new(C) CXXBaseSpecifier [Data.NumBases]; - for (unsigned i = 0; i != Data.NumBases; ++i) - Data.Bases[i] = Reader.ReadCXXBaseSpecifier(Record, Idx); + if (OwnsDefinitionData) { + assert(D->DefinitionData); + struct CXXRecordDecl::DefinitionData &Data = *D->DefinitionData; - // FIXME: Make VBases lazily computed when needed to avoid storing them. - Data.NumVBases = Record[Idx++]; - Data.VBases = new(C) CXXBaseSpecifier [Data.NumVBases]; - for (unsigned i = 0; i != Data.NumVBases; ++i) - Data.VBases[i] = Reader.ReadCXXBaseSpecifier(Record, Idx); + Data.UserDeclaredConstructor = Record[Idx++]; + Data.UserDeclaredCopyConstructor = Record[Idx++]; + Data.UserDeclaredCopyAssignment = Record[Idx++]; + Data.UserDeclaredDestructor = Record[Idx++]; + Data.Aggregate = Record[Idx++]; + Data.PlainOldData = Record[Idx++]; + Data.Empty = Record[Idx++]; + Data.Polymorphic = Record[Idx++]; + Data.Abstract = Record[Idx++]; + Data.HasTrivialConstructor = Record[Idx++]; + Data.HasTrivialCopyConstructor = Record[Idx++]; + Data.HasTrivialCopyAssignment = Record[Idx++]; + Data.HasTrivialDestructor = Record[Idx++]; + Data.ComputedVisibleConversions = Record[Idx++]; + Data.DeclaredDefaultConstructor = Record[Idx++]; + Data.DeclaredCopyConstructor = Record[Idx++]; + Data.DeclaredCopyAssignment = Record[Idx++]; + Data.DeclaredDestructor = Record[Idx++]; - Reader.ReadUnresolvedSet(Data.Conversions, Record, Idx); - Reader.ReadUnresolvedSet(Data.VisibleConversions, Record, Idx); - Data.Definition = cast(Reader.GetDecl(Record[Idx++])); - Data.FirstFriend - = cast_or_null(Reader.GetDecl(Record[Idx++])); - } - } else { - D->DefinitionData = D->getPreviousDeclaration()->DefinitionData; + // setBases() is unsuitable since it may try to iterate the bases of an + // unitialized base. + Data.NumBases = Record[Idx++]; + Data.Bases = new(C) CXXBaseSpecifier [Data.NumBases]; + for (unsigned i = 0; i != Data.NumBases; ++i) + Data.Bases[i] = Reader.ReadCXXBaseSpecifier(Record, Idx); + + // FIXME: Make VBases lazily computed when needed to avoid storing them. + Data.NumVBases = Record[Idx++]; + Data.VBases = new(C) CXXBaseSpecifier [Data.NumVBases]; + for (unsigned i = 0; i != Data.NumVBases; ++i) + Data.VBases[i] = Reader.ReadCXXBaseSpecifier(Record, Idx); + + Reader.ReadUnresolvedSet(Data.Conversions, Record, Idx); + Reader.ReadUnresolvedSet(Data.VisibleConversions, Record, Idx); + assert(Data.Definition && "Data.Definition should be already set!"); + Data.FirstFriend + = cast_or_null(Reader.GetDecl(Record[Idx++])); } enum CXXRecKind { diff --git a/clang/lib/Frontend/PCHWriterDecl.cpp b/clang/lib/Frontend/PCHWriterDecl.cpp index f1adc5b6fcf8..2dc59726eaeb 100644 --- a/clang/lib/Frontend/PCHWriterDecl.cpp +++ b/clang/lib/Frontend/PCHWriterDecl.cpp @@ -659,48 +659,63 @@ void PCHDeclWriter::VisitUnresolvedUsingTypenameDecl( } void PCHDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) { + // See comments at PCHDeclReader::VisitCXXRecordDecl about why this happens + // before VisitRecordDecl. + enum { Data_NoDefData, Data_Owner, Data_NotOwner }; + bool OwnsDefinitionData = false; + if (D->DefinitionData) { + assert(D->DefinitionData->Definition && + "DefinitionData don't point to a definition decl!"); + OwnsDefinitionData = D->DefinitionData->Definition == D; + if (OwnsDefinitionData) { + Record.push_back(Data_Owner); + } else { + Record.push_back(Data_NotOwner); + Writer.AddDeclRef(D->DefinitionData->Definition, Record); + } + } else + Record.push_back(Data_NoDefData); + VisitRecordDecl(D); - if (D->isFirstDeclaration()) { - Record.push_back(D->DefinitionData != 0); - if (D->DefinitionData) { - struct CXXRecordDecl::DefinitionData &Data = *D->DefinitionData; + if (OwnsDefinitionData) { + assert(D->DefinitionData); + struct CXXRecordDecl::DefinitionData &Data = *D->DefinitionData; - Record.push_back(Data.UserDeclaredConstructor); - Record.push_back(Data.UserDeclaredCopyConstructor); - Record.push_back(Data.UserDeclaredCopyAssignment); - Record.push_back(Data.UserDeclaredDestructor); - Record.push_back(Data.Aggregate); - Record.push_back(Data.PlainOldData); - Record.push_back(Data.Empty); - Record.push_back(Data.Polymorphic); - Record.push_back(Data.Abstract); - Record.push_back(Data.HasTrivialConstructor); - Record.push_back(Data.HasTrivialCopyConstructor); - Record.push_back(Data.HasTrivialCopyAssignment); - Record.push_back(Data.HasTrivialDestructor); - Record.push_back(Data.ComputedVisibleConversions); - Record.push_back(Data.DeclaredDefaultConstructor); - Record.push_back(Data.DeclaredCopyConstructor); - Record.push_back(Data.DeclaredCopyAssignment); - Record.push_back(Data.DeclaredDestructor); + Record.push_back(Data.UserDeclaredConstructor); + Record.push_back(Data.UserDeclaredCopyConstructor); + Record.push_back(Data.UserDeclaredCopyAssignment); + Record.push_back(Data.UserDeclaredDestructor); + Record.push_back(Data.Aggregate); + Record.push_back(Data.PlainOldData); + Record.push_back(Data.Empty); + Record.push_back(Data.Polymorphic); + Record.push_back(Data.Abstract); + Record.push_back(Data.HasTrivialConstructor); + Record.push_back(Data.HasTrivialCopyConstructor); + Record.push_back(Data.HasTrivialCopyAssignment); + Record.push_back(Data.HasTrivialDestructor); + Record.push_back(Data.ComputedVisibleConversions); + Record.push_back(Data.DeclaredDefaultConstructor); + Record.push_back(Data.DeclaredCopyConstructor); + Record.push_back(Data.DeclaredCopyAssignment); + Record.push_back(Data.DeclaredDestructor); - Record.push_back(D->getNumBases()); - for (CXXRecordDecl::base_class_iterator I = D->bases_begin(), - E = D->bases_end(); I != E; ++I) - Writer.AddCXXBaseSpecifier(*I, Record); + Record.push_back(D->getNumBases()); + for (CXXRecordDecl::base_class_iterator I = D->bases_begin(), + E = D->bases_end(); I != E; ++I) + Writer.AddCXXBaseSpecifier(*I, Record); - // FIXME: Make VBases lazily computed when needed to avoid storing them. - Record.push_back(D->getNumVBases()); - for (CXXRecordDecl::base_class_iterator I = D->vbases_begin(), - E = D->vbases_end(); I != E; ++I) - Writer.AddCXXBaseSpecifier(*I, Record); + // FIXME: Make VBases lazily computed when needed to avoid storing them. + Record.push_back(D->getNumVBases()); + for (CXXRecordDecl::base_class_iterator I = D->vbases_begin(), + E = D->vbases_end(); I != E; ++I) + Writer.AddCXXBaseSpecifier(*I, Record); - Writer.AddUnresolvedSet(Data.Conversions, Record); - Writer.AddUnresolvedSet(Data.VisibleConversions, Record); - Writer.AddDeclRef(Data.Definition, Record); - Writer.AddDeclRef(Data.FirstFriend, Record); - } + Writer.AddUnresolvedSet(Data.Conversions, Record); + Writer.AddUnresolvedSet(Data.VisibleConversions, Record); + // Data.Definition is written at the top. + Writer.AddDeclRef(Data.FirstFriend, Record); } enum {