DR2061 concerns the meaning of:
inline namespace One {
namespace Term { }
}
namespace Term {
}
Does that second Term open a new namespace inside :: or reopen ::One::Term?
DR2061 resolves to ::One::Term -- i.e. the lookup considers inline
namespaces.
This patch implements that behaviour. rather than a plain
get_namespace_binding we do a lookup.search_qualified, but ignore any
using directives.
nathan
--
Nathan Sidwell
2017-05-26 Nathan Sidwell <nat...@acm.org>
gcc/
Implement DR2061
* name-lookup.c (push_inline_namespaces): New.
(push_namespace): Look inside inline namespaces.
testsuite/
* g++.dg/cpp0x/dr2061.C: New.
* g++.dg/parse/namespace-alias-1.C: Add more test.
Index: cp/name-lookup.c
===================================================================
--- cp/name-lookup.c (revision 248520)
+++ cp/name-lookup.c (working copy)
@@ -6057,6 +6057,23 @@ pushdecl_top_level_and_finish (tree x, t
return x;
}
+/* Enter the namespaces from current_namerspace to NS. */
+
+static int
+push_inline_namespaces (tree ns)
+{
+ int count = 0;
+ if (ns != current_namespace)
+ {
+ gcc_assert (ns != global_namespace);
+ count += push_inline_namespaces (CP_DECL_CONTEXT (ns));
+ resume_scope (NAMESPACE_LEVEL (ns));
+ current_namespace = ns;
+ count++;
+ }
+ return count;
+}
+
/* Push into the scope of the NAME namespace. If NAME is NULL_TREE,
then we enter an anonymous namespace. If MAKE_INLINE is true, then
we create an inline namespace (it is up to the caller to check upon
@@ -6076,43 +6093,36 @@ push_namespace (tree name, bool make_inl
if (!name)
name = anon_identifier;
- /* Check whether this is an extended namespace definition. */
- tree ns = get_namespace_binding (current_namespace, name);
- if (ns && TREE_CODE (ns) == NAMESPACE_DECL)
- {
- if (tree dna = DECL_NAMESPACE_ALIAS (ns))
- {
- /* We do some error recovery for, eg, the redeclaration of M
- here:
-
- namespace N {}
- namespace M = N;
- namespace M {}
-
- However, in nasty cases like:
-
- namespace N
- {
- namespace M = N;
- namespace M {}
- }
-
- we just error out below, in duplicate_decls. */
- if (NAMESPACE_LEVEL (dna)->level_chain == current_binding_level)
- {
- error ("namespace alias %qD not allowed here, "
- "assuming %qD", ns, dna);
- ns = dna;
- }
- else
- ns = NULL_TREE;
- }
- }
- else
- ns = NULL_TREE;
+ tree ns = NULL_TREE;
+ {
+ name_lookup lookup (name, 0);
+ if (!lookup.search_qualified (current_namespace, /*usings=*/false))
+ ;
+ else if (TREE_CODE (lookup.value) != NAMESPACE_DECL)
+ ;
+ else if (tree dna = DECL_NAMESPACE_ALIAS (lookup.value))
+ {
+ /* A namespace alias is not allowed here, but if the alias
+ is for a namespace also inside the current scope,
+ accept it with a diagnostic. That's better than dying
+ horribly. */
+ if (is_nested_namespace (current_namespace, CP_DECL_CONTEXT (dna)))
+ {
+ error ("namespace alias %qD not allowed here, "
+ "assuming %qD", lookup.value, dna);
+ ns = dna;
+ }
+ }
+ else
+ ns = lookup.value;
+ }
bool new_ns = false;
- if (!ns)
+ if (ns)
+ /* DR2061. NS might be a member of an inline namespace. We
+ need to push into those namespaces. */
+ count += push_inline_namespaces (CP_DECL_CONTEXT (ns));
+ else
{
ns = build_lang_decl (NAMESPACE_DECL, name, void_type_node);
SCOPE_DEPTH (ns) = SCOPE_DEPTH (current_namespace) + 1;
Index: testsuite/g++.dg/cpp0x/dr2061.C
===================================================================
--- testsuite/g++.dg/cpp0x/dr2061.C (revision 0)
+++ testsuite/g++.dg/cpp0x/dr2061.C (working copy)
@@ -0,0 +1,46 @@
+// { dg-do compile { target c++11 } }
+
+// DR2061, look inside inline namespace when pushing a namespace.
+
+inline namespace One
+{
+ namespace Term
+ {
+ }
+ inline namespace Two
+ {
+ namespace Space
+ {
+ }
+ }
+}
+
+namespace Term
+{
+ void bob ();
+}
+
+namespace Space
+{
+ void bill ();
+}
+
+inline namespace Two
+{
+ void weed ();
+}
+
+void One::Term::bob () {}
+void One::Two::Space::bill () {}
+void One::Two::weed () {}
+
+void Thing ()
+{
+ Term::bob ();
+ Space::bill ();
+ weed ();
+}
+
+// { dg-final { scan-assembler "_ZN3One4Term3bobEv:" } }
+// { dg-final { scan-assembler "_ZN3One3Two5Space4billEv:" } }
+// { dg-final { scan-assembler "_ZN3One3Two4weedEv:" } }
Index: testsuite/g++.dg/parse/namespace-alias-1.C
===================================================================
--- testsuite/g++.dg/parse/namespace-alias-1.C (revision 248520)
+++ testsuite/g++.dg/parse/namespace-alias-1.C (working copy)
@@ -5,3 +5,18 @@ namespace N
namespace M = N; // { dg-message "previous declaration" }
namespace M {} // { dg-error "declaration of namespace" }
}
+
+namespace A
+{
+ namespace B
+ {
+ namespace C
+ {
+ }
+ }
+
+ namespace D = B::C;
+ namespace D // { dg-error "not allowed" }
+ {
+ }
+}