diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1128,6 +1128,33 @@ if (TUKind != TU_Prefix) { DiagnoseUseOfUnimplementedSelectors(); + // For C++20 modules, we are permitted to elide decls in the Global + // Module Fragment of a module interface if they are unused in the body + // of the interface. + if (!ModuleScopes.empty() && ModuleScopes.back().ModuleInterface && + getLangOpts().CPlusPlusModules) { + auto *DC = getASTContext().getTranslationUnitDecl(); + SmallVector WorkList; + for (DeclContext::decl_iterator DI = DC->decls_begin(), + DEnd = DC->decls_end(); + DI != DEnd; ++DI) { + Decl *D = *DI; + Module *M; + if (D->isImplicit() || !isa(D)) + continue; + M = D->getOwningModule(); + if (!M || !D->getOwningModule()->isGlobalModule()) + continue; + if (getASTContext().moduleInitializerContains(M, D)) + continue; + if (!D->isUsed(false) && !D->isReferenced()) + WorkList.push_back(D); + } + + for (auto *D : WorkList) + DC->removeDecl(D); + } + ActOnEndOfTranslationUnitFragment( !ModuleScopes.empty() && ModuleScopes.back().Module->Kind == Module::PrivateModuleFragment 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 @@ -29,8 +29,7 @@ #endif void test_early() { - in_header = 1; // expected-error {{missing '#include "foo.h"'; 'in_header' must be declared before it is used}} - // expected-note@*{{not visible}} + in_header = 1; // expected-error {{use of undeclared identifier 'in_header'}} global_module_fragment = 1; // expected-error {{missing '#include'; 'global_module_fragment' must be declared before it is used}} // expected-note@p2.cpp:16 {{not visible}} @@ -54,8 +53,7 @@ #endif void test_late() { - in_header = 1; // expected-error {{missing '#include "foo.h"'; 'in_header' must be declared before it is used}} - // expected-note@*{{not visible}} + in_header = 1; // expected-error {{use of undeclared identifier 'in_header'}} global_module_fragment = 1; // expected-error {{missing '#include'; 'global_module_fragment' must be declared before it is used}} // expected-note@p2.cpp:16 {{not visible}}