diff mbox

[C++] Using directives

Message ID 48850509-31d3-b820-c9e9-bcd246380cee@acm.org
State New
Headers show

Commit Message

Nathan Sidwell May 22, 2017, 3:58 p.m. UTC
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
diff mbox

Patch

2017-05-22  Nathan Sidwell  <nathan@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" "" }
+}