From 52c11ef6a3eb0e205899df0f54c1c41be31c8ae9 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 16 Jul 1998 12:38:26 -0400 Subject: [PATCH] decl.c (qualify_lookup): New fn. * decl.c (qualify_lookup): New fn. (lookup_name_real): Use it. * decl2.c (add_using_namespace): When directly using a namespace that was indirect before, promote it. * cp-tree.h (LOOKUP_PREFER_TYPES, LOOKUP_PREFER_NAMESPACES, LOOKUP_PREFER_BOTH, LOOKUP_NAMESPACES_ONLY, LOOKUP_TYPES_ONLY, LOOKUP_QUALIFIERS_ONLY, LOOKUP_TEMPLATES_EXPECTED): New macros. * decl.c (select_decl): Replace two flag parameters by one. (unqualified_namespace_lookup): Likewise, pass flag. (lookup_flags): New function. (lookup_name_real): Compute flags, pass them. (lookup_namespace_name): Call with zero-flag. * decl2.c (ambiguous_decl): Add flag parameter, complain only according to flags. (lookup_using_namespace, qualified_lookup_using_namespace): Add flag parameter, pass them through. * lex.c (do_scoped_id): Call with zero-flag. From-SVN: r21218 --- gcc/cp/ChangeLog | 24 ++++++++++++ gcc/cp/cp-tree.h | 26 ++++++++++-- gcc/cp/decl.c | 99 +++++++++++++++++++++++++++++----------------- gcc/cp/decl2.c | 100 ++++++++++++++++++++++++++++++++++------------- gcc/cp/lex.c | 2 +- 5 files changed, 183 insertions(+), 68 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 749bf212579..1abd30d818d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,27 @@ +1998-07-16 Jason Merrill + + * decl.c (qualify_lookup): New fn. + (lookup_name_real): Use it. + +1998-07-16 Martin v. Loewis + + * decl2.c (add_using_namespace): When directly using a namespace + that was indirect before, promote it. + + * cp-tree.h (LOOKUP_PREFER_TYPES, LOOKUP_PREFER_NAMESPACES, + LOOKUP_PREFER_BOTH, LOOKUP_NAMESPACES_ONLY, LOOKUP_TYPES_ONLY, + LOOKUP_QUALIFIERS_ONLY, LOOKUP_TEMPLATES_EXPECTED): New macros. + * decl.c (select_decl): Replace two flag parameters by one. + (unqualified_namespace_lookup): Likewise, pass flag. + (lookup_flags): New function. + (lookup_name_real): Compute flags, pass them. + (lookup_namespace_name): Call with zero-flag. + * decl2.c (ambiguous_decl): Add flag parameter, complain only + according to flags. + (lookup_using_namespace, qualified_lookup_using_namespace): + Add flag parameter, pass them through. + * lex.c (do_scoped_id): Call with zero-flag. + 1998-07-16 Jason Merrill * typeck.c (convert_for_assignment): Use comptypes. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 31098113b7c..3f8840a7609 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2174,7 +2174,16 @@ extern tree current_class_type; /* _TYPE: the type of the current class */ LOOKUP_NO_CONVERSION means that user-defined conversions are not permitted. Built-in conversions are permitted. LOOKUP_DESTRUCTOR means explicit call to destructor. - LOOKUP_NO_TEMP_BIND means temporaries will not be bound to references. */ + LOOKUP_NO_TEMP_BIND means temporaries will not be bound to references. + + These are used in global lookup to support elaborated types and + qualifiers. + + LOOKUP_PREFER_TYPES means not to accept objects, and possibly namespaces. + LOOKUP_PREFER_NAMESPACES means not to accept objects, and possibly types. + LOOKUP_PREFER_BOTH means class-or-namespace-name. + LOOKUP_TEMPLATES_EXPECTED means that class templates also count + as types. */ #define LOOKUP_PROTECT (1) #define LOOKUP_COMPLAIN (2) @@ -2189,6 +2198,17 @@ extern tree current_class_type; /* _TYPE: the type of the current class */ #define LOOKUP_NO_CONVERSION (512) #define LOOKUP_DESTRUCTOR (512) #define LOOKUP_NO_TEMP_BIND (1024) +#define LOOKUP_PREFER_TYPES (2048) +#define LOOKUP_PREFER_NAMESPACES (4096) +#define LOOKUP_PREFER_BOTH (6144) +#define LOOKUP_TEMPLATES_EXPECTED (8192) + +#define LOOKUP_NAMESPACES_ONLY(f) \ + (((f) & LOOKUP_PREFER_NAMESPACES) && !((f) & LOOKUP_PREFER_TYPES)) +#define LOOKUP_TYPES_ONLY(f) \ + (!((f) & LOOKUP_PREFER_NAMESPACES) && ((f) & LOOKUP_PREFER_TYPES)) +#define LOOKUP_QUALIFIERS_ONLY(f) ((f) & LOOKUP_PREFER_BOTH) + /* These flags are used by the conversion code. CONV_IMPLICIT : Perform implicit conversions (standard and user-defined). @@ -2386,8 +2406,8 @@ 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 int lookup_using_namespace PROTO((tree,tree,tree,tree,int)); +extern int qualified_lookup_using_namespace PROTO((tree,tree,tree,int)); 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)); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index e3f226cac4d..0801ab83a86 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -4646,7 +4646,7 @@ lookup_namespace_name (namespace, name) my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 373); val = binding_init (&_b); - if (!qualified_lookup_using_namespace (name, namespace, val)) + if (!qualified_lookup_using_namespace (name, namespace, val, 0)) return error_mark_node; if (BINDING_VALUE (val)) @@ -4736,13 +4736,13 @@ make_typename_type (context, name) /* Select the right _DECL from multiple choices. */ static tree -select_decl (binding, prefer_type, namespaces_only) +select_decl (binding, flags) tree binding; - int prefer_type, namespaces_only; + int flags; { tree val; val = BINDING_VALUE (binding); - if (namespaces_only) + if (LOOKUP_NAMESPACES_ONLY (flags)) { /* We are not interested in types. */ if (val && TREE_CODE (val) == NAMESPACE_DECL) @@ -4753,10 +4753,11 @@ select_decl (binding, prefer_type, namespaces_only) /* If we could have a type and we have nothing or we need a type and have none. */ if (BINDING_TYPE (binding) - && (!val || (prefer_type && TREE_CODE (val) != TYPE_DECL))) + && (!val || ((flags & LOOKUP_PREFER_TYPES) + && TREE_CODE (val) != TYPE_DECL))) val = TYPE_STUB_DECL (BINDING_TYPE (binding)); /* Don't return non-types if we really prefer types. */ - else if (val && prefer_type > 1 && TREE_CODE (val) != TYPE_DECL + else if (val && LOOKUP_TYPES_ONLY (flags) && TREE_CODE (val) != TYPE_DECL && (!looking_for_template || TREE_CODE (val) != TEMPLATE_DECL)) val = NULL_TREE; return val; @@ -4766,10 +4767,9 @@ select_decl (binding, prefer_type, namespaces_only) using namespace statements. */ static tree -unqualified_namespace_lookup (name, prefer_type, namespaces_only) +unqualified_namespace_lookup (name, flags) tree name; - int prefer_type; - int namespaces_only; + int flags; { struct tree_binding _binding; tree b = binding_init (&_binding); @@ -4791,7 +4791,8 @@ unqualified_namespace_lookup (name, prefer_type, namespaces_only) for (level = current_binding_level; !level->namespace_p; level = level->level_chain) - if (!lookup_using_namespace (name, b, level->using_directives, scope)) + if (!lookup_using_namespace (name, b, level->using_directives, + scope, flags)) /* Give up because of error. */ return NULL_TREE; @@ -4801,14 +4802,14 @@ unqualified_namespace_lookup (name, prefer_type, namespaces_only) while (1) { if (!lookup_using_namespace (name, b, DECL_NAMESPACE_USING (siter), - scope)) + scope, flags)) /* 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); + val = select_decl (b, flags); if (scope == global_namespace) break; scope = DECL_CONTEXT (scope); @@ -4818,6 +4819,38 @@ unqualified_namespace_lookup (name, prefer_type, namespaces_only) return val; } +/* Combine prefer_type and namespaces_only into flags. */ + +static int +lookup_flags (prefer_type, namespaces_only) + int prefer_type, namespaces_only; +{ + if (namespaces_only) + return LOOKUP_PREFER_NAMESPACES; + if (prefer_type > 1) + return LOOKUP_PREFER_TYPES; + if (prefer_type > 0) + return LOOKUP_PREFER_BOTH; + return 0; +} + +/* Given a lookup that returned VAL, use FLAGS to decide if we want to + ignore it or not. Subroutine of lookup_name_real. */ + +static tree +qualify_lookup (val, flags) + tree val; + int flags; +{ + if (val == NULL_TREE) + return val; + if (LOOKUP_NAMESPACES_ONLY (flags) && TREE_CODE (val) != NAMESPACE_DECL) + return NULL_TREE; + if (LOOKUP_TYPES_ONLY (flags) && TREE_CODE (val) != TYPE_DECL) + return NULL_TREE; + 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 @@ -4841,11 +4874,12 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only) int yylex = 0; tree from_obj = NULL_TREE; tree locval, classval; + int flags; /* Hack: copy flag set by parser, if set. */ if (only_namespace_names) namespaces_only = 1; - + if (prefer_type == -2) { extern int looking_for_typename; @@ -4854,6 +4888,13 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only) yylex = 1; prefer_type = looking_for_typename; + flags = lookup_flags (prefer_type, namespaces_only); + /* During parsing, we need to complain. */ + flags |= LOOKUP_COMPLAIN; + /* If the next thing is '<', class templates are types. */ + if (looking_for_template) + flags |= LOOKUP_TEMPLATES_EXPECTED; + /* std:: becomes :: for now. */ if (got_scope == std_node) got_scope = void_type_node; @@ -4879,9 +4920,9 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only) { struct tree_binding b; val = binding_init (&b); - if (!qualified_lookup_using_namespace (name, type, val)) + if (!qualified_lookup_using_namespace (name, type, val, flags)) return NULL_TREE; - val = select_decl (val, prefer_type, namespaces_only); + val = select_decl (val, flags); } else if (! IS_AGGR_TYPE (type) || TREE_CODE (type) == TEMPLATE_TYPE_PARM @@ -4922,29 +4963,13 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only) else if (got_object && val) from_obj = val; } + else + flags = lookup_flags (prefer_type, namespaces_only); locval = classval = NULL_TREE; - if (!current_binding_level->namespace_p - && IDENTIFIER_LOCAL_VALUE (name)) - switch (TREE_CODE (IDENTIFIER_LOCAL_VALUE (name))) - { - case NAMESPACE_DECL: - /* A namespace is rejected only if we strictly require types. */ - if (prefer_type <= 1) - locval = IDENTIFIER_LOCAL_VALUE (name); - break; - case TYPE_DECL: - /* A type is rejected only if we strictly require namespaces. */ - if (!namespaces_only) - locval = IDENTIFIER_LOCAL_VALUE (name); - break; - default: - /* We require neither types or namespaces. */ - if (!namespaces_only && prefer_type <= 0) - locval = IDENTIFIER_LOCAL_VALUE (name); - break; - } + if (! namespace_bindings_p ()) + locval = qualify_lookup (IDENTIFIER_LOCAL_VALUE (name), flags); /* In C++ class fields are between local and global scope, just before the global scope. */ @@ -4972,6 +4997,8 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only) created the COMPONENT_REF or anything like that. */ if (classval == NULL_TREE) classval = lookup_nested_field (name, ! yylex); + + classval = qualify_lookup (classval, flags); } if (locval && classval) @@ -5003,7 +5030,7 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only) else if (classval) val = classval; else - val = unqualified_namespace_lookup (name, prefer_type, namespaces_only); + val = unqualified_namespace_lookup (name, flags); done: if (val) diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 2e8d569aa31..bd32d627dbc 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -60,7 +60,7 @@ static void finish_sigtable_vardecl PROTO((tree, tree)); static int is_namespace_ancestor PROTO((tree, tree)); static tree namespace_ancestor PROTO((tree, tree)); static void add_using_namespace PROTO((tree, tree, int)); -static tree ambiguous_decl PROTO((tree, tree, tree)); +static tree ambiguous_decl PROTO((tree, tree, tree,int)); static tree build_anon_union_vars PROTO((tree, tree*, int, int)); static void check_decl_namespace PROTO((void)); @@ -3857,15 +3857,21 @@ add_using_namespace (user, used, indirect) tree used; int indirect; { - tree iter; + tree t; /* 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; + t = purpose_member (used, DECL_NAMESPACE_USING (user)); + if (t != NULL_TREE) + { + if (!indirect) + /* Promote to direct usage. */ + TREE_INDIRECT_USING (t) = 0; + return; + } /* Add used to the user's using list. */ DECL_NAMESPACE_USING (user) @@ -3879,13 +3885,13 @@ add_using_namespace (user, used, indirect) = perm_tree_cons (user, 0, DECL_NAMESPACE_USERS (used)); /* Recursively add all namespaces used. */ - for (iter = DECL_NAMESPACE_USING (used); iter; iter = TREE_CHAIN (iter)) + for (t = DECL_NAMESPACE_USING (used); t; t = TREE_CHAIN (t)) /* indirect usage */ - add_using_namespace (user, TREE_PURPOSE (iter), 1); + add_using_namespace (user, TREE_PURPOSE (t), 1); /* Tell everyone using us about the new used namespaces. */ - for (iter = DECL_NAMESPACE_USERS (user); iter; iter = TREE_CHAIN (iter)) - add_using_namespace (TREE_PURPOSE (iter), used, 1); + for (t = DECL_NAMESPACE_USERS (user); t; t = TREE_CHAIN (t)) + add_using_namespace (TREE_PURPOSE (t), used, 1); } /* Combines two sets of overloaded functions into an OVERLOAD chain. @@ -3916,42 +3922,77 @@ merge_functions (s1, s2) XXX I don't want to repeat the entire duplicate_decls here */ static tree -ambiguous_decl (name, old, new) +ambiguous_decl (name, old, new, flags) tree name; tree old; tree new; + int flags; { + tree val, type; my_friendly_assert (old != NULL_TREE, 393); /* Copy the value. */ + val = BINDING_VALUE (new); + if (val) + switch (TREE_CODE (val)) + { + case TEMPLATE_DECL: + /* If we expect types or namespaces, and not templates, + or this is not a template class. */ + if (LOOKUP_QUALIFIERS_ONLY (flags) + && (!(flags & LOOKUP_TEMPLATES_EXPECTED) + || !DECL_CLASS_TEMPLATE_P (val))) + val = NULL_TREE; + break; + case TYPE_DECL: + if (LOOKUP_NAMESPACES_ONLY (flags)) + val = NULL_TREE; + break; + case NAMESPACE_DECL: + if (LOOKUP_TYPES_ONLY (flags)) + val = NULL_TREE; + break; + default: + if (LOOKUP_QUALIFIERS_ONLY (flags)) + val = NULL_TREE; + } + if (!BINDING_VALUE (old)) - BINDING_VALUE (old) = BINDING_VALUE (new); - else if (BINDING_VALUE (new) - && BINDING_VALUE (new) != BINDING_VALUE (old)) + BINDING_VALUE (old) = val; + else if (val && val != BINDING_VALUE (old)) { if (is_overloaded_fn (BINDING_VALUE (old)) - && is_overloaded_fn (BINDING_VALUE (new))) + && is_overloaded_fn (val)) { BINDING_VALUE (old) = merge_functions (BINDING_VALUE (old), - BINDING_VALUE (new)); + val); } else { /* Some declarations are functions, some are not. */ - cp_error ("use of `%D' is ambiguous", name); - cp_error_at (" first declared as `%#D' here", BINDING_VALUE (old)); - cp_error_at (" also declared as `%#D' here", BINDING_VALUE (new)); + if (flags & LOOKUP_COMPLAIN) + { + cp_error ("use of `%D' is ambiguous", name); + cp_error_at (" first declared as `%#D' here", + BINDING_VALUE (old)); + cp_error_at (" also declared as `%#D' here", val); + } return error_mark_node; } } /* ... and copy the type. */ + type = BINDING_TYPE (new); + if (LOOKUP_NAMESPACES_ONLY (flags)) + type = NULL_TREE; if (!BINDING_TYPE (old)) - BINDING_TYPE (old) = BINDING_TYPE (new); - else if(BINDING_TYPE (new) - && BINDING_TYPE (old) != BINDING_TYPE (new)) + BINDING_TYPE (old) = type; + else if(type && BINDING_TYPE (old) != type) { - cp_error ("`%D' denotes an ambiguous type",name); - cp_error_at ("first type here", BINDING_TYPE (old)); - cp_error_at ("other type here", BINDING_TYPE (new)); + if (flags & LOOKUP_COMPLAIN) + { + cp_error ("`%D' denotes an ambiguous type",name); + cp_error_at (" first type here", BINDING_TYPE (old)); + cp_error_at (" other type here", type); + } } return old; } @@ -3961,8 +4002,9 @@ ambiguous_decl (name, old, new) Returns zero on errors. */ int -lookup_using_namespace (name, val, usings, scope) +lookup_using_namespace (name, val, usings, scope, flags) tree name, val, usings, scope; + int flags; { tree iter; tree val1; @@ -3973,7 +4015,7 @@ lookup_using_namespace (name, val, usings, scope) { val1 = binding_for_name (name, TREE_PURPOSE (iter)); /* Resolve ambiguities. */ - val = ambiguous_decl (name, val, val1); + val = ambiguous_decl (name, val, val1, flags); } return val != error_mark_node; } @@ -3984,10 +4026,11 @@ lookup_using_namespace (name, val, usings, scope) or 0 on error. */ int -qualified_lookup_using_namespace (name, scope, result) +qualified_lookup_using_namespace (name, scope, result, flags) tree name; tree scope; tree result; + int flags; { /* Maintain a list of namespaces visited... */ tree seen = NULL_TREE; @@ -3997,7 +4040,8 @@ qualified_lookup_using_namespace (name, scope, result) while (scope && (result != error_mark_node)) { seen = temp_tree_cons (scope, NULL_TREE, seen); - result = ambiguous_decl (name, result, binding_for_name (name, scope)); + result = ambiguous_decl (name, result, + binding_for_name (name, scope), flags); if (!BINDING_VALUE (result) && !BINDING_TYPE (result)) /* Consider using directives. */ for (usings = DECL_NAMESPACE_USING (scope); usings; @@ -4437,7 +4481,7 @@ do_nonmember_using_decl (scope, name, oldval, oldtype, newval, newtype) *newval = *newtype = NULL_TREE; decls = binding_init (&_decls); - if (!qualified_lookup_using_namespace (name, scope, decls)) + if (!qualified_lookup_using_namespace (name, scope, decls, 0)) /* Lookup error */ return; diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index 62d061b6a44..8573a8543fe 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -3014,7 +3014,7 @@ do_scoped_id (token, parsing) { struct tree_binding _b; id = binding_init (&_b); - if (!qualified_lookup_using_namespace (token, global_namespace, id)) + if (!qualified_lookup_using_namespace (token, global_namespace, id, 0)) id = NULL_TREE; else id = BINDING_VALUE (id); -- 2.30.2