diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2010-06-29 22:47:00 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2010-06-29 22:47:00 +0000 |
commit | 6764334dfa73d67cbbb1b1fc8fe00440aad00f2a (patch) | |
tree | 2ef6ea36799089d92fdb3102551d0a178d67204d /lib | |
parent | d98a2ab9275f896df49e42ea4e4b8871610e0f45 (diff) |
Support C++ friend declarations for PCH.
This commit 'introduces' a slightly different way to restore the state of the AST object.
It makes PCHDeclReader/PCHDeclWriter friends and gives them access to the private members of the object.
The rationale is to avoid using/modifying the AST interfaces for PCH read/write so that to:
-Avoid complications with objects that have side-effects during creation or when using some setters.
-Not 'pollute' the AST interface with methods only used by the PCH reader/writer
-Allow AST objects to be read-only.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@107219 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/DeclFriend.cpp | 4 | ||||
-rw-r--r-- | lib/Frontend/PCHReaderDecl.cpp | 17 | ||||
-rw-r--r-- | lib/Frontend/PCHWriter.cpp | 15 | ||||
-rw-r--r-- | lib/Frontend/PCHWriterDecl.cpp | 17 |
4 files changed, 44 insertions, 9 deletions
diff --git a/lib/AST/DeclFriend.cpp b/lib/AST/DeclFriend.cpp index ab3552db28..99bfe40c31 100644 --- a/lib/AST/DeclFriend.cpp +++ b/lib/AST/DeclFriend.cpp @@ -39,3 +39,7 @@ FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC, cast<CXXRecordDecl>(DC)->pushFriendDecl(FD); return FD; } + +FriendDecl *FriendDecl::Create(ASTContext &C, EmptyShell Empty) { + return new (C) FriendDecl(Empty); +} diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp index 05cefa9ffe..9f057b0c1d 100644 --- a/lib/Frontend/PCHReaderDecl.cpp +++ b/lib/Frontend/PCHReaderDecl.cpp @@ -27,7 +27,7 @@ using namespace clang; // Declaration deserialization //===----------------------------------------------------------------------===// -namespace { +namespace clang { class PCHDeclReader : public DeclVisitor<PCHDeclReader, void> { PCHReader &Reader; const PCHReader::RecordData &Record; @@ -81,6 +81,7 @@ namespace { void VisitLinkageSpecDecl(LinkageSpecDecl *D); void VisitFileScopeAsmDecl(FileScopeAsmDecl *AD); void VisitAccessSpecDecl(AccessSpecDecl *D); + void VisitFriendDecl(FriendDecl *D); void VisitFriendTemplateDecl(FriendTemplateDecl *D); void VisitStaticAssertDecl(StaticAssertDecl *D); void VisitBlockDecl(BlockDecl *BD); @@ -673,6 +674,9 @@ void PCHDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) { Bases.push_back(ReadCXXBaseSpecifier()); D->setBases(Bases.begin(), NumBases); + D->data().FirstFriend + = cast_or_null<FriendDecl>(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(); @@ -704,6 +708,15 @@ void PCHDeclReader::VisitAccessSpecDecl(AccessSpecDecl *D) { D->setColonLoc(Reader.ReadSourceLocation(Record, Idx)); } +void PCHDeclReader::VisitFriendDecl(FriendDecl *D) { + if (Record[Idx++]) + D->Friend = Reader.GetTypeSourceInfo(Record, Idx); + else + D->Friend = cast<NamedDecl>(Reader.GetDecl(Record[Idx++])); + D->NextFriend = cast_or_null<FriendDecl>(Reader.GetDecl(Record[Idx++])); + D->FriendLoc = Reader.ReadSourceLocation(Record, Idx); +} + void PCHDeclReader::VisitFriendTemplateDecl(FriendTemplateDecl *D) { assert(false && "cannot read FriendTemplateDecl"); } @@ -1204,7 +1217,7 @@ Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) { SourceLocation()); break; case pch::DECL_FRIEND: - assert(false && "cannot read FriendDecl"); + D = FriendDecl::Create(*Context, Decl::EmptyShell()); break; case pch::DECL_FRIEND_TEMPLATE: assert(false && "cannot read FriendTemplateDecl"); diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 8b714386c1..d947f7250d 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -1444,11 +1444,16 @@ uint64_t PCHWriter::WriteDeclContextVisibleBlock(ASTContext &Context, if (DC->getPrimaryContext() != DC) return 0; - // Since there is no name lookup into functions or methods, and we - // perform name lookup for the translation unit via the - // IdentifierInfo chains, don't bother to build a - // visible-declarations table for these entities. - if (DC->isFunctionOrMethod() || DC->isTranslationUnit()) + // Since there is no name lookup into functions or methods, don't bother to + // build a visible-declarations table for these entities. + if (DC->isFunctionOrMethod()) + return 0; + + // If not in C++, we perform name lookup for the translation unit via the + // IdentifierInfo chains, don't bother to build a visible-declarations table. + // FIXME: In C++ we need the visible declarations in order to "see" the + // friend declarations, is there a way to do this without writing the table ? + if (DC->isTranslationUnit() && !Context.getLangOptions().CPlusPlus) return 0; // Force the DeclContext to build a its name-lookup table. diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp index 42d506953c..309cc3536d 100644 --- a/lib/Frontend/PCHWriterDecl.cpp +++ b/lib/Frontend/PCHWriterDecl.cpp @@ -25,7 +25,7 @@ using namespace clang; // Declaration serialization //===----------------------------------------------------------------------===// -namespace { +namespace clang { class PCHDeclWriter : public DeclVisitor<PCHDeclWriter, void> { PCHWriter &Writer; @@ -82,6 +82,7 @@ namespace { void VisitLinkageSpecDecl(LinkageSpecDecl *D); void VisitFileScopeAsmDecl(FileScopeAsmDecl *D); void VisitAccessSpecDecl(AccessSpecDecl *D); + void VisitFriendDecl(FriendDecl *D); void VisitFriendTemplateDecl(FriendTemplateDecl *D); void VisitStaticAssertDecl(StaticAssertDecl *D); void VisitBlockDecl(BlockDecl *D); @@ -636,7 +637,6 @@ void PCHDeclWriter::WriteCXXBaseSpecifier(const CXXBaseSpecifier *Base) { } void PCHDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) { - // assert(false && "cannot write CXXRecordDecl"); VisitRecordDecl(D); enum { @@ -664,6 +664,8 @@ void PCHDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) { 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; } @@ -698,6 +700,17 @@ void PCHDeclWriter::VisitAccessSpecDecl(AccessSpecDecl *D) { Code = pch::DECL_ACCESS_SPEC; } +void PCHDeclWriter::VisitFriendDecl(FriendDecl *D) { + Record.push_back(D->Friend.is<TypeSourceInfo*>()); + if (D->Friend.is<TypeSourceInfo*>()) + Writer.AddTypeSourceInfo(D->Friend.get<TypeSourceInfo*>(), Record); + else + Writer.AddDeclRef(D->Friend.get<NamedDecl*>(), Record); + Writer.AddDeclRef(D->NextFriend, Record); + Writer.AddSourceLocation(D->FriendLoc, Record); + Code = pch::DECL_FRIEND; +} + void PCHDeclWriter::VisitFriendTemplateDecl(FriendTemplateDecl *D) { assert(false && "cannot write FriendTemplateDecl"); } |