This is the first half of using directive cleanup. I split the current
interface in two, one for namespace-level directives and one for local
directives. That avoids the need for a load if 'if (namespace_level_p
())' tests in the bodies of the worker functions. I also merged and
renamed do_using_directive & parse_using_directive, as we're not
actually parsing at this point, so a finish_FOO name seemed more
appropriate.
The second part of the patch removes the recursiveness of
add_using_namespace_1 and will wait until the namespace using
representation has been simplified.
Jason killed strong using directives earlier this year. I'd already
written the fragment suggesting an inline namespace, so included it here.
You may notice that push_namespace has two calls to add_using_directive,
which look like they could be combined. That's only because the
representation if inline namespaces hasn't yet been changed.
Applied to trunk.
nathan
--
Nathan Sidwell
2017-05-22 Nathan Sidwell <nat...@acm.org>
cp/
* name-lookup.h (parse_using_directive): Replace with ...
(finish_namespace_using_directive): ... this and ...
(finish_local_using_directive): ... this.
* name-lookup.c (add_using_namespace_1): Move later.
(add_using_namespace): Move later, add namespace_p arg, remove
indirect arg.
(push_using_directive_1): Directly recurse.
(do_using_directive, parse_using_directive): Delete, split into ...
(finish_namespace_using_directive): ... this and ...
(finish_local_using_directive): ... this.
(push_namespace): Use add_using_namespace.
* parser.c (cp_parser_using_directive): Call
finish_namespace_using_directive or finish_local_using_directive.
* pt.c (tsubst_expr): Call finish_local_using_directive.
testsuite/
* g++.dg/lookup/strong-using.C: New.
Index: cp/name-lookup.c
===================================================================
--- cp/name-lookup.c (revision 248327)
+++ cp/name-lookup.c (working copy)
@@ -4337,60 +4337,6 @@ pushdecl_namespace_level (tree x, bool i
return t;
}
-/* Insert USED into the using list of USER. Set INDIRECT_flag if this
- directive is not directly from the source. Also find the common
- ancestor and let our users know about the new namespace */
-
-static void
-add_using_namespace_1 (tree user, tree used, bool indirect)
-{
- tree t;
- /* Using oneself is a no-op. */
- if (user == used)
- return;
- gcc_assert (TREE_CODE (user) == NAMESPACE_DECL);
- gcc_assert (TREE_CODE (used) == NAMESPACE_DECL);
- /* Check if we already have this. */
- t = purpose_member (used, DECL_NAMESPACE_USING (user));
- if (t != NULL_TREE)
- {
- if (!indirect)
- /* Promote to direct usage. */
- TREE_INDIRECT_USING (t) = 0;
- return;
- }
-
- /* Add used to the user's using list. */
- DECL_NAMESPACE_USING (user)
- = tree_cons (used, namespace_ancestor (user, used),
- DECL_NAMESPACE_USING (user));
-
- TREE_INDIRECT_USING (DECL_NAMESPACE_USING (user)) = indirect;
-
- /* Add user to the used's users list. */
- DECL_NAMESPACE_USERS (used)
- = tree_cons (user, 0, DECL_NAMESPACE_USERS (used));
-
- /* Recursively add all namespaces used. */
- for (t = DECL_NAMESPACE_USING (used); t; t = TREE_CHAIN (t))
- /* indirect usage */
- add_using_namespace_1 (user, TREE_PURPOSE (t), 1);
-
- /* Tell everyone using us about the new used namespaces. */
- for (t = DECL_NAMESPACE_USERS (user); t; t = TREE_CHAIN (t))
- add_using_namespace_1 (TREE_PURPOSE (t), used, 1);
-}
-
-/* Wrapper for add_using_namespace_1. */
-
-static void
-add_using_namespace (tree user, tree used, bool indirect)
-{
- bool subtime = timevar_cond_start (TV_NAME_LOOKUP);
- add_using_namespace_1 (user, used, indirect);
- timevar_cond_stop (TV_NAME_LOOKUP, subtime);
-}
-
/* Process a using-declaration not appearing in class or local scope. */
void
@@ -4422,75 +4368,6 @@ do_toplevel_using_decl (tree decl, tree
binding->type = newtype;
}
-/* Process a using-directive. */
-
-void
-do_using_directive (tree name_space)
-{
- tree context = NULL_TREE;
-
- if (name_space == error_mark_node)
- return;
-
- gcc_assert (TREE_CODE (name_space) == NAMESPACE_DECL);
-
- if (building_stmt_list_p ())
- add_stmt (build_stmt (input_location, USING_STMT, name_space));
- name_space = ORIGINAL_NAMESPACE (name_space);
-
- if (!toplevel_bindings_p ())
- {
- push_using_directive (name_space);
- }
- else
- {
- /* direct usage */
- add_using_namespace (current_namespace, name_space, 0);
- if (current_namespace != global_namespace)
- context = current_namespace;
-
- /* Emit debugging info. */
- if (!processing_template_decl)
- (*debug_hooks->imported_module_or_decl) (name_space, NULL_TREE,
- context, false);
- }
-}
-
-/* Deal with a using-directive seen by the parser. Currently we only
- handle attributes here, since they cannot appear inside a template. */
-
-void
-parse_using_directive (tree name_space, tree attribs)
-{
- do_using_directive (name_space);
-
- if (attribs == error_mark_node)
- return;
-
- for (tree a = attribs; a; a = TREE_CHAIN (a))
- {
- tree name = get_attribute_name (a);
- if (is_attribute_p ("strong", name))
- {
- warning (OPT_Wdeprecated, "strong using is deprecated; use inline "
- "namespaces instead");
- if (!toplevel_bindings_p ())
- error ("strong using only meaningful at namespace scope");
- else if (name_space != error_mark_node)
- {
- if (!is_ancestor (current_namespace, name_space))
- error ("current namespace %qD does not enclose strongly used namespace %qD",
- current_namespace, name_space);
- DECL_NAMESPACE_ASSOCIATIONS (name_space)
- = tree_cons (current_namespace, 0,
- DECL_NAMESPACE_ASSOCIATIONS (name_space));
- }
- }
- else
- warning (OPT_Wattributes, "%qD attribute directive ignored", name);
- }
-}
-
/* Combines two sets of overloaded functions into an OVERLOAD chain, removing
duplicates. The first list becomes the tail of the result.
@@ -5827,7 +5704,7 @@ push_using_directive_1 (tree used)
/* Recursively add all namespaces used. */
for (iter = DECL_NAMESPACE_USING (used); iter; iter = TREE_CHAIN (iter))
- push_using_directive (TREE_PURPOSE (iter));
+ push_using_directive_1 (TREE_PURPOSE (iter));
return ud;
}
@@ -6363,6 +6240,113 @@ do_pop_nested_namespace (tree ns)
do_pop_from_top_level ();
}
+/* Insert USED into the using list of USER. Set INDIRECT_flag if this
+ directive is not directly from the source. Also find the common
+ ancestor and let our users know about the new namespace */
+
+static void
+add_using_namespace_1 (tree user, tree used, bool indirect)
+{
+ tree t;
+ /* Using oneself is a no-op. */
+ if (user == used)
+ return;
+ gcc_assert (TREE_CODE (user) == NAMESPACE_DECL);
+ gcc_assert (TREE_CODE (used) == NAMESPACE_DECL);
+ /* Check if we already have this. */
+ t = purpose_member (used, DECL_NAMESPACE_USING (user));
+ if (t != NULL_TREE)
+ {
+ if (!indirect)
+ /* Promote to direct usage. */
+ TREE_INDIRECT_USING (t) = 0;
+ return;
+ }
+
+ /* Add used to the user's using list. */
+ DECL_NAMESPACE_USING (user)
+ = tree_cons (used, namespace_ancestor (user, used),
+ DECL_NAMESPACE_USING (user));
+
+ TREE_INDIRECT_USING (DECL_NAMESPACE_USING (user)) = indirect;
+
+ /* Add user to the used's users list. */
+ DECL_NAMESPACE_USERS (used)
+ = tree_cons (user, 0, DECL_NAMESPACE_USERS (used));
+
+ /* Recursively add all namespaces used. */
+ for (t = DECL_NAMESPACE_USING (used); t; t = TREE_CHAIN (t))
+ /* indirect usage */
+ add_using_namespace_1 (user, TREE_PURPOSE (t), 1);
+
+ /* Tell everyone using us about the new used namespaces. */
+ for (t = DECL_NAMESPACE_USERS (user); t; t = TREE_CHAIN (t))
+ add_using_namespace_1 (TREE_PURPOSE (t), used, 1);
+}
+
+/* Wrapper for add_using_namespace_1. */
+
+static void
+add_using_namespace (bool namespace_level_p, tree from, tree target)
+{
+ bool subtime = timevar_cond_start (TV_NAME_LOOKUP);
+ add_using_namespace_1 (from, target, false);
+ if (namespace_level_p)
+ {
+ /* Emit debugging info. */
+ tree context = from != global_namespace ? from : NULL_TREE;
+ debug_hooks->imported_module_or_decl (target, NULL_TREE, context, false);
+ }
+ timevar_cond_stop (TV_NAME_LOOKUP, subtime);
+}
+
+/* Process a namespace-scope using directive. */
+
+void
+finish_namespace_using_directive (tree target, tree attribs)
+{
+ gcc_checking_assert (namespace_bindings_p ());
+ if (target == error_mark_node)
+ return;
+
+ add_using_namespace (true, current_namespace,
+ ORIGINAL_NAMESPACE (target));
+
+ if (attribs == error_mark_node)
+ return;
+
+ for (tree a = attribs; a; a = TREE_CHAIN (a))
+ {
+ tree name = get_attribute_name (a);
+ if (is_attribute_p ("strong", name))
+ {
+ warning (0, "strong using directive no longer supported");
+ if (CP_DECL_CONTEXT (target) == current_namespace)
+ inform (DECL_SOURCE_LOCATION (target),
+ "you may use an inline namespace instead");
+ }
+ else
+ warning (OPT_Wattributes, "%qD attribute directive ignored", name);
+ }
+}
+
+/* Process a function-scope using-directive. */
+
+void
+finish_local_using_directive (tree target, tree attribs)
+{
+ gcc_checking_assert (local_bindings_p ());
+ if (target == error_mark_node)
+ return;
+
+ if (attribs)
+ warning (OPT_Wattributes, "attributes ignored on local using directive");
+
+ add_stmt (build_stmt (input_location, USING_STMT, target));
+
+ push_using_directive (ORIGINAL_NAMESPACE (target));
+}
+
/* Pushes X into the global namespace. */
tree
@@ -6468,7 +6452,7 @@ push_namespace (tree name, bool make_inl
DECL_NAME (ns) = NULL_TREE;
if (!make_inline)
- do_using_directive (ns);
+ add_using_namespace (true, current_namespace, ns);
}
else if (TREE_PUBLIC (current_namespace))
TREE_PUBLIC (ns) = 1;
@@ -6480,7 +6464,7 @@ push_namespace (tree name, bool make_inl
DECL_NAMESPACE_ASSOCIATIONS (ns)
= tree_cons (current_namespace, NULL_TREE, NULL_TREE);
/* Import the contents of the inline namespace. */
- do_using_directive (ns);
+ add_using_namespace (true, current_namespace, ns);
}
}
}
@@ -6525,8 +6509,6 @@ push_to_top_level (void)
timevar_cond_stop (TV_NAME_LOOKUP, subtime);
}
-/* Wrapper for pop_from_top_level_1. */
-
void
pop_from_top_level (void)
{
Index: cp/name-lookup.h
===================================================================
--- cp/name-lookup.h (revision 248326)
+++ cp/name-lookup.h (working copy)
@@ -332,11 +332,12 @@ extern tree do_class_using_decl (tree, t
extern void do_using_directive (tree);
extern cp_expr lookup_arg_dependent (tree, tree, vec<tree, va_gc> *);
extern bool is_associated_namespace (tree, tree);
-extern void parse_using_directive (tree, tree);
extern tree innermost_non_namespace_value (tree);
extern cxx_binding *outer_binding (tree, cxx_binding *, bool);
extern void cp_emit_debug_info_for_using (tree, tree);
+extern void finish_namespace_using_directive (tree, tree);
+extern void finish_local_using_directive (tree, tree);
extern tree pushdecl_outermost_localscope (tree);
extern tree pushdecl (tree, bool is_friend = false);
extern tree pushdecl_top_level (tree, bool is_friend = false);
Index: cp/parser.c
===================================================================
--- cp/parser.c (revision 248326)
+++ cp/parser.c (working copy)
@@ -18692,8 +18692,13 @@ cp_parser_using_directive (cp_parser* pa
namespace_decl = cp_parser_namespace_name (parser);
/* And any specified attributes. */
attribs = cp_parser_attributes_opt (parser);
+
/* Update the symbol table. */
- parse_using_directive (namespace_decl, attribs);
+ if (namespace_bindings_p ())
+ finish_namespace_using_directive (namespace_decl, attribs);
+ else
+ finish_local_using_directive (namespace_decl, attribs);
+
/* Look for the final `;'. */
cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
}
Index: cp/pt.c
===================================================================
--- cp/pt.c (revision 248326)
+++ cp/pt.c (working copy)
@@ -15672,7 +15672,8 @@ tsubst_expr (tree t, tree args, tsubst_f
break;
case USING_STMT:
- do_using_directive (USING_STMT_NAMESPACE (t));
+ finish_local_using_directive (USING_STMT_NAMESPACE (t),
+ /*attribs=*/NULL_TREE);
break;
case DECL_EXPR:
Index: testsuite/g++.dg/lookup/strong-using.C
===================================================================
--- testsuite/g++.dg/lookup/strong-using.C (revision 0)
+++ testsuite/g++.dg/lookup/strong-using.C (working copy)
@@ -0,0 +1,10 @@
+// { dg-do compile { target c++11 } }
+
+namespace A
+{
+ namespace B // { dg-message "inline namespace" }
+ {
+ }
+
+ using namespace B __attribute__ ((strong)); // { dg-warning "no longer supported" "" }
+}