summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/Serialization/ASTReaderDecl.cpp27
-rw-r--r--clang/test/Modules/Inputs/anon-namespace/a.h1
-rw-r--r--clang/test/Modules/Inputs/anon-namespace/b1.h2
-rw-r--r--clang/test/Modules/Inputs/anon-namespace/b2.h2
-rw-r--r--clang/test/Modules/Inputs/anon-namespace/c.h1
-rw-r--r--clang/test/Modules/Inputs/anon-namespace/module.modulemap3
-rw-r--r--clang/test/Modules/anon-namespace.cpp6
7 files changed, 33 insertions, 9 deletions
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 96c16ea10ee..83882a83693 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -1198,13 +1198,13 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) {
D->LocStart = ReadSourceLocation(Record, Idx);
D->RBraceLoc = ReadSourceLocation(Record, Idx);
+ // Defer loading the anonymous namespace until we've finished merging
+ // this namespace; loading it might load a later declaration of the
+ // same namespace, and we have an invariant that older declarations
+ // get merged before newer ones try to merge.
+ GlobalDeclID AnonNamespace = 0;
if (Redecl.getFirstID() == ThisDeclID) {
- // Each module has its own anonymous namespace, which is disjoint from
- // any other module's anonymous namespaces, so don't attach the anonymous
- // namespace at all.
- NamespaceDecl *Anon = ReadDeclAs<NamespaceDecl>(Record, Idx);
- if (F.Kind != MK_ImplicitModule && F.Kind != MK_ExplicitModule)
- D->setAnonymousNamespace(Anon);
+ AnonNamespace = ReadDeclID(Record, Idx);
} else {
// Link this namespace back to the first declaration, which has already
// been deserialized.
@@ -1212,6 +1212,15 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) {
}
mergeRedeclarable(D, Redecl);
+
+ if (AnonNamespace) {
+ // Each module has its own anonymous namespace, which is disjoint from
+ // any other module's anonymous namespaces, so don't attach the anonymous
+ // namespace at all.
+ NamespaceDecl *Anon = cast<NamespaceDecl>(Reader.GetDecl(AnonNamespace));
+ if (F.Kind != MK_ImplicitModule && F.Kind != MK_ExplicitModule)
+ D->setAnonymousNamespace(Anon);
+ }
}
void ASTDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
@@ -2196,6 +2205,8 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing,
D->RedeclLink = Redeclarable<T>::PreviousDeclLink(ExistingCanon);
// When we merge a namespace, update its pointer to the first namespace.
+ // We cannot have loaded any redeclarations of this declaration yet, so
+ // there's nothing else that needs to be updated.
if (auto *Namespace = dyn_cast<NamespaceDecl>(D))
Namespace->AnonOrFirstNamespaceAndInline.setPointer(
assert_cast<NamespaceDecl*>(ExistingCanon));
@@ -2206,9 +2217,7 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing,
DTemplate, assert_cast<RedeclarableTemplateDecl*>(ExistingCanon),
TemplatePatternID);
- // If this declaration was the canonical declaration, make a note of
- // that. We accept the linear algorithm here because the number of
- // unique canonical declarations of an entity should always be tiny.
+ // If this declaration was the canonical declaration, make a note of that.
if (DCanon == D) {
Reader.MergedDecls[ExistingCanon].push_back(Redecl.getFirstID());
if (Reader.PendingDeclChainsKnown.insert(ExistingCanon).second)
diff --git a/clang/test/Modules/Inputs/anon-namespace/a.h b/clang/test/Modules/Inputs/anon-namespace/a.h
new file mode 100644
index 00000000000..fe71f4004e4
--- /dev/null
+++ b/clang/test/Modules/Inputs/anon-namespace/a.h
@@ -0,0 +1 @@
+namespace N {}
diff --git a/clang/test/Modules/Inputs/anon-namespace/b1.h b/clang/test/Modules/Inputs/anon-namespace/b1.h
new file mode 100644
index 00000000000..480e8e46a95
--- /dev/null
+++ b/clang/test/Modules/Inputs/anon-namespace/b1.h
@@ -0,0 +1,2 @@
+namespace N {}
+namespace N { namespace {} }
diff --git a/clang/test/Modules/Inputs/anon-namespace/b2.h b/clang/test/Modules/Inputs/anon-namespace/b2.h
new file mode 100644
index 00000000000..8e7535f3626
--- /dev/null
+++ b/clang/test/Modules/Inputs/anon-namespace/b2.h
@@ -0,0 +1,2 @@
+#include "a.h"
+namespace N {}
diff --git a/clang/test/Modules/Inputs/anon-namespace/c.h b/clang/test/Modules/Inputs/anon-namespace/c.h
new file mode 100644
index 00000000000..fe71f4004e4
--- /dev/null
+++ b/clang/test/Modules/Inputs/anon-namespace/c.h
@@ -0,0 +1 @@
+namespace N {}
diff --git a/clang/test/Modules/Inputs/anon-namespace/module.modulemap b/clang/test/Modules/Inputs/anon-namespace/module.modulemap
new file mode 100644
index 00000000000..3d390d2d4e7
--- /dev/null
+++ b/clang/test/Modules/Inputs/anon-namespace/module.modulemap
@@ -0,0 +1,3 @@
+module a { header "a.h" export * }
+module b { module b1 { header "b1.h" export * } module b2 { header "b2.h" export * } }
+module c { header "c.h" export * }
diff --git a/clang/test/Modules/anon-namespace.cpp b/clang/test/Modules/anon-namespace.cpp
new file mode 100644
index 00000000000..6c085ebc885
--- /dev/null
+++ b/clang/test/Modules/anon-namespace.cpp
@@ -0,0 +1,6 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -I%S/Inputs/anon-namespace -verify %s
+// expected-no-diagnostics
+#include "b1.h"
+#include "c.h"
+using namespace N;
OpenPOWER on IntegriCloud