* 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.
From-SVN: r73468
+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.
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) \
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. */
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. */
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)
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_using_directive (cp_parser* parser)
{
tree namespace_decl;
+ tree attribs;
/* Look for the `using' keyword. */
cp_parser_require_keyword (parser, RID_USING, "`using'");
/*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, "`;'");
}
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'",
* 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++.
@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