ChuanqiXu updated this revision to Diff 384968. ChuanqiXu added a comment. Updated diagnostic messages. It looks good to me to reject for exporting non-namespace-scope names in `diagnoseQualifiedDeclaration()`.
CHANGES SINCE LAST ACTION https://reviews.llvm.org/D112903/new/ https://reviews.llvm.org/D112903 Files: clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaDecl.cpp clang/test/CXX/module/module.interface/p6.cpp Index: clang/test/CXX/module/module.interface/p6.cpp =================================================================== --- /dev/null +++ clang/test/CXX/module/module.interface/p6.cpp @@ -0,0 +1,52 @@ +// RUN: %clang_cc1 -std=c++20 %s -verify + +export module X; + +export template <typename T> +struct X { + struct iterator { + T node; + }; + void foo() {} + template <typename U> + U bar(); +}; + +export template <typename T> X<T>::iterator; // expected-error {{cannot export 'iterator' here since only the entities in namespace scope could be exported.}} +export template <typename T> void X<T>::foo(); // expected-error {{cannot export 'foo' here since only the entities in namespace scope could be exported.}} +export template <typename T> template <typename U> U X<T>::bar(); // expected-error {{cannot export 'bar' here since only the entities in namespace scope could be exported.}} + +export struct Y { + struct iterator { + int node; + }; + void foo() {} + template <typename U> + U bar(); +}; + +export struct Y::iterator; // expected-error {{cannot export 'iterator' here since only the entities in namespace scope could be exported.}} +export void Y::foo(); // expected-error {{cannot export 'foo' here since only the entities in namespace scope could be exported.}} +export template <typename U> U Y::bar(); // expected-error {{cannot export 'bar' here since only the entities in namespace scope could be exported.}} + +export { + template <typename T> X<T>::iterator; // expected-error {{cannot export 'iterator' here since only the entities in namespace scope could be exported.}} + struct Y::iterator; // expected-error {{cannot export 'iterator' here since only the entities in namespace scope could be exported.}} +} + +namespace A { +export struct X; +struct Y; +export void foo(); +void bar(); +} // namespace A + +// [module.interface]/p6 +// A redeclaration of an entity X is implicitly exported if X was introduced by an exported declaration +void A::foo(); +export struct A::X; // expected-error {{cannot export redeclaration 'X' here.}} +export struct A::Y; // expected-error {{cannot export redeclaration 'Y' here.}} +export void A::foo(); // expected-error {{cannot export redeclaration 'foo' here.}} +// The compiler couldn't export A::bar() here since A::bar() is declared above without exported. +// See [module.interface]/p6 for details. +export void A::bar(); // expected-error {{cannot export redeclaration 'bar' here.}} Index: clang/lib/Sema/SemaDecl.cpp =================================================================== --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -5745,7 +5745,12 @@ else if (isa<BlockDecl>(Cur)) Diag(Loc, diag::err_invalid_declarator_in_block) << Name << SS.getRange(); - else + else if (isa<ExportDecl>(Cur)) { + if (!isa<NamespaceDecl>(DC)) + Diag(Loc, diag::err_export_non_namespace_scope_name) << Name; + else + Diag(Loc, diag::err_export_qualified_redeclaration) << Name; + } else Diag(Loc, diag::err_invalid_declarator_scope) << Name << cast<NamedDecl>(Cur) << cast<NamedDecl>(DC) << SS.getRange(); Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -7781,6 +7781,10 @@ "%select{ or namespace|, namespace, or enumeration}1">; def err_invalid_declarator_scope : Error<"cannot define or redeclare %0 here " "because namespace %1 does not enclose namespace %2">; +def err_export_non_namespace_scope_name : Error<"cannot export %0 here since " + "only the entities in namespace scope could be exported.">; +def err_export_qualified_redeclaration : Error<"cannot export redeclaration " + "%0 here.">; def err_invalid_declarator_global_scope : Error< "definition or redeclaration of %0 cannot name the global scope">; def err_invalid_declarator_in_function : Error<
Index: clang/test/CXX/module/module.interface/p6.cpp =================================================================== --- /dev/null +++ clang/test/CXX/module/module.interface/p6.cpp @@ -0,0 +1,52 @@ +// RUN: %clang_cc1 -std=c++20 %s -verify + +export module X; + +export template <typename T> +struct X { + struct iterator { + T node; + }; + void foo() {} + template <typename U> + U bar(); +}; + +export template <typename T> X<T>::iterator; // expected-error {{cannot export 'iterator' here since only the entities in namespace scope could be exported.}} +export template <typename T> void X<T>::foo(); // expected-error {{cannot export 'foo' here since only the entities in namespace scope could be exported.}} +export template <typename T> template <typename U> U X<T>::bar(); // expected-error {{cannot export 'bar' here since only the entities in namespace scope could be exported.}} + +export struct Y { + struct iterator { + int node; + }; + void foo() {} + template <typename U> + U bar(); +}; + +export struct Y::iterator; // expected-error {{cannot export 'iterator' here since only the entities in namespace scope could be exported.}} +export void Y::foo(); // expected-error {{cannot export 'foo' here since only the entities in namespace scope could be exported.}} +export template <typename U> U Y::bar(); // expected-error {{cannot export 'bar' here since only the entities in namespace scope could be exported.}} + +export { + template <typename T> X<T>::iterator; // expected-error {{cannot export 'iterator' here since only the entities in namespace scope could be exported.}} + struct Y::iterator; // expected-error {{cannot export 'iterator' here since only the entities in namespace scope could be exported.}} +} + +namespace A { +export struct X; +struct Y; +export void foo(); +void bar(); +} // namespace A + +// [module.interface]/p6 +// A redeclaration of an entity X is implicitly exported if X was introduced by an exported declaration +void A::foo(); +export struct A::X; // expected-error {{cannot export redeclaration 'X' here.}} +export struct A::Y; // expected-error {{cannot export redeclaration 'Y' here.}} +export void A::foo(); // expected-error {{cannot export redeclaration 'foo' here.}} +// The compiler couldn't export A::bar() here since A::bar() is declared above without exported. +// See [module.interface]/p6 for details. +export void A::bar(); // expected-error {{cannot export redeclaration 'bar' here.}} Index: clang/lib/Sema/SemaDecl.cpp =================================================================== --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -5745,7 +5745,12 @@ else if (isa<BlockDecl>(Cur)) Diag(Loc, diag::err_invalid_declarator_in_block) << Name << SS.getRange(); - else + else if (isa<ExportDecl>(Cur)) { + if (!isa<NamespaceDecl>(DC)) + Diag(Loc, diag::err_export_non_namespace_scope_name) << Name; + else + Diag(Loc, diag::err_export_qualified_redeclaration) << Name; + } else Diag(Loc, diag::err_invalid_declarator_scope) << Name << cast<NamedDecl>(Cur) << cast<NamedDecl>(DC) << SS.getRange(); Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -7781,6 +7781,10 @@ "%select{ or namespace|, namespace, or enumeration}1">; def err_invalid_declarator_scope : Error<"cannot define or redeclare %0 here " "because namespace %1 does not enclose namespace %2">; +def err_export_non_namespace_scope_name : Error<"cannot export %0 here since " + "only the entities in namespace scope could be exported.">; +def err_export_qualified_redeclaration : Error<"cannot export redeclaration " + "%0 here.">; def err_invalid_declarator_global_scope : Error< "definition or redeclaration of %0 cannot name the global scope">; def err_invalid_declarator_in_function : Error<
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits