From 945bf9e13f706bed44ec760ac60693e00c59b146 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Fri, 26 May 2017 18:13:53 +0000 Subject: [PATCH] Implement DR2061 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. From-SVN: r248521 --- gcc/cp/ChangeLog | 4 + gcc/cp/name-lookup.c | 80 +++++++++++-------- gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/g++.dg/cpp0x/dr2061.C | 46 +++++++++++ .../g++.dg/parse/namespace-alias-1.C | 15 ++++ 5 files changed, 115 insertions(+), 35 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/dr2061.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1890449046f..8e3530fb440 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,9 @@ 2017-05-26 Nathan Sidwell + Implement DR2061 + * name-lookup.c (push_inline_namespaces): New. + (push_namespace): Look inside inline namespaces. + Inline and using namespace representation change. * cp-tree.h (struct lang_decl_ns): Delete ns_using. Add usings, inlinees as vector. diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index dc0387741e7..9c0390175b3 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -6057,6 +6057,23 @@ pushdecl_top_level_and_finish (tree x, tree init) 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_inline) 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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5136e4ab6a5..8eca177d485 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-05-26 Nathan Sidwell + + * g++.dg/cpp0x/dr2061.C: New. + * g++.dg/parse/namespace-alias-1.C: Add more test. + 2017-05-26 Bin Cheng PR tree-optimization/80815 diff --git a/gcc/testsuite/g++.dg/cpp0x/dr2061.C b/gcc/testsuite/g++.dg/cpp0x/dr2061.C new file mode 100644 index 00000000000..302279b6631 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/dr2061.C @@ -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:" } } diff --git a/gcc/testsuite/g++.dg/parse/namespace-alias-1.C b/gcc/testsuite/g++.dg/parse/namespace-alias-1.C index 4b443359a61..5986ab69d00 100644 --- a/gcc/testsuite/g++.dg/parse/namespace-alias-1.C +++ b/gcc/testsuite/g++.dg/parse/namespace-alias-1.C @@ -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" } + { + } +} -- 2.30.2