From 30394414d9a403e26ab3cdc36514b0468167096d Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 24 Feb 1998 19:49:51 -0500 Subject: [PATCH] Partial implementation of namespaces. * 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. From-SVN: r18227 --- gcc/cp/ChangeLog | 78 +++++++++++++++++ gcc/cp/cp-tree.def | 4 + gcc/cp/cp-tree.h | 47 +++++++++- gcc/cp/decl.c | 194 +++++++++++++++++++++++++++++++++-------- gcc/cp/decl2.c | 213 ++++++++++++++++++++++++++++++++++++++++++++- gcc/cp/error.c | 5 ++ gcc/cp/init.c | 19 ++-- gcc/cp/lex.c | 25 ++++-- gcc/cp/method.c | 68 ++++++++++++--- gcc/cp/pt.c | 6 +- gcc/cp/ptree.c | 18 ++++ 11 files changed, 597 insertions(+), 80 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 757a1fd2389..115e786e47c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,81 @@ +Wed Feb 25 00:35:33 1998 Jason Merrill + + * 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 + + * 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 * pt.c (instantiate_class_template): Don't instantiate if pedantic diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index 74d64412cb8..1f39768a91d 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -169,6 +169,10 @@ DEFTREECODE (DEFAULT_ARG, "default_arg", 'c', 2) 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) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 22b41097dd5..dcaf69fb6de 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -58,13 +58,28 @@ typedef struct 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) @@ -161,6 +176,9 @@ extern int current_function_returns_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[]; @@ -967,6 +985,7 @@ struct lang_decl_flags tree memfunc_pointer_to; tree template_info; struct binding_level *level; + tree in_namespace; }; struct lang_decl @@ -1071,7 +1090,7 @@ 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)) \ @@ -1079,12 +1098,24 @@ struct lang_decl /* 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. */ @@ -1473,6 +1504,12 @@ extern int flag_new_for_scope; #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) @@ -2122,11 +2159,14 @@ extern tree gettags PROTO((void)); #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)); @@ -2375,6 +2415,7 @@ extern void synthesize_method PROTO((tree)); 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)); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index df260a304cd..92730438dc4 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -63,6 +63,9 @@ extern tree static_ctors, static_dtors; 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 @@ -1664,6 +1667,34 @@ print_binding_stack () 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. @@ -1692,7 +1723,7 @@ get_unique_name () /* 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 == '$' @@ -1716,13 +1747,42 @@ push_namespace (name) 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; @@ -1766,8 +1826,9 @@ push_namespace (name) 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); @@ -3242,11 +3303,12 @@ pushdecl (x) 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; @@ -3265,10 +3327,11 @@ pushdecl (x) 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 @@ -3276,7 +3339,12 @@ pushdecl (x) 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) @@ -3305,7 +3373,7 @@ pushdecl (x) { /* 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. */ @@ -3331,24 +3399,24 @@ pushdecl (x) 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)) { @@ -3398,7 +3466,8 @@ pushdecl (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) @@ -3641,7 +3710,7 @@ push_overloaded_decl (decl, forgettable) 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))) @@ -3704,7 +3773,7 @@ push_overloaded_decl (decl, forgettable) old = decl; if (doing_global) - IDENTIFIER_GLOBAL_VALUE (orig_name) = old; + IDENTIFIER_NAMESPACE_VALUE (orig_name) = old; else IDENTIFIER_LOCAL_VALUE (orig_name) = old; @@ -4207,7 +4276,8 @@ lookup_tag (form, name, binding_level, thislevel_only) { 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); @@ -4358,9 +4428,19 @@ tree 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) @@ -4379,6 +4459,7 @@ lookup_namespace_name (namespace, name) } #endif return x; +#endif } tree @@ -4518,7 +4599,7 @@ lookup_name_real (name, prefer_type, nonclass) 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 @@ -4635,7 +4716,22 @@ lookup_name_real (name, prefer_type, nonclass) 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) @@ -4695,7 +4791,7 @@ lookup_name_current_level (name) 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) @@ -4782,6 +4878,7 @@ record_builtin_type (rid_index, name, type) 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) @@ -4851,6 +4948,14 @@ init_decl_processing () 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) @@ -7484,6 +7589,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals, 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; @@ -7611,9 +7717,12 @@ grokvardecl (type, declarator, specbits_in, initialized, constp) 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)) { @@ -9928,7 +10037,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) 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) { @@ -10931,10 +11045,16 @@ xref_tag (code_type_node, name, binfo, globalize) 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) @@ -11465,11 +11585,13 @@ start_function (declspecs, declarator, attrs, pre_parsed_p) && 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); diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index c847a2782b5..b0363f1f2ce 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -90,6 +90,12 @@ int at_eof; /* 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; + /* C (and C++) language-specific option variables. */ @@ -2880,6 +2886,9 @@ get_sentry (base) 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) { @@ -3756,8 +3765,179 @@ check_cp_case_value (value) 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. */ @@ -3789,12 +3969,35 @@ current_namespace_id (name) 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 @@ -3856,7 +4059,11 @@ do_using_directive (namespace) { 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 diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 04517814a69..31a38bb52d3 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -697,6 +697,11 @@ dump_decl (t, v) break; case NAMESPACE_DECL: + if (DECL_NAMESPACE (t) != global_namespace) + { + dump_decl (DECL_NAMESPACE (t), v); + OB_PUTC2 (':',':'); + } OB_PUTID (DECL_NAME (t)); break; diff --git a/gcc/cp/init.c b/gcc/cp/init.c index ced15d45c86..c80403e7ae5 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -1703,6 +1703,9 @@ build_member_call (type, name, parmlist) 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; @@ -1840,20 +1843,8 @@ build_offset_ref (type, 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; diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index 8d6d62229c5..3b71c49f3ad 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -2800,7 +2800,7 @@ do_identifier (token, parsing) 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) { @@ -2868,7 +2868,7 @@ do_identifier (token, parsing) } 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; @@ -2884,7 +2884,7 @@ do_identifier (token, parsing) } 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); } } @@ -2896,7 +2896,7 @@ do_identifier (token, parsing) && 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)) @@ -2953,7 +2953,7 @@ do_identifier (token, parsing) { 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; } @@ -2971,7 +2971,12 @@ do_scoped_id (token, parsing) 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) @@ -2986,12 +2991,12 @@ do_scoped_id (token, parsing) 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 @@ -3040,7 +3045,7 @@ identifier_typedecl_value (node) } 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)) @@ -4376,6 +4381,8 @@ build_lang_decl (code, name, 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) { diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 1562f8070f1..beb5f295211 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -537,7 +537,14 @@ build_overload_nested_name (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) { @@ -553,6 +560,8 @@ build_overload_nested_name (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); } @@ -969,16 +978,37 @@ build_qualified_name (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) { @@ -1515,7 +1545,10 @@ build_decl_overload_real (dname, parms, ret_type, tparms, targs, } 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) @@ -1524,6 +1557,10 @@ build_decl_overload_real (dname, parms, ret_type, tparms, targs, 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) @@ -1552,7 +1589,14 @@ build_decl_overload_real (dname, parms, ret_type, tparms, targs, 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 */ { diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index d70bc62f27c..6783b12dbf8 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -788,7 +788,7 @@ check_explicit_specialization (declarator, decl, template_count, flags) my_friendly_assert (TREE_CODE (declarator) == IDENTIFIER_NODE, 0); if (!ctype) - fns = IDENTIFIER_GLOBAL_VALUE (dname); + fns = IDENTIFIER_NAMESPACE_VALUE (dname); else fns = dname; @@ -1465,7 +1465,7 @@ push_template_decl (decl) } } /* 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); @@ -2359,7 +2359,7 @@ lookup_template_class (d1, arglist, in_decl, context) 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); } diff --git a/gcc/cp/ptree.c b/gcc/cp/ptree.c index 4a6ce7bfaeb..13f171aa0a1 100644 --- a/gcc/cp/ptree.c +++ b/gcc/cp/ptree.c @@ -163,3 +163,21 @@ print_lang_identifier (file, node, indent) 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; + } +} -- 2.30.2