This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: PR 16965
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 17 Aug 2004 10:36:53 -0700
- Subject: C++ PATCH: PR 16965
- Reply-to: mark at codesourcery dot com
This patch fixes PR c++/16965, which is a case of an inferior error
message with the new C++ parser: the parser failed to distinguish
between an ambiguous lookup and a totally undeclared name.
Tested on i686-pc-linux-gnu, applied on the mainline.
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
2004-08-17 Mark Mitchell <mark@codesourcery.com>
PR c++/16965
* cp-tree.h (qualified_name_lookup_error): Add parameter.
* name-lookup.c (do_class_using_decl): Restrict set of entities
passed to cp_emit_debug_info_for_using more carefully.
(lookup_qualified_name): Allow lookup_member to return sets of
ambiguous entries.
* parser.c (cp_parser_lookup_name): Add ambiguous_p parameter.
(cp_parser_primary_expression): Handle ambiguous lookups.
(cp_parser_template_name): Adjust use of cp_parser_lookup_name.
(cp_parser_template_argument): Likewise.
(cp_parser_elaborate_type_specifier): Likewise.
(cp_parser_namespace_name): Likewise.
(cp_parser_class_name): Likewise.
(cp_parser_lookup_name_simple): Likewise.
* pt.c (tsubst_qualified_id): Handle ambiguous results.
(tsubst_expr): Likewise.
* semantics.c (qualified_name_lookup_error): Add decl paramter.
For ambiguous lookups, print candidates.
2004-08-17 Mark Mitchell <mark@codesourcery.com>
PR c++/16965
* g++.dg/parse/error17.C: New test.
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.1030
diff -c -5 -p -r1.1030 cp-tree.h
*** cp/cp-tree.h 16 Aug 2004 14:29:24 -0000 1.1030
--- cp/cp-tree.h 17 Aug 2004 17:31:08 -0000
*************** extern void finish_default_args
*** 4164,4174 ****
extern void finish_template_decl (tree);
extern tree finish_template_type (tree, tree, int);
extern tree finish_base_specifier (tree, tree, bool);
extern void finish_member_declaration (tree);
extern void check_multiple_declarators (void);
! extern void qualified_name_lookup_error (tree, tree);
extern tree finish_id_expression (tree, tree, tree,
cp_id_kind *, tree *,
bool, bool, bool *,
const char **);
extern tree finish_typeof (tree);
--- 4164,4174 ----
extern void finish_template_decl (tree);
extern tree finish_template_type (tree, tree, int);
extern tree finish_base_specifier (tree, tree, bool);
extern void finish_member_declaration (tree);
extern void check_multiple_declarators (void);
! extern void qualified_name_lookup_error (tree, tree, tree);
extern tree finish_id_expression (tree, tree, tree,
cp_id_kind *, tree *,
bool, bool, bool *,
const char **);
extern tree finish_typeof (tree);
Index: cp/name-lookup.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/name-lookup.c,v
retrieving revision 1.81
diff -c -5 -p -r1.81 name-lookup.c
*** cp/name-lookup.c 2 Aug 2004 18:49:06 -0000 1.81
--- cp/name-lookup.c 17 Aug 2004 17:31:08 -0000
*************** do_class_using_decl (tree decl)
*** 2951,2961 ****
if (scope && !processing_template_decl)
{
tree r;
r = lookup_qualified_name (scope, name, false, false);
! if (r && TREE_CODE (r) != ERROR_MARK)
cp_emit_debug_info_for_using (r, scope);
}
return value;
}
--- 2951,2961 ----
if (scope && !processing_template_decl)
{
tree r;
r = lookup_qualified_name (scope, name, false, false);
! if (r && (DECL_P (r) || TREE_CODE (r) == OVERLOAD))
cp_emit_debug_info_for_using (r, scope);
}
return value;
}
*************** unqualified_namespace_lookup (tree name,
*** 3811,3821 ****
or a class TYPE). If IS_TYPE_P is TRUE, then ignore non-type
bindings.
Returns a DECL (or OVERLOAD, or BASELINK) representing the
declaration found. If no suitable declaration can be found,
! ERROR_MARK_NODE is returned. Iif COMPLAIN is true and SCOPE is
neither a class-type nor a namespace a diagnostic is issued. */
tree
lookup_qualified_name (tree scope, tree name, bool is_type_p, bool complain)
{
--- 3811,3821 ----
or a class TYPE). If IS_TYPE_P is TRUE, then ignore non-type
bindings.
Returns a DECL (or OVERLOAD, or BASELINK) representing the
declaration found. If no suitable declaration can be found,
! ERROR_MARK_NODE is returned. If COMPLAIN is true and SCOPE is
neither a class-type nor a namespace a diagnostic is issued. */
tree
lookup_qualified_name (tree scope, tree name, bool is_type_p, bool complain)
{
*************** lookup_qualified_name (tree scope, tree
*** 3832,3842 ****
return select_decl (&binding, flags);
}
else if (is_aggr_type (scope, complain))
{
tree t;
! t = lookup_member (scope, name, 0, is_type_p);
if (t)
return t;
}
return error_mark_node;
--- 3832,3842 ----
return select_decl (&binding, flags);
}
else if (is_aggr_type (scope, complain))
{
tree t;
! t = lookup_member (scope, name, 2, is_type_p);
if (t)
return t;
}
return error_mark_node;
Index: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.236
diff -c -5 -p -r1.236 parser.c
*** cp/parser.c 12 Aug 2004 09:34:14 -0000 1.236
--- cp/parser.c 17 Aug 2004 17:31:08 -0000
*************** static void cp_parser_label_declaration
*** 1829,1839 ****
(cp_parser *);
/* Utility Routines */
static tree cp_parser_lookup_name
! (cp_parser *, tree, bool, bool, bool, bool);
static tree cp_parser_lookup_name_simple
(cp_parser *, tree);
static tree cp_parser_maybe_treat_template_as_class
(tree, bool);
static bool cp_parser_check_declarator_template_parameters
--- 1829,1839 ----
(cp_parser *);
/* Utility Routines */
static tree cp_parser_lookup_name
! (cp_parser *, tree, bool, bool, bool, bool, bool *);
static tree cp_parser_lookup_name_simple
(cp_parser *, tree);
static tree cp_parser_maybe_treat_template_as_class
(tree, bool);
static bool cp_parser_check_declarator_template_parameters
*************** cp_parser_primary_expression (cp_parser
*** 2903,2913 ****
|| TREE_CODE (id_expression) == TYPE_DECL)
decl = id_expression;
/* Look up the name. */
else
{
! decl = cp_parser_lookup_name_simple (parser, id_expression);
/* If name lookup gives us a SCOPE_REF, then the
qualifying scope was dependent. Just propagate the
name. */
if (TREE_CODE (decl) == SCOPE_REF)
{
--- 2903,2924 ----
|| TREE_CODE (id_expression) == TYPE_DECL)
decl = id_expression;
/* Look up the name. */
else
{
! bool ambiguous_p;
!
! decl = cp_parser_lookup_name (parser, id_expression,
! /*is_type=*/false,
! /*is_template=*/false,
! /*is_namespace=*/false,
! /*check_dependency=*/true,
! &ambiguous_p);
! /* If the lookup was ambiguous, an error will already have
! been issued. */
! if (ambiguous_p)
! return error_mark_node;
/* If name lookup gives us a SCOPE_REF, then the
qualifying scope was dependent. Just propagate the
name. */
if (TREE_CODE (decl) == SCOPE_REF)
{
*************** cp_parser_type_parameter (cp_parser* par
*** 8329,8339 ****
default_argument
= cp_parser_lookup_name (parser, default_argument,
/*is_type=*/false,
/*is_template=*/is_template,
/*is_namespace=*/false,
! /*check_dependency=*/true);
/* See if the default argument is valid. */
default_argument
= check_template_template_default_arg (default_argument);
}
else
--- 8340,8351 ----
default_argument
= cp_parser_lookup_name (parser, default_argument,
/*is_type=*/false,
/*is_template=*/is_template,
/*is_namespace=*/false,
! /*check_dependency=*/true,
! /*ambiguous_p=*/NULL);
/* See if the default argument is valid. */
default_argument
= check_template_template_default_arg (default_argument);
}
else
*************** cp_parser_template_name (cp_parser* pars
*** 8708,8718 ****
/* Look up the name. */
decl = cp_parser_lookup_name (parser, identifier,
/*is_type=*/false,
/*is_template=*/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)
;
--- 8720,8731 ----
/* Look up the name. */
decl = cp_parser_lookup_name (parser, identifier,
/*is_type=*/false,
/*is_template=*/false,
/*is_namespace=*/false,
! check_dependency_p,
! /*ambiguous_p=*/NULL);
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_template_argument (cp_parser*
*** 8898,8908 ****
if (TREE_CODE (argument) != TYPE_DECL)
argument = cp_parser_lookup_name (parser, argument,
/*is_type=*/false,
/*is_template=*/template_p,
/*is_namespace=*/false,
! /*check_dependency=*/true);
if (TREE_CODE (argument) != TEMPLATE_DECL
&& TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE)
cp_parser_error (parser, "expected template-name");
}
if (cp_parser_parse_definitely (parser))
--- 8911,8922 ----
if (TREE_CODE (argument) != TYPE_DECL)
argument = cp_parser_lookup_name (parser, argument,
/*is_type=*/false,
/*is_template=*/template_p,
/*is_namespace=*/false,
! /*check_dependency=*/true,
! /*ambiguous_p=*/NULL);
if (TREE_CODE (argument) != TEMPLATE_DECL
&& TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE)
cp_parser_error (parser, "expected template-name");
}
if (cp_parser_parse_definitely (parser))
*************** cp_parser_elaborated_type_specifier (cp_
*** 9751,9761 ****
cp_parser_lookup_name. */
decl = cp_parser_lookup_name (parser, identifier,
/*is_type=*/true,
/*is_template=*/false,
/*is_namespace=*/false,
! /*check_dependency=*/true);
/* If we are parsing friend declaration, DECL may be a
TEMPLATE_DECL tree node here. However, we need to check
whether this TEMPLATE_DECL results in valid code. Consider
the following example:
--- 9765,9776 ----
cp_parser_lookup_name. */
decl = cp_parser_lookup_name (parser, identifier,
/*is_type=*/true,
/*is_template=*/false,
/*is_namespace=*/false,
! /*check_dependency=*/true,
! /*ambiguous_p=*/NULL);
/* If we are parsing friend declaration, DECL may be a
TEMPLATE_DECL tree node here. However, we need to check
whether this TEMPLATE_DECL results in valid code. Consider
the following example:
*************** cp_parser_namespace_name (cp_parser* par
*** 10027,10037 ****
operator.) */
namespace_decl = cp_parser_lookup_name (parser, identifier,
/*is_type=*/false,
/*is_template=*/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");
--- 10042,10053 ----
operator.) */
namespace_decl = cp_parser_lookup_name (parser, identifier,
/*is_type=*/false,
/*is_template=*/false,
/*is_namespace=*/true,
! /*check_dependency=*/true,
! /*ambiguous_p=*/NULL);
/* 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,
*** 12237,12247 ****
/* Look up the name. */
decl = cp_parser_lookup_name (parser, identifier,
type_p,
/*is_template=*/false,
/*is_namespace=*/false,
! check_dependency_p);
}
}
else
{
/* Try a template-id. */
--- 12253,12264 ----
/* Look up the name. */
decl = cp_parser_lookup_name (parser, identifier,
type_p,
/*is_template=*/false,
/*is_namespace=*/false,
! check_dependency_p,
! /*ambiguous_p=*/NULL);
}
}
else
{
/* Try a template-id. */
*************** cp_parser_label_declaration (cp_parser*
*** 14119,14138 ****
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 is_type, bool is_template, 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
no longer valid. Note that if we are parsing tentatively, and
the parse fails, OBJECT_TYPE will be automatically restored. */
parser->context->object_type = NULL_TREE;
--- 14136,14163 ----
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.
!
! If AMBIGUOUS_P is non-NULL, it is set to true if name-lookup
! results in an ambiguity, and false otherwise. */
static tree
cp_parser_lookup_name (cp_parser *parser, tree name,
bool is_type, bool is_template, bool is_namespace,
! bool check_dependency,
! bool *ambiguous_p)
{
tree decl;
tree object_type = parser->context->object_type;
+ /* Assume that the lookup will be unambiguous. */
+ if (ambiguous_p)
+ *ambiguous_p = false;
+
/* 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
the parse fails, OBJECT_TYPE will be automatically restored. */
parser->context->object_type = NULL_TREE;
*************** cp_parser_lookup_name (cp_parser *parser
*** 14276,14285 ****
--- 14301,14312 ----
return error_mark_node;
/* 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;
/* 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))
{
error ("reference to `%D' is ambiguous", name);
*************** cp_parser_lookup_name_simple (cp_parser*
*** 14317,14327 ****
{
return cp_parser_lookup_name (parser, name,
/*is_type=*/false,
/*is_template=*/false,
/*is_namespace=*/false,
! /*check_dependency=*/true);
}
/* If DECL is a TEMPLATE_DECL that can be treated like a TYPE_DECL in
the current context, return the TYPE_DECL. If TAG_NAME_P is
true, the DECL indicates the class being defined in a class-head,
--- 14344,14355 ----
{
return cp_parser_lookup_name (parser, name,
/*is_type=*/false,
/*is_template=*/false,
/*is_namespace=*/false,
! /*check_dependency=*/true,
! /*ambiguous_p=*/NULL);
}
/* If DECL is a TEMPLATE_DECL that can be treated like a TYPE_DECL in
the current context, return the TYPE_DECL. If TAG_NAME_P is
true, the DECL indicates the class being defined in a class-head,
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.905
diff -c -5 -p -r1.905 pt.c
*** cp/pt.c 16 Aug 2004 14:29:25 -0000 1.905
--- cp/pt.c 17 Aug 2004 17:31:08 -0000
*************** tsubst_qualified_id (tree qualified_id,
*** 7394,7415 ****
return error_mark_node;
}
}
if (DECL_P (expr))
! check_accessibility_of_qualified_id (expr, /*object_type=*/NULL_TREE,
! scope);
!
! /* Remember that there was a reference to this entity. */
! if (DECL_P (expr))
! mark_used (expr);
if (is_template)
expr = lookup_template_function (expr, template_args);
if (expr == error_mark_node && complain & tf_error)
! qualified_name_lookup_error (scope, TREE_OPERAND (qualified_id, 1));
else if (TYPE_P (scope))
{
expr = (adjust_result_of_qualified_name_lookup
(expr, scope, current_class_type));
expr = finish_qualified_id_expr (scope, expr, done, address_p);
--- 7394,7425 ----
return error_mark_node;
}
}
if (DECL_P (expr))
! {
! check_accessibility_of_qualified_id (expr, /*object_type=*/NULL_TREE,
! scope);
! /* Remember that there was a reference to this entity. */
! mark_used (expr);
! }
!
! if (expr == error_mark_node || TREE_CODE (expr) == TREE_LIST)
! {
! if (complain & tf_error)
! qualified_name_lookup_error (scope,
! TREE_OPERAND (qualified_id, 1),
! expr);
! return error_mark_node;
! }
if (is_template)
expr = lookup_template_function (expr, template_args);
if (expr == error_mark_node && complain & tf_error)
! qualified_name_lookup_error (scope, TREE_OPERAND (qualified_id, 1),
! expr);
else if (TYPE_P (scope))
{
expr = (adjust_result_of_qualified_name_lookup
(expr, scope, current_class_type));
expr = finish_qualified_id_expr (scope, expr, done, address_p);
*************** tsubst_expr (tree t, tree args, tsubst_f
*** 7853,7864 ****
scope = tsubst_expr (scope, args, complain, in_decl);
decl = lookup_qualified_name (scope, name,
/*is_type_p=*/false,
/*complain=*/false);
! if (decl == error_mark_node)
! qualified_name_lookup_error (scope, name);
else
do_local_using_decl (decl, scope, name);
}
else
{
--- 7863,7874 ----
scope = tsubst_expr (scope, args, complain, in_decl);
decl = lookup_qualified_name (scope, name,
/*is_type_p=*/false,
/*complain=*/false);
! if (decl == error_mark_node || TREE_CODE (decl) == TREE_LIST)
! qualified_name_lookup_error (scope, name, decl);
else
do_local_using_decl (decl, scope, name);
}
else
{
*************** tsubst_copy_and_build (tree t,
*** 8508,8518 ****
BASELINK_FUNCTIONS (member)
= build_nt (TEMPLATE_ID_EXPR, BASELINK_FUNCTIONS (member),
args);
else
{
! qualified_name_lookup_error (TREE_TYPE (object), tmpl);
return error_mark_node;
}
}
else if (TREE_CODE (member) == SCOPE_REF
&& !CLASS_TYPE_P (TREE_OPERAND (member, 0))
--- 8518,8529 ----
BASELINK_FUNCTIONS (member)
= build_nt (TEMPLATE_ID_EXPR, BASELINK_FUNCTIONS (member),
args);
else
{
! qualified_name_lookup_error (TREE_TYPE (object), tmpl,
! member);
return error_mark_node;
}
}
else if (TREE_CODE (member) == SCOPE_REF
&& !CLASS_TYPE_P (TREE_OPERAND (member, 0))
Index: cp/semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/semantics.c,v
retrieving revision 1.423
diff -c -5 -p -r1.423 semantics.c
*** cp/semantics.c 16 Aug 2004 02:08:02 -0000 1.423
--- cp/semantics.c 17 Aug 2004 17:31:08 -0000
*************** check_multiple_declarators (void)
*** 2288,2306 ****
|| processing_explicit_instantiation
|| processing_specialization)
error ("multiple declarators in template declaration");
}
! /* Issue a diagnostic that NAME cannot be found in SCOPE. */
void
! qualified_name_lookup_error (tree scope, tree name)
{
if (TYPE_P (scope))
{
if (!COMPLETE_TYPE_P (scope))
error ("incomplete type `%T' used in nested name specifier", scope);
else
error ("`%D' is not a member of `%T'", name, scope);
}
else if (scope != global_namespace)
error ("`%D' is not a member of `%D'", name, scope);
--- 2288,2312 ----
|| processing_explicit_instantiation
|| processing_specialization)
error ("multiple declarators in template declaration");
}
! /* Issue a diagnostic that NAME cannot be found in SCOPE. DECL is
! what we found when we tried to do the lookup. */
void
! qualified_name_lookup_error (tree scope, tree name, tree decl)
{
if (TYPE_P (scope))
{
if (!COMPLETE_TYPE_P (scope))
error ("incomplete type `%T' used in nested name specifier", scope);
+ else if (TREE_CODE (decl) == TREE_LIST)
+ {
+ error ("reference to `%T::%D' is ambiguous", scope, name);
+ print_candidates (decl);
+ }
else
error ("`%D' is not a member of `%T'", name, scope);
}
else if (scope != global_namespace)
error ("`%D' is not a member of `%D'", name, scope);
*************** finish_id_expression (tree id_expression
*** 2372,2382 ****
&& dependent_type_p (TREE_TYPE (id_expression))))))
{
/* If the qualifying type is non-dependent (and the name
does not name a conversion operator to a dependent
type), issue an error. */
! qualified_name_lookup_error (scope, id_expression);
return error_mark_node;
}
else if (!scope)
{
/* It may be resolved via Koenig lookup. */
--- 2378,2388 ----
&& dependent_type_p (TREE_TYPE (id_expression))))))
{
/* If the qualifying type is non-dependent (and the name
does not name a conversion operator to a dependent
type), issue an error. */
! qualified_name_lookup_error (scope, id_expression, decl);
return error_mark_node;
}
else if (!scope)
{
/* It may be resolved via Koenig lookup. */
Index: testsuite/g++.dg/parse/error17.C
===================================================================
RCS file: testsuite/g++.dg/parse/error17.C
diff -N testsuite/g++.dg/parse/error17.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/parse/error17.C 17 Aug 2004 17:31:09 -0000
***************
*** 0 ****
--- 1,8 ----
+ // PR c++/16965
+
+ template <typename T> struct B {
+ static int Bar(T); // { dg-error "" }
+ };
+ struct D : B<int>, B<char> {};
+
+ int i2 = D::Bar(2); // { dg-error "" }