From 37ffed3b7f229844cae2463ff82b527506c86c74 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Fri, 2 Jul 2010 11:55:32 +0000 Subject: [PATCH] Fully read/write CXXRecordDecl for PCH. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@107475 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/DeclCXX.h | 7 +++ include/clang/AST/Redeclarable.h | 5 ++ include/clang/Frontend/PCHReader.h | 4 ++ include/clang/Frontend/PCHWriter.h | 3 ++ lib/AST/ASTContext.cpp | 3 +- lib/Frontend/PCHReader.cpp | 11 ++++ lib/Frontend/PCHReaderDecl.cpp | 80 ++++++++++++++++++------------ lib/Frontend/PCHWriter.cpp | 11 ++++ lib/Frontend/PCHWriterDecl.cpp | 50 ++++++++++++++----- 9 files changed, 129 insertions(+), 45 deletions(-) diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 63002913eb..88cc4e05a6 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -414,6 +414,13 @@ public: virtual const CXXRecordDecl *getCanonicalDecl() const { return cast(RecordDecl::getCanonicalDecl()); } + + const CXXRecordDecl *getPreviousDeclaration() const { + return cast_or_null(RecordDecl::getPreviousDeclaration()); + } + CXXRecordDecl *getPreviousDeclaration() { + return cast_or_null(RecordDecl::getPreviousDeclaration()); + } CXXRecordDecl *getDefinition() const { if (!DefinitionData) return 0; diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h index 01f4b29a61..55e1f84779 100644 --- a/include/clang/AST/Redeclarable.h +++ b/include/clang/AST/Redeclarable.h @@ -92,6 +92,11 @@ public: return D; } + /// \brief Returns true if this is the first declaration. + bool isFirstDeclaration() const { + return RedeclLink.NextIsLatest(); + } + /// \brief Returns the most recent (re)declaration of this declaration. decl_type *getMostRecentDeclaration() { return getFirstDeclaration()->RedeclLink.getNext(); diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h index dc9cb83edb..4f492946a0 100644 --- a/include/clang/Frontend/PCHReader.h +++ b/include/clang/Frontend/PCHReader.h @@ -743,6 +743,10 @@ public: ReadTemplateArgumentList(llvm::SmallVector &TemplArgs, const RecordData &Record, unsigned &Idx); + /// \brief Read a UnresolvedSet structure. + void ReadUnresolvedSet(UnresolvedSetImpl &Set, + const RecordData &Record, unsigned &Idx); + /// \brief Read a source location. SourceLocation ReadSourceLocation(const RecordData &Record, unsigned& Idx) { return SourceLocation::getFromRawEncoding(Record[Idx++]); diff --git a/include/clang/Frontend/PCHWriter.h b/include/clang/Frontend/PCHWriter.h index dddbf85b29..3930323bfb 100644 --- a/include/clang/Frontend/PCHWriter.h +++ b/include/clang/Frontend/PCHWriter.h @@ -343,6 +343,9 @@ public: void AddTemplateArgumentList(const TemplateArgumentList *TemplateArgs, RecordData &Record); + /// \brief Emit a UnresolvedSet structure. + void AddUnresolvedSet(const UnresolvedSetImpl &Set, RecordData &Record); + /// \brief Add a string to the given record. void AddString(const std::string &Str, RecordData &Record); diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 604cf2b5cf..ca83964b3e 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1741,8 +1741,7 @@ QualType ASTContext::getInjectedClassNameType(CXXRecordDecl *Decl, assert(NeedsInjectedClassNameType(Decl)); if (Decl->TypeForDecl) { assert(isa(Decl->TypeForDecl)); - } else if (CXXRecordDecl *PrevDecl - = cast_or_null(Decl->getPreviousDeclaration())) { + } else if (CXXRecordDecl *PrevDecl = Decl->getPreviousDeclaration()) { assert(PrevDecl->TypeForDecl && "previous declaration has no type"); Decl->TypeForDecl = PrevDecl->TypeForDecl; assert(isa(Decl->TypeForDecl)); diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 811db509af..5f00c677ba 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -3090,6 +3090,17 @@ ReadTemplateArgumentList(llvm::SmallVector &TemplArgs, TemplArgs.push_back(ReadTemplateArgument(Record, Idx)); } +/// \brief Read a UnresolvedSet structure. +void PCHReader::ReadUnresolvedSet(UnresolvedSetImpl &Set, + const RecordData &Record, unsigned &Idx) { + unsigned NumDecls = Record[Idx++]; + while (NumDecls--) { + NamedDecl *D = cast(GetDecl(Record[Idx++])); + AccessSpecifier AS = (AccessSpecifier)Record[Idx++]; + Set.addDecl(D, AS); + } +} + NestedNameSpecifier * PCHReader::ReadNestedNameSpecifier(const RecordData &Record, unsigned &Idx) { unsigned N = Record[Idx++]; diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp index 443842d342..ea99ff249d 100644 --- a/lib/Frontend/PCHReaderDecl.cpp +++ b/lib/Frontend/PCHReaderDecl.cpp @@ -39,7 +39,7 @@ namespace clang { unsigned &Idx) : Reader(Reader), Record(Record), Idx(Idx), TypeIDForTypeDecl(0) { } - CXXBaseSpecifier *ReadCXXBaseSpecifier(); + CXXBaseSpecifier ReadCXXBaseSpecifier(); void Visit(Decl *D); @@ -628,20 +628,63 @@ void PCHDeclReader::VisitUnresolvedUsingTypenameDecl( D->setTargetNestedNameSpecifier(Reader.ReadNestedNameSpecifier(Record, Idx)); } -CXXBaseSpecifier *PCHDeclReader::ReadCXXBaseSpecifier() { +CXXBaseSpecifier PCHDeclReader::ReadCXXBaseSpecifier() { bool isVirtual = static_cast(Record[Idx++]); bool isBaseOfClass = static_cast(Record[Idx++]); AccessSpecifier AS = static_cast(Record[Idx++]); QualType T = Reader.GetType(Record[Idx++]); SourceRange Range = Reader.ReadSourceRange(Record, Idx); - return new (*Reader.getContext()) - CXXBaseSpecifier(Range, isVirtual, isBaseOfClass, AS, T); + return CXXBaseSpecifier(Range, isVirtual, isBaseOfClass, AS, T); } void PCHDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) { - // assert(false && "cannot read CXXRecordDecl"); 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++]; + + // 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] = ReadCXXBaseSpecifier(); + + // 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] = ReadCXXBaseSpecifier(); + + 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; + } + enum CXXRecKind { CXXRecNotTemplate = 0, CXXRecTemplate, CXXRecMemberSpecialization }; @@ -663,31 +706,6 @@ void PCHDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) { break; } } - - // FIXME: Hack. See PCHDeclWriter::VisitTypeDecl. - D->setTypeForDecl(Reader.GetType(Record[Idx++]).getTypePtr()); - - // FIXME: this is far from complete - - if (D->isDefinition()) { - D->setDefinition(false); // make peace with an assertion - D->startDefinition(); - - unsigned NumBases = Record[Idx++]; - - llvm::SmallVector Bases; - Bases.reserve(NumBases); - for (unsigned I = 0; I != NumBases; ++I) - Bases.push_back(ReadCXXBaseSpecifier()); - D->setBases(Bases.begin(), NumBases); - - D->data().FirstFriend - = cast_or_null(Reader.GetDecl(Record[Idx++])); - - // FIXME: there's a lot of stuff we do here that's kindof sketchy - // if we're leaving the context incomplete. - D->completeDefinition(); - } } void PCHDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) { diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 99d228b6c0..65e8849adb 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -2621,3 +2621,14 @@ PCHWriter::AddTemplateArgumentList(const TemplateArgumentList *TemplateArgs, for (int i=0, e = TemplateArgs->flat_size(); i != e; ++i) AddTemplateArgument(TemplateArgs->get(i), Record); } + + +void +PCHWriter::AddUnresolvedSet(const UnresolvedSetImpl &Set, RecordData &Record) { + Record.push_back(Set.size()); + for (UnresolvedSetImpl::const_iterator + I = Set.begin(), E = Set.end(); I != E; ++I) { + AddDeclRef(I.getDecl(), Record); + Record.push_back(I.getAccess()); + } +} diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp index 000c2d8ba8..86af50b0bc 100644 --- a/lib/Frontend/PCHWriterDecl.cpp +++ b/lib/Frontend/PCHWriterDecl.cpp @@ -632,6 +632,44 @@ void PCHDeclWriter::WriteCXXBaseSpecifier(const CXXBaseSpecifier *Base) { void PCHDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) { 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(D->getNumBases()); + for (CXXRecordDecl::base_class_iterator I = D->bases_begin(), + E = D->bases_end(); I != E; ++I) + WriteCXXBaseSpecifier(&*I); + + // 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) + WriteCXXBaseSpecifier(&*I); + + Writer.AddUnresolvedSet(Data.Conversions, Record); + Writer.AddUnresolvedSet(Data.VisibleConversions, Record); + Writer.AddDeclRef(Data.Definition, Record); + Writer.AddDeclRef(Data.FirstFriend, Record); + } + } + enum { CXXRecNotTemplate = 0, CXXRecTemplate, CXXRecMemberSpecialization }; @@ -648,18 +686,6 @@ void PCHDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) { Record.push_back(CXXRecNotTemplate); } - // FIXME: Hack. See PCHDeclWriter::VisitTypeDecl. - Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record); - - if (D->isDefinition()) { - unsigned NumBases = D->getNumBases(); - Record.push_back(NumBases); - for (CXXRecordDecl::base_class_iterator I = D->bases_begin(), - E = D->bases_end(); I != E; ++I) - WriteCXXBaseSpecifier(&*I); - - Writer.AddDeclRef(D->data().FirstFriend, Record); - } Code = pch::DECL_CXX_RECORD; } -- 2.40.0