From a544c51e94445ad655e512af690cb214aac73321 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Mon, 30 Oct 2017 22:38:20 +0000 Subject: [PATCH] [modules] Retain multiple using-directives in the same scope even if they name the same namespace. They might have different visibility, and thus discarding all but one of them can result in rejecting valid code. Also fix name lookup to cope with multiple using-directives being found that denote the same namespace, where some are not visible -- don't cache an "already visited" state for a using-directive that we didn't visit because it was hidden. llvm-svn: 316965 --- clang/lib/AST/Decl.cpp | 8 ------ clang/lib/Sema/SemaLookup.cpp | 6 ++--- clang/test/Modules/using-directive-redecl.cpp | 37 +++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 11 deletions(-) create mode 100644 clang/test/Modules/using-directive-redecl.cpp diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index f27df1d..32a4907 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -1597,14 +1597,6 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD, bool IsKnownNewer) const { cast(OldD)->getQualifier()); } - // UsingDirectiveDecl's are not really NamedDecl's, and all have same name. - // They can be replaced if they nominate the same namespace. - // FIXME: Is this true even if they have different module visibility? - if (auto *UD = dyn_cast(this)) - return UD->getNominatedNamespace()->getOriginalNamespace() == - cast(OldD)->getNominatedNamespace() - ->getOriginalNamespace(); - if (isRedeclarable(getKind())) { if (getCanonicalDecl() != OldD->getCanonicalDecl()) return false; diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 73aceaa..d3f91a4 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -155,7 +155,7 @@ namespace { while (true) { for (auto UD : DC->using_directives()) { DeclContext *NS = UD->getNominatedNamespace(); - if (visited.insert(NS).second && SemaRef.isVisible(UD)) { + if (SemaRef.isVisible(UD) && visited.insert(NS).second) { addUsingDirective(UD, EffectiveDC); queue.push_back(NS); } @@ -1883,7 +1883,7 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R, // with its using-children. for (auto *I : StartDC->using_directives()) { NamespaceDecl *ND = I->getNominatedNamespace()->getOriginalNamespace(); - if (Visited.insert(ND).second && S.isVisible(I)) + if (S.isVisible(I) && Visited.insert(ND).second) Queue.push_back(ND); } @@ -1931,7 +1931,7 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R, for (auto I : ND->using_directives()) { NamespaceDecl *Nom = I->getNominatedNamespace(); - if (Visited.insert(Nom).second && S.isVisible(I)) + if (S.isVisible(I) && Visited.insert(Nom).second) Queue.push_back(Nom); } } diff --git a/clang/test/Modules/using-directive-redecl.cpp b/clang/test/Modules/using-directive-redecl.cpp new file mode 100644 index 0000000..94772f3 --- /dev/null +++ b/clang/test/Modules/using-directive-redecl.cpp @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -fmodules -fmodules-local-submodule-visibility -verify %s +// expected-no-diagnostics +#pragma clang module build M +module M { module TDFNodes {} module TDFInterface {} } +#pragma clang module contents + // TDFNodes + #pragma clang module begin M.TDFNodes + namespace Detail { + namespace TDF { + class TLoopManager {}; + } + } + namespace Internal { + namespace TDF { + using namespace Detail::TDF; + } + } + #pragma clang module end + + // TDFInterface + #pragma clang module begin M.TDFInterface + #pragma clang module import M.TDFNodes + namespace Internal { + namespace TDF { + using namespace Detail::TDF; + } + } + #pragma clang module end + +#pragma clang module endbuild + +#pragma clang module import M.TDFNodes +namespace Internal { + namespace TDF { + TLoopManager * use; + } +} -- 2.7.4