Skip to content

Commit

Permalink
Fix unloading from inline namespaces other than std.
Browse files Browse the repository at this point in the history
  • Loading branch information
marsupial authored and sftnight committed Feb 9, 2017
1 parent 87c97ba commit 185b905
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 16 deletions.
24 changes: 9 additions & 15 deletions lib/Interpreter/DeclUnloader.cpp
Expand Up @@ -737,23 +737,17 @@ bool DeclUnloader::VisitRedeclarable(clang::Redeclarable<T>* R, DeclContext* DC)
bool DeclUnloader::VisitNamespaceDecl(NamespaceDecl* NSD) {
// NamespaceDecl: NamedDecl, DeclContext, Redeclarable

// When unloading a NamedDecl within an inline namespace within std the
// NamedDecl needs to be removed from the parent std as well.
// Not sure why, but test/CodeUnloading/NameSpaces.C demonstrates
// that this only affects the std namespace
StoredDeclsMap *removeFromSTD = nullptr;
// When unloading a NamedDecl within an inline namespace within the
// NamedDecl needs to be removed from the parent well.
StoredDeclsMap *removeFromParent = nullptr;
if (NSD->isInline()) {
if (NamespaceDecl *parent = dyn_cast<NamespaceDecl>(NSD->getParent())) {
if (parent->getNameAsString()=="std") {
if ((parent = m_Sema->getStdNamespace()))
removeFromSTD = m_Sema->getStdNamespace()->getLookupPtr();
}
}
if (NamespaceDecl *parent = dyn_cast<NamespaceDecl>(NSD->getParent()))
removeFromParent = parent->getFirstDecl()->getLookupPtr();
}

bool Successful = VisitRedeclarable(NSD, NSD->getDeclContext());

// Inlined version of VisitDeclContext so we can check against removeFromSTD
// Inlined version of VisitDeclContext so we can check against parent
llvm::SmallVector<Decl*, 64> declsToErase;
for (Decl *D : NSD->noload_decls())
declsToErase.push_back(D);
Expand All @@ -762,11 +756,11 @@ bool DeclUnloader::VisitRedeclarable(clang::Redeclarable<T>* R, DeclContext* DC)
Successful = Visit(*I) & Successful;
assert(Successful);

if (removeFromSTD) {
if (removeFromParent) {
if (NamedDecl *ND = dyn_cast<NamedDecl>(*I)) {
eraseDeclFromMap(removeFromSTD, ND);
eraseDeclFromMap(removeFromParent, ND);
#ifndef NDEBUG
checkDeclIsGone(removeFromSTD, ND);
checkDeclIsGone(removeFromParent, ND);
#endif
}
}
Expand Down
13 changes: 12 additions & 1 deletion test/CodeUnloading/NameSpaces.C
Expand Up @@ -24,6 +24,18 @@
#undef TEST_NAMESPACE


namespace A{}
namespace A { inline namespace __BBB { int f; } }
namespace A { inline namespace __BBB { int f1; } }
namespace A { inline namespace __BBB { int f2; } }
.undo
A::f2 // expected-error {{no member named 'f2' in namespace 'A'}}
.undo
A::f1 // expected-error {{no member named 'f1' in namespace 'A'}}
.undo
A::f // expected-error {{no member named 'f' in namespace 'A'}}


#include <stdexcept>
.undo
#include <stdexcept>
Expand All @@ -32,5 +44,4 @@
101
// CHECK: (int) 101

// expected-no-diagnostics
.q

0 comments on commit 185b905

Please sign in to comment.