diff options
author | Mark Mitchell <mark@codesourcery.com> | 2005-11-14 01:45:19 +0000 |
---|---|---|
committer | Mark Mitchell <mark@codesourcery.com> | 2005-11-14 01:45:19 +0000 |
commit | 9a27a2990555a7539d45861411b808a0458cb9a5 (patch) | |
tree | 773dff07d2e51d7d8497844932653849d2201ca9 /gcc/cp | |
parent | c615af8d7390152fa890efa34a59aa59eecce6f9 (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/ChangeLog | 26 | ||||
-rw-r--r-- | gcc/cp/cxx-pretty-print.c | 9 | ||||
-rw-r--r-- | gcc/cp/name-lookup.c | 20 | ||||
-rw-r--r-- | gcc/cp/parser.c | 131 |
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 |