From fa2608147089e29e2c2e41dd33784a3dedbd5265 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 11 Oct 2017 01:49:57 +0000 Subject: [PATCH] [modules] Fix visibility checking for using declarations via ADL. We want to check whether the using (shadow) declaration itself is visible, not whether its target is visible. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@315408 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaLookup.cpp | 20 ++++++++++++++------ test/Modules/adl.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 6 deletions(-) create mode 100644 test/Modules/adl.cpp diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 8cb4fd63eb..8f3e93845b 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -3349,16 +3349,24 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc, continue; } - if (isa(D)) - D = cast(D)->getTargetDecl(); + auto *Underlying = D; + if (auto *USD = dyn_cast(D)) + Underlying = USD->getTargetDecl(); - if (!isa(D) && !isa(D)) + if (!isa(Underlying) && + !isa(Underlying)) continue; - if (!isVisible(D) && !(D = findAcceptableDecl(*this, D))) - continue; + if (!isVisible(D)) { + D = findAcceptableDecl(*this, D); + if (!D) + continue; + if (auto *USD = dyn_cast(D)) + Underlying = USD->getTargetDecl(); + } - Result.insert(D); + // FIXME: Preserve D as the FoundDecl. + Result.insert(Underlying); } } } diff --git a/test/Modules/adl.cpp b/test/Modules/adl.cpp new file mode 100644 index 0000000000..a1055a889d --- /dev/null +++ b/test/Modules/adl.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -fmodules -verify -fno-modules-error-recovery -fno-spell-checking %s +// RUN: %clang_cc1 -fmodules -verify -fno-modules-error-recovery -DONLY_Y %s + +#pragma clang module build a +module a { + explicit module x {} + explicit module y {} +} +#pragma clang module contents +#pragma clang module begin a.x +namespace N { + template extern int f(T) { return 0; } +} +#pragma clang module end + +#pragma clang module begin a.y +#pragma clang module import a.x +using N::f; +#pragma clang module end +#pragma clang module endbuild + +namespace N { struct A {}; } +struct B {}; + +#ifndef ONLY_Y +#pragma clang module import a.x +void test1() { + f(N::A()); + f(B()); // expected-error {{use of undeclared identifier 'f'}} +} +#else +// expected-no-diagnostics +#endif + +#pragma clang module import a.y +void test2() { + // These are OK even if a.x is not imported. + f(N::A()); + f(B()); +} -- 2.40.0