Commit ea9635c7 by Martin v. Löwis Committed by Jason Merrill

decl.c (struct binding_level): New field using_directives.

	* decl.c (struct binding_level): New field using_directives.
	(push_using_decl): Not sorry anymore.
	(push_using_directive): New function.
	(lookup_tag): Use CP_DECL_CONTEXT to iterate.
	(unqualified_namespace_lookup): New function, code from ...
	(lookup_name_real): ... here.
	* decl2.c (lookup_using_namespace): Pass using list instead of
	initial scope.
	(validate_nonmember_using_decl): New function.
	(do_nonmember_using_decl): New function.
	(do_toplevel_using_decl): Use them.
	(do_local_using_decl): New function.
	(do_using_directive): Support block-level directives.
	* parse.y (simple_stmt): Support using declarations and
	directives.
	(namespace_qualifier, namespace_using_decl): New non-terminals.

From-SVN: r21089
parent 11b5139c
1998-07-12 Martin von Lwis <loewis@informatik.hu-berlin.de> 1998-07-12 Martin von Lwis <loewis@informatik.hu-berlin.de>
* decl.c (struct binding_level): New field using_directives.
(push_using_decl): Not sorry anymore.
(push_using_directive): New function.
(lookup_tag): Use CP_DECL_CONTEXT to iterate.
(unqualified_namespace_lookup): New function, code from ...
(lookup_name_real): ... here.
* decl2.c (lookup_using_namespace): Pass using list instead of
initial scope.
(validate_nonmember_using_decl): New function.
(do_nonmember_using_decl): New function.
(do_toplevel_using_decl): Use them.
(do_local_using_decl): New function.
(do_using_directive): Support block-level directives.
* parse.y (simple_stmt): Support using declarations and
directives.
(namespace_qualifier, namespace_using_decl): New non-terminals.
* xref.c (classname): New function. * xref.c (classname): New function.
(GNU_xref_hier): Change class and base parameters to tree. (GNU_xref_hier): Change class and base parameters to tree.
* decl.c (xref_baseypes): Change caller. * decl.c (xref_baseypes): Change caller.
......
...@@ -2359,7 +2359,9 @@ extern void pushdecl_nonclass_level PROTO((tree)); ...@@ -2359,7 +2359,9 @@ extern void pushdecl_nonclass_level PROTO((tree));
#endif #endif
extern tree pushdecl_namespace_level PROTO((tree)); extern tree pushdecl_namespace_level PROTO((tree));
extern tree push_using_decl PROTO((tree, tree)); extern tree push_using_decl PROTO((tree, tree));
extern tree push_using_directive PROTO((tree, tree));
extern void push_class_level_binding PROTO((tree, tree)); extern void push_class_level_binding PROTO((tree, tree));
extern tree push_using_decl PROTO((tree, tree));
extern tree implicitly_declare PROTO((tree)); extern tree implicitly_declare PROTO((tree));
extern tree lookup_label PROTO((tree)); extern tree lookup_label PROTO((tree));
extern tree shadow_label PROTO((tree)); extern tree shadow_label PROTO((tree));
...@@ -2489,6 +2491,7 @@ extern void push_decl_namespace PROTO((tree)); ...@@ -2489,6 +2491,7 @@ extern void push_decl_namespace PROTO((tree));
extern void pop_decl_namespace PROTO((void)); extern void pop_decl_namespace PROTO((void));
extern void do_namespace_alias PROTO((tree, tree)); extern void do_namespace_alias PROTO((tree, tree));
extern void do_toplevel_using_decl PROTO((tree)); extern void do_toplevel_using_decl PROTO((tree));
extern void do_local_using_decl PROTO((tree));
extern tree do_class_using_decl PROTO((tree)); extern tree do_class_using_decl PROTO((tree));
extern void do_using_directive PROTO((tree)); extern void do_using_directive PROTO((tree));
extern void check_default_args PROTO((tree)); extern void check_default_args PROTO((tree));
......
...@@ -613,6 +613,10 @@ struct binding_level ...@@ -613,6 +613,10 @@ struct binding_level
/* A list of USING_DECL nodes. */ /* A list of USING_DECL nodes. */
tree usings; tree usings;
/* A list of used namespaces. PURPOSE is the namespace,
VALUE the common ancestor with this binding_level's namespace. */
tree using_directives;
/* For each level, a list of shadowed outer-level local definitions /* For each level, a list of shadowed outer-level local definitions
to be restored when this level is popped. to be restored when this level is popped.
Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and
...@@ -3822,12 +3826,6 @@ push_using_decl (scope, name) ...@@ -3822,12 +3826,6 @@ push_using_decl (scope, name)
{ {
tree decl; tree decl;
if (!toplevel_bindings_p ())
{
sorry ("using declaration inside function");
return NULL_TREE;
}
my_friendly_assert (TREE_CODE (scope) == NAMESPACE_DECL, 383); my_friendly_assert (TREE_CODE (scope) == NAMESPACE_DECL, 383);
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 384); my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 384);
for (decl = current_binding_level->usings; decl; decl = TREE_CHAIN (decl)) for (decl = current_binding_level->usings; decl; decl = TREE_CHAIN (decl))
...@@ -3842,6 +3840,26 @@ push_using_decl (scope, name) ...@@ -3842,6 +3840,26 @@ push_using_decl (scope, name)
return decl; return decl;
} }
/* 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. */
tree
push_using_directive (used, ancestor)
tree used;
tree ancestor;
{
tree ud = current_binding_level->using_directives;
/* Check if we already have this. */
if (purpose_member (used, ud) != NULL_TREE)
return NULL_TREE;
ud = perm_tree_cons (used, ancestor, ud);
current_binding_level->using_directives = ud;
return ud;
}
/* DECL is a FUNCTION_DECL which may have other definitions already in /* DECL is a FUNCTION_DECL which may have other definitions already in
place. We get around this by making the value of the identifier point place. We get around this by making the value of the identifier point
to a list of all the things that want to be referenced by that name. It to a list of all the things that want to be referenced by that name. It
...@@ -4732,6 +4750,62 @@ select_decl (binding, prefer_type, namespaces_only) ...@@ -4732,6 +4750,62 @@ select_decl (binding, prefer_type, namespaces_only)
return val; return val;
} }
/* Unscoped lookup of a global, iterate over namespaces, considering
using namespace statements. */
static tree
unqualified_namespace_lookup (name, prefer_type, namespaces_only)
tree name;
int prefer_type;
int namespaces_only;
{
struct tree_binding _binding;
tree b = binding_init (&_binding);
tree initial = current_decl_namespace();
tree scope = initial;
tree siter;
struct binding_level *level;
tree val = NULL_TREE;
while (!val)
{
val = binding_for_name (name, scope);
/* Initialize binding for this context. */
BINDING_VALUE (b) = BINDING_VALUE (val);
BINDING_TYPE (b) = BINDING_TYPE (val);
/* Add all _DECLs seen through local using-directives. */
for (level = current_binding_level;
!level->namespace_p;
level = level->level_chain)
if (!lookup_using_namespace (name, b, level->using_directives, scope))
/* Give up because of error. */
return NULL_TREE;
/* Add all _DECLs seen through global using-directives. */
/* XXX local and global using lists should work equally. */
siter = initial;
while (1)
{
if (!lookup_using_namespace (name, b, DECL_NAMESPACE_USING (siter),
scope))
/* Give up because of error. */
return NULL_TREE;
if (siter == scope) break;
siter = CP_DECL_CONTEXT (siter);
}
val = select_decl (b, prefer_type, namespaces_only);
if (scope == global_namespace)
break;
scope = DECL_CONTEXT (scope);
if (scope == NULL_TREE)
scope = global_namespace;
}
return val;
}
/* Look up NAME in the current binding level and its superiors in the /* Look up NAME in the current binding level and its superiors in the
namespace of variables, functions and typedefs. Return a ..._DECL namespace of variables, functions and typedefs. Return a ..._DECL
node of some kind representing its definition if there is only one node of some kind representing its definition if there is only one
...@@ -4903,35 +4977,7 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only) ...@@ -4903,35 +4977,7 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
else if (classval) else if (classval)
val = classval; val = classval;
else else
{ val = unqualified_namespace_lookup (name, prefer_type, namespaces_only);
/* Unscoped lookup of a global, iterate over namespaces,
considering using namespace statements. */
struct tree_binding _binding;
tree b = binding_init (&_binding);
tree initial = current_decl_namespace();
tree scope = initial;
val = NULL_TREE;
while (!val)
{
val = binding_for_name (name, scope);
/* Initialize binding for this context. */
BINDING_VALUE (b) = BINDING_VALUE (val);
BINDING_TYPE (b) = BINDING_TYPE (val);
/* Add all _DECLs seen through using-directives. */
if (!lookup_using_namespace (name, b, initial, scope))
{
/* Give up because of error. */
val = NULL_TREE;
break;
}
val = select_decl (b, prefer_type, namespaces_only);
if (scope == global_namespace)
break;
scope = DECL_CONTEXT (scope);
if (scope == NULL_TREE)
scope = global_namespace;
}
}
done: done:
if (val) if (val)
......
...@@ -3940,32 +3940,24 @@ ambiguous_decl (name, old, new) ...@@ -3940,32 +3940,24 @@ ambiguous_decl (name, old, new)
} }
/* Add the bindings of name in used namespaces to val. /* Add the bindings of name in used namespaces to val.
The using list is defined by current, and the lookup goes to scope. The using list is defined by usings, and the lookup goes to scope.
Returns zero on errors. */ Returns zero on errors. */
int int
lookup_using_namespace (name, val, current, scope) lookup_using_namespace (name, val, usings, scope)
tree name, val, current, scope; tree name, val, usings, scope;
{ {
tree iter; tree iter;
tree val1; tree val1;
/* Iterate over all namespaces from current to scope. */ /* Iterate over all used namespaces in current, searching for using
while (val != error_mark_node) directives of scope. */
{ for (iter = usings; iter; iter = TREE_CHAIN (iter))
/* Iterate over all used namespaces in current, searching for
using directives of scope. */
for (iter = DECL_NAMESPACE_USING (current);
iter; iter = TREE_CHAIN (iter))
if (TREE_VALUE (iter) == scope) if (TREE_VALUE (iter) == scope)
{ {
val1 = binding_for_name (name, TREE_PURPOSE (iter)); val1 = binding_for_name (name, TREE_PURPOSE (iter));
/* Resolve ambiguities. */ /* Resolve ambiguities. */
val = ambiguous_decl (name, val, val1); val = ambiguous_decl (name, val, val1);
} }
if (current == scope)
break;
current = CP_DECL_CONTEXT (current);
}
return val != error_mark_node; return val != error_mark_node;
} }
...@@ -4405,39 +4397,49 @@ do_namespace_alias (alias, namespace) ...@@ -4405,39 +4397,49 @@ do_namespace_alias (alias, namespace)
} }
} }
/* Process a using-declaration not appearing in class or local scope. */ /* Check a non-member using-declaration. Return the name and scope
being used, and the USING_DECL, or NULL_TREE on failure. */
void static tree
do_toplevel_using_decl (decl) validate_nonmember_using_decl (decl, scope, name)
tree decl; tree decl;
tree *scope;
tree *name;
{ {
tree scope, name, binding, decls, newval, newtype;
struct tree_binding _decls;
if (TREE_CODE (decl) == SCOPE_REF if (TREE_CODE (decl) == SCOPE_REF
&& TREE_OPERAND (decl, 0) == std_node) && TREE_OPERAND (decl, 0) == std_node)
return; return NULL_TREE;
if (TREE_CODE (decl) == SCOPE_REF) if (TREE_CODE (decl) == SCOPE_REF)
{ {
scope = TREE_OPERAND (decl, 0); *scope = TREE_OPERAND (decl, 0);
name = TREE_OPERAND (decl, 1); *name = TREE_OPERAND (decl, 1);
} }
else if (TREE_CODE (decl) == IDENTIFIER_NODE else if (TREE_CODE (decl) == IDENTIFIER_NODE
|| TREE_CODE (decl) == TYPE_DECL) || TREE_CODE (decl) == TYPE_DECL)
{ {
scope = global_namespace; *scope = global_namespace;
name = decl; *name = decl;
} }
else else
my_friendly_abort (382); my_friendly_abort (382);
if (TREE_CODE_CLASS (TREE_CODE (name)) == 'd') if (TREE_CODE_CLASS (TREE_CODE (*name)) == 'd')
name = DECL_NAME (name); *name = DECL_NAME (*name);
/* Make a USING_DECL. */ /* Make a USING_DECL. */
decl = push_using_decl (scope, name); return push_using_decl (*scope, *name);
if (!decl) }
return;
binding = binding_for_name (name, current_namespace); /* Process local and global using-declarations. */
static void
do_nonmember_using_decl (scope, name, oldval, oldtype, newval, newtype)
tree scope, name;
tree oldval, oldtype;
tree *newval, *newtype;
{
tree decls;
struct tree_binding _decls;
*newval = *newtype = NULL_TREE;
decls = binding_init (&_decls); decls = binding_init (&_decls);
if (!qualified_lookup_using_namespace (name, scope, decls)) if (!qualified_lookup_using_namespace (name, scope, decls))
/* Lookup error */ /* Lookup error */
...@@ -4448,14 +4450,12 @@ do_toplevel_using_decl (decl) ...@@ -4448,14 +4450,12 @@ do_toplevel_using_decl (decl)
cp_error ("`%D' not declared", name); cp_error ("`%D' not declared", name);
return; return;
} }
newval = newtype = NULL_TREE;
/* Check for using functions. */ /* Check for using functions. */
if (BINDING_VALUE (decls) && is_overloaded_fn (BINDING_VALUE (decls))) if (BINDING_VALUE (decls) && is_overloaded_fn (BINDING_VALUE (decls)))
{ {
tree oldval = BINDING_VALUE (binding);
tree tmp, tmp1; tree tmp, tmp1;
newval = oldval; *newval = oldval;
for (tmp = BINDING_VALUE (decls); tmp; tmp = OVL_NEXT (tmp)) for (tmp = BINDING_VALUE (decls); tmp; tmp = OVL_NEXT (tmp))
{ {
...@@ -4473,27 +4473,48 @@ do_toplevel_using_decl (decl) ...@@ -4473,27 +4473,48 @@ do_toplevel_using_decl (decl)
if (tmp1) if (tmp1)
continue; continue;
newval = build_overload (OVL_CURRENT (tmp), newval); *newval = build_overload (OVL_CURRENT (tmp), *newval);
if (TREE_CODE (newval) != OVERLOAD) if (TREE_CODE (*newval) != OVERLOAD)
newval = ovl_cons (newval, NULL_TREE); *newval = ovl_cons (*newval, NULL_TREE);
OVL_USED (newval) = 1; OVL_USED (*newval) = 1;
} }
} }
else else
{ {
tree oldval = BINDING_VALUE (binding); *newval = BINDING_VALUE (decls);
newval = BINDING_VALUE (decls); if (oldval && oldval != *newval && !duplicate_decls (*newval, oldval))
if (oldval && oldval != newval && !duplicate_decls (newval, oldval)) *newval = oldval;
newval = oldval;
} }
newtype = BINDING_TYPE (decls); *newtype = BINDING_TYPE (decls);
if (BINDING_TYPE (binding) && newtype && BINDING_TYPE (binding) != newtype) if (oldtype && *newtype && oldtype != *newtype)
{ {
cp_error ("using directive `%D' introduced ambiguous type `%T'", cp_error ("using directive `%D' introduced ambiguous type `%T'",
name, BINDING_TYPE (decls)); name, oldtype);
return; return;
} }
}
/* Process a using-declaration not appearing in class or local scope. */
void
do_toplevel_using_decl (decl)
tree decl;
{
tree scope, name, binding;
tree oldval, oldtype, newval, newtype;
decl = validate_nonmember_using_decl (decl, &scope, &name);
if (decl == NULL_TREE)
return;
binding = binding_for_name (name, current_namespace);
oldval = BINDING_VALUE (binding);
oldtype = BINDING_TYPE (binding);
do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
/* Copy declarations found. */ /* Copy declarations found. */
if (newval) if (newval)
BINDING_VALUE (binding) = newval; BINDING_VALUE (binding) = newval;
...@@ -4502,6 +4523,29 @@ do_toplevel_using_decl (decl) ...@@ -4502,6 +4523,29 @@ do_toplevel_using_decl (decl)
return; return;
} }
void
do_local_using_decl (decl)
tree decl;
{
tree scope, name;
tree oldval, oldtype, newval, newtype;
decl = validate_nonmember_using_decl (decl, &scope, &name);
if (decl == NULL_TREE)
return;
/* XXX nested values */
oldval = IDENTIFIER_LOCAL_VALUE (name);
/* XXX get local type */
oldtype = NULL_TREE;
do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
if (newval)
/* XXX update bindings */
IDENTIFIER_LOCAL_VALUE (name) = newval;
/* XXX type */
}
tree tree
do_class_using_decl (decl) do_class_using_decl (decl)
tree decl; tree decl;
...@@ -4534,11 +4578,6 @@ do_using_directive (namespace) ...@@ -4534,11 +4578,6 @@ do_using_directive (namespace)
{ {
if (namespace == std_node) if (namespace == std_node)
return; return;
if (!toplevel_bindings_p ())
{
sorry ("using directives inside functions");
return;
}
/* using namespace A::B::C; */ /* using namespace A::B::C; */
if (TREE_CODE (namespace) == SCOPE_REF) if (TREE_CODE (namespace) == SCOPE_REF)
namespace = TREE_OPERAND (namespace, 1); namespace = TREE_OPERAND (namespace, 1);
...@@ -4554,6 +4593,11 @@ do_using_directive (namespace) ...@@ -4554,6 +4593,11 @@ do_using_directive (namespace)
return; return;
} }
namespace = ORIGINAL_NAMESPACE (namespace); namespace = ORIGINAL_NAMESPACE (namespace);
if (!toplevel_bindings_p ())
push_using_directive
(namespace, namespace_ancestor (current_decl_namespace(),
current_namespace));
else
/* direct usage */ /* direct usage */
add_using_namespace (current_namespace, namespace, 0); add_using_namespace (current_namespace, namespace, 0);
} }
......
...@@ -223,6 +223,7 @@ empty_parms () ...@@ -223,6 +223,7 @@ empty_parms ()
%type <ttype> overqualified_id notype_qualified_id any_id %type <ttype> overqualified_id notype_qualified_id any_id
%type <ttype> complex_direct_notype_declarator functional_cast %type <ttype> complex_direct_notype_declarator functional_cast
%type <ttype> complex_parmlist parms_comma %type <ttype> complex_parmlist parms_comma
%type <ttype> namespace_qualifier namespace_using_decl
%type <ftype> type_id new_type_id typed_typespecs typespec typed_declspecs %type <ftype> type_id new_type_id typed_typespecs typespec typed_declspecs
%type <ftype> typed_declspecs1 type_specifier_seq nonempty_cv_qualifiers %type <ftype> typed_declspecs1 type_specifier_seq nonempty_cv_qualifiers
...@@ -438,6 +439,29 @@ using_decl: ...@@ -438,6 +439,29 @@ using_decl:
{ $$ = $3; } { $$ = $3; }
; ;
namespace_using_decl:
USING namespace_qualifier identifier
{ $$ = build_parse_node (SCOPE_REF, $2, $3); }
| USING global_scope identifier
{ $$ = build_parse_node (SCOPE_REF, global_namespace, $3); }
| USING global_scope namespace_qualifier identifier
{ $$ = build_parse_node (SCOPE_REF, $3, $4); }
;
namespace_qualifier:
NSNAME SCOPE
{
if (TREE_CODE ($$) == IDENTIFIER_NODE)
$$ = lastiddecl;
got_scope = $$;
}
| namespace_qualifier NSNAME SCOPE
{
if (TREE_CODE ($$) == IDENTIFIER_NODE)
$$ = lastiddecl;
got_scope = $$;
}
any_id: any_id:
unqualified_id unqualified_id
| qualified_id | qualified_id
...@@ -3244,6 +3268,14 @@ simple_stmt: ...@@ -3244,6 +3268,14 @@ simple_stmt:
| ';' | ';'
{ finish_stmt (); } { finish_stmt (); }
| try_block | try_block
| USING NAMESPACE any_id ';'
{
if (TREE_CODE ($3) == IDENTIFIER_NODE && lastiddecl)
$3 = lastiddecl;
do_using_directive ($3);
}
| namespace_using_decl
{ do_local_using_decl ($1); }
; ;
function_try_block: function_try_block:
......
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