зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
5705f21147
Коммит
e565bfa2d6
|
@ -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);
|
||||||
|
|
||||||
|
@ -443,6 +449,7 @@ void ASTDeclReader::VisitTagDecl(TagDecl *TD) {
|
||||||
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
|
||||||
|
ASTDeclReader::VisitClassTemplateSpecializationDeclImpl(
|
||||||
ClassTemplateSpecializationDecl *D) {
|
ClassTemplateSpecializationDecl *D) {
|
||||||
VisitCXXRecordDecl(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++]);
|
||||||
|
@ -1781,6 +1797,13 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
|
||||||
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)) {
|
||||||
TagDecl *TagY = cast<TagDecl>(Y);
|
TagDecl *TagY = cast<TagDecl>(Y);
|
||||||
|
|
|
@ -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
|
||||||
|
|
Загрузка…
Ссылка в новой задаче