[clang] 25558a1 - [C++20][Modules] Update ADL to handle basic.lookup.argdep p4 [P1815R2 part 1]
Iain Sandoe via cfe-commits
cfe-commits at lists.llvm.org
Mon Jul 25 06:29:27 PDT 2022
Author: Iain Sandoe
Date: 2022-07-25T14:28:59+01:00
New Revision: 25558a1bfd79e03bed74873ab83ccfc3650fb64f
URL: https://github.com/llvm/llvm-project/commit/25558a1bfd79e03bed74873ab83ccfc3650fb64f
DIFF: https://github.com/llvm/llvm-project/commit/25558a1bfd79e03bed74873ab83ccfc3650fb64f.diff
LOG: [C++20][Modules] Update ADL to handle basic.lookup.argdep p4 [P1815R2 part 1]
This includes the revised provisions of [basic.lookup.argdep] p4
1. ADL is amended to handle p 4.3 where functions in trasitively imported modules may
become visible when they are exported in the same namespace as a visible type.
2. If a function is in a different modular TU, and has internal-linkage, we invalidate
its entry in an overload set.
[basic.lookup.argdep] p5 ex 2 now passes.
Differential Revision: https://reviews.llvm.org/D129174
Added:
clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p5-ex2.cpp
Modified:
clang/include/clang/Sema/Overload.h
clang/lib/Sema/SemaLookup.cpp
clang/lib/Sema/SemaOverload.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h
index 48997e186ef69..fb4812675d9a3 100644
--- a/clang/include/clang/Sema/Overload.h
+++ b/clang/include/clang/Sema/Overload.h
@@ -795,6 +795,10 @@ class Sema;
/// This candidate was not viable because its associated constraints were
/// not satisfied.
ovl_fail_constraints_not_satisfied,
+
+ /// This candidate was not viable because it has internal linkage and is
+ /// from a
diff erent module unit than the use.
+ ovl_fail_module_mismatched,
};
/// A list of implicit conversion sequences for the arguments of an
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 242e1f81d75c0..66e0efccb4b47 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -3838,6 +3838,12 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc,
// associated classes are visible within their respective
// namespaces even if they are not visible during an ordinary
// lookup (11.4).
+ //
+ // C++20 [basic.lookup.argdep] p4.3
+ // -- are exported, are attached to a named module M, do not appear
+ // in the translation unit containing the point of the lookup, and
+ // have the same innermost enclosing non-inline namespace scope as
+ // a declaration of an associated entity attached to M.
DeclContext::lookup_result R = NS->lookup(Name);
for (auto *D : R) {
auto *Underlying = D;
@@ -3858,6 +3864,36 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc,
if (isVisible(D)) {
Visible = true;
break;
+ } else if (getLangOpts().CPlusPlusModules &&
+ D->isInExportDeclContext()) {
+ // C++20 [basic.lookup.argdep] p4.3 .. are exported ...
+ Module *FM = D->getOwningModule();
+ // exports are only valid in module purview and outside of any
+ // PMF (although a PMF should not even be present in a module
+ // with an import).
+ assert(FM && FM->isModulePurview() && !FM->isPrivateModule() &&
+ "bad export context");
+ // .. are attached to a named module M, do not appear in the
+ // translation unit containing the point of the lookup..
+ if (!isModuleUnitOfCurrentTU(FM) &&
+ llvm::any_of(AssociatedClasses, [&](auto *E) {
+ // ... and have the same innermost enclosing non-inline
+ // namespace scope as a declaration of an associated entity
+ // attached to M
+ if (!E->hasOwningModule() ||
+ E->getOwningModule()->getTopLevelModuleName() !=
+ FM->getTopLevelModuleName())
+ return false;
+ // TODO: maybe this could be cached when generating the
+ // associated namespaces / entities.
+ DeclContext *Ctx = E->getDeclContext();
+ while (!Ctx->isFileContext() || Ctx->isInlineNamespace())
+ Ctx = Ctx->getParent();
+ return Ctx == NS;
+ })) {
+ Visible = true;
+ break;
+ }
}
} else if (D->getFriendObjectKind()) {
auto *RD = cast<CXXRecordDecl>(D->getLexicalDeclContext());
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index c226ed6254790..65dae00345f6d 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -6400,6 +6400,17 @@ void Sema::AddOverloadCandidate(
return;
}
+ // Functions with internal linkage are only viable in the same module unit.
+ if (auto *MF = Function->getOwningModule()) {
+ if (getLangOpts().CPlusPlusModules && !MF->isModuleMapModule() &&
+ Function->getFormalLinkage() <= Linkage::InternalLinkage &&
+ !isModuleUnitOfCurrentTU(MF)) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_module_mismatched;
+ return;
+ }
+ }
+
if (Function->isMultiVersion() && Function->hasAttr<TargetAttr>() &&
!Function->getAttr<TargetAttr>()->isDefaultVersion()) {
Candidate.Viable = false;
diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p5-ex2.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p5-ex2.cpp
new file mode 100644
index 0000000000000..05044d131c1ae
--- /dev/null
+++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p5-ex2.cpp
@@ -0,0 +1,68 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+//
+// RUN: %clang_cc1 -std=c++20 M.cpp -emit-module-interface -o M.pcm
+// RUN: %clang_cc1 -std=c++20 N.cpp -emit-module-interface -o N.pcm \
+// RUN: -fmodule-file=M.pcm
+// RUN: %clang_cc1 -std=c++20 Q.cpp -emit-module-interface -o Q.pcm
+// RUN: %clang_cc1 -std=c++20 Q-impl.cpp -fsyntax-only -fmodule-file=Q.pcm \
+// RUN: -fmodule-file=N.pcm -verify
+
+//--- M.cpp
+export module M;
+namespace R {
+export struct X {};
+export void f(X);
+} // namespace R
+namespace S {
+export void f(R::X, R::X);
+}
+
+//--- N.cpp
+export module N;
+import M;
+export R::X make();
+namespace R {
+static int g(X);
+}
+export template <typename T, typename U>
+void apply(T t, U u) {
+ f(t, u);
+ g(t);
+}
+
+//--- Q.cpp
+export module Q;
+
+//--- Q-impl.cpp
+module Q;
+import N;
+
+namespace S {
+struct Z {
+ template <typename T> operator T();
+};
+} // namespace S
+void test() {
+ // OK, decltype(x) is R::X in module M
+ auto x = make();
+
+ // error: R and R::f are not visible here
+ R::f(x); // expected-error {{declaration of 'R' must be imported from module 'N' before it is required}}
+ // expected-note at N.cpp:4 {{declaration here is not visible}}
+ // expected-error at -2 {{no type named 'f' in namespace 'R'}}
+
+ f(x); // Found by [basic.lookup.argdep] / p4.3
+
+ // error: S::f in module M not considered even though S is an associated
+ // namespace, since the entity Z is in a
diff erent module from f.
+ f(x, S::Z()); // expected-error {{no matching function for call to 'f'}}
+ // expected-note at M.cpp:4 {{candidate function not viable: requires 1 argument, but 2 were provided}}
+
+ // error: S::f is visible in instantiation context, but R::g has internal
+ // linkage and cannot be used outside N.cpp
+ apply(x, S::Z()); // expected-error at N.cpp:10 {{no matching function for call to 'g'}}
+ // expected-note at -1 {{in instantiation of function template specialization 'apply<R::X, S::Z>' requested here}}
+}
More information about the cfe-commits
mailing list