Commit 44e00a7a by Nathan Sidwell Committed by Nathan Sidwell

Kill DECL_NAMESPACE_USERS, DECL_NAMESPACE_ASSOCIATIONS.

	gcc/cp/
	Kill DECL_NAMESPACE_USERS, DECL_NAMESPACE_ASSOCIATIONS.
	* cp-tree.h (lang_decl_ns): Remove ns_users field.
	(DECL_NAMESPACE_USERS, DECL_NAMESPACE_ASSOCIATIONS): Delete.
	(TREE_INDIRECT_USING): Delete.
	* name-lookup.h (is_associated_namespace): Delete.
	* name-lookup.c (name_lookup::search_usings
	name_lookup::do_queue_usings): Usings are always direct.
	(is_associated_namespace): Delete.
	(handle_namespace_attrs): Use DECL_NAMESPACE_INLINE_P.
	(namespace_ancestor_1, namespace_ancestor): Delete.
	(push_using_directive_1, push_using_directive): Delete.
	(add_using_namespace_1): Delete.
	(add_using_namespace): Reimplement.
	(emit_debug_info_using_namespace): New.
	(finish_namespace_using_directive, finish_local_using_directive
	push_namespace): Adjust.
	* tree.c (cp_free_lang_data): Remove DECL_NAMESPACE_USERS
	handling.

	libcc1/
	* libcp1plugin.cc (plugin_make_namespace_inline): Check and set
	DECL_NAMESPACE_INLINE_P.

	gcc/testsuite/
	* g++.dg/lookup/using56.C: New.
	* g++.dg/lookup/using57.C: New.
	* g++.dg/lookup/using58.C: New.
	* g++.dg/lookup/using59.C: New.

From-SVN: r248467
parent 63dbcd13
2017-05-25 Nathan Sidwell <nathan@acm.org>
Kill DECL_NAMESPACE_USERS, DECL_NAMESPACE_ASSOCIATIONS.
* cp-tree.h (lang_decl_ns): Remove ns_users field.
(DECL_NAMESPACE_USERS, DECL_NAMESPACE_ASSOCIATIONS): Delete.
(TREE_INDIRECT_USING): Delete.
* name-lookup.h (is_associated_namespace): Delete.
* name-lookup.c (name_lookup::search_usings,
name_lookup::do_queue_usings): Usings are always direct.
(is_associated_namespace): Delete.
(handle_namespace_attrs): Use DECL_NAMESPACE_INLINE_P.
(namespace_ancestor_1, namespace_ancestor): Delete.
(push_using_directive_1, push_using_directive): Delete.
(add_using_namespace_1): Delete.
(add_using_namespace): Reimplement.
(emit_debug_info_using_namespace): New.
(finish_namespace_using_directive, finish_local_using_directive,
push_namespace): Adjust.
* tree.c (cp_free_lang_data): Remove DECL_NAMESPACE_USERS handling.
2017-05-25 Volker Reichelt <v.reichelt@netcologne.de> 2017-05-25 Volker Reichelt <v.reichelt@netcologne.de>
* semantics.c (finish_handler_parms): Warn about non-reference type * semantics.c (finish_handler_parms): Warn about non-reference type
......
...@@ -328,7 +328,6 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; ...@@ -328,7 +328,6 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
BASELINK_QUALIFIED_P (in BASELINK) BASELINK_QUALIFIED_P (in BASELINK)
TARGET_EXPR_IMPLICIT_P (in TARGET_EXPR) TARGET_EXPR_IMPLICIT_P (in TARGET_EXPR)
TEMPLATE_PARM_PARAMETER_PACK (in TEMPLATE_PARM_INDEX) TEMPLATE_PARM_PARAMETER_PACK (in TEMPLATE_PARM_INDEX)
TREE_INDIRECT_USING (in a TREE_LIST of using-directives)
ATTR_IS_DEPENDENT (in the TREE_LIST for an attribute) ATTR_IS_DEPENDENT (in the TREE_LIST for an attribute)
ABI_TAG_IMPLICIT (in the TREE_LIST for the argument of abi_tag) ABI_TAG_IMPLICIT (in the TREE_LIST for the argument of abi_tag)
CONSTRUCTOR_IS_DIRECT_INIT (in CONSTRUCTOR) CONSTRUCTOR_IS_DIRECT_INIT (in CONSTRUCTOR)
...@@ -2513,7 +2512,6 @@ struct GTY(()) lang_decl_ns { ...@@ -2513,7 +2512,6 @@ struct GTY(()) lang_decl_ns {
struct lang_decl_base base; struct lang_decl_base base;
cp_binding_level *level; cp_binding_level *level;
tree ns_using; tree ns_using;
tree ns_users;
}; };
/* DECL_LANG_SPECIFIC for parameters. */ /* DECL_LANG_SPECIFIC for parameters. */
...@@ -3085,15 +3083,6 @@ struct GTY(()) lang_decl { ...@@ -3085,15 +3083,6 @@ struct GTY(()) lang_decl {
that is the common ancestor. */ that is the common ancestor. */
#define DECL_NAMESPACE_USING(NODE) (LANG_DECL_NS_CHECK (NODE)->ns_using) #define DECL_NAMESPACE_USING(NODE) (LANG_DECL_NS_CHECK (NODE)->ns_using)
/* In a NAMESPACE_DECL, the DECL_INITIAL is used to record all users
of a namespace, to record the transitive closure of using namespace. */
#define DECL_NAMESPACE_USERS(NODE) (LANG_DECL_NS_CHECK (NODE)->ns_users)
/* In a NAMESPACE_DECL, the list of namespaces which have associated
themselves with this one. */
#define DECL_NAMESPACE_ASSOCIATIONS(NODE) \
DECL_INITIAL (NAMESPACE_DECL_CHECK (NODE))
/* In a NAMESPACE_DECL, points to the original namespace if this is /* In a NAMESPACE_DECL, points to the original namespace if this is
a namespace alias. */ a namespace alias. */
#define DECL_NAMESPACE_ALIAS(NODE) \ #define DECL_NAMESPACE_ALIAS(NODE) \
...@@ -3107,10 +3096,6 @@ struct GTY(()) lang_decl { ...@@ -3107,10 +3096,6 @@ struct GTY(()) lang_decl {
&& CP_DECL_CONTEXT (NODE) == global_namespace \ && CP_DECL_CONTEXT (NODE) == global_namespace \
&& DECL_NAME (NODE) == std_identifier) && DECL_NAME (NODE) == std_identifier)
/* In a TREE_LIST concatenating using directives, indicate indirect
directives */
#define TREE_INDIRECT_USING(NODE) TREE_LANG_FLAG_0 (TREE_LIST_CHECK (NODE))
/* In a TREE_LIST in an attribute list, indicates that the attribute /* In a TREE_LIST in an attribute list, indicates that the attribute
must be applied at instantiation time. */ must be applied at instantiation time. */
#define ATTR_IS_DEPENDENT(NODE) TREE_LANG_FLAG_0 (TREE_LIST_CHECK (NODE)) #define ATTR_IS_DEPENDENT(NODE) TREE_LANG_FLAG_0 (TREE_LIST_CHECK (NODE))
......
...@@ -533,7 +533,6 @@ name_lookup::search_usings (tree scope) ...@@ -533,7 +533,6 @@ name_lookup::search_usings (tree scope)
/* Look in direct usings. */ /* Look in direct usings. */
for (tree usings = DECL_NAMESPACE_USING (scope); for (tree usings = DECL_NAMESPACE_USING (scope);
usings; usings = TREE_CHAIN (usings)) usings; usings = TREE_CHAIN (usings))
if (!TREE_INDIRECT_USING (usings))
found |= search_qualified (TREE_PURPOSE (usings), true); found |= search_qualified (TREE_PURPOSE (usings), true);
/* Look in its inline children. */ /* Look in its inline children. */
...@@ -607,7 +606,6 @@ name_lookup::using_queue * ...@@ -607,7 +606,6 @@ name_lookup::using_queue *
name_lookup::do_queue_usings (using_queue *queue, int depth, tree usings) name_lookup::do_queue_usings (using_queue *queue, int depth, tree usings)
{ {
for (; usings; usings = TREE_CHAIN (usings)) for (; usings; usings = TREE_CHAIN (usings))
if (!TREE_INDIRECT_USING (usings))
queue = queue_namespace (queue, depth, TREE_PURPOSE (usings)); queue = queue_namespace (queue, depth, TREE_PURPOSE (usings));
return queue; return queue;
...@@ -1019,7 +1017,6 @@ static void consider_binding_level (tree name, ...@@ -1019,7 +1017,6 @@ static void consider_binding_level (tree name,
cp_binding_level *lvl, cp_binding_level *lvl,
bool look_within_fields, bool look_within_fields,
enum lookup_name_fuzzy_kind kind); enum lookup_name_fuzzy_kind kind);
static tree push_using_directive (tree);
static void diagnose_name_conflict (tree, tree); static void diagnose_name_conflict (tree, tree);
/* ADL lookup of NAME. FNS is the result of regular lookup, and we /* ADL lookup of NAME. FNS is the result of regular lookup, and we
...@@ -1036,47 +1033,6 @@ lookup_arg_dependent (tree name, tree fns, vec<tree, va_gc> *args) ...@@ -1036,47 +1033,6 @@ lookup_arg_dependent (tree name, tree fns, vec<tree, va_gc> *args)
return fns; return fns;
} }
/* 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)
{
vec<tree, va_gc> *seen = make_tree_vector ();
vec<tree, va_gc> *todo = make_tree_vector ();
tree t;
bool ret;
while (1)
{
if (scope == current)
{
ret = true;
break;
}
vec_safe_push (seen, scope);
for (t = DECL_NAMESPACE_ASSOCIATIONS (scope); t; t = TREE_CHAIN (t))
if (!vec_member (TREE_PURPOSE (t), seen))
vec_safe_push (todo, TREE_PURPOSE (t));
if (!todo->is_empty ())
{
scope = todo->last ();
todo->pop ();
}
else
{
ret = false;
break;
}
}
release_tree_vector (seen);
release_tree_vector (todo);
return ret;
}
/* Compute the chain index of a binding_entry given the HASH value of its /* Compute the chain index of a binding_entry given the HASH value of its
name and the total COUNT of chains. COUNT is assumed to be a power name and the total COUNT of chains. COUNT is assumed to be a power
of 2. */ of 2. */
...@@ -4426,15 +4382,15 @@ handle_namespace_attrs (tree ns, tree attributes) ...@@ -4426,15 +4382,15 @@ handle_namespace_attrs (tree ns, tree attributes)
} }
else if (is_attribute_p ("abi_tag", name)) else if (is_attribute_p ("abi_tag", name))
{ {
if (!DECL_NAMESPACE_ASSOCIATIONS (ns)) if (!DECL_NAME (ns))
{ {
warning (OPT_Wattributes, "ignoring %qD attribute on non-inline " warning (OPT_Wattributes, "ignoring %qD attribute on anonymous "
"namespace", name); "namespace", name);
continue; continue;
} }
if (!DECL_NAME (ns)) if (!DECL_NAMESPACE_INLINE_P (ns))
{ {
warning (OPT_Wattributes, "ignoring %qD attribute on anonymous " warning (OPT_Wattributes, "ignoring %qD attribute on non-inline "
"namespace", name); "namespace", name);
continue; continue;
} }
...@@ -4479,32 +4435,6 @@ pop_decl_namespace (void) ...@@ -4479,32 +4435,6 @@ pop_decl_namespace (void)
decl_namespace_list->pop (); decl_namespace_list->pop ();
} }
/* Return the namespace that is the common ancestor
of two given namespaces. */
static tree
namespace_ancestor_1 (tree ns1, tree ns2)
{
tree nsr;
if (is_ancestor (ns1, ns2))
nsr = ns1;
else
nsr = namespace_ancestor_1 (CP_DECL_CONTEXT (ns1), ns2);
return nsr;
}
/* Wrapper for namespace_ancestor_1. */
static tree
namespace_ancestor (tree ns1, tree ns2)
{
tree nsr;
bool subtime = timevar_cond_start (TV_NAME_LOOKUP);
nsr = namespace_ancestor_1 (ns1, ns2);
timevar_cond_stop (TV_NAME_LOOKUP, subtime);
return nsr;
}
/* Process a namespace-alias declaration. */ /* Process a namespace-alias declaration. */
void void
...@@ -5537,44 +5467,6 @@ is_local_extern (tree decl) ...@@ -5537,44 +5467,6 @@ is_local_extern (tree decl)
return false; return false;
} }
/* Add namespace to using_directives. Return NULL_TREE if nothing was
changed (i.e. there was already a directive), or the fresh
TREE_LIST otherwise. */
static tree
push_using_directive_1 (tree used)
{
tree ud = current_binding_level->using_directives;
tree iter, ancestor;
/* Check if we already have this. */
if (purpose_member (used, ud) != NULL_TREE)
return NULL_TREE;
ancestor = namespace_ancestor (current_decl_namespace (), used);
ud = current_binding_level->using_directives;
ud = tree_cons (used, ancestor, ud);
current_binding_level->using_directives = ud;
/* Recursively add all namespaces used. */
for (iter = DECL_NAMESPACE_USING (used); iter; iter = TREE_CHAIN (iter))
push_using_directive_1 (TREE_PURPOSE (iter));
return ud;
}
/* Wrapper for push_using_directive_1. */
static tree
push_using_directive (tree used)
{
tree ret;
bool subtime = timevar_cond_start (TV_NAME_LOOKUP);
ret = push_using_directive_1 (used);
timevar_cond_stop (TV_NAME_LOOKUP, subtime);
return ret;
}
/* The type TYPE is being declared. If it is a class template, or a /* The type TYPE is being declared. If it is a class template, or a
specialization of a class template, do any processing required and specialization of a class template, do any processing required and
perform error-checking. If IS_FRIEND is nonzero, this TYPE is perform error-checking. If IS_FRIEND is nonzero, this TYPE is
...@@ -6094,64 +5986,29 @@ do_pop_nested_namespace (tree ns) ...@@ -6094,64 +5986,29 @@ do_pop_nested_namespace (tree ns)
do_pop_from_top_level (); do_pop_from_top_level ();
} }
/* Insert USED into the using list of USER. Set INDIRECT_flag if this /* Add TARGET to USINGS, if it does not already exist there.
directive is not directly from the source. Also find the common We used to build the complete graph of usings at this point, from
ancestor and let our users know about the new namespace */ the POV of the source namespaces. Now we build that as we perform
the unqualified search. */
static void static void
add_using_namespace_1 (tree user, tree used, bool indirect) add_using_namespace (tree &usings, tree target)
{ {
tree t; for (tree probe = usings; probe; probe = TREE_CHAIN (probe))
/* Using oneself is a no-op. */ if (target == TREE_PURPOSE (probe))
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; 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. */ usings = tree_cons (target, NULL_TREE, usings);
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. */ /* Tell the debug system of a using directive. */
static void static void
add_using_namespace (bool namespace_level_p, tree from, tree target) emit_debug_info_using_namespace (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. */ /* Emit debugging info. */
tree context = from != global_namespace ? from : NULL_TREE; tree context = from != global_namespace ? from : NULL_TREE;
debug_hooks->imported_module_or_decl (target, NULL_TREE, context, false); debug_hooks->imported_module_or_decl (target, NULL_TREE, context, false);
}
timevar_cond_stop (TV_NAME_LOOKUP, subtime);
} }
/* Process a namespace-scope using directive. */ /* Process a namespace-scope using directive. */
...@@ -6163,7 +6020,9 @@ finish_namespace_using_directive (tree target, tree attribs) ...@@ -6163,7 +6020,9 @@ finish_namespace_using_directive (tree target, tree attribs)
if (target == error_mark_node) if (target == error_mark_node)
return; return;
add_using_namespace (true, current_namespace, add_using_namespace (DECL_NAMESPACE_USING (current_namespace),
ORIGINAL_NAMESPACE (target));
emit_debug_info_using_namespace (current_namespace,
ORIGINAL_NAMESPACE (target)); ORIGINAL_NAMESPACE (target));
if (attribs == error_mark_node) if (attribs == error_mark_node)
...@@ -6198,7 +6057,8 @@ finish_local_using_directive (tree target, tree attribs) ...@@ -6198,7 +6057,8 @@ finish_local_using_directive (tree target, tree attribs)
add_stmt (build_stmt (input_location, USING_STMT, target)); add_stmt (build_stmt (input_location, USING_STMT, target));
push_using_directive (ORIGINAL_NAMESPACE (target)); add_using_namespace (current_binding_level->using_directives,
ORIGINAL_NAMESPACE (target));
} }
/* Pushes X into the global namespace. */ /* Pushes X into the global namespace. */
...@@ -6306,20 +6166,14 @@ push_namespace (tree name, bool make_inline) ...@@ -6306,20 +6166,14 @@ push_namespace (tree name, bool make_inline)
DECL_NAME (ns) = NULL_TREE; DECL_NAME (ns) = NULL_TREE;
if (!make_inline) if (!make_inline)
add_using_namespace (true, current_namespace, ns); add_using_namespace (DECL_NAMESPACE_USING (current_namespace),
ns);
} }
else if (TREE_PUBLIC (current_namespace)) else if (TREE_PUBLIC (current_namespace))
TREE_PUBLIC (ns) = 1; TREE_PUBLIC (ns) = 1;
if (make_inline) if (make_inline)
{
DECL_NAMESPACE_INLINE_P (ns) = true; DECL_NAMESPACE_INLINE_P (ns) = true;
/* Set up namespace association. */
DECL_NAMESPACE_ASSOCIATIONS (ns)
= tree_cons (current_namespace, NULL_TREE, NULL_TREE);
/* Import the contents of the inline namespace. */
add_using_namespace (true, current_namespace, ns);
}
} }
} }
......
...@@ -325,7 +325,6 @@ extern void do_namespace_alias (tree, tree); ...@@ -325,7 +325,6 @@ extern void do_namespace_alias (tree, tree);
extern tree do_class_using_decl (tree, tree); extern tree do_class_using_decl (tree, tree);
extern void do_using_directive (tree); extern void do_using_directive (tree);
extern tree lookup_arg_dependent (tree, tree, vec<tree, va_gc> *); extern tree lookup_arg_dependent (tree, tree, vec<tree, va_gc> *);
extern bool is_associated_namespace (tree, tree);
extern tree innermost_non_namespace_value (tree); extern tree innermost_non_namespace_value (tree);
extern cxx_binding *outer_binding (tree, cxx_binding *, bool); extern cxx_binding *outer_binding (tree, cxx_binding *, bool);
extern void cp_emit_debug_info_for_using (tree, tree); extern void cp_emit_debug_info_for_using (tree, tree);
......
...@@ -5123,14 +5123,9 @@ cp_free_lang_data (tree t) ...@@ -5123,14 +5123,9 @@ cp_free_lang_data (tree t)
TREE_STATIC (t) = 0; TREE_STATIC (t) = 0;
} }
if (TREE_CODE (t) == NAMESPACE_DECL) if (TREE_CODE (t) == NAMESPACE_DECL)
{ /* We do not need the leftover chaining of namespaces from the
/* The list of users of a namespace isn't useful for the middle-end binding level. */
or debug generators. */
DECL_NAMESPACE_USERS (t) = NULL_TREE;
/* Neither do we need the leftover chaining of namespaces
from the binding level. */
DECL_CHAIN (t) = NULL_TREE; DECL_CHAIN (t) = NULL_TREE;
}
} }
/* Stub for c-common. Please keep in sync with c-decl.c. /* Stub for c-common. Please keep in sync with c-decl.c.
......
...@@ -6,6 +6,11 @@ ...@@ -6,6 +6,11 @@
2017-05-25 Nathan Sidwell <nathan@acm.org> 2017-05-25 Nathan Sidwell <nathan@acm.org>
* g++.dg/lookup/using56.C: New.
* g++.dg/lookup/using57.C: New.
* g++.dg/lookup/using58.C: New.
* g++.dg/lookup/using59.C: New.
* g++.dg/lookup/using17.C: Adjust diagnostics. * g++.dg/lookup/using17.C: Adjust diagnostics.
2017-05-25 Martin Sebor <msebor@redhat.com> 2017-05-25 Martin Sebor <msebor@redhat.com>
......
// The anticipated decl for 'log' got retained, leading to confusion */
extern double log (double) throw ();
namespace std
{
using ::log;
float log (float) throw ();
long double log (long double) throw ();
}
void Foo (double x)
{
std::log (x);
}
// Addr of function from multiple namespaces
namespace X
{
void Foo (int);
void Foo (short);
}
namespace Y
{
void Foo (float);
void Foo (double);
}
template <typename T> void Foo (T *);
using namespace X;
using namespace Y;
void (*(Baz ())) (float)
{
return Foo;
}
void (*(Bar ())) (void *)
{
return Foo;
}
void Foo (int);
void Foo (double);
namespace Y
{
void Baz (int); // { dg-message "previous declaration" }
}
void X ()
{
using ::Foo;
extern void Foo (int);
using Y::Baz;
extern void Baz (int); // { dg-error "conflicts with" }
}
namespace Y
{
extern int I; // { dg-message "previous declaration" }
}
using Y::I;
extern int I; // { dg-error "conflicts with a previous" }
extern int J;
extern int J; // { dg-message "previous declaration" }
extern char J; // { dg-error "conflicting declaration" }
2017-05-25 Nathan Sidwell <nathan@acm.org>
* libcp1plugin.cc (plugin_make_namespace_inline): Check and set
DECL_NAMESPACE_INLINE_P.
2017-05-23 Nathan Sidwell <nathan@acm.org> 2017-05-23 Nathan Sidwell <nathan@acm.org>
* libcp1plugin.cc (plugin_add_using_decl): Call * libcp1plugin.cc (plugin_add_using_decl): Call
......
...@@ -930,20 +930,10 @@ plugin_make_namespace_inline (cc1_plugin::connection *) ...@@ -930,20 +930,10 @@ plugin_make_namespace_inline (cc1_plugin::connection *)
tree parent_ns = CP_DECL_CONTEXT (inline_ns); tree parent_ns = CP_DECL_CONTEXT (inline_ns);
if (purpose_member (DECL_NAMESPACE_ASSOCIATIONS (inline_ns), if (DECL_NAMESPACE_INLINE_P (inline_ns))
parent_ns))
return 0; return 0;
pop_namespace (); DECL_NAMESPACE_INLINE_P (inline_ns) = true;
gcc_assert (current_namespace == parent_ns);
DECL_NAMESPACE_ASSOCIATIONS (inline_ns)
= tree_cons (parent_ns, 0,
DECL_NAMESPACE_ASSOCIATIONS (inline_ns));
do_using_directive (inline_ns);
push_namespace (DECL_NAME (inline_ns));
return 1; return 1;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment