From: Sebastian Redl Date: Sun, 24 Apr 2011 16:28:21 +0000 (+0000) Subject: Set the correct anonymous namespace (must be last reopening), and behave correctly... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=74b485a2b36c0ba33a85ba9cb6e36e0e3a1fada1;p=clang Set the correct anonymous namespace (must be last reopening), and behave correctly in the presence of the ever-annoying linkage specifications. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130105 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 419e84e846..b778a60f60 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -447,7 +447,7 @@ public: void setAnonymousNamespace(NamespaceDecl *D) { assert(!D || D->isAnonymousNamespace()); - assert(!D || D->getParent() == this); + assert(!D || D->getParent()->getRedeclContext() == this); getOriginalNamespace()->OrigOrAnonNamespace.setPointer(D); } diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 3d4e4cdd00..52eff1957d 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -1741,10 +1741,15 @@ void ASTDeclReader::UpdateDecl(Decl *D, const RecordData &Record) { case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE: { NamespaceDecl *Anon = cast(Reader.GetDecl(Record[Idx++])); - if (TranslationUnitDecl *TU = dyn_cast(D)) - TU->setAnonymousNamespace(Anon); - else - cast(D)->OrigOrAnonNamespace.setPointer(Anon); + // Guard against these being loaded out of original order. Don't use + // getNextNamespace(), since it tries to access the context and can't in + // the middle of deserialization. + if (!Anon->NextNamespace) { + if (TranslationUnitDecl *TU = dyn_cast(D)) + TU->setAnonymousNamespace(Anon); + else + cast(D)->OrigOrAnonNamespace.setPointer(Anon); + } break; } } diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index db72be3f58..df83f2f694 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -708,11 +708,13 @@ void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) { } } - if (Writer.hasChain() && D->isOriginalNamespace() && - D->isAnonymousNamespace()) { - // This is an original anonymous namespace. If its parent is in a previous - // PCH (or is the TU), mark that parent for update. - Decl *Parent = cast(D->getParent()->getPrimaryContext()); + if (Writer.hasChain() && D->isAnonymousNamespace() && !D->getNextNamespace()){ + // This is a most recent reopening of the anonymous namespace. If its parent + // is in a previous PCH (or is the TU), mark that parent for update, because + // the original namespace always points to the latest re-opening of its + // anonymous namespace. + Decl *Parent = cast( + D->getParent()->getRedeclContext()->getPrimaryContext()); if (Parent->getPCHLevel() > 0) { ASTWriter::UpdateRecord &Record = Writer.DeclUpdates[Parent]; Record.push_back(UPD_CXX_ADDED_ANONYMOUS_NAMESPACE); diff --git a/test/PCH/chain-late-anonymous-namespace.cpp b/test/PCH/chain-late-anonymous-namespace.cpp index 53699477c9..87205c631b 100644 --- a/test/PCH/chain-late-anonymous-namespace.cpp +++ b/test/PCH/chain-late-anonymous-namespace.cpp @@ -6,6 +6,7 @@ #define PASS1 namespace ns {} +namespace os {} #elif !defined(PASS2) #define PASS2 @@ -19,6 +20,16 @@ namespace ns { namespace { extern int y; } +namespace { +} + +namespace os { + extern "C" { + namespace { + extern int z; + } + } +} #else @@ -38,4 +49,13 @@ void test() { (void)y; } +namespace os { + namespace { + int z; + } + void test() { + (void)z; + } +} + #endif