DeclUnloader: reset the anonymous namespace in the enclosing DC

From SemaDeclCXX.cpp:
```
C++ [namespace.unnamed]p1.  An unnamed-namespace-definition behaves as if it
were replaced by
     namespace unique { /* empty body */ }
     using namespace unique;
     namespace unique { namespace-body }
where all occurrences of 'unique' in a translation unit are replaced by the same
identifier and this identifier differs from all other identifiers in the entire
program.
```

Thus, the first declaration of an unnamed namespace creates an implicit
UsingDirectiveDecl that makes the names available in the parent DC.

If we are reverting such first declaration, make sure we reset the anonymous
namespace for the parent DeclContext so that the implicit UsingDirectiveDecl
is created again when parsing the next anonymous namespace.

Fixes issue #7483.
This commit is contained in:
Javier Lopez-Gomez 2022-02-28 17:40:45 +01:00 committed by jenkins
parent b651b2bdb4
commit 2ec73dd62a
3 changed files with 28 additions and 0 deletions

View File

@ -733,6 +733,22 @@ bool DeclUnloader::VisitRedeclarable(clang::Redeclarable<T>* R, DeclContext* DC)
}
bool DeclUnloader::VisitNamespaceDecl(NamespaceDecl* NSD) {
// The first declaration of an unnamed namespace, creates an implicit
// UsingDirectiveDecl that makes the names available in the parent DC (see
// `Sema::ActOnStartNamespaceDef()`).
// If we are reverting such first declaration, make sure we reset the
// anonymous namespace for the parent DeclContext so that the
// implicit UsingDirectiveDecl is created again when parsing the next
// anonymous namespace.
if (NSD->isAnonymousNamespace() && NSD->isFirstDecl()) {
auto Parent = NSD->getParent();
if (auto TU = dyn_cast<TranslationUnitDecl>(Parent)) {
TU->setAnonymousNamespace(nullptr);
} else if (auto NS = dyn_cast<NamespaceDecl>(Parent)) {
NS->setAnonymousNamespace(nullptr);
}
}
// NamespaceDecl: NamedDecl, DeclContext, Redeclarable
bool Successful = VisitDeclContext(NSD);
Successful &= VisitRedeclarable(NSD, NSD->getDeclContext());

View File

@ -23,3 +23,8 @@ macro() // CHECK: version 1
.L macro2.h
macro() // CHECK: 2.version 2
//CHECK: (int) 2
.x unnamedns.h
//CHECK: 13
.x unnamedns.h
//CHECK-NEXT: 13

View File

@ -0,0 +1,7 @@
namespace {
int h = 12;
}
void unnamedns() {
printf("%d\n", ++h);
}