Index: clang/lib/Serialization/ASTReader.cpp =================================================================== --- clang/lib/Serialization/ASTReader.cpp +++ clang/lib/Serialization/ASTReader.cpp @@ -7785,7 +7785,29 @@ llvm::SmallPtrSet Found; for (DeclID ID : It->second.Table.find(Name)) { NamedDecl *ND = cast(GetDecl(ID)); - if (ND->getDeclName() == Name && Found.insert(ND).second) + if (ND->getDeclName() != Name) + continue; + + // The named decls with internal linkage in a module unit + // shouldn't be visible to external sources. + // + // This is imply by: [basic.lookup.general]p2.3: + // either X is exported or else D and L are part of the same module and X + // does not inhabit a namespace with internal linkage or declare a name + // with internal linkage. + Module *M = ND->getOwningModule(); + if (M && M->getTopLevelModule()->isModulePurview() && + // Note: In C++'s sepc, only a 'name' have a linkage. + // But in clang, the linkage is bounded to the named decls and + // each named decl doesn't refer to a name simply. See + // `NamedDecl::getName()` for example. So here we only handle the case + // that the named decl refers to a simple identifier. + ND->getIdentifier() && + cast(ND->getCanonicalDecl())->getFormalLinkage() == + Linkage::InternalLinkage) + continue; + + if (Found.insert(ND).second) Decls.push_back(ND); } Index: clang/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp =================================================================== --- clang/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp +++ clang/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp @@ -66,11 +66,7 @@ // expected-note@p2.cpp:19 {{declaration here is not visible}} #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 {{undeclared identifier 'internal'}} not_exported_private = 1; #ifndef IMPLEMENTATION @@ -78,11 +74,7 @@ // expected-error@-3 {{undeclared identifier}} #endif - 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 Index: clang/test/CXX/module/basic/basic.def.odr/p4.cppm =================================================================== --- clang/test/CXX/module/basic/basic.def.odr/p4.cppm +++ 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; @@ -143,9 +142,6 @@ (void)&inline_var_exported; (void)&const_var_exported; - // CHECK: define {{.*}}@_ZL26used_static_module_linkagev - used_static_module_linkage(); - // CHECK: define linkonce_odr {{.*}}@_ZW6Module26used_inline_module_linkagev used_inline_module_linkage(); @@ -154,7 +150,6 @@ (void)&extern_var_module_linkage; (void)&inline_var_module_linkage; - (void)&static_var_module_linkage; // FIXME: Should not be visible here. (void)&const_var_module_linkage; } Index: clang/test/CXX/module/basic/basic.link/p2.cppm =================================================================== --- clang/test/CXX/module/basic/basic.link/p2.cppm +++ clang/test/CXX/module/basic/basic.link/p2.cppm @@ -39,20 +39,19 @@ } //--- M.cpp -// expected-no-diagnostics module M; -// FIXME: Use of internal linkage entities should be rejected. void use_from_module_impl() { external_linkage_fn(); module_linkage_fn(); - internal_linkage_fn(); + internal_linkage_fn(); // expected-error {{use of undeclared identifier 'internal_linkage_fn';}} expected-note@* {{}} (void)external_linkage_class{}; (void)module_linkage_class{}; - (void)internal_linkage_class{}; + (void)internal_linkage_class{}; // expected-error {{use of undeclared identifier 'internal_linkage_class'}} + // expected-error@-1 {{expected ';' after expression}} (void)external_linkage_var; (void)module_linkage_var; - (void)internal_linkage_var; + (void)internal_linkage_var; // expected-error {{use of undeclared identifier 'internal_linkage_var'}} } //--- user.cpp @@ -61,13 +60,11 @@ 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}} + internal_linkage_fn(); // expected-error {{use of undeclared identifier 'internal_linkage_fn'}} expected-note@* {{}} (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}} (void)external_linkage_var; (void)module_linkage_var; // expected-error {{undeclared identifier}} - (void)internal_linkage_var; // expected-error {{undeclared identifier}} + (void)internal_linkage_var; // expected-error {{undeclared identifier}} expected-note@* {{}} } Index: clang/test/Modules/pr61601.cppm =================================================================== --- /dev/null +++ clang/test/Modules/pr61601.cppm @@ -0,0 +1,85 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/part1.cppm -o %t/m-part1.pcm +// RUN: %clang_cc1 -std=c++20 %t/part2.cppm -fprebuilt-module-path=%t -fsyntax-only \ +// RUN: -verify +// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/part3.cppm -o %t/m-part3.pcm +// RUN: %clang_cc1 -std=c++20 %t/part4.cppm -fprebuilt-module-path=%t -fsyntax-only \ +// RUN: -verify +// +// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/a.cppm -o %t/a.pcm +// RUN: %clang_cc1 -std=c++20 %t/b.cppm -emit-module-interface -o %t/b.pcm \ +// RUN: -fprebuilt-module-path=%t +// +// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/c.cppm -o %t/c.pcm \ +// RUN: -fprebuilt-module-path=%t +// RUN: %clang_cc1 -std=c++20 %t/use.cpp -fprebuilt-module-path=%t -fsyntax-only \ +// RUN: -verify +// RUN: %clang_cc1 -std=c++20 %t/use2.cpp -fprebuilt-module-path=%t -fsyntax-only \ +// RUN: -verify + +//--- part1.cppm +export module m:part1; +static int a = 43; +namespace { + int b = 44; +} + +//--- part2.cppm +// expected-no-diagnostics +export module m:part2; +import :part1; +static int a =44; + +//--- part3.cppm +export module m:part3; +namespace { + int b = 44; +} + +//--- part4.cppm +export module m:part4; +import :part1; +import :part3; +export int f3() { + return b; // expected-error {{use of undeclared identifier 'b'}} +} + +//--- a.cppm +export module a; +static constexpr int value = 43; + +//--- b.cppm +export module b; +import a; +static constexpr int value = 44; +export template +constexpr T b() { + return value; +} + +//--- c.cppm +export module c; +export import a; +export constexpr int value = 45; + +//--- use.cpp +// expected-no-diagnostics +import c; +import a; +int use() { + static_assert(value == 45); + return value; +} + +//--- use2.cpp +// expected-no-diagnostics +import a; +import b; +import c; +int use2() { + static_assert((b() + value) == 89); + return b() + value; +}