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
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index 8cf41f5..2ed3645 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -62,6 +62,9 @@
// Null statements
static const TerminalColor NullColor = { raw_ostream::BLUE, false };
+ // Undeserialized entities
+ static const TerminalColor UndeserializedColor = { raw_ostream::GREEN, true };
+
// CastKind from CastExpr's
static const TerminalColor CastColor = { raw_ostream::RED, false };
@@ -477,20 +480,28 @@
if (!DC)
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) {
if (!DC)
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) {
DeclContext::decl_iterator Next = I;
++Next;
- if (Next == E)
+ if (Next == E && !HasUndeserializedDecls)
lastChild();
dumpDecl(*I);
}
+ if (HasUndeserializedDecls) {
+ lastChild();
+ IndentScope Indent(*this);
+ ColorScope Color(*this, UndeserializedColor);
+ OS << "<undeserialized declarations>";
+ }
}
void ASTDumper::dumpAttr(const Attr *A) {
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index 11c82da..6eed40c 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -223,12 +223,18 @@
void VisitTypedefDecl(TypedefDecl *TD);
void VisitTypeAliasDecl(TypeAliasDecl *TD);
void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
- void VisitTagDecl(TagDecl *TD);
+ RedeclarableResult VisitTagDecl(TagDecl *TD);
void VisitEnumDecl(EnumDecl *ED);
- void VisitRecordDecl(RecordDecl *RD);
- void VisitCXXRecordDecl(CXXRecordDecl *D);
- void VisitClassTemplateSpecializationDecl(
+ RedeclarableResult VisitRecordDeclImpl(RecordDecl *RD);
+ void VisitRecordDecl(RecordDecl *RD) { VisitRecordDeclImpl(RD); }
+ RedeclarableResult VisitCXXRecordDeclImpl(CXXRecordDecl *D);
+ void VisitCXXRecordDecl(CXXRecordDecl *D) { VisitCXXRecordDeclImpl(D); }
+ RedeclarableResult VisitClassTemplateSpecializationDeclImpl(
ClassTemplateSpecializationDecl *D);
+ void VisitClassTemplateSpecializationDecl(
+ ClassTemplateSpecializationDecl *D) {
+ VisitClassTemplateSpecializationDeclImpl(D);
+ }
void VisitClassTemplatePartialSpecializationDecl(
ClassTemplatePartialSpecializationDecl *D);
void VisitClassScopeFunctionSpecializationDecl(
@@ -424,7 +430,7 @@
VisitTypedefNameDecl(TD);
}
-void ASTDeclReader::VisitTagDecl(TagDecl *TD) {
+ASTDeclReader::RedeclarableResult ASTDeclReader::VisitTagDecl(TagDecl *TD) {
RedeclarableResult Redecl = VisitRedeclarable(TD);
VisitTypeDecl(TD);
@@ -442,7 +448,8 @@
} else
TD->setTypedefNameForAnonDecl(ReadDeclAs<TypedefNameDecl>(Record, Idx));
- mergeRedeclarable(TD, Redecl);
+ mergeRedeclarable(TD, Redecl);
+ return Redecl;
}
void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) {
@@ -466,12 +473,14 @@
}
}
-void ASTDeclReader::VisitRecordDecl(RecordDecl *RD) {
- VisitTagDecl(RD);
+ASTDeclReader::RedeclarableResult
+ASTDeclReader::VisitRecordDeclImpl(RecordDecl *RD) {
+ RedeclarableResult Redecl = VisitTagDecl(RD);
RD->setHasFlexibleArrayMember(Record[Idx++]);
RD->setAnonymousStructOrUnion(Record[Idx++]);
RD->setHasObjectMember(Record[Idx++]);
RD->setHasVolatileMember(Record[Idx++]);
+ return Redecl;
}
void ASTDeclReader::VisitValueDecl(ValueDecl *VD) {
@@ -1022,6 +1031,7 @@
D->setInline(Record[Idx++]);
D->LocStart = ReadSourceLocation(Record, Idx);
D->RBraceLoc = ReadSourceLocation(Record, Idx);
+ // FIXME: At the point of this call, D->getCanonicalDecl() returns 0.
mergeRedeclarable(D, Redecl);
if (Redecl.getFirstID() == ThisDeclID) {
@@ -1180,8 +1190,9 @@
}
}
-void ASTDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) {
- VisitRecordDecl(D);
+ASTDeclReader::RedeclarableResult
+ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
+ RedeclarableResult Redecl = VisitRecordDeclImpl(D);
ASTContext &C = Reader.getContext();
if (Record[Idx++]) {
@@ -1236,6 +1247,8 @@
if (CXXMethodDecl *Key = ReadDeclAs<CXXMethodDecl>(Record, Idx))
C.KeyFunctions[D] = Key;
}
+
+ return Redecl;
}
void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) {
@@ -1391,9 +1404,10 @@
}
}
-void ASTDeclReader::VisitClassTemplateSpecializationDecl(
- ClassTemplateSpecializationDecl *D) {
- VisitCXXRecordDecl(D);
+ASTDeclReader::RedeclarableResult
+ASTDeclReader::VisitClassTemplateSpecializationDeclImpl(
+ ClassTemplateSpecializationDecl *D) {
+ RedeclarableResult Redecl = VisitCXXRecordDeclImpl(D);
ASTContext &C = Reader.getContext();
if (Decl *InstD = ReadDecl(Record, Idx)) {
@@ -1444,11 +1458,13 @@
}
}
}
+
+ return Redecl;
}
void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl(
ClassTemplatePartialSpecializationDecl *D) {
- VisitClassTemplateSpecializationDecl(D);
+ RedeclarableResult Redecl = VisitClassTemplateSpecializationDeclImpl(D);
ASTContext &C = Reader.getContext();
D->TemplateParams = Reader.ReadTemplateParameterList(F, Record, Idx);
@@ -1464,7 +1480,7 @@
D->SequenceNumber = Record[Idx++];
// These are read/set from/to the first declaration.
- if (D->getPreviousDecl() == 0) {
+ if (ThisDeclID == Redecl.getFirstID()) {
D->InstantiatedFromMember.setPointer(
ReadDeclAs<ClassTemplatePartialSpecializationDecl>(Record, Idx));
D->InstantiatedFromMember.setInt(Record[Idx++]);
@@ -1780,6 +1796,13 @@
// Objective-C classes and protocols with the same name always match.
if (isa<ObjCInterfaceDecl>(X) || isa<ObjCProtocolDecl>(X))
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.
if (TagDecl *TagX = dyn_cast<TagDecl>(X)) {
diff --git a/test/PCH/chain-cxx.cpp b/test/PCH/chain-cxx.cpp
index 4b64f51..6e9c174 100644
--- a/test/PCH/chain-cxx.cpp
+++ b/test/PCH/chain-cxx.cpp
@@ -6,6 +6,9 @@
// With PCH
// 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
#ifndef HEADER1
diff --git a/test/PCH/chain-friend-instantiation.cpp b/test/PCH/chain-friend-instantiation.cpp
index 294d979..2f042a8 100644
--- a/test/PCH/chain-friend-instantiation.cpp
+++ b/test/PCH/chain-friend-instantiation.cpp
@@ -1,4 +1,5 @@
// 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)
#define PASS1