Fix bitcode desynchronization when loading a PCH containing a class template

specialization with modules enabled. Just don't merge them at all for now;
we'll revisit this when support for template merging is added.

In passing, make Decl::dump() a little safer to use with PCH/modules, by making
it not deserialize any additional declarations. From a debugger you can call
decls_begin() or similar first if you want to dump all child decls.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@182544 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Richard Smith 2013-05-23 01:49:11 +00:00
Родитель 5705f21147
Коммит e565bfa2d6
4 изменённых файлов: 56 добавлений и 18 удалений

Просмотреть файл

@ -62,6 +62,9 @@ namespace {
// Null statements // Null statements
static const TerminalColor NullColor = { raw_ostream::BLUE, false }; static const TerminalColor NullColor = { raw_ostream::BLUE, false };
// Undeserialized entities
static const TerminalColor UndeserializedColor = { raw_ostream::GREEN, true };
// CastKind from CastExpr's // CastKind from CastExpr's
static const TerminalColor CastColor = { raw_ostream::RED, false }; static const TerminalColor CastColor = { raw_ostream::RED, false };
@ -477,20 +480,28 @@ bool ASTDumper::hasNodes(const DeclContext *DC) {
if (!DC) if (!DC)
return false; return false;
return DC->decls_begin() != DC->decls_end(); return DC->hasExternalLexicalStorage() ||
DC->noload_decls_begin() != DC->noload_decls_end();
} }
void ASTDumper::dumpDeclContext(const DeclContext *DC) { void ASTDumper::dumpDeclContext(const DeclContext *DC) {
if (!DC) if (!DC)
return; return;
for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end(); bool HasUndeserializedDecls = DC->hasExternalLexicalStorage();
for (DeclContext::decl_iterator I = DC->noload_decls_begin(), E = DC->noload_decls_end();
I != E; ++I) { I != E; ++I) {
DeclContext::decl_iterator Next = I; DeclContext::decl_iterator Next = I;
++Next; ++Next;
if (Next == E) if (Next == E && !HasUndeserializedDecls)
lastChild(); lastChild();
dumpDecl(*I); dumpDecl(*I);
} }
if (HasUndeserializedDecls) {
lastChild();
IndentScope Indent(*this);
ColorScope Color(*this, UndeserializedColor);
OS << "<undeserialized declarations>";
}
} }
void ASTDumper::dumpAttr(const Attr *A) { void ASTDumper::dumpAttr(const Attr *A) {

Просмотреть файл

@ -223,12 +223,18 @@ namespace clang {
void VisitTypedefDecl(TypedefDecl *TD); void VisitTypedefDecl(TypedefDecl *TD);
void VisitTypeAliasDecl(TypeAliasDecl *TD); void VisitTypeAliasDecl(TypeAliasDecl *TD);
void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
void VisitTagDecl(TagDecl *TD); RedeclarableResult VisitTagDecl(TagDecl *TD);
void VisitEnumDecl(EnumDecl *ED); void VisitEnumDecl(EnumDecl *ED);
void VisitRecordDecl(RecordDecl *RD); RedeclarableResult VisitRecordDeclImpl(RecordDecl *RD);
void VisitCXXRecordDecl(CXXRecordDecl *D); void VisitRecordDecl(RecordDecl *RD) { VisitRecordDeclImpl(RD); }
void VisitClassTemplateSpecializationDecl( RedeclarableResult VisitCXXRecordDeclImpl(CXXRecordDecl *D);
void VisitCXXRecordDecl(CXXRecordDecl *D) { VisitCXXRecordDeclImpl(D); }
RedeclarableResult VisitClassTemplateSpecializationDeclImpl(
ClassTemplateSpecializationDecl *D); ClassTemplateSpecializationDecl *D);
void VisitClassTemplateSpecializationDecl(
ClassTemplateSpecializationDecl *D) {
VisitClassTemplateSpecializationDeclImpl(D);
}
void VisitClassTemplatePartialSpecializationDecl( void VisitClassTemplatePartialSpecializationDecl(
ClassTemplatePartialSpecializationDecl *D); ClassTemplatePartialSpecializationDecl *D);
void VisitClassScopeFunctionSpecializationDecl( void VisitClassScopeFunctionSpecializationDecl(
@ -424,7 +430,7 @@ void ASTDeclReader::VisitTypeAliasDecl(TypeAliasDecl *TD) {
VisitTypedefNameDecl(TD); VisitTypedefNameDecl(TD);
} }
void ASTDeclReader::VisitTagDecl(TagDecl *TD) { ASTDeclReader::RedeclarableResult ASTDeclReader::VisitTagDecl(TagDecl *TD) {
RedeclarableResult Redecl = VisitRedeclarable(TD); RedeclarableResult Redecl = VisitRedeclarable(TD);
VisitTypeDecl(TD); VisitTypeDecl(TD);
@ -442,7 +448,8 @@ void ASTDeclReader::VisitTagDecl(TagDecl *TD) {
} else } else
TD->setTypedefNameForAnonDecl(ReadDeclAs<TypedefNameDecl>(Record, Idx)); TD->setTypedefNameForAnonDecl(ReadDeclAs<TypedefNameDecl>(Record, Idx));
mergeRedeclarable(TD, Redecl); mergeRedeclarable(TD, Redecl);
return Redecl;
} }
void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) { void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) {
@ -466,12 +473,14 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) {
} }
} }
void ASTDeclReader::VisitRecordDecl(RecordDecl *RD) { ASTDeclReader::RedeclarableResult
VisitTagDecl(RD); ASTDeclReader::VisitRecordDeclImpl(RecordDecl *RD) {
RedeclarableResult Redecl = VisitTagDecl(RD);
RD->setHasFlexibleArrayMember(Record[Idx++]); RD->setHasFlexibleArrayMember(Record[Idx++]);
RD->setAnonymousStructOrUnion(Record[Idx++]); RD->setAnonymousStructOrUnion(Record[Idx++]);
RD->setHasObjectMember(Record[Idx++]); RD->setHasObjectMember(Record[Idx++]);
RD->setHasVolatileMember(Record[Idx++]); RD->setHasVolatileMember(Record[Idx++]);
return Redecl;
} }
void ASTDeclReader::VisitValueDecl(ValueDecl *VD) { void ASTDeclReader::VisitValueDecl(ValueDecl *VD) {
@ -1022,6 +1031,7 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) {
D->setInline(Record[Idx++]); D->setInline(Record[Idx++]);
D->LocStart = ReadSourceLocation(Record, Idx); D->LocStart = ReadSourceLocation(Record, Idx);
D->RBraceLoc = ReadSourceLocation(Record, Idx); D->RBraceLoc = ReadSourceLocation(Record, Idx);
// FIXME: At the point of this call, D->getCanonicalDecl() returns 0.
mergeRedeclarable(D, Redecl); mergeRedeclarable(D, Redecl);
if (Redecl.getFirstID() == ThisDeclID) { if (Redecl.getFirstID() == ThisDeclID) {
@ -1180,8 +1190,9 @@ void ASTDeclReader::ReadCXXDefinitionData(
} }
} }
void ASTDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) { ASTDeclReader::RedeclarableResult
VisitRecordDecl(D); ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
RedeclarableResult Redecl = VisitRecordDeclImpl(D);
ASTContext &C = Reader.getContext(); ASTContext &C = Reader.getContext();
if (Record[Idx++]) { if (Record[Idx++]) {
@ -1236,6 +1247,8 @@ void ASTDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) {
if (CXXMethodDecl *Key = ReadDeclAs<CXXMethodDecl>(Record, Idx)) if (CXXMethodDecl *Key = ReadDeclAs<CXXMethodDecl>(Record, Idx))
C.KeyFunctions[D] = Key; C.KeyFunctions[D] = Key;
} }
return Redecl;
} }
void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) { void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) {
@ -1391,9 +1404,10 @@ void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
} }
} }
void ASTDeclReader::VisitClassTemplateSpecializationDecl( ASTDeclReader::RedeclarableResult
ClassTemplateSpecializationDecl *D) { ASTDeclReader::VisitClassTemplateSpecializationDeclImpl(
VisitCXXRecordDecl(D); ClassTemplateSpecializationDecl *D) {
RedeclarableResult Redecl = VisitCXXRecordDeclImpl(D);
ASTContext &C = Reader.getContext(); ASTContext &C = Reader.getContext();
if (Decl *InstD = ReadDecl(Record, Idx)) { if (Decl *InstD = ReadDecl(Record, Idx)) {
@ -1444,11 +1458,13 @@ void ASTDeclReader::VisitClassTemplateSpecializationDecl(
} }
} }
} }
return Redecl;
} }
void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl( void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl(
ClassTemplatePartialSpecializationDecl *D) { ClassTemplatePartialSpecializationDecl *D) {
VisitClassTemplateSpecializationDecl(D); RedeclarableResult Redecl = VisitClassTemplateSpecializationDeclImpl(D);
ASTContext &C = Reader.getContext(); ASTContext &C = Reader.getContext();
D->TemplateParams = Reader.ReadTemplateParameterList(F, Record, Idx); D->TemplateParams = Reader.ReadTemplateParameterList(F, Record, Idx);
@ -1464,7 +1480,7 @@ void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl(
D->SequenceNumber = Record[Idx++]; D->SequenceNumber = Record[Idx++];
// These are read/set from/to the first declaration. // These are read/set from/to the first declaration.
if (D->getPreviousDecl() == 0) { if (ThisDeclID == Redecl.getFirstID()) {
D->InstantiatedFromMember.setPointer( D->InstantiatedFromMember.setPointer(
ReadDeclAs<ClassTemplatePartialSpecializationDecl>(Record, Idx)); ReadDeclAs<ClassTemplatePartialSpecializationDecl>(Record, Idx));
D->InstantiatedFromMember.setInt(Record[Idx++]); D->InstantiatedFromMember.setInt(Record[Idx++]);
@ -1780,6 +1796,13 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
// Objective-C classes and protocols with the same name always match. // Objective-C classes and protocols with the same name always match.
if (isa<ObjCInterfaceDecl>(X) || isa<ObjCProtocolDecl>(X)) if (isa<ObjCInterfaceDecl>(X) || isa<ObjCProtocolDecl>(X))
return true; return true;
if (isa<ClassTemplateSpecializationDecl>(X)) {
// FIXME: Deal with merging of template specializations.
// For now, don't merge these; we need to check more than just the name to
// determine if they refer to the same entity.
return false;
}
// Compatible tags match. // Compatible tags match.
if (TagDecl *TagX = dyn_cast<TagDecl>(X)) { if (TagDecl *TagX = dyn_cast<TagDecl>(X)) {

Просмотреть файл

@ -6,6 +6,9 @@
// With PCH // With PCH
// RUN: %clang_cc1 -fsyntax-only -verify %s -chain-include %s -chain-include %s // RUN: %clang_cc1 -fsyntax-only -verify %s -chain-include %s -chain-include %s
// With modules
// RUN: %clang_cc1 -fsyntax-only -verify -fmodules %s -chain-include %s -chain-include %s
// expected-no-diagnostics // expected-no-diagnostics
#ifndef HEADER1 #ifndef HEADER1

Просмотреть файл

@ -1,4 +1,5 @@
// RUN: %clang_cc1 %s -ast-print -o - -chain-include %s -chain-include %s // RUN: %clang_cc1 %s -ast-print -o - -chain-include %s -chain-include %s
// RUN: %clang_cc1 %s -ast-print -o - -fmodules -chain-include %s -chain-include %s
#if !defined(PASS1) #if !defined(PASS1)
#define PASS1 #define PASS1