C++ PATCH: Fix namespace lookup bug
Mark Mitchell
mark@codesourcery.com
Tue Dec 31 19:14:00 GMT 2002
This patch fixes the problem that Gaby, Neil, and I discussed today;
names before "::" are looked up ignoring objects, functions, and
enumerators that might be found.
Tested on i686-pc-linux-gnu, applied on the mainline.
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
2002-12-31 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (LOOKUP_TEMPLATES_EXPECTED): Remove.
(lookup_name_namespace_only): Likewise.
(begin_only_namespace_names): Likewise.
(end_only_namespace_names): Likewise.
* decl.c (only_namespace_names): Remove.
(qualify_lookup): Do not check LOOKUP_TEMPLATES_EXPECTED.
(lookup_name_real): Do not check only_namespace_names.
(lookup_name_namespace_only): Remove.
(begin_only_namespace_names): Likewise.
(end_only_namespace_names): Likewise.
* parser.c (cp_parser_nested_name_specifier_opt): Handle erroneous
nested-name-specifiers more gracefully.
(cp_parser_class_or_namespace_name): Avoid looking up namespace
names when they cannot possibly appear.
(cp_parser_template_name): Adjust call to cp_parser_lookup_name.
(cp_parser_elaborated_type_specifier): Likewise.
(cp_parser_namespace_name): Only look for namespace names.
(cp_parser_lookup_name): Add is_namespace parameter.
(cp_parser_lookup_name_simple): Adjust call to
cp_parser_lookup_name.
2002-12-31 Mark Mitchell <mark@codesourcery.com>
* g++.dg/parse/namespace1.C: New test.
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.791
diff -c -5 -p -r1.791 cp-tree.h
*** cp/cp-tree.h 31 Dec 2002 19:43:14 -0000 1.791
--- cp/cp-tree.h 1 Jan 2003 02:40:24 -0000
*************** enum overload_flags { NO_SPECIAL = 0, DT
*** 3383,3395 ****
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)
#define LOOKUP_NORMAL (3)
#define LOOKUP_NONVIRTUAL (8)
--- 3383,3393 ----
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. */
#define LOOKUP_PROTECT (1)
#define LOOKUP_COMPLAIN (2)
#define LOOKUP_NORMAL (3)
#define LOOKUP_NONVIRTUAL (8)
*************** enum overload_flags { NO_SPECIAL = 0, DT
*** 3401,3411 ****
#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))
--- 3399,3408 ----
*************** extern tree lookup_name_nonclass PARAMS
*** 3736,3749 ****
extern tree lookup_function_nonclass PARAMS ((tree, tree));
extern tree lookup_qualified_name (tree, tree, bool, int);
extern tree lookup_name PARAMS ((tree, int));
extern tree lookup_name_current_level PARAMS ((tree));
extern tree lookup_type_current_level PARAMS ((tree));
- extern tree lookup_name_namespace_only PARAMS ((tree));
extern tree lookup_name_real (tree, int, int, int, int);
- extern void begin_only_namespace_names PARAMS ((void));
- extern void end_only_namespace_names PARAMS ((void));
extern tree namespace_ancestor PARAMS ((tree, tree));
extern tree unqualified_namespace_lookup PARAMS ((tree, int, tree *));
extern tree check_for_out_of_scope_variable (tree);
extern bool lookup_using_namespace (tree, tree, tree, tree, int, tree *);
extern bool qualified_lookup_using_namespace (tree, tree, tree, int);
--- 3733,3743 ----
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.977
diff -c -5 -p -r1.977 decl.c
*** cp/decl.c 31 Dec 2002 18:58:05 -0000 1.977
--- cp/decl.c 1 Jan 2003 02:40:27 -0000
*************** tree cp_global_trees[CPTI_MAX];
*** 205,217 ****
/* Indicates that there is a type value in some namespace, although
that is not necessarily in scope at the moment. */
static GTY(()) tree global_type_node;
- /* Expect only namespace names now. */
- static int only_namespace_names;
-
/* Used only for jumps to as-yet undefined labels, since jumps to
defined labels can have their validity checked immediately. */
struct named_label_use_list GTY(())
{
--- 205,214 ----
*************** qualify_lookup (val, flags)
*** 5929,5942 ****
{
if (val == NULL_TREE)
return val;
if ((flags & LOOKUP_PREFER_NAMESPACES) && TREE_CODE (val) == NAMESPACE_DECL)
return val;
! if ((flags & LOOKUP_PREFER_TYPES)
! && (TREE_CODE (val) == TYPE_DECL
! || ((flags & LOOKUP_TEMPLATES_EXPECTED)
! && DECL_CLASS_TEMPLATE_P (val))))
return val;
if (flags & (LOOKUP_PREFER_NAMESPACES | LOOKUP_PREFER_TYPES))
return NULL_TREE;
return val;
}
--- 5926,5936 ----
{
if (val == NULL_TREE)
return val;
if ((flags & LOOKUP_PREFER_NAMESPACES) && TREE_CODE (val) == NAMESPACE_DECL)
return val;
! if ((flags & LOOKUP_PREFER_TYPES) && TREE_CODE (val) == TYPE_DECL)
return val;
if (flags & (LOOKUP_PREFER_NAMESPACES | LOOKUP_PREFER_TYPES))
return NULL_TREE;
return val;
}
*************** lookup_name_real (tree name,
*** 6103,6116 ****
}
return NULL_TREE;
}
- /* Hack: copy flag set by parser, if set. */
- if (only_namespace_names)
- namespaces_only = 1;
-
flags |= lookup_flags (prefer_type, namespaces_only);
/* First, look in non-namespace scopes. */
if (current_class_type == NULL_TREE)
--- 6097,6106 ----
*************** lookup_function_nonclass (name, args)
*** 6182,6199 ****
{
return lookup_arg_dependent (name, lookup_name_nonclass (name), args);
}
tree
- lookup_name_namespace_only (name)
- tree name;
- {
- /* type-or-namespace, nonclass, namespace_only */
- return lookup_name_real (name, 1, 1, 1, LOOKUP_COMPLAIN);
- }
-
- tree
lookup_name (name, prefer_type)
tree name;
int prefer_type;
{
return lookup_name_real (name, prefer_type, 0, 0, LOOKUP_COMPLAIN);
--- 6172,6181 ----
*************** lookup_type_current_level (name)
*** 6265,6285 ****
}
return t;
}
- void
- begin_only_namespace_names ()
- {
- only_namespace_names = 1;
- }
-
- void
- end_only_namespace_names ()
- {
- only_namespace_names = 0;
- }
/* Push the declarations of builtin types into the namespace.
RID_INDEX is the index of the builtin type
in the array RID_POINTERS. NAME is the name used when looking
up the builtin type. TYPE is the _TYPE node for the builtin type. */
--- 6247,6256 ----
Index: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.10
diff -c -5 -p -r1.10 parser.c
*** cp/parser.c 31 Dec 2002 20:28:27 -0000 1.10
--- cp/parser.c 1 Jan 2003 02:40:29 -0000
*************** static void cp_parser_label_declaration
*** 1682,1692 ****
PARAMS ((cp_parser *));
/* Utility Routines */
static tree cp_parser_lookup_name
! PARAMS ((cp_parser *, tree, bool, bool, bool));
static tree cp_parser_lookup_name_simple
PARAMS ((cp_parser *, tree));
static tree cp_parser_resolve_typename_type
PARAMS ((cp_parser *, tree));
static tree cp_parser_maybe_treat_template_as_class
--- 1682,1692 ----
PARAMS ((cp_parser *));
/* Utility Routines */
static tree cp_parser_lookup_name
! PARAMS ((cp_parser *, tree, bool, bool, bool, bool));
static tree cp_parser_lookup_name_simple
PARAMS ((cp_parser *, tree));
static tree cp_parser_resolve_typename_type
PARAMS ((cp_parser *, tree));
static tree cp_parser_maybe_treat_template_as_class
*************** cp_parser_nested_name_specifier_opt (cp_
*** 3556,3565 ****
--- 3556,3574 ----
else
error ("`%D' is not a class-name or namespace-name",
token->value);
parser->scope = NULL_TREE;
error_p = true;
+ /* Treat this as a successful nested-name-specifier
+ due to:
+
+ [basic.lookup.qual]
+
+ If the name found is not a class-name (clause
+ _class_) or namespace-name (_namespace.def_), the
+ program is ill-formed. */
+ success = true;
}
cp_lexer_consume_token (parser->lexer);
}
break;
}
*************** cp_parser_nested_name_specifier (cp_pars
*** 3661,3671 ****
TYPE_P is TRUE iff the next name should be taken as a class-name,
even the same name is declared to be another entity in the same
scope.
Returns the class (TYPE_DECL) or namespace (NAMESPACE_DECL)
! specified by the class-or-namespace-name. */
static tree
cp_parser_class_or_namespace_name (cp_parser *parser,
bool typename_keyword_p,
bool template_keyword_p,
--- 3670,3681 ----
TYPE_P is TRUE iff the next name should be taken as a class-name,
even the same name is declared to be another entity in the same
scope.
Returns the class (TYPE_DECL) or namespace (NAMESPACE_DECL)
! specified by the class-or-namespace-name. If neither is found the
! ERROR_MARK_NODE is returned. */
static tree
cp_parser_class_or_namespace_name (cp_parser *parser,
bool typename_keyword_p,
bool template_keyword_p,
*************** cp_parser_class_or_namespace_name (cp_pa
*** 3674,3683 ****
--- 3684,3694 ----
{
tree saved_scope;
tree saved_qualifying_scope;
tree saved_object_scope;
tree scope;
+ bool only_class_p;
/* If the next token is the `template' keyword, we know that we are
looking at a class-name. */
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TEMPLATE))
return cp_parser_class_name (parser,
*************** cp_parser_class_or_namespace_name (cp_pa
*** 3691,3717 ****
current PARSER->SCOPE since cp_parser_class_name will destroy
it. */
saved_scope = parser->scope;
saved_qualifying_scope = parser->qualifying_scope;
saved_object_scope = parser->object_scope;
! /* Try for a class-name first. */
! cp_parser_parse_tentatively (parser);
scope = cp_parser_class_name (parser,
typename_keyword_p,
template_keyword_p,
type_p,
/*check_access_p=*/true,
check_dependency_p,
/*class_head_p=*/false);
/* If that didn't work, try for a namespace-name. */
! if (!cp_parser_parse_definitely (parser))
{
/* Restore the saved scope. */
parser->scope = saved_scope;
parser->qualifying_scope = saved_qualifying_scope;
parser->object_scope = saved_object_scope;
! /* Now look for a namespace-name. */
scope = cp_parser_namespace_name (parser);
}
return scope;
}
--- 3702,3737 ----
current PARSER->SCOPE since cp_parser_class_name will destroy
it. */
saved_scope = parser->scope;
saved_qualifying_scope = parser->qualifying_scope;
saved_object_scope = parser->object_scope;
! /* Try for a class-name first. If the SAVED_SCOPE is a type, then
! there is no need to look for a namespace-name. */
! only_class_p = saved_scope && TYPE_P (saved_scope);
! if (!only_class_p)
! cp_parser_parse_tentatively (parser);
scope = cp_parser_class_name (parser,
typename_keyword_p,
template_keyword_p,
type_p,
/*check_access_p=*/true,
check_dependency_p,
/*class_head_p=*/false);
/* If that didn't work, try for a namespace-name. */
! if (!only_class_p && !cp_parser_parse_definitely (parser))
{
/* Restore the saved scope. */
parser->scope = saved_scope;
parser->qualifying_scope = saved_qualifying_scope;
parser->object_scope = saved_object_scope;
! /* If we are not looking at an identifier followed by the scope
! resolution operator, then this is not part of a
! nested-name-specifier. (Note that this function is only used
! to parse the components of a nested-name-specifier.) */
! if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME)
! || cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_SCOPE)
! return error_mark_node;
scope = cp_parser_namespace_name (parser);
}
return scope;
}
*************** cp_parser_template_name (parser, templat
*** 8223,8232 ****
--- 8243,8253 ----
/* Look up the name. */
decl = cp_parser_lookup_name (parser, identifier,
/*check_access=*/true,
/*is_type=*/false,
+ /*is_namespace=*/false,
check_dependency_p);
decl = maybe_get_template_decl_from_type_decl (decl);
/* If DECL is a template, then the name was a template-name. */
if (TREE_CODE (decl) == TEMPLATE_DECL)
*************** cp_parser_elaborated_type_specifier (par
*** 8964,8973 ****
--- 8985,8995 ----
types, so we set IS_TYPE to TRUE when calling
cp_parser_lookup_name. */
decl = cp_parser_lookup_name (parser, identifier,
/*check_access=*/true,
/*is_type=*/true,
+ /*is_namespace=*/false,
/*check_dependency=*/true);
decl = (cp_parser_maybe_treat_template_as_class
(decl, /*tag_name_p=*/is_friend));
if (TREE_CODE (decl) != TYPE_DECL)
*************** cp_parser_namespace_name (parser)
*** 9191,9202 ****
/* Get the name of the namespace. */
identifier = cp_parser_identifier (parser);
if (identifier == error_mark_node)
return error_mark_node;
! /* Look up the identifier in the currently active scope. */
! namespace_decl = cp_parser_lookup_name_simple (parser, identifier);
/* If it's not a namespace, issue an error. */
if (namespace_decl == error_mark_node
|| TREE_CODE (namespace_decl) != NAMESPACE_DECL)
{
cp_parser_error (parser, "expected namespace-name");
--- 9213,9245 ----
/* Get the name of the namespace. */
identifier = cp_parser_identifier (parser);
if (identifier == error_mark_node)
return error_mark_node;
! /* Look up the identifier in the currently active scope. Look only
! for namespaces, due to:
!
! [basic.lookup.udir]
!
! When looking up a namespace-name in a using-directive or alias
! definition, only namespace names are considered.
!
! And:
!
! [basic.lookup.qual]
!
! During the lookup of a name preceding the :: scope resolution
! operator, object, function, and enumerator names are ignored.
!
! (Note that cp_parser_class_or_namespace_name only calls this
! function if the token after the name is the scope resolution
! operator.) */
! namespace_decl = cp_parser_lookup_name (parser, identifier,
! /*check_access=*/true,
! /*is_type=*/false,
! /*is_namespace=*/true,
! /*check_dependency=*/true);
/* If it's not a namespace, issue an error. */
if (namespace_decl == error_mark_node
|| TREE_CODE (namespace_decl) != NAMESPACE_DECL)
{
cp_parser_error (parser, "expected namespace-name");
*************** cp_parser_class_name (cp_parser *parser,
*** 11404,11413 ****
--- 11447,11457 ----
type_p = true;
/* Look up the name. */
decl = cp_parser_lookup_name (parser, identifier,
check_access_p,
type_p,
+ /*is_namespace=*/false,
check_dependency_p);
}
}
else
{
*************** cp_parser_label_declaration (parser)
*** 13266,13286 ****
issued if the declaration is inaccessible.
If IS_TYPE is TRUE, bindings that do not refer to types are
ignored.
If CHECK_DEPENDENCY is TRUE, names are not looked up in dependent
types. */
static tree
! cp_parser_lookup_name (parser, name, check_access, is_type,
! check_dependency)
! cp_parser *parser;
! tree name;
! bool check_access;
! bool is_type;
! bool check_dependency;
{
tree decl;
tree object_type = parser->context->object_type;
/* Now that we have looked up the name, the OBJECT_TYPE (if any) is
--- 13310,13328 ----
issued if the declaration is inaccessible.
If IS_TYPE is TRUE, bindings that do not refer to types are
ignored.
+ If IS_NAMESPACE is TRUE, bindings that do not refer to namespaces
+ are ignored.
+
If CHECK_DEPENDENCY is TRUE, names are not looked up in dependent
types. */
static tree
! cp_parser_lookup_name (cp_parser *parser, tree name, bool check_access,
! bool is_type, bool is_namespace, bool check_dependency)
{
tree decl;
tree object_type = parser->context->object_type;
/* Now that we have looked up the name, the OBJECT_TYPE (if any) is
*************** cp_parser_lookup_name (parser, name, che
*** 13394,13414 ****
object_decl = lookup_member (object_type,
name,
/*protect=*/0, is_type);
/* Look it up in the enclosing context, too. */
decl = lookup_name_real (name, is_type, /*nonclass=*/0,
! /*namespaces_only=*/0,
/*flags=*/0);
parser->object_scope = object_type;
parser->qualifying_scope = NULL_TREE;
if (object_decl)
decl = object_decl;
}
else
{
decl = lookup_name_real (name, is_type, /*nonclass=*/0,
! /*namespaces_only=*/0,
/*flags=*/0);
parser->qualifying_scope = NULL_TREE;
parser->object_scope = NULL_TREE;
}
--- 13436,13456 ----
object_decl = lookup_member (object_type,
name,
/*protect=*/0, is_type);
/* Look it up in the enclosing context, too. */
decl = lookup_name_real (name, is_type, /*nonclass=*/0,
! is_namespace,
/*flags=*/0);
parser->object_scope = object_type;
parser->qualifying_scope = NULL_TREE;
if (object_decl)
decl = object_decl;
}
else
{
decl = lookup_name_real (name, is_type, /*nonclass=*/0,
! is_namespace,
/*flags=*/0);
parser->qualifying_scope = NULL_TREE;
parser->object_scope = NULL_TREE;
}
*************** cp_parser_lookup_name_simple (parser, na
*** 13479,13489 ****
cp_parser *parser;
tree name;
{
return cp_parser_lookup_name (parser, name,
/*check_access=*/true,
! /*is_type=*/false,
/*check_dependency=*/true);
}
/* TYPE is a TYPENAME_TYPE. Returns the ordinary TYPE to which the
TYPENAME_TYPE corresponds. Note that this function peers inside
--- 13521,13532 ----
cp_parser *parser;
tree name;
{
return cp_parser_lookup_name (parser, name,
/*check_access=*/true,
! /*is_type=*/false,
! /*is_namespace=*/false,
/*check_dependency=*/true);
}
/* TYPE is a TYPENAME_TYPE. Returns the ordinary TYPE to which the
TYPENAME_TYPE corresponds. Note that this function peers inside
Index: testsuite/g++.dg/parse/namespace1.C
===================================================================
RCS file: testsuite/g++.dg/parse/namespace1.C
diff -N testsuite/g++.dg/parse/namespace1.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/parse/namespace1.C 1 Jan 2003 02:40:30 -0000
***************
*** 0 ****
--- 1,7 ----
+ namespace foo {
+ void baz(int);
+ }
+
+ int bar(int foo) {
+ foo::baz (3);
+ }
More information about the Gcc-patches
mailing list