aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp14
-rw-r--r--lib/Serialization/ASTWriterDecl.cpp55
-rw-r--r--test/Modules/Inputs/redecl-merge-bottom.h3
-rw-r--r--test/Modules/Inputs/redecl-merge-left.h4
-rw-r--r--test/Modules/Inputs/redecl-merge-right.h2
-rw-r--r--test/Modules/Inputs/redecl-merge-top.h2
-rw-r--r--test/Modules/redecl-merge.m5
7 files changed, 45 insertions, 40 deletions
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index d538d6ebb6..3e08d99ae6 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -1410,9 +1410,18 @@ ASTDeclReader::VisitDeclContext(DeclContext *DC) {
template <typename T>
void ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
- enum RedeclKind { FirstInFile, PointsToPrevious };
+ enum RedeclKind { OnlyDeclaration = 0, FirstInFile, PointsToPrevious };
RedeclKind Kind = (RedeclKind)Record[Idx++];
+ // If this is the only known declaration of this entity, this module file
+ // has no additional redeclaration information. However, other module
+ // files might have redeclarations.
+ if (Kind == OnlyDeclaration) {
+ if (Reader.PendingDeclChainsKnown.insert(ThisDeclID))
+ Reader.PendingDeclChains.push_back(ThisDeclID);
+ return;
+ }
+
// Read the first declaration ID, and note that we need to reconstruct
// the redeclaration chain once we hit the top level.
DeclID FirstDeclID = ReadDeclID(Record, Idx);
@@ -1422,6 +1431,9 @@ void ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
T *FirstDecl = cast_or_null<T>(Reader.GetDecl(FirstDeclID));
switch (Kind) {
+ case OnlyDeclaration:
+ llvm_unreachable("only declaration handled above");
+
case FirstInFile:
if (FirstDecl != D)
D->RedeclLink = typename Redeclarable<T>::PreviousDeclLink(FirstDecl);
diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp
index 4e9a315d22..bb4359a54b 100644
--- a/lib/Serialization/ASTWriterDecl.cpp
+++ b/lib/Serialization/ASTWriterDecl.cpp
@@ -126,30 +126,6 @@ namespace clang {
};
}
-static bool isFirstDeclInFile(Decl *D) {
- // FIXME: There must be a better way to abstract Redeclarable<T> into a
- // more-general "redeclarable type".
- if (TagDecl *Tag = dyn_cast<TagDecl>(D))
- return !Tag->getPreviousDeclaration() ||
- Tag->getPreviousDeclaration()->isFromASTFile();
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
- return !FD->getPreviousDeclaration() ||
- FD->getPreviousDeclaration()->isFromASTFile();
- if (VarDecl *VD = dyn_cast<VarDecl>(D))
- return !VD->getPreviousDeclaration() ||
- VD->getPreviousDeclaration()->isFromASTFile();
- if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D))
- return !TD->getPreviousDeclaration() ||
- TD->getPreviousDeclaration()->isFromASTFile();
- if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
- return !ID->getPreviousDeclaration() ||
- ID->getPreviousDeclaration()->isFromASTFile();
-
- RedeclarableTemplateDecl *RTD = cast<RedeclarableTemplateDecl>(D);
- return !RTD->getPreviousDeclaration() ||
- RTD->getPreviousDeclaration()->isFromASTFile();
-}
-
void ASTDeclWriter::Visit(Decl *D) {
DeclVisitor<ASTDeclWriter>::Visit(D);
@@ -212,7 +188,7 @@ void ASTDeclWriter::VisitTypedefDecl(TypedefDecl *D) {
if (!D->hasAttrs() &&
!D->isImplicit() &&
!D->isUsed(false) &&
- isFirstDeclInFile(D) &&
+ D->RedeclLink.getPointer() == D &&
!D->isInvalidDecl() &&
!D->isReferenced() &&
!D->isTopLevelDeclInObjCContainer() &&
@@ -262,7 +238,7 @@ void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) {
!D->isImplicit() &&
!D->isUsed(false) &&
!D->hasExtInfo() &&
- isFirstDeclInFile(D) &&
+ D->RedeclLink.getPointer() == D &&
!D->isInvalidDecl() &&
!D->isReferenced() &&
!D->isTopLevelDeclInObjCContainer() &&
@@ -286,7 +262,7 @@ void ASTDeclWriter::VisitRecordDecl(RecordDecl *D) {
!D->isImplicit() &&
!D->isUsed(false) &&
!D->hasExtInfo() &&
- isFirstDeclInFile(D) &&
+ D->RedeclLink.getPointer() == D &&
!D->isInvalidDecl() &&
!D->isReferenced() &&
!D->isTopLevelDeclInObjCContainer() &&
@@ -732,7 +708,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
!D->isModulePrivate() &&
D->getDeclName().getNameKind() == DeclarationName::Identifier &&
!D->hasExtInfo() &&
- isFirstDeclInFile(D) &&
+ D->RedeclLink.getPointer() == D &&
!D->hasCXXDirectInitializer() &&
D->getInit() == 0 &&
!isa<ParmVarDecl>(D) &&
@@ -1298,7 +1274,13 @@ void ASTDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
template <typename T>
void ASTDeclWriter::VisitRedeclarable(Redeclarable<T> *D) {
- enum { FirstInFile, PointsToPrevious };
+ enum { OnlyDeclaration = 0, FirstInFile, PointsToPrevious };
+ if (D->RedeclLink.getPointer() == D) {
+ // This is the only declaration.
+ Record.push_back(OnlyDeclaration);
+ return;
+ }
+
T *First = D->getFirstDeclaration();
if (!D->getPreviousDeclaration() ||
D->getPreviousDeclaration()->isFromASTFile()) {
@@ -1399,8 +1381,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
Abv = new BitCodeAbbrev();
Abv->Add(BitCodeAbbrevOp(serialization::DECL_ENUM));
// Redeclarable
- Abv->Add(BitCodeAbbrevOp(0)); // First in file
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // First ID
+ Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration
// Decl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext
@@ -1447,8 +1428,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
Abv = new BitCodeAbbrev();
Abv->Add(BitCodeAbbrevOp(serialization::DECL_RECORD));
// Redeclarable
- Abv->Add(BitCodeAbbrevOp(0)); // First in file
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // First ID
+ Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration
// Decl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext
@@ -1489,8 +1469,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
Abv = new BitCodeAbbrev();
Abv->Add(BitCodeAbbrevOp(serialization::DECL_PARM_VAR));
// Redeclarable
- Abv->Add(BitCodeAbbrevOp(0)); // First in file
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // First ID
+ Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration
// Decl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext
@@ -1540,8 +1519,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
Abv = new BitCodeAbbrev();
Abv->Add(BitCodeAbbrevOp(serialization::DECL_TYPEDEF));
// Redeclarable
- Abv->Add(BitCodeAbbrevOp(0)); // First in file
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // First ID
+ Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration
// Decl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext
@@ -1569,8 +1547,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
Abv = new BitCodeAbbrev();
Abv->Add(BitCodeAbbrevOp(serialization::DECL_VAR));
// Redeclarable
- Abv->Add(BitCodeAbbrevOp(0)); // First in file
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // First ID
+ Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration
// Decl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext
diff --git a/test/Modules/Inputs/redecl-merge-bottom.h b/test/Modules/Inputs/redecl-merge-bottom.h
index e45e0dea04..198bde3e5f 100644
--- a/test/Modules/Inputs/redecl-merge-bottom.h
+++ b/test/Modules/Inputs/redecl-merge-bottom.h
@@ -1,4 +1,7 @@
__import_module__ redecl_merge_left;
__import_module__ redecl_merge_right;
+@class B;
+
@class A;
+
diff --git a/test/Modules/Inputs/redecl-merge-left.h b/test/Modules/Inputs/redecl-merge-left.h
index 0858922348..048b3e6c2d 100644
--- a/test/Modules/Inputs/redecl-merge-left.h
+++ b/test/Modules/Inputs/redecl-merge-left.h
@@ -4,4 +4,8 @@ __import_module__ redecl_merge_top;
@class A;
+@interface B
+@end
+
@class A;
+
diff --git a/test/Modules/Inputs/redecl-merge-right.h b/test/Modules/Inputs/redecl-merge-right.h
index 266146c995..d8fd45f2b9 100644
--- a/test/Modules/Inputs/redecl-merge-right.h
+++ b/test/Modules/Inputs/redecl-merge-right.h
@@ -7,3 +7,5 @@ __import_module__ redecl_merge_top;
- (Super*)init;
@end
+@class B;
+
diff --git a/test/Modules/Inputs/redecl-merge-top.h b/test/Modules/Inputs/redecl-merge-top.h
index 886436cdda..68dae5058e 100644
--- a/test/Modules/Inputs/redecl-merge-top.h
+++ b/test/Modules/Inputs/redecl-merge-top.h
@@ -3,3 +3,5 @@
@class A;
@class A;
+
+@class B;
diff --git a/test/Modules/redecl-merge.m b/test/Modules/redecl-merge.m
index d62d504868..fe25044166 100644
--- a/test/Modules/redecl-merge.m
+++ b/test/Modules/redecl-merge.m
@@ -14,8 +14,13 @@ void f(A *a) {
@class A;
+@class B;
+
__import_module__ redecl_merge_bottom;
+@implementation B
+@end
+
void g(A *a) {
[a init];
}