* decl.c (push_namespace): Handle redeclaration error.
* cp-tree.h (IDENTIFIER_NAMESPACE_VALUE): New macro.
(IDENTIFIER_NAMESPACE_BINDINGS): New macro.
(NAMESPACE_BINDING): New macro.
(IDENTIFIER_GLOBAL_VALUE): Use NAMESPACE_BINDING.
* *.c: Use them.
* pt.c (push_template_decl): Use innermost_args.
* decl.c (get_unique_name): Tweak from earlier in the name.
* cp-tree.def: Add CPLUS_BINDING node.
* cp-tree.h (tree_binding): new struct
(BINDING_SCOPE, BINDING_VALUE): new macros
(current_namespace, global_namespace): declare extern
(struct lang_decl_flags): new field in_namespace
(DECL_NAMESPACE_USING, DECL_NAMESPACE_USERS): new macros
(DECL_NAMESPACE, SET_DECL_NAMESPACE): new macros
(TREE_INDIRECT_USING): new macro
* decl2.c (current_namespace, global_namespace): Declare. The
value is a NAMESPACE_DECL now, not a TREE_LIST.
(is_namespace_ancestor, namespace_ancestor):new static functions.
(add_using_namespace, ambiguous_decl): likewise.
(lookup_using_namespace): new support function for lookup_name.
(qualified_lookup_using_namespace): new support function for
do_scoped_id and lookup_namespace_name
(get_namespace_id): mark as obsolete.
(current_namespace_id): Likewise.
(do_namespace_alias): Implement.
(do_using_directive): Implement as call to add_using_namespace.
* decl.c (binding_for_name): new function.
(push_namespace, pop_namespace): implement.
(push_decl): don't install a FUNCTION_DECL in the global branch.
(lookup_namespace_name): implement using qualified lookup.
(lookup_name_real): For global scoping, lookup in
global_namespace. For namespace scoping, lookup in given
namespace. For unscoped lookup, iterate over namespace,
considering using directives.
(init_decl_processing): initialize global_namespace.
(grokvardecl): Build assembler name as static name for globals.
(grokdeclarator): Remove old namespace mangling.
(xref_tag): When installing a global binding for the
tag, make sure we have an identifier.
* method.c (build_overload_nested_name): mangle namespaces.
(build_qualified_name): Likewise.
(build_decl_overload_real): Likewise.
* lex.c (build_lang_decl): set namespace for new declaration to
current_namespace.
(do_scoped_id): find global names in global or current
namespace, or using qualified namespace lookup, depending on
context.
* init.c (build_member_call): When scope is namespace, use
build_x_function_call instead.
(build_offset_ref): When scope is namespace, collapse processing
to lookup_namespace_name instead.
* error.c (dump_decl): Support NAMESPACE_DECL.
* decl.c (pushdecl): Bind globals to current namespace.
(push_overloaded_decl): Likewise.
(lookup_tag): Likewise.
(lookup_name_current_level): Likewise.
(xref_tag): Likewise.
(start_function): Likewise.
* lex.c (do_identifier): Likewise.
(identifier_typedecl_value): Likewise.
(real_yylex): Likewise.
* method.c (do_inline_function_hair): Likewise.
* parse.y (unscoped): Likewise.
* pt.c (check_explicit_specialization): Likewise.
(lookup_template_class): Likewise.
* rtti.c (call_void_fn): Likewise.
* sig.c (build_sigtable): Likewise.
* ptree.c (lang_print_xnode): New function.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@18227
138bc75d-0d04-0410-961f-
82ee72b054a4
+Wed Feb 25 00:35:33 1998 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (push_namespace): Handle redeclaration error.
+
+ * cp-tree.h (IDENTIFIER_NAMESPACE_VALUE): New macro.
+ (IDENTIFIER_NAMESPACE_BINDINGS): New macro.
+ (NAMESPACE_BINDING): New macro.
+ (IDENTIFIER_GLOBAL_VALUE): Use NAMESPACE_BINDING.
+ * *.c: Use them.
+
+ * pt.c (push_template_decl): Use innermost_args.
+
+ * decl.c (get_unique_name): Tweak from earlier in the name.
+
+Tue Feb 24 22:15:04 1998 Martin von Loewis <loewis@informatik.hu-berlin.de>
+
+ * cp-tree.def: Add CPLUS_BINDING node.
+ * cp-tree.h (tree_binding): new struct
+ (BINDING_SCOPE, BINDING_VALUE): new macros
+ (current_namespace, global_namespace): declare extern
+ (struct lang_decl_flags): new field in_namespace
+ (DECL_NAMESPACE_USING, DECL_NAMESPACE_USERS): new macros
+ (DECL_NAMESPACE, SET_DECL_NAMESPACE): new macros
+ (TREE_INDIRECT_USING): new macro
+ * decl2.c (current_namespace, global_namespace): Declare. The
+ value is a NAMESPACE_DECL now, not a TREE_LIST.
+ (is_namespace_ancestor, namespace_ancestor):new static functions.
+ (add_using_namespace, ambiguous_decl): likewise.
+ (lookup_using_namespace): new support function for lookup_name.
+ (qualified_lookup_using_namespace): new support function for
+ do_scoped_id and lookup_namespace_name
+ (get_namespace_id): mark as obsolete.
+ (current_namespace_id): Likewise.
+ (do_namespace_alias): Implement.
+ (do_using_directive): Implement as call to add_using_namespace.
+ * decl.c (binding_for_name): new function.
+ (push_namespace, pop_namespace): implement.
+ (push_decl): don't install a FUNCTION_DECL in the global branch.
+ (lookup_namespace_name): implement using qualified lookup.
+ (lookup_name_real): For global scoping, lookup in
+ global_namespace. For namespace scoping, lookup in given
+ namespace. For unscoped lookup, iterate over namespace,
+ considering using directives.
+ (init_decl_processing): initialize global_namespace.
+ (grokvardecl): Build assembler name as static name for globals.
+ (grokdeclarator): Remove old namespace mangling.
+ (xref_tag): When installing a global binding for the
+ tag, make sure we have an identifier.
+ * method.c (build_overload_nested_name): mangle namespaces.
+ (build_qualified_name): Likewise.
+ (build_decl_overload_real): Likewise.
+ * lex.c (build_lang_decl): set namespace for new declaration to
+ current_namespace.
+ (do_scoped_id): find global names in global or current
+ namespace, or using qualified namespace lookup, depending on
+ context.
+ * init.c (build_member_call): When scope is namespace, use
+ build_x_function_call instead.
+ (build_offset_ref): When scope is namespace, collapse processing
+ to lookup_namespace_name instead.
+ * error.c (dump_decl): Support NAMESPACE_DECL.
+ * decl.c (pushdecl): Bind globals to current namespace.
+ (push_overloaded_decl): Likewise.
+ (lookup_tag): Likewise.
+ (lookup_name_current_level): Likewise.
+ (xref_tag): Likewise.
+ (start_function): Likewise.
+ * lex.c (do_identifier): Likewise.
+ (identifier_typedecl_value): Likewise.
+ (real_yylex): Likewise.
+ * method.c (do_inline_function_hair): Likewise.
+ * parse.y (unscoped): Likewise.
+ * pt.c (check_explicit_specialization): Likewise.
+ (lookup_template_class): Likewise.
+ * rtti.c (call_void_fn): Likewise.
+ * sig.c (build_sigtable): Likewise.
+ * ptree.c (lang_print_xnode): New function.
+
Tue Feb 24 01:40:24 1998 Jason Merrill <jason@yorick.cygnus.com>
* pt.c (instantiate_class_template): Don't instantiate if pedantic
the template will will be an IDENTIFIER_NODE. */
DEFTREECODE (TEMPLATE_ID_EXPR, "template_id_expr", 'e', 2)
+/* has two fields: scope and value */
+/* XXX: could recycle some of the common fields */
+DEFTREECODE (CPLUS_BINDING, "binding", 'x', 2)
+
/* A whole bunch of tree codes for the initial, superficial parsing of
templates. */
DEFTREECODE (LOOKUP_EXPR, "lookup_expr", 'e', 2)
tree decl;
} template_parm_index;
+#define BINDING_SCOPE(NODE) (((struct tree_binding*)NODE)->scope)
+#define BINDING_VALUE(NODE) (((struct tree_binding*)NODE)->value)
+#define NAMESPACE_BINDING(ID,NS) BINDING_VALUE (binding_for_name (ID, NS))
+#define IDENTIFIER_GLOBAL_VALUE(NODE) \
+ NAMESPACE_BINDING (NODE, global_namespace)
+#define IDENTIFIER_NAMESPACE_VALUE(NODE) \
+ NAMESPACE_BINDING (NODE, current_namespace)
+
+struct tree_binding
+{
+ char common[sizeof (struct tree_common)];
+ tree scope;
+ tree value;
+};
+
/* To identify to the debug emitters if it should pay attention to the
flag `-Wtemplate-debugging'. */
#define HAVE_TEMPLATES 1
/* Macros for access to language-specific slots in an identifier. */
-#define IDENTIFIER_GLOBAL_VALUE(NODE) \
+#define IDENTIFIER_NAMESPACE_BINDINGS(NODE) \
(((struct lang_identifier *)(NODE))->global_value)
#define IDENTIFIER_CLASS_VALUE(NODE) \
(((struct lang_identifier *)(NODE))->class_value)
extern int current_function_returns_null;
extern tree current_function_return_value;
+extern tree current_namespace;
+extern tree global_namespace;
+
extern tree ridpointers[];
extern tree ansi_opname[];
extern tree ansi_assopname[];
tree memfunc_pointer_to;
tree template_info;
struct binding_level *level;
+ tree in_namespace;
};
struct lang_decl
/* The _TYPE context in which this _DECL appears. This field holds the
class where a virtual function instance is actually defined, and the
- lexical scope of a friend function defined in a class body. */
+ lexical scope of a friend function defined in a class body. */
#define DECL_CLASS_CONTEXT(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.context)
#define DECL_REAL_CONTEXT(NODE) \
((TREE_CODE (NODE) == FUNCTION_DECL && DECL_FUNCTION_MEMBER_P (NODE)) \
/* For a FUNCTION_DECL: the chain through which the next method
with the same name is found. We now use TREE_CHAIN to
- walk through the methods in order of declaration. */
+ walk through the methods in order of declaration.
+ For a NAMESPACE_DECL: the list of using namespace directives
+ The PURPOSE is the used namespace, the value is the namespace
+ that is the common ancestor */
#if 1
#define DECL_CHAIN(NODE) (DECL_LANG_SPECIFIC(NODE)->chain)
#else
#define DECL_CHAIN(NODE) (TREE_CHAIN (NODE))
#endif
+#define DECL_NAMESPACE_USING(NODE) (DECL_LANG_SPECIFIC(NODE)->chain)
+
+/* 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) DECL_INITIAL (NODE)
+
+/* In a TREE_LIST concatenating using directives, indicate indirekt
+ directives */
+#define TREE_INDIRECT_USING(NODE) ((NODE)->common.lang_flag_0)
/* In a VAR_DECL for a variable declared in a for statement,
this is the shadowed (local) variable. */
#define DECL_REALLY_EXTERN(NODE) \
(DECL_EXTERNAL (NODE) && ! DECL_NOT_REALLY_EXTERN (NODE))
+/* Records the namespace we are in */
+#define DECL_NAMESPACE(NODE) \
+ (DECL_LANG_SPECIFIC (NODE) ? DECL_LANG_SPECIFIC (NODE)->decl_flags.in_namespace : 0)
+#define SET_DECL_NAMESPACE(NODE, val) \
+ DECL_LANG_SPECIFIC (NODE)->decl_flags.in_namespace = val
+
/* Used to tell cp_finish_decl that it should approximate comdat linkage
as best it can for this decl. */
#define DECL_COMDAT(NODE) (DECL_LANG_SPECIFIC (NODE)->decl_flags.comdat)
#if 0
extern void set_current_level_tags_transparency PROTO((int));
#endif
+extern tree binding_for_name PROTO((tree, tree));
extern tree lookup_namespace_name PROTO((tree, tree));
extern tree make_typename_type PROTO((tree, tree));
extern tree lookup_name_nonclass PROTO((tree));
extern tree lookup_name PROTO((tree, int));
extern tree lookup_name_current_level PROTO((tree));
+extern tree lookup_using_namespace PROTO((tree,tree,tree,tree));
+extern tree qualified_lookup_using_namespace PROTO((tree,tree));
extern tree auto_function PROTO((tree, tree, enum built_in_function));
extern void init_decl_processing PROTO((void));
extern int init_type_desc PROTO((void));
extern tree get_id_2 PROTO((char *, tree));
/* in pt.c */
+extern tree innermost_args PROTO ((tree, int));
extern tree tsubst PROTO ((tree, tree, tree));
extern tree tsubst_expr PROTO ((tree, tree, tree));
extern tree tsubst_copy PROTO ((tree, tree, tree));
extern int static_labelno;
+extern tree current_namespace;
+extern tree global_namespace;
+
/* Stack of places to restore the search obstack back to. */
/* Obstack used for remembering local class declarations (like
print_binding_level (global_binding_level);
}
+/* Return the tree_binding for the name in the given scope
+ If there are no bindings for the name in the scope, make a new
+ bindings node. This bindings list of this node will be empty, though. */
+
+tree
+binding_for_name (name, scope)
+ tree name;
+ tree scope;
+{
+ tree iter;
+ for (iter = IDENTIFIER_NAMESPACE_BINDINGS (name); iter;
+ iter = TREE_CHAIN (iter))
+ {
+ my_friendly_assert (TREE_CODE (iter) == CPLUS_BINDING, 374);
+ if (BINDING_SCOPE (iter) == scope)
+ return iter;
+ }
+ /* not found, make a new permanent one */
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+ iter = make_node (CPLUS_BINDING);
+ TREE_CHAIN (iter) = IDENTIFIER_NAMESPACE_BINDINGS (name);
+ IDENTIFIER_NAMESPACE_BINDINGS (name) = iter;
+ BINDING_SCOPE (iter) = scope;
+ BINDING_VALUE (iter) = NULL_TREE;
+ pop_obstacks ();
+ return iter;
+}
+
extern char * first_global_object_name;
/* Get a unique name for each call to this routine for unnamed namespaces.
/* Don't need to pull weird characters out of global names. */
if (p != first_global_object_name)
{
- for (p = buf+11; *p; p++)
+ for (p = buf+2; *p; p++)
if (! ((*p >= '0' && *p <= '9')
#ifndef NO_DOLLAR_IN_LABEL /* this for `$'; unlikely, but... -- kr */
|| *p == '$'
tree name;
{
#if 1
- static int warned;
- if (! warned)
- sorry ("namespace");
+ tree d;
+ int need_new = 1;
+ int implicit_use = 0;
+ int nodecl = 0;
+ if (!global_namespace)
+ {
+ /* this must be :: */
+ my_friendly_assert (name == get_identifier ("::"), 377);
+ nodecl = 1;
+ }
+ else if (!name)
+ {
+ name = get_unique_name ();
+ implicit_use = 1;
+ }
+ else
+ {
+ /* 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;
+ }
- warned = 1;
+ if (need_new)
+ {
+ /* make a new namespace, binding the name to it */
+ d = build_lang_decl (NAMESPACE_DECL, name, void_type_node);
+ if (!nodecl)
+ d = pushdecl (d);
+ }
+ if (implicit_use)
+ do_using_directive (d);
+ /* enter the name space */
+ current_namespace = d;
+
#else
- extern tree current_namespace;
tree old_id = get_namespace_id ();
char *buf;
tree d;
void
pop_namespace ()
{
-#if 0
- extern tree current_namespace;
+#if 1
+ current_namespace = DECL_NAMESPACE (current_namespace);
+#else
tree decls, link;
current_namespace = TREE_CHAIN (current_namespace);
if (TREE_PUBLIC (x) && TREE_CODE (x) != FUNCTION_DECL)
{
tree decl;
+ tree bindings = binding_for_name (name, current_namespace);
- if (IDENTIFIER_GLOBAL_VALUE (name) != NULL_TREE
- && (DECL_EXTERNAL (IDENTIFIER_GLOBAL_VALUE (name))
- || TREE_PUBLIC (IDENTIFIER_GLOBAL_VALUE (name))))
- decl = IDENTIFIER_GLOBAL_VALUE (name);
+ if (BINDING_VALUE (bindings) != NULL_TREE
+ && (DECL_EXTERNAL (BINDING_VALUE (bindings))
+ || TREE_PUBLIC (BINDING_VALUE (bindings))))
+ decl = BINDING_VALUE (bindings);
else
decl = NULL_TREE;
if (b == global_binding_level)
{
/* Install a global value. */
+ tree bindings = binding_for_name (name, current_namespace);
/* If the first global decl has external linkage,
warn if we later see static one. */
- if (IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE && TREE_PUBLIC (x))
+ if (BINDING_VALUE (bindings) == NULL_TREE && TREE_PUBLIC (x))
TREE_PUBLIC (name) = 1;
/* Don't install an artificial TYPE_DECL if we already have
if (TREE_CODE (x) != TYPE_DECL
|| t == NULL_TREE
|| ! DECL_ARTIFICIAL (x))
- IDENTIFIER_GLOBAL_VALUE (name) = x;
+ {
+ if (TREE_CODE (x) == FUNCTION_DECL)
+ my_friendly_assert ((BINDING_VALUE (bindings) == NULL_TREE)
+ || BINDING_VALUE (bindings) == x, 378);
+ BINDING_VALUE (bindings) = x;
+ }
/* Don't forget if the function was used via an implicit decl. */
if (IDENTIFIER_IMPLICIT_DECL (name)
{
/* Here to install a non-global value. */
tree oldlocal = IDENTIFIER_LOCAL_VALUE (name);
- tree oldglobal = IDENTIFIER_GLOBAL_VALUE (name);
+ tree oldglobal = binding_for_name (name, current_namespace);
/* Don't install an artificial TYPE_DECL if we already have
another _DECL with that name. */
have a global definition or declaration for the function. */
if (oldlocal == NULL_TREE
&& DECL_EXTERNAL (x)
- && oldglobal != NULL_TREE
+ && BINDING_VALUE (oldglobal) != NULL_TREE
&& TREE_CODE (x) == FUNCTION_DECL
- && TREE_CODE (oldglobal) == FUNCTION_DECL)
+ && TREE_CODE (BINDING_VALUE (oldglobal)) == FUNCTION_DECL)
{
/* We have one. Their types must agree. */
- if (decls_match (x, oldglobal))
+ if (decls_match (x, BINDING_VALUE (oldglobal)))
/* OK */;
else
{
cp_warning ("extern declaration of `%#D' doesn't match", x);
- cp_warning_at ("global declaration `%#D'", oldglobal);
+ cp_warning_at ("global declaration `%#D'", BINDING_VALUE (oldglobal));
}
}
/* If we have a local external declaration,
and no file-scope declaration has yet been seen,
then if we later have a file-scope decl it must not be static. */
if (oldlocal == NULL_TREE
- && oldglobal == NULL_TREE
+ && BINDING_VALUE (oldglobal) == NULL_TREE
&& DECL_EXTERNAL (x)
&& TREE_PUBLIC (x))
{
warnstring = "declaration of `%s' shadows a member of `this'";
else if (oldlocal != NULL_TREE)
warnstring = "declaration of `%s' shadows previous local";
- else if (oldglobal != NULL_TREE)
+ else if (BINDING_VALUE (oldglobal) != NULL_TREE)
+ /* XXX shadow warnings in outer-more namespaces */
warnstring = "declaration of `%s' shadows global declaration";
if (warnstring)
if (doing_global)
{
- old = IDENTIFIER_GLOBAL_VALUE (orig_name);
+ old = IDENTIFIER_NAMESPACE_VALUE (orig_name);
if (old && TREE_CODE (old) == FUNCTION_DECL
&& DECL_ARTIFICIAL (old)
&& (DECL_BUILT_IN (old) || DECL_BUILT_IN_NONANSI (old)))
old = decl;
if (doing_global)
- IDENTIFIER_GLOBAL_VALUE (orig_name) = old;
+ IDENTIFIER_NAMESPACE_VALUE (orig_name) = old;
else
IDENTIFIER_LOCAL_VALUE (orig_name) = old;
{
if (level->pseudo_global)
{
- tree t = IDENTIFIER_GLOBAL_VALUE (name);
+ /* XXX MvL */
+ tree t = IDENTIFIER_NAMESPACE_VALUE (name);
if (t && TREE_CODE (t) == TEMPLATE_DECL
&& TREE_CODE (DECL_TEMPLATE_RESULT (t)) == TYPE_DECL)
return TREE_TYPE (t);
lookup_namespace_name (namespace, name)
tree namespace, name;
{
+#if 1
+ tree val;
+ my_friendly_assert (TREE_CODE (namespace) == NAMESPACE_DECL, 370);
+ my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 373);
+
+ val = qualified_lookup_using_namespace (name, namespace);
+ if (val)
+ return val;
+ cp_error ("`%D' undeclared in namespace `%D'", name, namespace);
+ return error_mark_node;
+#else
struct binding_level *b = (struct binding_level *)NAMESPACE_LEVEL (namespace);
tree x = NULL_TREE;
-
#if 1
/* This searches just one level. */
if (b)
}
#endif
return x;
+#endif
}
tree
val = IDENTIFIER_GLOBAL_VALUE (name);
else if (TREE_CODE (type) == NAMESPACE_DECL)
{
- val = lookup_namespace_name (type, name);
+ val = NAMESPACE_BINDING (name, type);
}
else if (! IS_AGGR_TYPE (type)
|| TREE_CODE (type) == TEMPLATE_TYPE_PARM
else if (classval)
val = classval;
else
- val = IDENTIFIER_GLOBAL_VALUE (name);
+ {
+ /* unscoped lookup of a global, iterate over namespaces,
+ considering using namespace statements */
+ tree binding;
+ tree scope = current_namespace;
+ do
+ {
+ binding = binding_for_name (name, scope);
+ val = BINDING_VALUE (binding);
+ val = lookup_using_namespace (name, val, current_namespace, scope);
+ if (scope == global_namespace)
+ break;
+ scope = DECL_NAMESPACE (scope);
+ }
+ while (!val);
+ }
done:
if (val)
if (current_binding_level == global_binding_level)
{
- t = IDENTIFIER_GLOBAL_VALUE (name);
+ t = IDENTIFIER_NAMESPACE_VALUE (name);
/* extern "C" function() */
if (t != NULL_TREE && TREE_CODE (t) == TREE_LIST)
tdecl = pushdecl (build_decl (TYPE_DECL, tname, type));
set_identifier_type_value (tname, NULL_TREE);
if ((int) rid_index < (int) RID_MAX)
+ /* builtin types live in the global namespace */
IDENTIFIER_GLOBAL_VALUE (tname) = tdecl;
}
if (rname != NULL_TREE)
lang_name_cplusplus = get_identifier ("C++");
lang_name_c = get_identifier ("C");
+ /* enter the global namespace */
+ my_friendly_assert (global_namespace == NULL_TREE, 375);
+ my_friendly_assert (current_lang_name == NULL_TREE, 375);
+ current_lang_name = lang_name_cplusplus;
+ push_namespace (get_identifier ("::"));
+ global_namespace = current_namespace;
+ current_lang_name = NULL_TREE;
+
if (flag_strict_prototype == 2)
{
if (pedantic)
if (check == 0 && ! current_function_decl)
{
+ /* assembler names live in the global namespace */
tmp = IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl));
if (tmp == NULL_TREE)
IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl)) = decl;
DECL_ASSEMBLER_NAME (decl) = build_static_name (basetype, declarator);
}
else
- decl = build_decl (VAR_DECL, declarator, complete_type (type));
-
- DECL_ASSEMBLER_NAME (decl) = current_namespace_id (DECL_ASSEMBLER_NAME (decl));
+ {
+ decl = build_decl (VAR_DECL, declarator, complete_type (type));
+ if (current_namespace != global_namespace)
+ DECL_ASSEMBLER_NAME (decl) = build_static_name (current_namespace,
+ declarator);
+ }
if (RIDBIT_SETP (RID_EXTERN, specbits))
{
if (ctype == NULL_TREE && DECL_LANGUAGE (decl) != lang_c
&& (! DECL_USE_TEMPLATE (decl) ||
name_mangling_version < 1))
+#if 0
+ /* XXX is support for the old __ns_ mangling really needed? MvL */
DECL_ASSEMBLER_NAME (decl) = current_namespace_id (declarator);
+#else
+ DECL_ASSEMBLER_NAME (decl) = declarator;
+#endif
if (staticp == 1)
{
else
{
/* If it no longer looks like a nested type, make sure it's
- in global scope. */
+ in global scope.
+ If it is not an IDENTIFIER, this is not a declaration */
if (b == global_binding_level && !class_binding_level
- && IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE)
- IDENTIFIER_GLOBAL_VALUE (name) = TYPE_NAME (ref);
+ && TREE_CODE (name) == IDENTIFIER_NODE)
+ {
+ tree binding;
+ binding = binding_for_name (name, current_namespace);
+ if (BINDING_VALUE (binding) == NULL_TREE)
+ BINDING_VALUE (binding) = TYPE_NAME (ref);
+ }
}
if (binfo)
&& TYPE_IDENTIFIER (DECL_CONTEXT (decl1))
&& IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (DECL_CONTEXT (decl1))))
{
+ tree binding = binding_for_name (DECL_NAME (decl1),
+ current_namespace);
cp_error ("redeclaration of `%#D'", decl1);
if (IDENTIFIER_CLASS_VALUE (DECL_NAME (decl1)))
cp_error_at ("previous declaration here", IDENTIFIER_CLASS_VALUE (DECL_NAME (decl1)));
- else if (IDENTIFIER_GLOBAL_VALUE (DECL_NAME (decl1)))
- cp_error_at ("previous declaration here", IDENTIFIER_GLOBAL_VALUE (DECL_NAME (decl1)));
+ else if (BINDING_VALUE (binding))
+ cp_error_at ("previous declaration here", BINDING_VALUE (binding));
}
fntype = TREE_TYPE (decl1);
/* Functions called along with real static constructors and destructors. */
tree static_ctors, static_dtors;
+
+/* The current open namespace, and :: */
+
+tree current_namespace;
+tree global_namespace;
+
\f
/* C (and C++) language-specific option variables. */
tree base;
{
tree sname = get_id_2 ("__sn", base);
+ /* for struct X foo __attribute__((weak)), there is a counter
+ __snfoo. Since base is already an assembler name, sname should
+ be globally unique */
tree sentry = IDENTIFIER_GLOBAL_VALUE (sname);
if (! sentry)
{
return value;
}
-tree current_namespace;
+/* return 1 if root encloses child */
+static int
+is_namespace_ancestor (root, child)
+ tree root, child;
+{
+ if (root == child)
+ return 1;
+ if (root == global_namespace)
+ return 1;
+ if (child == global_namespace)
+ return 0;
+ return is_namespace_ancestor (root, DECL_NAMESPACE (child));
+}
+
+
+/* return the namespace that is the common ancestor
+ of two given namespaces */
+static tree
+namespace_ancestor (ns1, ns2)
+ tree ns1, ns2;
+{
+ if (is_namespace_ancestor (ns1, ns2))
+ return ns1;
+ return namespace_ancestor (DECL_NAMESPACE (ns1), ns2);
+}
+
+/* Insert used into the using list of user. Set indirect_flag if this
+ directive is not directly from the source. Also find the common
+ ancestor and let our users know about the new namespace */
+static void
+add_using_namespace (user, used, indirect)
+ tree user;
+ tree used;
+ int indirect;
+{
+ tree iter;
+ /* using oneself is a no-op */
+ if (user == used)
+ return;
+ my_friendly_assert (TREE_CODE (user) == NAMESPACE_DECL, 380);
+ my_friendly_assert (TREE_CODE (used) == NAMESPACE_DECL, 380);
+ /* check if we already have this */
+ if (purpose_member (used, DECL_NAMESPACE_USING (user)) != NULL_TREE)
+ return;
+
+ /* add used to the user's using list */
+ DECL_NAMESPACE_USING (user)
+ = perm_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)
+ = perm_tree_cons (user, 0, DECL_NAMESPACE_USERS (used));
+
+ for (iter = DECL_NAMESPACE_USERS (user); iter; iter = TREE_CHAIN (iter))
+ /* indirect usage */
+ add_using_namespace (TREE_PURPOSE (iter), used, 1);
+}
+
+/* This should return an error not all definitions define functions.
+ It is not an error if we find two functions with exactly the
+ same signature, only if these are selected in overload resolution.
+ XXX Do we want to give *all* candidates in case of ambiguity?
+ XXX In what way should I treat extern declarations?
+ XXX I don't want to repeat the entire duplicate_decls here */
+static tree
+ambiguous_decl (name, val1, val2)
+ tree val1, val2;
+{
+ my_friendly_assert (val1 != val2, 376);
+ if (is_overloaded_fn (val1) && is_overloaded_fn (val1))
+ {
+ /* now built a joint list of all overloaded declarations */
+ /* XXX if I chain'em together, they will be always considered
+ as overloaded */
+ sorry ("overloaded functions used from different namespaces");
+ }
+ cp_error ("ambiguous definition `%D' used", name);
+ cp_error_at ("first definition here", val1);
+ cp_error_at ("other definition here", val2);
+ return error_mark_node;
+}
+
+/* add the bindings of name in used namespaces to val
+ the using list is defined by current, and the lookup goes to scope */
+tree
+lookup_using_namespace (name, val, current, scope)
+ tree name, val, current, scope;
+{
+ tree iter;
+ tree val1;
+ /* iterate over all namespaces from current to scope */
+ while (1)
+ {
+ /* 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 = NAMESPACE_BINDING (name, TREE_PURPOSE (iter));
+ /* name not found in this space */
+ if (!val1)
+ continue;
+ /* first definition ever */
+ if (!val)
+ {
+ val = val1;
+ continue;
+ }
+ /* Hmmm. Ambiguity. As long as both are overloaded functions,
+ this is fine */
+ val = ambiguous_decl (name, val, val1);
+ if (val == error_mark_node)
+ break;
+ }
+ if (current == scope)
+ break;
+ current = DECL_NAMESPACE (current);
+ }
+ return val;
+}
+/* [namespace.qual] */
+tree
+qualified_lookup_using_namespace (name, scope)
+ tree name;
+ tree scope;
+{
+ tree val = NULL_TREE;
+ tree val1;
+ /* maintain a list of namespaces visited */
+ tree seen = NULL_TREE;
+ /* and a list of namespace yet to see */
+ tree todo = NULL_TREE;
+ tree usings;
+ while (scope)
+ {
+ seen = temp_tree_cons (scope, NULL_TREE, seen);
+ val1 = NAMESPACE_BINDING (name, scope);
+ if (val1)
+ {
+ if (val)
+ {
+ val = ambiguous_decl (name, val, val1);
+ break;
+ }
+ else
+ val = val1;
+ }
+ else
+ /* consider using directives */
+ for (usings = DECL_NAMESPACE_USING (scope); usings;
+ usings = TREE_CHAIN (usings))
+ /* if this was a real directive, and we have not seen it */
+ if (!TREE_INDIRECT_USING (usings)
+ && !purpose_member (seen, TREE_PURPOSE (usings)))
+ todo = temp_tree_cons (TREE_PURPOSE (usings), NULL_TREE, todo);
+ if (todo)
+ {
+ scope = TREE_PURPOSE (todo);
+ todo = TREE_CHAIN (todo);
+ }
+ else
+ scope = NULL_TREE; /* if there never was a todo list */
+ }
+ return val;
+}
+
+#if 0
+/* this is broken and should not be called anymore */
/* Get the inner part of a namespace id. It doesn't have any prefix, nor
postfix. Returns 0 if in global namespace. */
IDENTIFIER_POINTER (name));
return get_identifier (buf);
}
+#endif
void
do_namespace_alias (alias, namespace)
tree alias, namespace;
{
- sorry ("namespace alias");
+ 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;
+ }
}
void
{
if (namespace == std_node)
return;
- sorry ("using directive");
+ /* using A::B::C; */
+ if (TREE_CODE (namespace) == SCOPE_REF)
+ namespace = TREE_OPERAND (namespace, 1);
+ /* direct usage */
+ add_using_namespace (current_namespace, namespace, 0);
}
void
break;
case NAMESPACE_DECL:
+ if (DECL_NAMESPACE (t) != global_namespace)
+ {
+ dump_decl (DECL_NAMESPACE (t), v);
+ OB_PUTC2 (':',':');
+ }
OB_PUTID (DECL_NAME (t));
break;
if (type == std_node)
return build_x_function_call (do_scoped_id (name, 0), parmlist,
current_class_ref);
+ if (TREE_CODE (type) == NAMESPACE_DECL)
+ return build_x_function_call (lookup_namespace_name (type, name),
+ parmlist, current_class_ref);
if (TREE_CODE (name) != TEMPLATE_ID_EXPR)
method_name = name;
return build_min_nt (SCOPE_REF, type, name);
/* Handle namespace names fully here. */
- if (TREE_CODE (type) == IDENTIFIER_NODE
- && get_aggr_from_typedef (type, 0) == 0)
- {
- tree ns = lookup_name (type, 0);
- tree val;
- if (ns && TREE_CODE (ns) == NAMESPACE_DECL)
- {
- val = lookup_namespace_name (ns, name);
- if (val)
- return val;
- cp_error ("namespace `%D' has no member named `%D'", ns, name);
- return error_mark_node;
- }
- }
+ if (TREE_CODE (type) == NAMESPACE_DECL)
+ return lookup_namespace_name (type, name);
if (type == NULL_TREE || ! is_aggr_type (type, 1))
return error_mark_node;
yychar = yylex ();
/* Scope class declarations before global
declarations. */
- if (id == IDENTIFIER_GLOBAL_VALUE (token)
+ if (id == IDENTIFIER_NAMESPACE_VALUE (token)
&& current_class_type != 0
&& TYPE_SIZE (current_class_type) == 0)
{
}
else
{
- if (IDENTIFIER_GLOBAL_VALUE (token) != error_mark_node
+ if (IDENTIFIER_NAMESPACE_VALUE (token) != error_mark_node
|| IDENTIFIER_ERROR_LOCUS (token) != current_function_decl)
{
static int undeclared_variable_notice;
}
id = error_mark_node;
/* Prevent repeated error messages. */
- IDENTIFIER_GLOBAL_VALUE (token) = error_mark_node;
+ IDENTIFIER_NAMESPACE_VALUE (token) = error_mark_node;
SET_IDENTIFIER_ERROR_LOCUS (token, current_function_decl);
}
}
&& DECL_DEAD_FOR_LOCAL (shadowed))
shadowed = DECL_SHADOWED_FOR_VAR (shadowed);
if (!shadowed)
- shadowed = IDENTIFIER_GLOBAL_VALUE (DECL_NAME (id));
+ shadowed = IDENTIFIER_NAMESPACE_VALUE (DECL_NAME (id));
if (shadowed)
{
if (!DECL_ERROR_REPORTED (id))
{
tree t = build_min (LOOKUP_EXPR, unknown_type_node,
token, get_first_fn (id));
- if (id != IDENTIFIER_GLOBAL_VALUE (token))
+ if (id != IDENTIFIER_NAMESPACE_VALUE (token))
TREE_OPERAND (t, 1) = error_mark_node;
id = t;
}
tree token;
int parsing;
{
- tree id = IDENTIFIER_GLOBAL_VALUE (token);
+ tree id;
+ /* during parsing, this is ::name. Otherwise, it is black magic. */
+ if (parsing)
+ id = qualified_lookup_using_namespace (token, global_namespace);
+ else
+ id = IDENTIFIER_GLOBAL_VALUE (token);
if (parsing && yychar == YYEMPTY)
yychar = yylex ();
if (! id)
id = implicitly_declare (token);
else
{
- if (IDENTIFIER_GLOBAL_VALUE (token) != error_mark_node)
+ if (IDENTIFIER_NAMESPACE_VALUE (token) != error_mark_node)
error ("undeclared variable `%s' (first use here)",
IDENTIFIER_POINTER (token));
id = error_mark_node;
/* Prevent repeated error messages. */
- IDENTIFIER_GLOBAL_VALUE (token) = error_mark_node;
+ IDENTIFIER_NAMESPACE_VALUE (token) = error_mark_node;
}
}
else
}
do (IDENTIFIER_LOCAL_VALUE (node));
do (IDENTIFIER_CLASS_VALUE (node));
- do (IDENTIFIER_GLOBAL_VALUE (node));
+ do (IDENTIFIER_NAMESPACE_VALUE (node));
#undef do
/* Will this one ever happen? */
if (TYPE_MAIN_DECL (type))
DECL_LANGUAGE (t) = lang_c;
else my_friendly_abort (64);
+ SET_DECL_NAMESPACE (t, current_namespace);
+
#if 0 /* not yet, should get fixed properly later */
if (code == TYPE_DECL)
{
}
}
}
-
+ else if (decl == global_namespace)
+ return;
+ else if (DECL_NAMESPACE (decl))
+ build_overload_nested_name (DECL_NAMESPACE (decl));
+ else
+ /* XXX the above does not work for non-namespaces */
+ if (current_namespace && TREE_CODE (decl) != NAMESPACE_DECL)
+ build_overload_nested_name (current_namespace);
if (TREE_CODE (decl) == FUNCTION_DECL)
{
OB_PUTCP (label);
numeric_output_need_bar = 1;
}
+ else if (TREE_CODE (decl) == NAMESPACE_DECL)
+ build_overload_identifier (DECL_NAME (decl));
else /* TYPE_DECL */
build_overload_identifier (decl);
}
context = decl;
/* if we can't find a Ktype, do it the hard way */
if (check_ktype (context, FALSE) == -1)
- while (DECL_CONTEXT (context))
- {
- i += 1;
- context = DECL_CONTEXT (context);
- if (check_ktype (context, FALSE) != -1) /* found it! */
- break;
- if (TREE_CODE_CLASS (TREE_CODE (context)) == 't')
- context = TYPE_NAME (context);
- }
+ {
+ /* count type scopes */
+ while (DECL_CONTEXT (context))
+ {
+ i += 1;
+ context = DECL_CONTEXT (context);
+ if (check_ktype (context, FALSE) != -1) /* found it! */
+ break;
+ if (TREE_CODE_CLASS (TREE_CODE (context)) == 't')
+ context = TYPE_NAME (context);
+ }
+ /* now count namespace scopes */
+ if (TREE_CODE (decl) == NAMESPACE_DECL)
+ {
+ i = 0; /* we have nothing done, yet: reset */
+ context = decl;
+ }
+ else
+ /* decl must be a type, which we have to scope with the
+ namespace */
+ {
+ /* XXX MvL somehow, types have no lang_decl, so no namespace */
+ context = current_namespace;
+ }
+ }
+ while (context != global_namespace)
+ {
+ i += 1;
+ context = DECL_NAMESPACE (context);
+ }
if (i > 1)
{
}
else if (tparms)
OB_PUTC ('H');
- else
+ /* XXX this works only if we call this in the same namespace
+ as the declaration. Unfortunately, we don't have the _DECL,
+ only its name */
+ else if (current_namespace == global_namespace)
OB_PUTC ('F');
if (tparms)
OB_PUTC ('_');
}
+ /* qualify with namespace */
+ if (!for_method && current_namespace != global_namespace)
+ build_qualified_name (current_namespace);
+
if (parms == NULL_TREE)
OB_PUTC ('e');
else if (parms == void_list_node)
OB_PUTC ('e');
}
else
- build_mangled_name (parms, 0, 0);
+ {
+ /* the namespace qualifier for a global function
+ will count as type */
+ if (current_namespace != global_namespace
+ && !flag_do_squangling)
+ typevec[maxtype++] = current_namespace;
+ build_mangled_name (parms, 0, 0);
+ }
if (!flag_do_squangling) /* Deallocate typevec array */
{
my_friendly_assert (TREE_CODE (declarator) == IDENTIFIER_NODE,
0);
if (!ctype)
- fns = IDENTIFIER_GLOBAL_VALUE (dname);
+ fns = IDENTIFIER_NAMESPACE_VALUE (dname);
else
fns = dname;
}
}
/* Get the innermost set of template arguments. */
- args = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1);
+ args = innermost_args (args, 0);
DECL_TEMPLATE_RESULT (tmpl) = decl;
TREE_TYPE (tmpl) = TREE_TYPE (decl);
template = IDENTIFIER_LOCAL_VALUE (d1);
else
{
- template = IDENTIFIER_GLOBAL_VALUE (d1); /* XXX */
+ template = IDENTIFIER_NAMESPACE_VALUE (d1); /* XXX */
if (! template)
template = IDENTIFIER_CLASS_VALUE (d1);
}
print_node (file, "implicit", IDENTIFIER_IMPLICIT_DECL (node), indent + 4);
print_node (file, "error locus", IDENTIFIER_ERROR_LOCUS (node), indent + 4);
}
+
+void
+lang_print_xnode (file, node, indent)
+ FILE *file;
+ tree node;
+ int indent;
+{
+ switch (TREE_CODE (node))
+ {
+ case CPLUS_BINDING:
+ print_node (file, "scope", BINDING_SCOPE (node), indent+4);
+ print_node (file, "value", BINDING_VALUE (node), indent+4);
+ print_node (file, "chain", TREE_CHAIN (node), indent+4);
+ break;
+ default:
+ break;
+ }
+}