diff options
author | Mark Mitchell <mark@codesourcery.com> | 2005-11-14 01:45:19 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2005-11-14 01:45:19 +0000 |
commit | 91b1ca65f39ecca8525536d3f4dfa80144e68afd (patch) | |
tree | 773dff07d2e51d7d8497844932653849d2201ca9 /gcc/cp/parser.c | |
parent | 43258b67a9f414823ec75d2b9c2d9596c6317824 (diff) | |
download | gcc-91b1ca65f39ecca8525536d3f4dfa80144e68afd.zip gcc-91b1ca65f39ecca8525536d3f4dfa80144e68afd.tar.gz gcc-91b1ca65f39ecca8525536d3f4dfa80144e68afd.tar.bz2 |
re PR c++/20293 (Wrong diagnostic for ambiguous access)
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.
From-SVN: r106879
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r-- | gcc/cp/parser.c | 131 |
1 files changed, 90 insertions, 41 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index bbc5c11..2b850c0 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 |