OSDN Git Service

* cp-tree.h (DECL_NAMESPACE_ASSOCIATIONS): New macro.
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 11 Nov 2003 22:27:32 +0000 (22:27 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 11 Nov 2003 22:27:32 +0000 (22:27 +0000)
        * 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@73468 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/name-lookup.c
gcc/cp/name-lookup.h
gcc/cp/parser.c
gcc/cp/pt.c
gcc/doc/extend.texi

index 5ea6d94..d3b8316 100644 (file)
@@ -1,3 +1,15 @@
+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.
+
 2003-11-10  Richard Henderson  <rth@redhat.com>
 
        * cvt.c (convert_to_void): Use void_zero_node after overload failure.
index 0603160..def9b81 100644 (file)
@@ -2063,6 +2063,11 @@ struct lang_decl GTY(())
    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) \
index 624e86e..185c04f 100644 (file)
@@ -3286,6 +3286,33 @@ do_using_directive (tree namespace)
     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.  */
@@ -4011,6 +4038,34 @@ add_function (struct arg_lookup *k, tree fn)
   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.  */
 
@@ -4022,6 +4077,12 @@ arg_assoc_namespace (struct arg_lookup *k, tree scope)
   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)
index 36643b2..df7615a 100644 (file)
@@ -306,6 +306,8 @@ extern void do_local_using_decl (tree);
 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,
index 9b040f5..d08588f 100644 (file)
@@ -9078,6 +9078,7 @@ static void
 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'");
@@ -9092,8 +9093,10 @@ cp_parser_using_directive (cp_parser* parser)
                                       /*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.  */
-  do_using_directive (namespace_decl);
+  parse_using_directive (namespace_decl, attribs);
   /* Look for the final `;'.  */
   cp_parser_require (parser, CPP_SEMICOLON, "`;'");
 }
index e464af3..cd93423 100644 (file)
@@ -731,8 +731,10 @@ maybe_process_partial_specialization (tree type)
       if (CLASSTYPE_IMPLICIT_INSTANTIATION (type)
          && !COMPLETE_TYPE_P (type))
        {
-         if (current_namespace
-             != decl_namespace_context (CLASSTYPE_TI_TEMPLATE (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'",
index fdc1c7c..7825a12 100644 (file)
@@ -7649,6 +7649,7 @@ Predefined Macros,cpp,The GNU C Preprocessor}).
 * 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++.
@@ -8249,6 +8250,45 @@ interface table mechanism, instead of regular virtual table dispatch.
 
 @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