diff options
-rw-r--r-- | include/clang/AST/DeclCXX.h | 9 | ||||
-rw-r--r-- | lib/Frontend/PCHReaderDecl.cpp | 82 | ||||
-rw-r--r-- | lib/Frontend/PCHWriterDecl.cpp | 61 |
3 files changed, 135 insertions, 17 deletions
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 88cc4e05a6..d8ad02a41b 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -1455,6 +1455,9 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const CXXConstructorDecl *D) { return true; } static bool classofKind(Kind K) { return K == CXXConstructor; } + + friend class PCHDeclReader; + friend class PCHDeclWriter; }; /// CXXDestructorDecl - Represents a C++ destructor within a @@ -1518,6 +1521,9 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const CXXDestructorDecl *D) { return true; } static bool classofKind(Kind K) { return K == CXXDestructor; } + + friend class PCHDeclReader; + friend class PCHDeclWriter; }; /// CXXConversionDecl - Represents a C++ conversion function within a @@ -1572,6 +1578,9 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const CXXConversionDecl *D) { return true; } static bool classofKind(Kind K) { return K == CXXConversion; } + + friend class PCHDeclReader; + friend class PCHDeclWriter; }; /// LinkageSpecDecl - This represents a linkage specification. For example: diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp index 8af8dc8d78..9bc7099079 100644 --- a/lib/Frontend/PCHReaderDecl.cpp +++ b/lib/Frontend/PCHReaderDecl.cpp @@ -113,9 +113,14 @@ namespace clang { void PCHDeclReader::Visit(Decl *D) { DeclVisitor<PCHDeclReader, void>::Visit(D); - // if we have a fully initialized TypeDecl, we can safely read its type now. - if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) + if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) { + // if we have a fully initialized TypeDecl, we can safely read its type now. TD->setTypeForDecl(Reader.GetType(TypeIDForTypeDecl).getTypePtr()); + } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + // FunctionDecl's body was written last after all other Stmts/Exprs. + if (Record[Idx++]) + FD->setLazyBody(Reader.getDeclsCursor().GetCurrentBitNo()); + } } void PCHDeclReader::VisitDecl(Decl *D) { @@ -272,8 +277,9 @@ void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) { } } - if (Record[Idx++]) - FD->setLazyBody(Reader.getDeclsCursor().GetCurrentBitNo()); + // FunctionDecl's body is handled last at PCHReaderDecl::Visit, + // after everything else is read. + FD->setPreviousDeclaration( cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++]))); FD->setStorageClass((FunctionDecl::StorageClass)Record[Idx++]); @@ -710,23 +716,83 @@ void PCHDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) { } void PCHDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) { - // assert(false && "cannot read CXXMethodDecl"); VisitFunctionDecl(D); } void PCHDeclReader::VisitCXXConstructorDecl(CXXConstructorDecl *D) { - // assert(false && "cannot read CXXConstructorDecl"); VisitCXXMethodDecl(D); + + D->IsExplicitSpecified = Record[Idx++]; + D->ImplicitlyDefined = Record[Idx++]; + + unsigned NumInitializers = Record[Idx++]; + D->NumBaseOrMemberInitializers = NumInitializers; + if (NumInitializers) { + ASTContext &C = *Reader.getContext(); + + D->BaseOrMemberInitializers + = new (C) CXXBaseOrMemberInitializer*[NumInitializers]; + for (unsigned i=0; i != NumInitializers; ++i) { + TypeSourceInfo *BaseClassInfo; + bool IsBaseVirtual; + FieldDecl *Member; + + bool IsBaseInitializer = Record[Idx++]; + if (IsBaseInitializer) { + BaseClassInfo = Reader.GetTypeSourceInfo(Record, Idx); + IsBaseVirtual = Record[Idx++]; + } else { + Member = cast<FieldDecl>(Reader.GetDecl(Record[Idx++])); + } + SourceLocation MemberLoc = Reader.ReadSourceLocation(Record, Idx); + Expr *Init = Reader.ReadExpr(); + FieldDecl *AnonUnionMember + = cast_or_null<FieldDecl>(Reader.GetDecl(Record[Idx++])); + SourceLocation LParenLoc = Reader.ReadSourceLocation(Record, Idx); + SourceLocation RParenLoc = Reader.ReadSourceLocation(Record, Idx); + bool IsWritten = Record[Idx++]; + unsigned SourceOrderOrNumArrayIndices; + llvm::SmallVector<VarDecl *, 8> Indices; + if (IsWritten) { + SourceOrderOrNumArrayIndices = Record[Idx++]; + } else { + SourceOrderOrNumArrayIndices = Record[Idx++]; + Indices.reserve(SourceOrderOrNumArrayIndices); + for (unsigned i=0; i != SourceOrderOrNumArrayIndices; ++i) + Indices.push_back(cast<VarDecl>(Reader.GetDecl(Record[Idx++]))); + } + + CXXBaseOrMemberInitializer *BOMInit; + if (IsBaseInitializer) { + BOMInit = new (C) CXXBaseOrMemberInitializer(C, BaseClassInfo, + IsBaseVirtual, LParenLoc, + Init, RParenLoc); + } else if (IsWritten) { + BOMInit = new (C) CXXBaseOrMemberInitializer(C, Member, MemberLoc, + LParenLoc, Init, RParenLoc); + } else { + BOMInit = CXXBaseOrMemberInitializer::Create(C, Member, MemberLoc, + LParenLoc, Init, RParenLoc, + Indices.data(), + Indices.size()); + } + + BOMInit->setAnonUnionMember(AnonUnionMember); + D->BaseOrMemberInitializers[i] = BOMInit; + } + } } void PCHDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) { - // assert(false && "cannot read CXXDestructorDecl"); VisitCXXMethodDecl(D); + + D->ImplicitlyDefined = Record[Idx++]; + D->OperatorDelete = cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++])); } void PCHDeclReader::VisitCXXConversionDecl(CXXConversionDecl *D) { - // assert(false && "cannot read CXXConversionDecl"); VisitCXXMethodDecl(D); + D->IsExplicitSpecified = Record[Idx++]; } void PCHDeclReader::VisitAccessSpecDecl(AccessSpecDecl *D) { diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp index cea7ba0d9e..936ca5e818 100644 --- a/lib/Frontend/PCHWriterDecl.cpp +++ b/lib/Frontend/PCHWriterDecl.cpp @@ -40,6 +40,8 @@ namespace clang { PCHWriter::RecordData &Record) : Writer(Writer), Context(Context), Record(Record) { } + + void Visit(Decl *D); void VisitDecl(Decl *D); void VisitTranslationUnitDecl(TranslationUnitDecl *D); @@ -112,6 +114,19 @@ namespace clang { }; } +void PCHDeclWriter::Visit(Decl *D) { + DeclVisitor<PCHDeclWriter>::Visit(D); + + // Handle FunctionDecl's body here and write it after all other Stmts/Exprs + // have been written. We want it last because we will not read it back when + // retrieving it from the PCH, we'll just lazily set the offset. + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + Record.push_back(FD->isThisDeclarationADefinition()); + if (FD->isThisDeclarationADefinition()) + Writer.AddStmt(FD->getBody()); + } +} + void PCHDeclWriter::VisitDecl(Decl *D) { Writer.AddDeclRef(cast_or_null<Decl>(D->getDeclContext()), Record); Writer.AddDeclRef(cast_or_null<Decl>(D->getLexicalDeclContext()), Record); @@ -255,11 +270,8 @@ void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) { } } - // Make sure no Exprs are emitted after the body, because when reading the - // function, the body doesn't get read so the cursor doesn't advance. - Record.push_back(D->isThisDeclarationADefinition()); - if (D->isThisDeclarationADefinition()) - Writer.AddStmt(D->getBody()); + // FunctionDecl's body is handled last at PCHWriterDecl::Visit, + // after everything else is written. Writer.AddDeclRef(D->getPreviousDeclaration(), Record); Record.push_back(D->getStorageClass()); // FIXME: stable encoding @@ -691,26 +703,57 @@ void PCHDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) { } void PCHDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) { - // assert(false && "cannot write CXXMethodDecl"); VisitFunctionDecl(D); Code = pch::DECL_CXX_METHOD; } void PCHDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) { - // assert(false && "cannot write CXXConstructorDecl"); VisitCXXMethodDecl(D); + + Record.push_back(D->IsExplicitSpecified); + Record.push_back(D->ImplicitlyDefined); + + Record.push_back(D->NumBaseOrMemberInitializers); + for (unsigned i=0; i != D->NumBaseOrMemberInitializers; ++i) { + CXXBaseOrMemberInitializer *Init = D->BaseOrMemberInitializers[i]; + + Record.push_back(Init->isBaseInitializer()); + if (Init->isBaseInitializer()) { + Writer.AddTypeSourceInfo(Init->getBaseClassInfo(), Record); + Record.push_back(Init->isBaseVirtual()); + } else { + Writer.AddDeclRef(Init->getMember(), Record); + } + Writer.AddSourceLocation(Init->getMemberLocation(), Record); + Writer.AddStmt(Init->getInit()); + Writer.AddDeclRef(Init->getAnonUnionMember(), Record); + Writer.AddSourceLocation(Init->getLParenLoc(), Record); + Writer.AddSourceLocation(Init->getRParenLoc(), Record); + Record.push_back(Init->isWritten()); + if (Init->isWritten()) { + Record.push_back(Init->getSourceOrder()); + } else { + Record.push_back(Init->getNumArrayIndices()); + for (unsigned i=0, e=Init->getNumArrayIndices(); i != e; ++i) + Writer.AddDeclRef(Init->getArrayIndex(i), Record); + } + } + Code = pch::DECL_CXX_CONSTRUCTOR; } void PCHDeclWriter::VisitCXXDestructorDecl(CXXDestructorDecl *D) { - // assert(false && "cannot write CXXDestructorDecl"); VisitCXXMethodDecl(D); + + Record.push_back(D->ImplicitlyDefined); + Writer.AddDeclRef(D->OperatorDelete, Record); + Code = pch::DECL_CXX_DESTRUCTOR; } void PCHDeclWriter::VisitCXXConversionDecl(CXXConversionDecl *D) { - // assert(false && "cannot write CXXConversionDecl"); VisitCXXMethodDecl(D); + Record.push_back(D->IsExplicitSpecified); Code = pch::DECL_CXX_CONVERSION; } |