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
This commit is contained in:
parent
11b5139c46
commit
ea9635c739
@ -1,5 +1,22 @@
|
||||
1998-07-12 Martin von Löwis <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.
|
||||
(GNU_xref_hier): Change class and base parameters to tree.
|
||||
* decl.c (xref_baseypes): Change caller.
|
||||
|
@ -2359,7 +2359,9 @@ extern void pushdecl_nonclass_level PROTO((tree));
|
||||
#endif
|
||||
extern tree pushdecl_namespace_level PROTO((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 tree push_using_decl PROTO((tree, tree));
|
||||
extern tree implicitly_declare PROTO((tree));
|
||||
extern tree lookup_label PROTO((tree));
|
||||
extern tree shadow_label PROTO((tree));
|
||||
@ -2489,6 +2491,7 @@ extern void push_decl_namespace PROTO((tree));
|
||||
extern void pop_decl_namespace PROTO((void));
|
||||
extern void do_namespace_alias PROTO((tree, 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 void do_using_directive PROTO((tree));
|
||||
extern void check_default_args PROTO((tree));
|
||||
|
116
gcc/cp/decl.c
116
gcc/cp/decl.c
@ -613,6 +613,10 @@ struct binding_level
|
||||
/* A list of USING_DECL nodes. */
|
||||
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
|
||||
to be restored when this level is popped.
|
||||
Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and
|
||||
@ -3822,12 +3826,6 @@ push_using_decl (scope, name)
|
||||
{
|
||||
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 (name) == IDENTIFIER_NODE, 384);
|
||||
for (decl = current_binding_level->usings; decl; decl = TREE_CHAIN (decl))
|
||||
@ -3842,6 +3840,26 @@ push_using_decl (scope, name)
|
||||
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
|
||||
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
|
||||
@ -4732,6 +4750,62 @@ select_decl (binding, prefer_type, namespaces_only)
|
||||
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
|
||||
namespace of variables, functions and typedefs. Return a ..._DECL
|
||||
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)
|
||||
else if (classval)
|
||||
val = classval;
|
||||
else
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
val = unqualified_namespace_lookup (name, prefer_type, namespaces_only);
|
||||
|
||||
done:
|
||||
if (val)
|
||||
|
162
gcc/cp/decl2.c
162
gcc/cp/decl2.c
@ -3940,32 +3940,24 @@ ambiguous_decl (name, old, new)
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
|
||||
int
|
||||
lookup_using_namespace (name, val, current, scope)
|
||||
tree name, val, current, scope;
|
||||
lookup_using_namespace (name, val, usings, scope)
|
||||
tree name, val, usings, scope;
|
||||
{
|
||||
tree iter;
|
||||
tree val1;
|
||||
/* Iterate over all namespaces from current to scope. */
|
||||
while (val != error_mark_node)
|
||||
{
|
||||
/* 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)
|
||||
{
|
||||
val1 = binding_for_name (name, TREE_PURPOSE (iter));
|
||||
/* Resolve ambiguities. */
|
||||
val = ambiguous_decl (name, val, val1);
|
||||
}
|
||||
if (current == scope)
|
||||
break;
|
||||
current = CP_DECL_CONTEXT (current);
|
||||
}
|
||||
/* Iterate over all used namespaces in current, searching for using
|
||||
directives of scope. */
|
||||
for (iter = usings; iter; iter = TREE_CHAIN (iter))
|
||||
if (TREE_VALUE (iter) == scope)
|
||||
{
|
||||
val1 = binding_for_name (name, TREE_PURPOSE (iter));
|
||||
/* Resolve ambiguities. */
|
||||
val = ambiguous_decl (name, val, val1);
|
||||
}
|
||||
return val != error_mark_node;
|
||||
}
|
||||
|
||||
@ -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
|
||||
do_toplevel_using_decl (decl)
|
||||
static tree
|
||||
validate_nonmember_using_decl (decl, scope, name)
|
||||
tree decl;
|
||||
tree *scope;
|
||||
tree *name;
|
||||
{
|
||||
tree scope, name, binding, decls, newval, newtype;
|
||||
struct tree_binding _decls;
|
||||
|
||||
if (TREE_CODE (decl) == SCOPE_REF
|
||||
&& TREE_OPERAND (decl, 0) == std_node)
|
||||
return;
|
||||
return NULL_TREE;
|
||||
if (TREE_CODE (decl) == SCOPE_REF)
|
||||
{
|
||||
scope = TREE_OPERAND (decl, 0);
|
||||
name = TREE_OPERAND (decl, 1);
|
||||
*scope = TREE_OPERAND (decl, 0);
|
||||
*name = TREE_OPERAND (decl, 1);
|
||||
}
|
||||
else if (TREE_CODE (decl) == IDENTIFIER_NODE
|
||||
|| TREE_CODE (decl) == TYPE_DECL)
|
||||
{
|
||||
scope = global_namespace;
|
||||
name = decl;
|
||||
*scope = global_namespace;
|
||||
*name = decl;
|
||||
}
|
||||
else
|
||||
my_friendly_abort (382);
|
||||
if (TREE_CODE_CLASS (TREE_CODE (name)) == 'd')
|
||||
name = DECL_NAME (name);
|
||||
if (TREE_CODE_CLASS (TREE_CODE (*name)) == 'd')
|
||||
*name = DECL_NAME (*name);
|
||||
/* Make a USING_DECL. */
|
||||
decl = push_using_decl (scope, name);
|
||||
if (!decl)
|
||||
return;
|
||||
|
||||
binding = binding_for_name (name, current_namespace);
|
||||
return push_using_decl (*scope, *name);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
if (!qualified_lookup_using_namespace (name, scope, decls))
|
||||
/* Lookup error */
|
||||
@ -4448,14 +4450,12 @@ do_toplevel_using_decl (decl)
|
||||
cp_error ("`%D' not declared", name);
|
||||
return;
|
||||
}
|
||||
newval = newtype = NULL_TREE;
|
||||
|
||||
/* Check for using functions. */
|
||||
if (BINDING_VALUE (decls) && is_overloaded_fn (BINDING_VALUE (decls)))
|
||||
{
|
||||
tree oldval = BINDING_VALUE (binding);
|
||||
tree tmp, tmp1;
|
||||
newval = oldval;
|
||||
*newval = oldval;
|
||||
for (tmp = BINDING_VALUE (decls); tmp; tmp = OVL_NEXT (tmp))
|
||||
{
|
||||
|
||||
@ -4473,27 +4473,48 @@ do_toplevel_using_decl (decl)
|
||||
if (tmp1)
|
||||
continue;
|
||||
|
||||
newval = build_overload (OVL_CURRENT (tmp), newval);
|
||||
if (TREE_CODE (newval) != OVERLOAD)
|
||||
newval = ovl_cons (newval, NULL_TREE);
|
||||
OVL_USED (newval) = 1;
|
||||
*newval = build_overload (OVL_CURRENT (tmp), *newval);
|
||||
if (TREE_CODE (*newval) != OVERLOAD)
|
||||
*newval = ovl_cons (*newval, NULL_TREE);
|
||||
OVL_USED (*newval) = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tree oldval = BINDING_VALUE (binding);
|
||||
newval = BINDING_VALUE (decls);
|
||||
if (oldval && oldval != newval && !duplicate_decls (newval, oldval))
|
||||
newval = oldval;
|
||||
*newval = BINDING_VALUE (decls);
|
||||
if (oldval && oldval != *newval && !duplicate_decls (*newval, oldval))
|
||||
*newval = oldval;
|
||||
}
|
||||
|
||||
newtype = BINDING_TYPE (decls);
|
||||
if (BINDING_TYPE (binding) && newtype && BINDING_TYPE (binding) != newtype)
|
||||
*newtype = BINDING_TYPE (decls);
|
||||
if (oldtype && *newtype && oldtype != *newtype)
|
||||
{
|
||||
cp_error ("using directive `%D' introduced ambiguous type `%T'",
|
||||
name, BINDING_TYPE (decls));
|
||||
name, oldtype);
|
||||
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. */
|
||||
if (newval)
|
||||
BINDING_VALUE (binding) = newval;
|
||||
@ -4502,6 +4523,29 @@ do_toplevel_using_decl (decl)
|
||||
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
|
||||
do_class_using_decl (decl)
|
||||
tree decl;
|
||||
@ -4534,11 +4578,6 @@ do_using_directive (namespace)
|
||||
{
|
||||
if (namespace == std_node)
|
||||
return;
|
||||
if (!toplevel_bindings_p ())
|
||||
{
|
||||
sorry ("using directives inside functions");
|
||||
return;
|
||||
}
|
||||
/* using namespace A::B::C; */
|
||||
if (TREE_CODE (namespace) == SCOPE_REF)
|
||||
namespace = TREE_OPERAND (namespace, 1);
|
||||
@ -4554,8 +4593,13 @@ do_using_directive (namespace)
|
||||
return;
|
||||
}
|
||||
namespace = ORIGINAL_NAMESPACE (namespace);
|
||||
/* direct usage */
|
||||
add_using_namespace (current_namespace, namespace, 0);
|
||||
if (!toplevel_bindings_p ())
|
||||
push_using_directive
|
||||
(namespace, namespace_ancestor (current_decl_namespace(),
|
||||
current_namespace));
|
||||
else
|
||||
/* direct usage */
|
||||
add_using_namespace (current_namespace, namespace, 0);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -222,7 +222,8 @@ empty_parms ()
|
||||
%type <ttype> template_id do_id object_template_id notype_template_declarator
|
||||
%type <ttype> overqualified_id notype_qualified_id any_id
|
||||
%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> typed_declspecs1 type_specifier_seq nonempty_cv_qualifiers
|
||||
@ -438,6 +439,29 @@ using_decl:
|
||||
{ $$ = $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:
|
||||
unqualified_id
|
||||
| qualified_id
|
||||
@ -3244,6 +3268,14 @@ simple_stmt:
|
||||
| ';'
|
||||
{ finish_stmt (); }
|
||||
| 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:
|
||||
|
Loading…
Reference in New Issue
Block a user