Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10971,9 +10971,6 @@ def err_export_within_anonymous_namespace : Error< "export declaration appears within anonymous namespace">; def note_anonymous_namespace : Note<"anonymous namespace begins here">; -def ext_export_no_name_block : ExtWarn< - "ISO C++20 does not permit %select{an empty|a static_assert}0 declaration " - "to appear in an export block">, InGroup; def ext_export_no_names : ExtWarn< "ISO C++20 does not permit a declaration that does not introduce any names " "to be exported">, InGroup; Index: clang/lib/Sema/SemaModule.cpp =================================================================== --- clang/lib/Sema/SemaModule.cpp +++ clang/lib/Sema/SemaModule.cpp @@ -615,13 +615,11 @@ return llvm::None; } -unsigned getUnnamedDeclDiag(UnnamedDeclKind UDK, bool InBlock) { +static unsigned getUnnamedDeclDiag(UnnamedDeclKind UDK) { switch (UDK) { case UnnamedDeclKind::Empty: case UnnamedDeclKind::StaticAssert: - // Allow empty-declarations and static_asserts in an export block as an - // extension. - return InBlock ? diag::ext_export_no_name_block : diag::err_export_no_name; + return diag::err_export_no_name; case UnnamedDeclKind::UsingDirective: // Allow exporting using-directives as an extension. @@ -640,8 +638,7 @@ static void diagExportedUnnamedDecl(Sema &S, UnnamedDeclKind UDK, Decl *D, SourceLocation BlockStart) { - S.Diag(D->getLocation(), getUnnamedDeclDiag(UDK, BlockStart.isValid())) - << (unsigned)UDK; + S.Diag(D->getLocation(), getUnnamedDeclDiag(UDK)) << (unsigned)UDK; if (BlockStart.isValid()) S.Diag(BlockStart, diag::note_export); } @@ -650,8 +647,10 @@ static bool checkExportedDecl(Sema &S, Decl *D, SourceLocation BlockStart) { // C++2a [module.interface]p3: // An exported declaration shall declare at least one name - if (auto UDK = getUnnamedDeclKind(D)) - diagExportedUnnamedDecl(S, *UDK, D, BlockStart); + if (!BlockStart.isValid()) { + if (auto UDK = getUnnamedDeclKind(D)) + diagExportedUnnamedDecl(S, *UDK, D, BlockStart); + } // [...] shall not declare a name with internal linkage. if (auto *ND = dyn_cast(D)) { Index: clang/test/CXX/module/module.interface/p3.cpp =================================================================== --- clang/test/CXX/module/module.interface/p3.cpp +++ clang/test/CXX/module/module.interface/p3.cpp @@ -9,12 +9,6 @@ export static_assert(true); // expected-error {{static_assert declaration cannot be exported}} export using namespace A; // expected-error {{ISO C++20 does not permit using directive to be exported}} -export { // expected-note 3{{export block begins here}} - ; // expected-error {{ISO C++20 does not permit an empty declaration to appear in an export block}} - static_assert(true); // expected-error {{ISO C++20 does not permit a static_assert declaration to appear in an export block}} - using namespace A; // expected-error {{ISO C++20 does not permit using directive to be exported}} -} - export struct {}; // expected-error {{must be class member}} expected-error {{GNU extension}} expected-error {{does not declare anything}} export struct {} struct_; export union {}; // expected-error {{must be declared 'static'}} expected-error {{does not declare anything}} Index: clang/test/Modules/cxx20-export.cpp =================================================================== --- /dev/null +++ clang/test/Modules/cxx20-export.cpp @@ -0,0 +1,22 @@ + +// RUN: %clang_cc1 -std=c++20 -fmodules -verify %s +export module testmodule; + +export static_assert(true); // expected-error {{static_assert declaration cannot be exported}} + +namespace A {}; + +export { +#define STR(x) constexpr char x[] = #x; + STR(foo); +#undef STR + + static_assert(true); + + template struct X { T t; }; + template X(T) -> X; + + ; // Empty declaration + + using namespace A; +} Index: clang/test/SemaCXX/modules-ts.cppm =================================================================== --- clang/test/SemaCXX/modules-ts.cppm +++ clang/test/SemaCXX/modules-ts.cppm @@ -50,11 +50,8 @@ import foo; export {} // expected-error {{export declaration cannot be empty}} -export { // expected-note {{begins here}} - ; // expected-warning {{ISO C++20 does not permit an empty declaration to appear in an export block}} -} -export { // expected-note {{begins here}} - static_assert(true); // expected-warning {{ISO C++20 does not permit a static_assert declaration to appear in an export block}} +export { + static_assert(true); } int use_b = b;