diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -11223,6 +11223,17 @@ "%select{declaration|definition|default argument|" "explicit specialization|partial specialization}0 of %1 must be imported " "from module '%2' before it is required">; +def err_module_private_use : Error< + "%select{declaration|definition|default argument|" + "explicit specialization|partial specialization}0 of %1 is private to module " + "'%2'">; +def err_module_internal_use : Error< + "%select{declaration|definition|default argument|" + "explicit specialization|partial specialization}0 of %1 is internal to " + "'%2'">; +def note_suggest_export : Note< + "export the %select{declaration|definition|default argument|" + "explicit specialization|partial specialization}0 to make it available">; def err_module_unimported_use_header : Error< "%select{missing '#include'|missing '#include %3'}2; " "%select{||default argument of |explicit specialization of |" diff --git a/clang/include/clang/Sema/Lookup.h b/clang/include/clang/Sema/Lookup.h --- a/clang/include/clang/Sema/Lookup.h +++ b/clang/include/clang/Sema/Lookup.h @@ -346,7 +346,7 @@ /// Determine whether the given declaration is visible to the /// program. - static bool isVisible(Sema &SemaRef, NamedDecl *D); + static bool isVisible(Sema &SemaRef, NamedDecl *D, bool ForTypo = false); static bool isReachable(Sema &SemaRef, NamedDecl *D); diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2366,6 +2366,24 @@ return Entity->getOwningModule(); } + // Determine whether the module M belongs to the current TU. + bool isModuleUnitOfCurrentTU(const Module *M) const; + + /// Determine whether the module MA is part of the same named module as MB. + bool arePartOfSameNamedModule(const Module *MA, const Module *MB) const { + if (!MA || MA->isGlobalModule()) + return false; + if (!MB || MB->isGlobalModule()) + return false; + return MA->getPrimaryModuleInterfaceName() == + MB->getPrimaryModuleInterfaceName(); + } + + /// Determine whether the module M is part of the current named module. + bool isPartOfCurrentNamedModule(const Module *M) const { + return arePartOfSameNamedModule(getCurrentModule(), M); + } + /// Make a merged definition of an existing hidden definition \p ND /// visible at the specified location. void makeMergedDefinitionVisible(NamedDecl *ND); diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -1782,7 +1782,7 @@ Module *DeclModule = SemaRef.getOwningModule(D); assert(DeclModule && "hidden decl has no owning module"); - // If the owning module is visible, the decl is acceptable. + // If the owning module is visible, the decl is potentially acceptable. if (SemaRef.isModuleVisible(DeclModule, D->isInvisibleOutsideTheOwningModule())) return true; @@ -2064,14 +2064,27 @@ return findAcceptableDecl(getSema(), D, IDNS); } -bool LookupResult::isVisible(Sema &SemaRef, NamedDecl *D) { +bool LookupResult::isVisible(Sema &SemaRef, NamedDecl *D, bool ForTypo) { // If this declaration is already visible, return it directly. if (D->isUnconditionallyVisible()) return true; // During template instantiation, we can refer to hidden declarations, if // they were visible in any module along the path of instantiation. - return isAcceptableSlow(SemaRef, D, Sema::AcceptableKind::Visible); + if (!isAcceptableSlow(SemaRef, D, Sema::AcceptableKind::Visible)) + return false; + + if (ForTypo && SemaRef.getLangOpts().CPlusPlusModules) { + // There is no point in offering a typo correction to an item that we will + // reject because it has internal linkage and is in a different module TU; + Module *DeclModule = SemaRef.getOwningModule(D); + if (DeclModule && !DeclModule->isHeaderLikeModule() && + !SemaRef.isModuleUnitOfCurrentTU(DeclModule) && + (D->getFormalLinkage() == Linkage::InternalLinkage || + DeclModule->isPrivateModule())) + return false; // This is not usefully visible. + } + return true; } bool LookupResult::isReachable(Sema &SemaRef, NamedDecl *D) { @@ -2083,8 +2096,22 @@ bool LookupResult::isAvailableForLookup(Sema &SemaRef, NamedDecl *ND) { // We should check the visibility at the callsite already. - if (isVisible(SemaRef, ND)) + if (isVisible(SemaRef, ND)) { + if (SemaRef.getLangOpts().CPlusPlusModules) { + // The module that owns the decl is visible; However + // [basic.lookup.general]/2, specifically 2.3 + // If the owning module is part of a different TU than the current one, + // and declaration is internal (or from the PMF), then we should not + // include it. + Module *DeclModule = SemaRef.getOwningModule(ND); + if (DeclModule && !DeclModule->isHeaderLikeModule() && + !SemaRef.isModuleUnitOfCurrentTU(DeclModule) && + (ND->getFormalLinkage() == Linkage::InternalLinkage || + DeclModule->isPrivateModule())) + return false; + } return true; + } // Deduction guide lives in namespace scope generally, but it is just a // hint to the compilers. What we actually lookup for is the generated member @@ -3874,16 +3901,44 @@ for (D = D->getMostRecentDecl(); D; D = cast_or_null(D->getPreviousDecl())) { if (D->getIdentifierNamespace() & Decl::IDNS_Ordinary) { - if (isVisible(D)) { - Visible = true; - break; + Visible = isVisible(D); + if (!getLangOpts().CPlusPlusModules) { + if (Visible) + break; + continue; } - if (!getLangOpts().CPlusPlusModules) - continue; + Module *FM = D->getOwningModule(); + if (Visible) { + if (!FM) + break; + assert(Underlying->hasLinkage() && "an imported func with no linkage?"); + // Unless the module is a defining one for the + bool Ovr = true; + for (unsigned I = 0; I < CodeSynthesisContexts.size(); ++I) { + Module *M = CodeSynthesisContexts[I].Entity + ? getDefiningModule( + *this, CodeSynthesisContexts[I].Entity) + : nullptr; + if (FM == M) { + Ovr = false; + break; + } + } + if (Ovr && Underlying->getFormalLinkage() == Linkage::InternalLinkage && + !isModuleUnitOfCurrentTU(FM)) { + Visible = false; + continue; + } + if (Ovr && Underlying->getFormalLinkage() == Linkage::ModuleLinkage && + !isPartOfCurrentNamedModule(FM)) { + Visible = false; + continue; + } + break; + } if (D->isInExportDeclContext()) { - Module *FM = D->getOwningModule(); // C++20 [basic.lookup.argdep] p4.3 .. are exported ... // exports are only valid in module purview and outside of any // PMF (although a PMF should not even be present in a module @@ -4460,9 +4515,13 @@ static void checkCorrectionVisibility(Sema &SemaRef, TypoCorrection &TC) { TypoCorrection::decl_iterator DI = TC.begin(), DE = TC.end(); - for (/**/; DI != DE; ++DI) - if (!LookupResult::isVisible(SemaRef, *DI)) + // During the lookups for Typo corrections, we allow 'hidden' decls to be + // found, this can also include (potential typo correction) decls that are + // not in their own right viable. Filter these from the visible set. + for (/**/; DI != DE; ++DI) { + if (!LookupResult::isVisible(SemaRef, *DI, /*ForTypo*/ true)) break; + } // No filtering needed if all decls are visible. if (DI == DE) { TC.setRequiresImport(false); @@ -4473,15 +4532,25 @@ bool AnyVisibleDecls = !NewDecls.empty(); for (/**/; DI != DE; ++DI) { - if (LookupResult::isVisible(SemaRef, *DI)) { + if (LookupResult::isVisible(SemaRef, *DI, /*ForTypo*/ true)) { if (!AnyVisibleDecls) { // Found a visible decl, discard all hidden ones. AnyVisibleDecls = true; NewDecls.clear(); } NewDecls.push_back(*DI); - } else if (!AnyVisibleDecls && !(*DI)->isModulePrivate()) - NewDecls.push_back(*DI); + } else if (!AnyVisibleDecls) { + // We do not want to push a hidden decl if it is not usefully reported + // as a typo (which means the proposed replacement has to be viable). + NamedDecl *ND = *DI; + if (SemaRef.getLangOpts().CPlusPlusModules && ND->isFromASTFile() && + ND->getOwningModule() && + !SemaRef.isModuleUnitOfCurrentTU(ND->getOwningModule()) && + ND->getFormalLinkage() == Linkage::InternalLinkage) + continue; // Internal symbol from a different TU, not visible. + if (!ND->isModulePrivate()) + NewDecls.push_back(ND); + } } if (NewDecls.empty()) @@ -4549,7 +4618,7 @@ // Only consider visible declarations and declarations from modules with // names that exactly match. - if (!LookupResult::isVisible(SemaRef, ND) && Name != Typo) + if (!LookupResult::isVisible(SemaRef, ND, /*ForTypo*/ true) && Name != Typo) return; FoundName(Name->getName()); @@ -5732,6 +5801,7 @@ Modules = UniqueModules; + bool DidFixit = false; if (Modules.size() > 1) { std::string ModuleList; unsigned N = 0; @@ -5746,13 +5816,26 @@ Diag(UseLoc, diag::err_module_unimported_use_multiple) << (int)MIK << Decl << ModuleList; + } else if (Decl->hasLinkage() && + Decl->getFormalLinkage() == Linkage::ModuleLinkage) { + Diag(UseLoc, diag::err_module_private_use) + << (int)MIK << Decl << Modules[0]->getFullModuleName(); + Diag(Decl->getBeginLoc(), diag::note_suggest_export) + << (int)MIK + << FixItHint::CreateInsertion(Decl->getBeginLoc(), "export"); + DidFixit = true; + } else if (Decl->hasLinkage() && + Decl->getFormalLinkage() == Linkage::InternalLinkage) { + Diag(UseLoc, diag::err_module_internal_use) + << (int)MIK << Decl << Modules[0]->getFullModuleName(); } else { // FIXME: Add a FixItHint that imports the corresponding module. Diag(UseLoc, diag::err_module_unimported_use) << (int)MIK << Decl << Modules[0]->getFullModuleName(); } - NotePrevious(); + if (!DidFixit) + NotePrevious(); // Try to recover by implicitly importing this module. if (Recover) diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp --- a/clang/lib/Sema/SemaModule.cpp +++ b/clang/lib/Sema/SemaModule.cpp @@ -964,3 +964,16 @@ "left the wrong module scope, which is not global module fragment"); ModuleScopes.pop_back(); } + +bool Sema::isModuleUnitOfCurrentTU(const Module *M) const { + assert(M); + + Module *CurrentModuleUnit = getCurrentModule(); + + // If we are not in a module currently, M must not be the module unit of + // current TU. + if (!CurrentModuleUnit) + return false; + + return M->isSubModuleOf(CurrentModuleUnit->getTopLevelModule()); +} diff --git a/clang/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp b/clang/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp --- a/clang/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp +++ b/clang/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp @@ -62,27 +62,15 @@ not_exported = 1; #ifndef IMPLEMENTATION - // expected-error@-2 {{declaration of 'not_exported' must be imported from module 'A' before it is required}} - // expected-note@p2.cpp:19 {{declaration here is not visible}} + // expected-error@-2 {{declaration of 'not_exported' is private to module 'A'}} + // expected-note@p2.cpp:19 {{export the declaration to make it available}} #endif - internal = 1; -#ifndef IMPLEMENTATION - // expected-error@-2 {{declaration of 'internal' must be imported from module 'A' before it is required}} - // expected-note@p2.cpp:20 {{declaration here is not visible}} -#endif + internal = 1; // expected-error {{use of undeclared identifier 'internal'}} - not_exported_private = 1; -#ifndef IMPLEMENTATION - // FIXME: should not be visible here - // expected-error@-3 {{undeclared identifier}} -#endif + not_exported_private = 1; // expected-error {{use of undeclared identifier 'not_exported_private'}} - internal_private = 1; -#ifndef IMPLEMENTATION - // FIXME: should not be visible here - // expected-error@-3 {{undeclared identifier}} -#endif + internal_private = 1; // expected-error {{undeclared identifier 'internal_private'}} } #endif diff --git a/clang/test/CXX/module/basic/basic.def.odr/p4.cppm b/clang/test/CXX/module/basic/basic.def.odr/p4.cppm --- a/clang/test/CXX/module/basic/basic.def.odr/p4.cppm +++ b/clang/test/CXX/module/basic/basic.def.odr/p4.cppm @@ -128,7 +128,6 @@ // // CHECK-DAG: @_ZW6Module25extern_var_module_linkage = external {{(dso_local )?}}global // CHECK-DAG: @_ZW6Module25inline_var_module_linkage = linkonce_odr {{(dso_local )?}}global -// CHECK-DAG: @_ZL25static_var_module_linkage = internal {{(dso_local )?}}global i32 0, // CHECK-DAG: @_ZW6Module24const_var_module_linkage = available_externally {{(dso_local )?}}constant i32 3, module Module; @@ -151,12 +150,9 @@ (void)&extern_var_module_linkage; (void)&inline_var_module_linkage; + (void)&const_var_module_linkage; - // FIXME: Issue #61427 Internal-linkage declarations in the interface TU - // should not be not visible here. - (void)&static_var_module_linkage; // FIXME: Should not be visible here. - - (void)&const_var_module_linkage; // FIXME: will be visible after P2788R0 + // Internal-linkage declarations are not visible here. } //--- user.cpp @@ -177,6 +173,6 @@ (void)&inline_var_exported; (void)&const_var_exported; - // Internal-linkage declarations are not visible here. // Module-linkage declarations are not visible here. + // Internal-linkage declarations are not visible here. } diff --git a/clang/test/CXX/module/basic/basic.link/p2.cppm b/clang/test/CXX/module/basic/basic.link/p2.cppm --- a/clang/test/CXX/module/basic/basic.link/p2.cppm +++ b/clang/test/CXX/module/basic/basic.link/p2.cppm @@ -39,22 +39,19 @@ } //--- M.cpp - module M; void use_from_module_impl() { external_linkage_fn(); module_linkage_fn(); - internal_linkage_fn(); // expected-error {{no matching function for call to 'internal_linkage_fn'}} + internal_linkage_fn(); // expected-error {{use of undeclared identifier 'internal_linkage_fn'; did you mean 'external_linkage_fn'}} + // expected-note@M.cppm:8 {{'external_linkage_fn' declared here}} (void)external_linkage_class{}; (void)module_linkage_class{}; + (void)internal_linkage_class; // expected-error {{use of undeclared identifier 'internal_linkage_class'}} (void)external_linkage_var; (void)module_linkage_var; - - // FIXME: Issue #61427 Internal-linkage declarations in the interface TU - // should not be not visible here. - (void)internal_linkage_class{}; - (void)internal_linkage_var; + (void)internal_linkage_var; // expected-error {{use of undeclared identifier 'internal_linkage_var'}} } //--- user.cpp @@ -62,13 +59,13 @@ void use_from_module_impl() { external_linkage_fn(); - module_linkage_fn(); // expected-error {{declaration of 'module_linkage_fn' must be imported}} - internal_linkage_fn(); // expected-error {{declaration of 'internal_linkage_fn' must be imported}} + module_linkage_fn(); // expected-error {{declaration of 'module_linkage_fn' is private to module 'M'}} + // expected-note@M.cppm:9 {{export the declaration to make it available}} + internal_linkage_fn(); // expected-error {{use of undeclared identifier 'internal_linkage_fn'; did you mean 'external_linkage_fn'}} (void)external_linkage_class{}; (void)module_linkage_class{}; // expected-error {{undeclared identifier}} expected-error 0+{{}} (void)internal_linkage_class{}; // expected-error {{undeclared identifier}} expected-error 0+{{}} - // expected-note@M.cppm:9 {{declaration here is not visible}} - // expected-note@M.cppm:10 {{declaration here is not visible}} + // expected-note@M.cppm:8 {{'external_linkage_fn' declared here}} (void)external_linkage_var; (void)module_linkage_var; // expected-error {{undeclared identifier}} (void)internal_linkage_var; // expected-error {{undeclared identifier}} diff --git a/clang/test/CXX/module/module.import/p2.cpp b/clang/test/CXX/module/module.import/p2.cpp --- a/clang/test/CXX/module/module.import/p2.cpp +++ b/clang/test/CXX/module/module.import/p2.cpp @@ -23,10 +23,10 @@ //--- Use.cpp import M; void test() { - A a; // expected-error {{declaration of 'A' must be imported from module 'M:impl'}} - // expected-error@-1 {{definition of 'A' must be imported from module 'M:impl'}} expected-error@-1 {{}} - // expected-note@impl.cppm:2 {{declaration here is not visible}} - // expected-note@impl.cppm:2 {{definition here is not reachable}} expected-note@impl.cppm:2 {{}} + A a; // expected-error {{declaration of 'A' is private to module 'M:impl'}} + // expected-note@impl.cppm:2 {{export the declaration to make it available}} + // expected-error@-2 1+{{definition of 'A' is private to module 'M:impl'}} + // expected-note@impl.cppm:2 1+{{export the definition to make it available}} } //--- UseInPartA.cppm @@ -41,10 +41,10 @@ export module B; import M; void test() { - A a; // expected-error {{declaration of 'A' must be imported from module 'M:impl'}} - // expected-error@-1 {{definition of 'A' must be imported from module 'M:impl'}} expected-error@-1 {{}} - // expected-note@impl.cppm:2 {{declaration here is not visible}} - // expected-note@impl.cppm:2 {{definition here is not reachable}} expected-note@impl.cppm:2 {{}} + A a; // expected-error {{declaration of 'A' is private to module 'M:impl'}} + // expected-note@impl.cppm:2 {{export the declaration to make it available}} + // expected-error@-2 1+{{definition of 'A' is private to module 'M:impl'}} + // expected-note@impl.cppm:2 1+{{export the definition to make it available}} } //--- Private.cppm diff --git a/clang/test/CXX/module/module.interface/p2.cpp b/clang/test/CXX/module/module.interface/p2.cpp --- a/clang/test/CXX/module/module.interface/p2.cpp +++ b/clang/test/CXX/module/module.interface/p2.cpp @@ -72,29 +72,29 @@ void use() { // namespace A is implicitly exported by the export of A::g. - A::f(); // expected-error {{declaration of 'f' must be imported from module 'p2' before it is required}} - // expected-note@* {{declaration here is not visible}} + A::f(); // expected-error {{declaration of 'f' is private to module 'p2'}} + // expected-note@* {{export the declaration to make it available}} A::g(); - A::h(); // expected-error {{declaration of 'h' must be imported from module 'p2' before it is required}} - // expected-note@* {{declaration here is not visible}} + A::h(); // expected-error {{declaration of 'h' is private to module 'p2'}} + // expected-note@* {{export the declaration to make it available}} using namespace A::inner; // expected-error {{declaration of 'inner' must be imported from module 'p2' before it is required}} // expected-note@* {{declaration here is not visible}} // namespace B and B::inner are explicitly exported using namespace B; using namespace B::inner; - B::f(); // expected-error {{declaration of 'f' must be imported from module 'p2' before it is required}} - // expected-note@* {{declaration here is not visible}} - f(); // expected-error {{declaration of 'f' must be imported from module 'p2' before it is required}} - // expected-note@* {{declaration here is not visible}} + B::f(); // expected-error {{declaration of 'f' is private to module 'p2'}} + // expected-note@* {{export the declaration to make it available}} + f(); // expected-error {{declaration of 'f' is private to module 'p2'}} + // expected-note@* {{export the declaration to make it available}} // namespace C is not exported using namespace C; // expected-error {{declaration of 'C' must be imported from module 'p2' before it is required}} // expected-note@* {{declaration here is not visible}} // namespace D is exported, but D::f is not - D::f(); // expected-error {{declaration of 'f' must be imported from module 'p2' before it is required}} - // expected-note@* {{declaration here is not visible}} + D::f(); // expected-error {{declaration of 'f' is private to module 'p2'}} + // expected-note@* {{export the declaration to make it available}} } int use_header() { return foo + bar::baz(); } diff --git a/clang/test/CXX/module/module.interface/p7.cpp b/clang/test/CXX/module/module.interface/p7.cpp --- a/clang/test/CXX/module/module.interface/p7.cpp +++ b/clang/test/CXX/module/module.interface/p7.cpp @@ -57,12 +57,12 @@ void test2() { auto a = E1::e1; // OK, namespace-scope name E1 is visible and e1 is reachable auto b = e1; // OK, namespace-scope name e1 is visible - auto c = E2::e2; // expected-error {{declaration of 'E2' must be imported from module}} - // expected-note@* {{declaration here is not visible}} + auto c = E2::e2; // expected-error {{declaration of 'E2' is private to module 'p7'}} + // expected-note@* {{export the declaration to make it available}} auto d = e2; // should be error, namespace-scope name e2 is not visible auto e = E2U::e2; // OK, namespace-scope name E2U is visible and E2::e2 is reachable - auto f = E3::e3; // expected-error {{declaration of 'E3' must be imported from module 'p7' before it is required}} - // expected-note@* {{declaration here is not visible}} + auto f = E3::e3; // expected-error {{declaration of 'E3' is private to module 'p7'}} + // expected-note@* {{export the declaration to make it available}} auto g = e3; // should be error, namespace-scope name e3 is not visible auto h = decltype(func())::e3; // OK, namespace-scope name f is visible and E3::e3 is reachable } diff --git a/clang/test/CXX/module/module.reach/ex1.cpp b/clang/test/CXX/module/module.reach/ex1.cpp --- a/clang/test/CXX/module/module.reach/ex1.cpp +++ b/clang/test/CXX/module/module.reach/ex1.cpp @@ -37,10 +37,10 @@ //--- X.cppm export module X; import M; -B b3; // expected-error {{definition of 'B' must be imported from module 'M:B' before it is required}} expected-error {{}} - // expected-note@* {{definition here is not reachable}} expected-note@* {{}} -// FIXME: We should emit an error for unreachable definition of B. +B b3; // expected-error {{definition of 'B' is private to module 'M:B'}} expected-error {{}} + // expected-note@* {{export the definition to make it available}} expected-note@* {{}} + void g() { f(); } -void g1() { f(B()); } // expected-error 1+{{definition of 'B' must be imported from module 'M:B' before it is required}} - // expected-note@* 1+{{definition here is not reachable}} +void g1() { f(B()); } // expected-error 1+{{definition of 'B' is private to module 'M:B'}} + // expected-note@* 1+{{export the definition to make it available}} // expected-note@M.cppm:5 {{passing argument to parameter 'b' here}} diff --git a/clang/test/CXX/module/module.reach/p2.cpp b/clang/test/CXX/module/module.reach/p2.cpp --- a/clang/test/CXX/module/module.reach/p2.cpp +++ b/clang/test/CXX/module/module.reach/p2.cpp @@ -17,6 +17,6 @@ //--- UseStrict.cpp import M; void test() { - auto a = f(); // expected-error {{definition of 'A' must be imported from module 'M:impl' before it is required}} expected-error{{}} - // expected-note@* {{definition here is not reachable}} expected-note@* {{}} + auto a = f(); // expected-error 1+{{definition of 'A' is private to module 'M:impl'}} + // expected-note@* 1+{{export the definition to make it available}} } diff --git a/clang/test/CXX/module/module.reach/p5.cpp b/clang/test/CXX/module/module.reach/p5.cpp --- a/clang/test/CXX/module/module.reach/p5.cpp +++ b/clang/test/CXX/module/module.reach/p5.cpp @@ -14,5 +14,5 @@ export module B; import A; Y y; // OK, definition of X is reachable -X x; // expected-error {{declaration of 'X' must be imported from module 'A' before it is required}} - // expected-note@* {{declaration here is not visible}} +X x; // expected-error {{declaration of 'X' is private to module 'A'}} + // expected-note@* {{export the declaration to make it available}} diff --git a/clang/test/Modules/Reachability-template-default-arg.cpp b/clang/test/Modules/Reachability-template-default-arg.cpp --- a/clang/test/Modules/Reachability-template-default-arg.cpp +++ b/clang/test/Modules/Reachability-template-default-arg.cpp @@ -18,6 +18,6 @@ import template_default_arg; void bar() { A<> a0; - A a1; // expected-error {{declaration of 't' must be imported from module 'template_default_arg' before it is required}} - // expected-note@* {{declaration here is not visible}} + A a1; // expected-error {{declaration of 't' is private to module 'template_default_arg'}} + // expected-note@* {{export the declaration to make it available}} } diff --git a/clang/test/Modules/cxx20-10-1-ex2.cpp b/clang/test/Modules/cxx20-10-1-ex2.cpp --- a/clang/test/Modules/cxx20-10-1-ex2.cpp +++ b/clang/test/Modules/cxx20-10-1-ex2.cpp @@ -54,8 +54,8 @@ //--- std10-1-ex2-tu6.cpp import B; // error, n is module-local and this is not a module. -int &c = n; // expected-error {{declaration of 'n' must be imported}} - // expected-note@* {{declaration here is not visible}} +int &c = n; // expected-error {{declaration of 'n' is private to module 'B'}} + // expected-note@* {{export the declaration to make it available}} //--- std10-1-ex2-tu7.cpp // expected-no-diagnostics diff --git a/clang/test/Modules/deduction-guide3.cppm b/clang/test/Modules/deduction-guide3.cppm --- a/clang/test/Modules/deduction-guide3.cppm +++ b/clang/test/Modules/deduction-guide3.cppm @@ -19,8 +19,8 @@ //--- Use.cpp import Templ; void func() { - Templ t(5); // expected-error {{declaration of 'Templ' must be imported from module 'Templ' before it is required}} + Templ t(5); // expected-error {{declaration of 'Templ' is private to module 'Templ'}} // expected-error@-1 {{unknown type name 'Templ'}} - // expected-note@Templ.cppm:3 {{declaration here is not visible}} + // expected-note@Templ.cppm:3 {{export the declaration to make it available}} } diff --git a/clang/test/Modules/diagnose-missing-import.m b/clang/test/Modules/diagnose-missing-import.m --- a/clang/test/Modules/diagnose-missing-import.m +++ b/clang/test/Modules/diagnose-missing-import.m @@ -6,9 +6,9 @@ void foo(void) { XYZLogEvent(xyzRiskyCloseOpenParam, xyzRiskyCloseOpenParam); // expected-error {{call to undeclared function 'XYZLogEvent'; ISO C99 and later do not support implicit function declarations}} \ - expected-error {{declaration of 'XYZLogEvent' must be imported}} \ - expected-error {{declaration of 'xyzRiskyCloseOpenParam' must be imported from module 'NCI.A'}} \ - expected-error {{declaration of 'xyzRiskyCloseOpenParam' must be imported from module 'NCI.A'}} + expected-error {{declaration of 'XYZLogEvent' is internal to 'NCI.A'}} \ + expected-error {{declaration of 'xyzRiskyCloseOpenParam' is internal to 'NCI.A'}} \ + expected-error {{declaration of 'xyzRiskyCloseOpenParam' is internal to 'NCI.A'}} } // expected-note@Inputs/diagnose-missing-import/a.h:5 {{declaration here is not visible}} diff --git a/clang/test/Modules/pr61601.cpp b/clang/test/Modules/pr61601.cpp new file mode 100644 --- /dev/null +++ b/clang/test/Modules/pr61601.cpp @@ -0,0 +1,30 @@ +// RUN: mkdir -p %t +// RUN: split-file %s %t + +// All of the following should build without diagnostics. +// +// RUN: %clang_cc1 -std=c++20 %t/Part1.cpp -emit-module-interface -o %t/TheMod-Part1.pcm +// +// RUN: %clang_cc1 -std=c++20 %t/Part2.cpp -emit-module-interface -o %t/TheMod-Part2.pcm +// +// RUN: %clang_cc1 -std=c++20 %t/TheMod.cpp -emit-module-interface -o %t/TheMod.pcm \ +// RUN: -fprebuilt-module-path=%t + +//--- Part1.cpp + +export module TheMod:Part1; +static int loog = 1; + +//--- Part2.cpp + +export module TheMod:Part2; +static int loog = 2; + +//--- TheMod.cpp + +export module TheMod; +export import :Part1; +export import :Part2; + +static int loog = 3; +export int V = loog;