diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 4ffc9a6dad2..e7bb4fa3089 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -16737,12 +16737,14 @@ xref_tag (enum tag_types tag_code, tree name, if (CLASS_TYPE_P (t) && CLASSTYPE_IS_TEMPLATE (t)) maybe_tmpl = CLASSTYPE_TI_TEMPLATE (t); + /* FIXME: we should do a more precise check for redefinitions + of a conflicting using-declaration here, as these diagnostics + are not ideal. */ if (DECL_LANG_SPECIFIC (decl) && DECL_MODULE_IMPORT_P (decl) - && TREE_CODE (CP_DECL_CONTEXT (decl)) == NAMESPACE_DECL) + && CP_DECL_CONTEXT (decl) == current_namespace) { /* Push it into this TU's symbol slot. */ - gcc_checking_assert (current_namespace == CP_DECL_CONTEXT (decl)); if (maybe_tmpl != decl) /* We're in the template parm binding level. Pushtag has logic to slide under that, but we're diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc index e5f8562105e..361dc3d953d 100644 --- a/gcc/cp/name-lookup.cc +++ b/gcc/cp/name-lookup.cc @@ -3782,18 +3782,30 @@ check_module_override (tree decl, tree mvec, bool hiding, /* Errors could cause there to be nothing. */ continue; + tree type = NULL_TREE; if (STAT_HACK_P (bind)) - /* We do not have to check STAT_TYPE here, the xref_tag - machinery deals with that problem. */ - bind = STAT_VISIBLE (bind); + { + /* If there was a matching STAT_TYPE here then xref_tag + should have found it, but we need to check anyway because + a conflicting using-declaration may exist. */ + if (STAT_TYPE_VISIBLE_P (bind)) + type = STAT_TYPE (bind); + bind = STAT_VISIBLE (bind); + } - for (ovl_iterator iter (bind); iter; ++iter) - if (!iter.using_p ()) - { - match = duplicate_decls (decl, *iter, hiding); - if (match) - goto matched; - } + if (type) + { + match = duplicate_decls (decl, strip_using_decl (type), hiding); + if (match) + goto matched; + } + + for (ovl_iterator iter (strip_using_decl (bind)); iter; ++iter) + { + match = duplicate_decls (decl, *iter, hiding); + if (match) + goto matched; + } } if (TREE_PUBLIC (scope) && TREE_PUBLIC (STRIP_TEMPLATE (decl)) diff --git a/gcc/testsuite/g++.dg/modules/using-19_a.C b/gcc/testsuite/g++.dg/modules/using-19_a.C new file mode 100644 index 00000000000..693a70ce7d4 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/using-19_a.C @@ -0,0 +1,18 @@ +// { dg-additional-options "-fmodules-ts -Wno-global-module" } +// { dg-module-cmi M } + +module; + +namespace hidden { + struct S {}; + enum E { e }; + void f(); +} + +export module M; +export namespace exposed { + using hidden::S; + using hidden::E; + using hidden::e; + using hidden::f; +} diff --git a/gcc/testsuite/g++.dg/modules/using-19_b.C b/gcc/testsuite/g++.dg/modules/using-19_b.C new file mode 100644 index 00000000000..dbe8d9f3c01 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/using-19_b.C @@ -0,0 +1,10 @@ +// { dg-additional-options "-fmodules-ts" } + +import M; + +namespace exposed { + struct S {}; // { dg-error "redefinition" } + enum E { x }; // { dg-error "multiple definition" } + int e(); // { dg-error "redeclared" } + int f; // { dg-error "redeclared" } +}