This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[C++] PATCH to support strong using extension


This extension is necessary to support the libstdc++ debug mode code which
Benjamin just checked in.  The documentation is at the bottom of the patch.

Applied to trunk.  I'm not sure that I've tested this exact version of the
patch, but I'm checking it in now anyway to fix bootstrap.

2003-11-11  Jason Merrill  <jason@redhat.com>

	* cp-tree.h (DECL_NAMESPACE_ASSOCIATIONS): New macro.
	* name-lookup.c (parse_using_directive): New fn.
	(is_associated_namespace): New fn.
	(arg_assoc_namespace): Also check associated namespaces.
	* name-lookup.h: Declare new fns.
	* pt.c (maybe_process_partial_specialization): Allow
	specialization in associated namespace.
	* parser.c (cp_parser_using_directive): Accept attributes.  Use
	parse_using_directive.

*** cp/cp-tree.h.~1~	2003-11-10 18:59:57.000000000 -0500
--- cp/cp-tree.h	2003-11-04 13:55:25.000000000 -0500
*************** struct lang_decl GTY(())
*** 2063,2068 ****
--- 2063,2073 ----
     of a namespace, to record the transitive closure of using namespace.  */
  #define DECL_NAMESPACE_USERS(NODE) DECL_INITIAL (NAMESPACE_DECL_CHECK (NODE))
  
+ /* In a NAMESPACE_DECL, the list of namespaces which have associated
+    themselves with this one.  */
+ #define DECL_NAMESPACE_ASSOCIATIONS(NODE) \
+   (NAMESPACE_DECL_CHECK (NODE)->decl.saved_tree)
+ 
  /* In a NAMESPACE_DECL, points to the original namespace if this is
     a namespace alias.  */
  #define DECL_NAMESPACE_ALIAS(NODE) \
*** cp/name-lookup.c.~1~	2003-11-10 18:59:57.000000000 -0500
--- cp/name-lookup.c	2003-11-10 18:57:09.000000000 -0500
*************** do_using_directive (tree namespace)
*** 3286,3291 ****
--- 3286,3318 ----
      add_using_namespace (current_namespace, namespace, 0);
  }
  
+ /* 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 namespace, tree attribs)
+ {
+   tree a;
+ 
+   do_using_directive (namespace);
+ 
+   for (a = attribs; a; a = TREE_CHAIN (a))
+     {
+       tree name = TREE_PURPOSE (a);
+       if (is_attribute_p ("strong", name))
+ 	{
+ 	  if (!toplevel_bindings_p ())
+ 	    error ("strong using only meaningful at namespace scope");
+ 	  else
+ 	    DECL_NAMESPACE_ASSOCIATIONS (namespace)
+ 	      = tree_cons (current_namespace, 0,
+ 			   DECL_NAMESPACE_ASSOCIATIONS (namespace));
+ 	}
+       else
+ 	warning ("`%D' attribute directive ignored", name);
+     }
+ }
+ 
  /* Like pushdecl, only it places X in the global scope if appropriate.
     Calls cp_finish_decl to register the variable, initializing it with
     *INIT, if INIT is non-NULL.  */
*************** add_function (struct arg_lookup *k, tree
*** 4011,4016 ****
--- 4038,4071 ----
    return false;
  }
  
+ /* Returns true iff CURRENT has declared itself to be an associated
+    namespace of SCOPE via a strong using-directive (or transitive chain
+    thereof).  Both are namespaces.  */
+ 
+ bool
+ is_associated_namespace (tree current, tree scope)
+ {
+   tree seen = NULL_TREE;
+   tree todo = NULL_TREE;
+   tree t;
+   while (1)
+     {
+       if (scope == current)
+ 	return true;
+       seen = tree_cons (scope, NULL_TREE, seen);
+       for (t = DECL_NAMESPACE_ASSOCIATIONS (scope); t; t = TREE_CHAIN (t))
+ 	if (!purpose_member (TREE_PURPOSE (t), seen))
+ 	  todo = tree_cons (TREE_PURPOSE (t), NULL_TREE, todo);
+       if (todo)
+ 	{
+ 	  scope = TREE_PURPOSE (todo);
+ 	  todo = TREE_CHAIN (todo);
+ 	}
+       else
+ 	return false;
+     }
+ }
+ 
  /* Add functions of a namespace to the lookup structure.
     Returns true on error.  */
  
*************** arg_assoc_namespace (struct arg_lookup *
*** 4022,4027 ****
--- 4077,4088 ----
    if (purpose_member (scope, k->namespaces))
      return 0;
    k->namespaces = tree_cons (scope, NULL_TREE, k->namespaces);
+ 
+   /* Check out our super-users.  */
+   for (value = DECL_NAMESPACE_ASSOCIATIONS (scope); value;
+        value = TREE_CHAIN (value))
+     if (arg_assoc_namespace (k, TREE_PURPOSE (value)))
+       return true;
    
    value = namespace_binding (k->name, scope);
    if (!value)
*** cp/name-lookup.h.~1~	2003-11-10 18:59:57.000000000 -0500
--- cp/name-lookup.h	2003-10-30 14:39:34.000000000 -0500
*************** extern void do_local_using_decl (tree);
*** 306,311 ****
--- 306,313 ----
  extern tree do_class_using_decl (tree);
  extern void do_using_directive (tree);
  extern tree lookup_arg_dependent (tree, tree, tree);
+ extern bool is_associated_namespace (tree, tree);
+ extern void parse_using_directive (tree, tree);
  
  
  /* Set *DECL to the (non-hidden) declaration for ID at global scope,
*** cp/parser.c.~1~	2003-11-10 18:59:57.000000000 -0500
--- cp/parser.c	2003-10-31 13:56:46.000000000 -0500
*************** static void
*** 9078,9083 ****
--- 9078,9084 ----
  cp_parser_using_directive (cp_parser* parser)
  {
    tree namespace_decl;
+   tree attribs;
  
    /* Look for the `using' keyword.  */
    cp_parser_require_keyword (parser, RID_USING, "`using'");
*************** cp_parser_using_directive (cp_parser* pa
*** 9092,9099 ****
  				       /*type_p=*/false);
    /* Get the namespace being used.  */
    namespace_decl = cp_parser_namespace_name (parser);
    /* Update the symbol table.  */
!   do_using_directive (namespace_decl);
    /* Look for the final `;'.  */
    cp_parser_require (parser, CPP_SEMICOLON, "`;'");
  }
--- 9093,9102 ----
  				       /*type_p=*/false);
    /* Get the namespace being used.  */
    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);
    /* Look for the final `;'.  */
    cp_parser_require (parser, CPP_SEMICOLON, "`;'");
  }
*** cp/pt.c.~1~	2003-11-10 18:59:57.000000000 -0500
--- cp/pt.c	2003-11-10 18:57:10.000000000 -0500
*************** maybe_process_partial_specialization (tr
*** 731,738 ****
        if (CLASSTYPE_IMPLICIT_INSTANTIATION (type)
  	  && !COMPLETE_TYPE_P (type))
  	{
! 	  if (current_namespace
! 	      != decl_namespace_context (CLASSTYPE_TI_TEMPLATE (type)))
  	    {
  	      pedwarn ("specializing `%#T' in different namespace", type);
  	      cp_pedwarn_at ("  from definition of `%#D'",
--- 731,740 ----
        if (CLASSTYPE_IMPLICIT_INSTANTIATION (type)
  	  && !COMPLETE_TYPE_P (type))
  	{
! 	  tree tpl_ns = decl_namespace_context (CLASSTYPE_TI_TEMPLATE (type));
! 	  if (is_associated_namespace (current_namespace, tpl_ns))
! 	    /* Same or super-using namespace.  */;
! 	  else
  	    {
  	      pedwarn ("specializing `%#T' in different namespace", type);
  	      cp_pedwarn_at ("  from definition of `%#D'",
*** doc/extend.texi.~1~	2003-11-10 18:59:57.000000000 -0500
--- doc/extend.texi	2003-11-10 18:57:13.000000000 -0500
*************** Predefined Macros,cpp,The GNU C Preproce
*** 7649,7654 ****
--- 7649,7655 ----
  * Bound member functions:: You can extract a function pointer to the
                          method denoted by a @samp{->*} or @samp{.*} expression.
  * C++ Attributes::      Variable, function, and type attributes for C++ only.
+ * Strong Using::      Strong using-directives for namespace composition.
  * Java Exceptions::     Tweaking exception handling to work with Java.
  * Deprecated Features:: Things will disappear from g++.
  * Backwards Compatibility:: Compatibilities with earlier definitions of C++.
*************** interface table mechanism, instead of re
*** 8249,8254 ****
--- 8250,8294 ----
  
  @end table
  
+ See also @xref{Strong Using}.
+ 
+ @node Strong Using
+ @section Strong Using
+ 
+ A using-directive with @code{__attribute ((strong))} is stronger
+ than a normal using-directive in two ways:
+ 
+ @itemize @bullet
+ @item
+ Templates from the used namespace can be specialized as though they were members of the using namespace.
+ 
+ @item
+ The using namespace is considered an associated namespace of all
+ templates in the used namespace for purposes of argument-dependent
+ name lookup.
+ @end itemize
+ 
+ This is useful for composing a namespace transparently from
+ implementation namespaces.  For example:
+ 
+ @smallexample
+ namespace std @{
+   namespace debug @{
+     template <class T> struct A @{ @};
+   @}
+   using namespace debug __attribute ((__strong__));
+   template <> struct A<int> @{ @};   // ok to specialize
+ 
+   template <class T> void f (A<T>);
+ @}
+ 
+ int main()
+ @{
+   f (std::A<float>());             // lookup finds std::f
+   f (std::A<int>());
+ @}
+ @end smallexample
+ 
  @node Java Exceptions
  @section Java Exceptions
  

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]