mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-02 23:27:16 +00:00
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. llvm-svn: 107219
This commit is contained in:
parent
26d7201d5d
commit
74d28bd084
@ -248,6 +248,14 @@ protected:
|
||||
if (Decl::CollectingStats()) add(DK);
|
||||
}
|
||||
|
||||
Decl(Kind DK, EmptyShell Empty)
|
||||
: NextDeclInContext(0), DeclKind(DK), InvalidDecl(0),
|
||||
HasAttrs(false), Implicit(false), Used(false),
|
||||
Access(AS_none), PCHLevel(0),
|
||||
IdentifierNamespace(getIdentifierNamespaceForKind(DK)) {
|
||||
if (Decl::CollectingStats()) add(DK);
|
||||
}
|
||||
|
||||
virtual ~Decl();
|
||||
|
||||
public:
|
||||
|
@ -973,6 +973,9 @@ public:
|
||||
static bool classof(const ClassTemplateSpecializationDecl *D) {
|
||||
return true;
|
||||
}
|
||||
|
||||
friend class PCHDeclReader;
|
||||
friend class PCHDeclWriter;
|
||||
};
|
||||
|
||||
/// CXXMethodDecl - Represents a static or instance method of a
|
||||
|
@ -59,10 +59,13 @@ private:
|
||||
FriendLoc(FriendL) {
|
||||
}
|
||||
|
||||
FriendDecl(EmptyShell Empty) : Decl(Decl::Friend, Empty), NextFriend(0) { }
|
||||
|
||||
public:
|
||||
static FriendDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L, FriendUnion Friend_,
|
||||
SourceLocation FriendL);
|
||||
static FriendDecl *Create(ASTContext &C, EmptyShell Empty);
|
||||
|
||||
/// If this friend declaration names an (untemplated but
|
||||
/// possibly dependent) type, return the type; otherwise
|
||||
@ -87,6 +90,9 @@ public:
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const FriendDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == Decl::Friend; }
|
||||
|
||||
friend class PCHDeclReader;
|
||||
friend class PCHDeclWriter;
|
||||
};
|
||||
|
||||
/// An iterator over the friend declarations of a class.
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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.
|
||||
|
@ -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");
|
||||
}
|
||||
|
13
clang/test/PCH/cxx-friends.cpp
Normal file
13
clang/test/PCH/cxx-friends.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
// Test this without pch.
|
||||
// RUN: %clang_cc1 -include %S/cxx-friends.h -fsyntax-only -verify %s
|
||||
|
||||
// Test with pch.
|
||||
// RUN: %clang_cc1 -x c++-header -emit-pch -o %t %S/cxx-friends.h
|
||||
// RUN: %clang_cc1 -include-pch %t -fsyntax-only -verify %s
|
||||
|
||||
class F {
|
||||
void m() {
|
||||
A* a;
|
||||
a->x = 0;
|
||||
}
|
||||
};
|
6
clang/test/PCH/cxx-friends.h
Normal file
6
clang/test/PCH/cxx-friends.h
Normal file
@ -0,0 +1,6 @@
|
||||
// Header for PCH test cxx-friends.cpp
|
||||
|
||||
class A {
|
||||
int x;
|
||||
friend class F;
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user