This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: Namespace aliases
> This seems wrong; a namespace alias is not automatically in the same scope
> as the namespace it refers to.
Oops, right.
> Also, the if (alias) ns = alias; structure is awkward. This should use a
> macro or a function
Ok, it is ORIGINAL_NAMESPACE, then.
Martin
1998-06-02 Martin v. Loewis <loewis@informatik.hu-berlin.de>
* cp-tree.h (DECL_NAMESPACE_ALIAS, ORIGINAL_NAMESPACE): Declare.
* decl.c (lookup_name_real): Add namespaces_only parameter.
If set, return only NAMESPACE_DECLs.
(select_decl): Likewise.
(identifier_type_value): Give additional parameter.
(lookup_name_nonclass): Likewise.
(lookup_name): Likewise.
(find_binding): Skip namespace aliases.
(binding_for_name): Likewise.
(push_namespace): Check for namespace aliases.
(lookup_name_namespace_only): New function.
(begin_only_namespace_names, end_only_namespace_names): New functions.
* decl2.c (set_decl_namespace): Skip namespace aliases.
(do_using_directive): Likewise.
(do_namespace_alias): Produce namespace aliases, fix alias redeclaration.
* error.c (dump_decl): Support SCOPE_REF.
* parse.y (extdef): Wrap lookup with namespace_only for namespace
aliases and using declarations.
Index: cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.78
diff -c -p -r1.78 cp-tree.h
*** cp-tree.h 1998/06/01 18:25:26 1.78
--- cp-tree.h 1998/06/04 20:07:58
*************** struct lang_decl
*** 1205,1210 ****
--- 1205,1216 ----
of a namespace, to record the transitive closure of using namespace. */
#define DECL_NAMESPACE_USERS(NODE) DECL_INITIAL (NODE)
+ /* In a NAMESPACE_DECL, points to the original namespace if this is
+ a namespace alias. */
+ #define DECL_NAMESPACE_ALIAS(NODE) DECL_ABSTRACT_ORIGIN (NODE)
+ #define ORIGINAL_NAMESPACE(NODE) \
+ (DECL_NAMESPACE_ALIAS (NODE) ? DECL_NAMESPACE_ALIAS (NODE) : (NODE))
+
/* In a TREE_LIST concatenating using directives, indicate indirekt
directives */
#define TREE_INDIRECT_USING(NODE) ((NODE)->common.lang_flag_0)
*************** extern tree lookup_name_nonclass PROTO(
*** 2354,2359 ****
--- 2360,2368 ----
extern tree lookup_function_nonclass PROTO((tree, tree));
extern tree lookup_name PROTO((tree, int));
extern tree lookup_name_current_level PROTO((tree));
+ extern tree lookup_name_namespace_only PROTO((tree));
+ extern void begin_only_namespace_names PROTO((void));
+ extern void end_only_namespace_names PROTO((void));
extern int lookup_using_namespace PROTO((tree,tree,tree,tree));
extern int qualified_lookup_using_namespace PROTO((tree,tree,tree));
extern tree auto_function PROTO((tree, tree, enum built_in_function));
Index: decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.130
diff -c -p -r1.130 decl.c
*** decl.c 1998/06/01 18:25:28 1.130
--- decl.c 1998/06/04 20:08:03
*************** static tree store_bindings PROTO((tree,
*** 157,163 ****
static tree lookup_tag_reverse PROTO((tree, tree));
static tree obscure_complex_init PROTO((tree, tree));
static tree maybe_build_cleanup_1 PROTO((tree, tree));
! static tree lookup_name_real PROTO((tree, int, int));
static void warn_extern_redeclared_static PROTO((tree, tree));
static void grok_reference_init PROTO((tree, tree, tree));
static tree grokfndecl PROTO((tree, tree, tree, tree, int,
--- 157,163 ----
static tree lookup_tag_reverse PROTO((tree, tree));
static tree obscure_complex_init PROTO((tree, tree));
static tree maybe_build_cleanup_1 PROTO((tree, tree));
! static tree lookup_name_real PROTO((tree, int, int, int));
static void warn_extern_redeclared_static PROTO((tree, tree));
static void grok_reference_init PROTO((tree, tree, tree));
static tree grokfndecl PROTO((tree, tree, tree, tree, int,
*************** tree vtbl_type_node;
*** 331,336 ****
--- 331,339 ----
tree std_node;
int in_std = 0;
+ /* Expect only namespace names now. */
+ static int only_namespace_names;
+
/* In a destructor, the point at which all derived class destroying
has been done, just before any base class destroying will be done. */
*************** find_binding (name, scope)
*** 1646,1651 ****
--- 1649,1657 ----
tree scope;
{
tree iter, prev = NULL_TREE;
+
+ scope = ORIGINAL_NAMESPACE (scope);
+
for (iter = IDENTIFIER_NAMESPACE_BINDINGS (name); iter;
iter = TREE_CHAIN (iter))
{
*************** binding_for_name (name, scope)
*** 1678,1683 ****
--- 1684,1692 ----
{
tree b = IDENTIFIER_NAMESPACE_BINDINGS (name);
tree result;
+
+ scope = ORIGINAL_NAMESPACE (scope);
+
if (b && TREE_CODE (b) != CPLUS_BINDING)
{
/* Get rid of optimization for global scope. */
*************** push_namespace (name)
*** 1783,1789 ****
/* Check whether this is an extended namespace definition. */
d = IDENTIFIER_NAMESPACE_VALUE (name);
if (d != NULL_TREE && TREE_CODE (d) == NAMESPACE_DECL)
! need_new = 0;
}
if (need_new)
--- 1792,1806 ----
/* Check whether this is an extended namespace definition. */
d = IDENTIFIER_NAMESPACE_VALUE (name);
if (d != NULL_TREE && TREE_CODE (d) == NAMESPACE_DECL)
! {
! need_new = 0;
! if (DECL_NAMESPACE_ALIAS (d))
! {
! cp_error ("namespace alias `%D' not allowed here, assuming `%D'",
! d, DECL_NAMESPACE_ALIAS (d));
! d = DECL_NAMESPACE_ALIAS (d);
! }
! }
}
if (need_new)
*************** identifier_type_value (id)
*** 2145,2151 ****
return REAL_IDENTIFIER_TYPE_VALUE (id);
/* Have to search for it. It must be on the global level, now.
Ask lookup_name not to return non-types. */
! id = lookup_name_real (id, 2, 1);
if (id)
return TREE_TYPE (id);
return NULL_TREE;
--- 2162,2168 ----
return REAL_IDENTIFIER_TYPE_VALUE (id);
/* Have to search for it. It must be on the global level, now.
Ask lookup_name not to return non-types. */
! id = lookup_name_real (id, 2, 1, 0);
if (id)
return TREE_TYPE (id);
return NULL_TREE;
*************** make_typename_type (context, name)
*** 4680,4691 ****
/* Select the right _DECL from multiple choices. */
static tree
! select_decl (binding, prefer_type)
tree binding;
int prefer_type;
{
tree val;
val = BINDING_VALUE (binding);
/* If we could have a type and
we have nothing or we need a type and have none. */
if (BINDING_TYPE (binding)
--- 4697,4716 ----
/* Select the right _DECL from multiple choices. */
static tree
! select_decl (binding, prefer_type, namespaces_only)
tree binding;
int prefer_type;
{
tree val;
val = BINDING_VALUE (binding);
+ if (namespaces_only)
+ {
+ /* We are not interested in types. */
+ if (val && TREE_CODE (val) == NAMESPACE_DECL)
+ return val;
+ return NULL_TREE;
+ }
+
/* If we could have a type and
we have nothing or we need a type and have none. */
if (BINDING_TYPE (binding)
*************** select_decl (binding, prefer_type)
*** 4713,4727 ****
using IDENTIFIER_CLASS_VALUE. */
static tree
! lookup_name_real (name, prefer_type, nonclass)
tree name;
! int prefer_type, nonclass;
{
register tree val;
int yylex = 0;
tree from_obj = NULL_TREE;
tree locval, classval;
if (prefer_type == -2)
{
extern int looking_for_typename;
--- 4738,4756 ----
using IDENTIFIER_CLASS_VALUE. */
static tree
! lookup_name_real (name, prefer_type, nonclass, namespaces_only)
tree name;
! int prefer_type, nonclass, namespaces_only;
{
register tree val;
int yylex = 0;
tree from_obj = NULL_TREE;
tree locval, classval;
+ /* Hack: copy flag set by parser, if set. */
+ if (only_namespace_names)
+ namespaces_only = 1;
+
if (prefer_type == -2)
{
extern int looking_for_typename;
*************** lookup_name_real (name, prefer_type, non
*** 4756,4762 ****
val = binding_init (&b);
if (!qualified_lookup_using_namespace (name, type, val))
return NULL_TREE;
! val = select_decl (val, prefer_type);
}
else if (! IS_AGGR_TYPE (type)
|| TREE_CODE (type) == TEMPLATE_TYPE_PARM
--- 4785,4791 ----
val = binding_init (&b);
if (!qualified_lookup_using_namespace (name, type, val))
return NULL_TREE;
! val = select_decl (val, prefer_type, namespaces_only);
}
else if (! IS_AGGR_TYPE (type)
|| TREE_CODE (type) == TEMPLATE_TYPE_PARM
*************** lookup_name_real (name, prefer_type, non
*** 4800,4806 ****
locval = classval = NULL_TREE;
! if (!current_binding_level->namespace_p
&& IDENTIFIER_LOCAL_VALUE (name)
/* Kludge to avoid infinite recursion with identifier_type_value. */
&& (prefer_type <= 0
--- 4829,4835 ----
locval = classval = NULL_TREE;
! if (!namespaces_only && !current_binding_level->namespace_p
&& IDENTIFIER_LOCAL_VALUE (name)
/* Kludge to avoid infinite recursion with identifier_type_value. */
&& (prefer_type <= 0
*************** lookup_name_real (name, prefer_type, non
*** 4885,4891 ****
val = NULL_TREE;
break;
}
! val = select_decl (b, prefer_type);
if (scope == global_namespace)
break;
scope = DECL_CONTEXT (scope);
--- 4914,4920 ----
val = NULL_TREE;
break;
}
! val = select_decl (b, prefer_type, namespaces_only);
if (scope == global_namespace)
break;
scope = DECL_CONTEXT (scope);
*************** tree
*** 4932,4938 ****
lookup_name_nonclass (name)
tree name;
{
! return lookup_name_real (name, 0, 1);
}
tree
--- 4961,4967 ----
lookup_name_nonclass (name)
tree name;
{
! return lookup_name_real (name, 0, 1, 0);
}
tree
*************** lookup_function_nonclass (name, args)
*** 4944,4954 ****
}
tree
lookup_name (name, prefer_type)
tree name;
int prefer_type;
{
! return lookup_name_real (name, prefer_type, 0);
}
/* Similar to `lookup_name' but look only at current binding level. */
--- 4973,4991 ----
}
tree
+ lookup_name_namespace_only (name)
+ tree name;
+ {
+ /* type-or-namespace, nonclass, namespace_only */
+ return lookup_name_real (name, 1, 1, 1);
+ }
+
+ tree
lookup_name (name, prefer_type)
tree name;
int prefer_type;
{
! return lookup_name_real (name, prefer_type, 0, 0);
}
/* Similar to `lookup_name' but look only at current binding level. */
*************** lookup_name_current_level (name)
*** 4985,4990 ****
--- 5022,5039 ----
}
return t;
+ }
+
+ void
+ begin_only_namespace_names ()
+ {
+ only_namespace_names = 1;
+ }
+
+ void
+ end_only_namespace_names ()
+ {
+ only_namespace_names = 0;
}
/* Arrange for the user to get a source line number, even when the
Index: decl2.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl2.c,v
retrieving revision 1.83
diff -c -p -r1.83 decl2.c
*** decl2.c 1998/06/04 02:13:29 1.83
--- decl2.c 1998/06/04 20:08:04
*************** set_decl_namespace (decl, scope)
*** 4003,4008 ****
--- 4003,4011 ----
tree old;
if (scope == std_node)
scope = global_namespace;
+ /* Get rid of namespace aliases. */
+ scope = ORIGINAL_NAMESPACE (scope);
+
if (!is_namespace_ancestor (current_namespace, scope))
cp_error ("declaration of `%D' not in a namespace surrounding `%D'",
decl, scope);
*************** do_namespace_alias (alias, namespace)
*** 4354,4380 ****
tree alias, namespace;
{
tree binding;
! tree ns;
! if (TREE_CODE (namespace) == IDENTIFIER_NODE)
! ns = lookup_name (namespace, 1);
! else
! ns = namespace;
! if (TREE_CODE (ns) != NAMESPACE_DECL)
{
! cp_error ("`%D' is not a namespace", namespace);
return;
}
binding = binding_for_name (alias, current_namespace);
! if (BINDING_VALUE (binding) && BINDING_VALUE (binding) != namespace)
{
cp_error ("invalid namespace alias `%D'", alias);
! cp_error_at ("`%D' previously declared here", alias);
}
else
{
! /* XXX the alias is not exactly identical to the name space,
! it must not be used in a using directive or namespace alias */
! BINDING_VALUE (binding) = ns;
}
}
--- 4357,4391 ----
tree alias, namespace;
{
tree binding;
! tree old;
!
! if (TREE_CODE (namespace) != NAMESPACE_DECL)
{
! /* The parser did not find it, so it's not there. */
! cp_error ("unknown namespace `%D'", namespace);
return;
}
+
+ namespace = ORIGINAL_NAMESPACE (namespace);
+
binding = binding_for_name (alias, current_namespace);
! old = BINDING_VALUE (binding);
! if (old)
{
+ if (TREE_CODE (old) == NAMESPACE_DECL
+ && DECL_NAMESPACE_ALIAS (old) == namespace)
+ /* Ok: redeclaration. */
+ return;
cp_error ("invalid namespace alias `%D'", alias);
! cp_error_at ("`%D' previously declared here", old);
}
else
{
! /* Build the alias. */
! alias = build_lang_decl (NAMESPACE_DECL, alias, void_type_node);
! DECL_NAMESPACE_ALIAS (alias) = namespace;
! DECL_CONTEXT (alias) = current_namespace;
! BINDING_VALUE (binding) = alias;
}
}
*************** do_using_directive (namespace)
*** 4512,4518 ****
sorry ("using directives inside functions");
return;
}
! /* using A::B::C; */
if (TREE_CODE (namespace) == SCOPE_REF)
namespace = TREE_OPERAND (namespace, 1);
if (TREE_CODE (namespace) == IDENTIFIER_NODE)
--- 4523,4529 ----
sorry ("using directives inside functions");
return;
}
! /* using namespace A::B::C; */
if (TREE_CODE (namespace) == SCOPE_REF)
namespace = TREE_OPERAND (namespace, 1);
if (TREE_CODE (namespace) == IDENTIFIER_NODE)
*************** do_using_directive (namespace)
*** 4526,4531 ****
--- 4537,4543 ----
cp_error ("`%T' is not a namespace", namespace);
return;
}
+ namespace = ORIGINAL_NAMESPACE (namespace);
/* direct usage */
add_using_namespace (current_namespace, namespace, 0);
}
Index: error.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/error.c,v
retrieving revision 1.45
diff -c -p -r1.45 error.c
*** error.c 1998/06/04 01:33:02 1.45
--- error.c 1998/06/04 20:08:29
*************** dump_decl (t, v)
*** 726,731 ****
--- 726,737 ----
OB_PUTID (DECL_NAME (t));
break;
+ case SCOPE_REF:
+ dump_decl (TREE_OPERAND (t, 0), 0);
+ OB_PUTS ("::");
+ dump_decl (TREE_OPERAND (t, 1), 0);
+ break;
+
case ARRAY_REF:
dump_decl (TREE_OPERAND (t, 0), v);
OB_PUTC ('[');
Index: parse.y
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/parse.y,v
retrieving revision 1.60
diff -c -p -r1.60 parse.y
*** parse.y 1998/05/27 01:25:47 1.60
--- parse.y 1998/06/04 20:09:41
*************** extdef:
*** 401,418 ****
{ push_namespace (NULL_TREE); }
extdefs_opt '}'
{ pop_namespace (); }
! | NAMESPACE identifier '=' any_id ';'
! { do_namespace_alias ($2, $4); }
| using_decl ';'
{ do_toplevel_using_decl ($1); }
! | USING NAMESPACE any_id ';'
{
/* If no declaration was found, the using-directive is
invalid. Since that was not reported, we need the
identifier for the error message. */
! if (TREE_CODE ($3) == IDENTIFIER_NODE && lastiddecl)
! $3 = lastiddecl;
! do_using_directive ($3);
}
| extension extdef
{ pedantic = $<itype>1; }
--- 401,428 ----
{ push_namespace (NULL_TREE); }
extdefs_opt '}'
{ pop_namespace (); }
! | NAMESPACE identifier '='
! { begin_only_namespace_names (); }
! any_id ';'
! {
! end_only_namespace_names ();
! if (lastiddecl)
! $5 = lastiddecl;
! do_namespace_alias ($2, $5);
! }
| using_decl ';'
{ do_toplevel_using_decl ($1); }
! | USING NAMESPACE
! { begin_only_namespace_names (); }
! any_id ';'
{
+ end_only_namespace_names ();
/* If no declaration was found, the using-directive is
invalid. Since that was not reported, we need the
identifier for the error message. */
! if (TREE_CODE ($4) == IDENTIFIER_NODE && lastiddecl)
! $4 = lastiddecl;
! do_using_directive ($4);
}
| extension extdef
{ pedantic = $<itype>1; }