aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2005-11-14 01:45:19 +0000
committerMark Mitchell <mark@codesourcery.com>2005-11-14 01:45:19 +0000
commit9a27a2990555a7539d45861411b808a0458cb9a5 (patch)
tree773dff07d2e51d7d8497844932653849d2201ca9 /gcc/cp
parentc615af8d7390152fa890efa34a59aa59eecce6f9 (diff)
PR c++/20293
* cxx-pretty-print.c (pp_cxx_statement): Print qualifying scopes for namespaces. (pp_cxx_original_namespace_definition): Likewise. * name-lookup.c (ambiguous_decl): Don't issue error messages; instead return lists of ambiguous candidates. (select_decl): Handle ambiguous namespace lookups. * parser.c (cp_token): Add ambiguous_p. (cp_lexer_get_preprocessor_token): Set it. (cp_parser_diagnose_invalid_type_name): Avoid duplicate messages when a qualified name uses an invalid scope. (cp_parser_primary_expression): Print ambiguous candidates. (cp_parser_type_parameter): Adjust comment to reflect new parameter name for cp_parser_lookup_name. (cp_parser_template_argument): Likewise. (cp_parser_elaborated_type_specifier): Likewise. (cp_parser_namespace_name): Likewise. (cp_parser_class_name): Print ambiguous candidates. (cp_parser_lookup_name): Rename ambiguous_p parameter to ambiguous_decls. Use it to return a list of ambiguous candiates when a lookup is ambiguous. (cp_parser_lookup_name_simple): Adjust comment to reflect new parameter name for cp_parser_lookup_name. PR c++/20293 * g++.dg/parse/ambig4.C: New test. * g++.dg/tc1/dr101.C: Adjust error markers. * g++.dg/lookup/strong-using-2.C: Likewise. * g++.dg/lookup/ambig5.C: Likewise. * g++.dg/lookup/ambig4.C: Likewise. * g++.dg/parse/crash22.C: Likewise. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@106879 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog26
-rw-r--r--gcc/cp/cxx-pretty-print.c9
-rw-r--r--gcc/cp/name-lookup.c20
-rw-r--r--gcc/cp/parser.c131
4 files changed, 130 insertions, 56 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 6edab04fe2b..4fafe495d2e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,29 @@
+2005-11-13 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/20293
+ * cxx-pretty-print.c (pp_cxx_statement): Print qualifying scopes
+ for namespaces.
+ (pp_cxx_original_namespace_definition): Likewise.
+ * name-lookup.c (ambiguous_decl): Don't issue error messages;
+ instead return lists of ambiguous candidates.
+ (select_decl): Handle ambiguous namespace lookups.
+ * parser.c (cp_token): Add ambiguous_p.
+ (cp_lexer_get_preprocessor_token): Set it.
+ (cp_parser_diagnose_invalid_type_name): Avoid duplicate messages
+ when a qualified name uses an invalid scope.
+ (cp_parser_primary_expression): Print ambiguous candidates.
+ (cp_parser_type_parameter): Adjust comment to reflect new
+ parameter name for cp_parser_lookup_name.
+ (cp_parser_template_argument): Likewise.
+ (cp_parser_elaborated_type_specifier): Likewise.
+ (cp_parser_namespace_name): Likewise.
+ (cp_parser_class_name): Print ambiguous candidates.
+ (cp_parser_lookup_name): Rename ambiguous_p parameter to
+ ambiguous_decls. Use it to return a list of ambiguous candiates
+ when a lookup is ambiguous.
+ (cp_parser_lookup_name_simple): Adjust comment to reflect new
+ parameter name for cp_parser_lookup_name.
+
2005-11-12 Jakub Jelinek <jakub@redhat.com>
PR c++/24780
diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c
index f4f8819d1ed..cdaf470ce26 100644
--- a/gcc/cp/cxx-pretty-print.c
+++ b/gcc/cp/cxx-pretty-print.c
@@ -1514,6 +1514,8 @@ pp_cxx_statement (cxx_pretty_printer *pp, tree t)
case USING_STMT:
pp_cxx_identifier (pp, "using");
pp_cxx_identifier (pp, "namespace");
+ if (DECL_CONTEXT (t))
+ pp_cxx_nested_name_specifier (pp, DECL_CONTEXT (t));
pp_cxx_qualified_id (pp, USING_STMT_NAMESPACE (t));
break;
@@ -1701,6 +1703,8 @@ static void
pp_cxx_original_namespace_definition (cxx_pretty_printer *pp, tree t)
{
pp_cxx_identifier (pp, "namespace");
+ if (DECL_CONTEXT (t))
+ pp_cxx_nested_name_specifier (pp, DECL_CONTEXT (t));
if (DECL_NAME (t))
pp_cxx_unqualified_id (pp, t);
pp_cxx_whitespace (pp);
@@ -1723,10 +1727,15 @@ static void
pp_cxx_namespace_alias_definition (cxx_pretty_printer *pp, tree t)
{
pp_cxx_identifier (pp, "namespace");
+ if (DECL_CONTEXT (t))
+ pp_cxx_nested_name_specifier (pp, DECL_CONTEXT (t));
pp_cxx_unqualified_id (pp, t);
pp_cxx_whitespace (pp);
pp_equal (pp);
pp_cxx_whitespace (pp);
+ if (DECL_CONTEXT (DECL_NAMESPACE_ALIAS (t)))
+ pp_cxx_nested_name_specifier (pp,
+ DECL_CONTEXT (DECL_NAMESPACE_ALIAS (t)));
pp_cxx_qualified_id (pp, DECL_NAMESPACE_ALIAS (t));
pp_cxx_semicolon (pp);
}
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 13d789b1f56..20ea311196f 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -3400,20 +3400,9 @@ ambiguous_decl (tree name, struct scope_binding *old, cxx_binding *new,
old->value = merge_functions (old->value, val);
else
{
- /* Some declarations are functions, some are not. */
- if (flags & LOOKUP_COMPLAIN)
- {
- /* If we've already given this error for this lookup,
- old->value is error_mark_node, so let's not
- repeat ourselves. */
- if (old->value != error_mark_node)
- {
- error ("use of %qD is ambiguous", name);
- error (" first declared as %q+#D here", old->value);
- }
- error (" also declared as %q+#D here", val);
- }
- old->value = error_mark_node;
+ old->value = tree_cons (NULL_TREE, old->value,
+ build_tree_list (NULL_TREE, new->value));
+ TREE_TYPE (old->value) = error_mark_node;
}
}
/* ... and copy the type. */
@@ -3609,7 +3598,8 @@ select_decl (const struct scope_binding *binding, int flags)
if (LOOKUP_NAMESPACES_ONLY (flags))
{
/* We are not interested in types. */
- if (val && TREE_CODE (val) == NAMESPACE_DECL)
+ if (val && (TREE_CODE (val) == NAMESPACE_DECL
+ || TREE_CODE (val) == TREE_LIST))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index bbc5c1156bd..2b850c0d197 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -59,6 +59,10 @@ typedef struct cp_token GTY (())
BOOL_BITFIELD in_system_header : 1;
/* True if this token is from a context where it is implicitly extern "C" */
BOOL_BITFIELD implicit_extern_c : 1;
+ /* True for a CPP_NAME token that is not a keyword (i.e., for which
+ KEYWORD is RID_MAX) iff this name was looked up and found to be
+ ambiguous. An error has already been reported. */
+ BOOL_BITFIELD ambiguous_p : 1;
/* The value associated with this token, if any. */
tree value;
/* The location at which this token was found. */
@@ -401,18 +405,22 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
token->implicit_extern_c = is_extern_c > 0;
/* Check to see if this token is a keyword. */
- if (token->type == CPP_NAME
- && C_IS_RESERVED_WORD (token->value))
+ if (token->type == CPP_NAME)
{
- /* Mark this token as a keyword. */
- token->type = CPP_KEYWORD;
- /* Record which keyword. */
- token->keyword = C_RID_CODE (token->value);
- /* Update the value. Some keywords are mapped to particular
- entities, rather than simply having the value of the
- corresponding IDENTIFIER_NODE. For example, `__const' is
- mapped to `const'. */
- token->value = ridpointers[token->keyword];
+ if (C_IS_RESERVED_WORD (token->value))
+ {
+ /* Mark this token as a keyword. */
+ token->type = CPP_KEYWORD;
+ /* Record which keyword. */
+ token->keyword = C_RID_CODE (token->value);
+ /* Update the value. Some keywords are mapped to particular
+ entities, rather than simply having the value of the
+ corresponding IDENTIFIER_NODE. For example, `__const' is
+ mapped to `const'. */
+ token->value = ridpointers[token->keyword];
+ }
+ else
+ token->ambiguous_p = false;
}
/* Handle Objective-C++ keywords. */
else if (token->type == CPP_AT_NAME)
@@ -1699,7 +1707,7 @@ static tree cp_parser_objc_statement
/* Utility Routines */
static tree cp_parser_lookup_name
- (cp_parser *, tree, enum tag_types, bool, bool, bool, bool *);
+ (cp_parser *, tree, enum tag_types, bool, bool, bool, tree *);
static tree cp_parser_lookup_name_simple
(cp_parser *, tree);
static tree cp_parser_maybe_treat_template_as_class
@@ -2052,7 +2060,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
if (TREE_CODE (decl) == TEMPLATE_DECL)
error ("invalid use of template-name %qE without an argument list",
decl);
- else if (!parser->scope || parser->scope == error_mark_node)
+ else if (!parser->scope)
{
/* Issue an error message. */
error ("%qE does not name a type", id);
@@ -2099,7 +2107,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
}
/* Here we diagnose qualified-ids where the scope is actually correct,
but the identifier does not resolve to a valid type name. */
- else
+ else if (parser->scope != error_mark_node)
{
if (TREE_CODE (parser->scope) == NAMESPACE_DECL)
error ("%qE in namespace %qE does not name a type",
@@ -2994,17 +3002,17 @@ cp_parser_primary_expression (cp_parser *parser,
/* Look up the name. */
else
{
- bool ambiguous_p;
+ tree ambiguous_decls;
decl = cp_parser_lookup_name (parser, id_expression,
none_type,
template_p,
/*is_namespace=*/false,
/*check_dependency=*/true,
- &ambiguous_p);
+ &ambiguous_decls);
/* If the lookup was ambiguous, an error will already have
been issued. */
- if (ambiguous_p)
+ if (ambiguous_decls)
return error_mark_node;
/* In Objective-C++, an instance variable (ivar) may be preferred
@@ -3610,16 +3618,32 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
token = cp_lexer_consume_token (parser->lexer);
if (!error_p)
{
- tree decl;
-
- decl = cp_parser_lookup_name_simple (parser, token->value);
- if (TREE_CODE (decl) == TEMPLATE_DECL)
- error ("%qD used without template parameters", decl);
- else
- cp_parser_name_lookup_error
- (parser, token->value, decl,
- "is not a class or namespace");
- parser->scope = NULL_TREE;
+ if (!token->ambiguous_p)
+ {
+ tree decl;
+ tree ambiguous_decls;
+
+ decl = cp_parser_lookup_name (parser, token->value,
+ none_type,
+ /*is_template=*/false,
+ /*is_namespace=*/false,
+ /*check_dependency=*/true,
+ &ambiguous_decls);
+ if (TREE_CODE (decl) == TEMPLATE_DECL)
+ error ("%qD used without template parameters", decl);
+ else if (ambiguous_decls)
+ {
+ error ("reference to %qD is ambiguous",
+ token->value);
+ print_candidates (ambiguous_decls);
+ decl = error_mark_node;
+ }
+ else
+ cp_parser_name_lookup_error
+ (parser, token->value, decl,
+ "is not a class or namespace");
+ }
+ parser->scope = error_mark_node;
error_p = true;
/* Treat this as a successful nested-name-specifier
due to:
@@ -8457,7 +8481,7 @@ cp_parser_type_parameter (cp_parser* parser)
/*is_template=*/is_template,
/*is_namespace=*/false,
/*check_dependency=*/true,
- /*ambiguous_p=*/NULL);
+ /*ambiguous_decls=*/NULL);
/* See if the default argument is valid. */
default_argument
= check_template_template_default_arg (default_argument);
@@ -8813,7 +8837,7 @@ cp_parser_template_name (cp_parser* parser,
/*is_template=*/false,
/*is_namespace=*/false,
check_dependency_p,
- /*ambiguous_p=*/NULL);
+ /*ambiguous_decls=*/NULL);
decl = maybe_get_template_decl_from_type_decl (decl);
/* If DECL is a template, then the name was a template-name. */
@@ -9014,7 +9038,7 @@ cp_parser_template_argument (cp_parser* parser)
/*is_template=*/template_p,
/*is_namespace=*/false,
/*check_dependency=*/true,
- /*ambiguous_p=*/NULL);
+ /*ambiguous_decls=*/NULL);
if (TREE_CODE (argument) != TEMPLATE_DECL
&& TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE)
cp_parser_error (parser, "expected template-name");
@@ -9937,7 +9961,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
/*is_template=*/false,
/*is_namespace=*/false,
/*check_dependency=*/true,
- /*ambiguous_p=*/NULL);
+ /*ambiguous_decls=*/NULL);
/* If we are parsing friend declaration, DECL may be a
TEMPLATE_DECL tree node here. However, we need to check
@@ -10233,7 +10257,7 @@ cp_parser_namespace_name (cp_parser* parser)
/*is_template=*/false,
/*is_namespace=*/true,
/*check_dependency=*/true,
- /*ambiguous_p=*/NULL);
+ /*ambiguous_decls=*/NULL);
/* If it's not a namespace, issue an error. */
if (namespace_decl == error_mark_node
|| TREE_CODE (namespace_decl) != NAMESPACE_DECL)
@@ -12469,9 +12493,13 @@ cp_parser_class_name (cp_parser *parser,
if (token->type == CPP_NAME
&& !cp_parser_nth_token_starts_template_argument_list_p (parser, 2))
{
+ cp_token *identifier_token;
tree identifier;
+ bool ambiguous_p;
/* Look for the identifier. */
+ identifier_token = cp_lexer_peek_token (parser->lexer);
+ ambiguous_p = identifier_token->ambiguous_p;
identifier = cp_parser_identifier (parser);
/* If the next token isn't an identifier, we are certainly not
looking at a class-name. */
@@ -12483,6 +12511,15 @@ cp_parser_class_name (cp_parser *parser,
decl = identifier;
else
{
+ tree ambiguous_decls;
+ /* If we already know that this lookup is ambiguous, then
+ we've already issued an error message; there's no reason
+ to check again. */
+ if (ambiguous_p)
+ {
+ cp_parser_simulate_error (parser);
+ return error_mark_node;
+ }
/* If the next token is a `::', then the name must be a type
name.
@@ -12499,7 +12536,18 @@ cp_parser_class_name (cp_parser *parser,
/*is_template=*/false,
/*is_namespace=*/false,
check_dependency_p,
- /*ambiguous_p=*/NULL);
+ &ambiguous_decls);
+ if (ambiguous_decls)
+ {
+ error ("reference to %qD is ambiguous", identifier);
+ print_candidates (ambiguous_decls);
+ if (cp_parser_parsing_tentatively (parser))
+ {
+ identifier_token->ambiguous_p = true;
+ cp_parser_simulate_error (parser);
+ }
+ return error_mark_node;
+ }
}
}
else
@@ -14438,8 +14486,9 @@ cp_parser_label_declaration (cp_parser* parser)
If CHECK_DEPENDENCY is TRUE, names are not looked up in dependent
types.
- If AMBIGUOUS_P is non-NULL, it is set to true if name-lookup
- results in an ambiguity, and false otherwise. */
+ If AMBIGUOUS_DECLS is non-NULL, *AMBIGUOUS_DECLS is set to a
+ TREE_LIST of candiates if name-lookup results in an ambiguity, and
+ NULL_TREE otherwise. */
static tree
cp_parser_lookup_name (cp_parser *parser, tree name,
@@ -14447,7 +14496,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
bool is_template,
bool is_namespace,
bool check_dependency,
- bool *ambiguous_p)
+ tree *ambiguous_decls)
{
int flags = 0;
tree decl;
@@ -14457,8 +14506,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
flags |= LOOKUP_COMPLAIN;
/* Assume that the lookup will be unambiguous. */
- if (ambiguous_p)
- *ambiguous_p = false;
+ if (ambiguous_decls)
+ *ambiguous_decls = NULL_TREE;
/* Now that we have looked up the name, the OBJECT_TYPE (if any) is
no longer valid. Note that if we are parsing tentatively, and
@@ -14615,8 +14664,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
/* If it's a TREE_LIST, the result of the lookup was ambiguous. */
if (TREE_CODE (decl) == TREE_LIST)
{
- if (ambiguous_p)
- *ambiguous_p = true;
+ if (ambiguous_decls)
+ *ambiguous_decls = decl;
/* The error message we have to print is too complicated for
cp_parser_error, so we incorporate its actions directly. */
if (!cp_parser_simulate_error (parser))
@@ -14658,7 +14707,7 @@ cp_parser_lookup_name_simple (cp_parser* parser, tree name)
/*is_template=*/false,
/*is_namespace=*/false,
/*check_dependency=*/true,
- /*ambiguous_p=*/NULL);
+ /*ambiguous_decls=*/NULL);
}
/* If DECL is a TEMPLATE_DECL that can be treated like a TYPE_DECL in