From: Argyrios Kyrtzidis Date: Tue, 6 Jul 2010 15:36:58 +0000 (+0000) Subject: Allow a CXXRecordDecl to get a DefinitionData pointer even when its owner is still... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0f47bb98cbc52a6ead2aef8a2f8315c0b6167e6c;p=clang Allow a CXXRecordDecl to get a DefinitionData pointer even when its owner is still initializing. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@107663 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp index 25d16f8ea2..698adf49b5 100644 --- a/lib/Frontend/PCHReaderDecl.cpp +++ b/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; - - 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++]; - - // 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); - Data.Definition = cast(Reader.GetDecl(Record[Idx++])); - Data.FirstFriend - = cast_or_null(Reader.GetDecl(Record[Idx++])); - } - } else { - D->DefinitionData = D->getPreviousDeclaration()->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; + } + + VisitRecordDecl(D); + + if (OwnsDefinitionData) { + assert(D->DefinitionData); + struct CXXRecordDecl::DefinitionData &Data = *D->DefinitionData; + + 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++]; + + // 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/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp index f1adc5b6fc..2dc59726ea 100644 --- a/lib/Frontend/PCHWriterDecl.cpp +++ b/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; - - 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); - - // 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); - } + 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(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); + + Writer.AddUnresolvedSet(Data.Conversions, Record); + Writer.AddUnresolvedSet(Data.VisibleConversions, Record); + // Data.Definition is written at the top. + Writer.AddDeclRef(Data.FirstFriend, Record); } enum {