This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH]: name lookup fix
- From: Nathan Sidwell <nathan at codesourcery dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>, Mark Mitchell <mark at codesourcery dot com>
- Date: Thu, 17 Jul 2003 13:29:34 +0100
- Subject: [C++ PATCH]: name lookup fix
- Organization: Codesourcery LLC
Hi,
this patch fixes a name lookup issue. In a template definition, when 'i'
refers to a field of a non-dependent base, the expression is non-dependent,
and should not be looked up again at instantiation time.
booted & tested on i686-pc-linux-gnu, ok?
nathan
--
Nathan Sidwell :: http://www.codesourcery.com :: CodeSourcery LLC
The voices in my head said this was stupid too
nathan@codesourcery.com :: http://www.planetfall.pwp.blueyonder.co.uk
2003-07-16 Nathan Sidwell <nathan@codesourcery.com>
* cp-tree.h (finish_non_static_data_member): Add object param.
* method.c (hack_identifier): Adjust.
* pt.c (tsubst_copy_and_build) <COMPONENT_REF case>: Don't search
again for a FIELD_DECL.
* semantics.c (finish_non_static_data_member): Add object
parameter. Always save the DECL in the COMPONENT_REF.
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.877
diff -c -3 -p -r1.877 cp-tree.h
*** cp/cp-tree.h 14 Jul 2003 19:05:01 -0000 1.877
--- cp/cp-tree.h 16 Jul 2003 16:54:21 -0000
*************** extern tree finish_label_stmt
*** 4126,4132 ****
extern void finish_label_decl (tree);
extern void finish_subobject (tree);
extern tree finish_parenthesized_expr (tree);
! extern tree finish_non_static_data_member (tree, tree);
extern tree begin_stmt_expr (void);
extern tree finish_stmt_expr (tree);
extern tree perform_koenig_lookup (tree, tree);
--- 4127,4133 ----
extern void finish_label_decl (tree);
extern void finish_subobject (tree);
extern tree finish_parenthesized_expr (tree);
! extern tree finish_non_static_data_member (tree, tree, tree);
extern tree begin_stmt_expr (void);
extern tree finish_stmt_expr (tree);
extern tree perform_koenig_lookup (tree, tree);
Index: cp/method.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/method.c,v
retrieving revision 1.260
diff -c -3 -p -r1.260 method.c
*** cp/method.c 8 Jul 2003 01:38:44 -0000 1.260
--- cp/method.c 16 Jul 2003 16:54:23 -0000
*************** hack_identifier (tree value, tree name)
*** 117,123 ****
type = TREE_TYPE (value);
if (TREE_CODE (value) == FIELD_DECL)
! value = finish_non_static_data_member (value,
/*qualifying_scope=*/NULL_TREE);
else if ((TREE_CODE (value) == FUNCTION_DECL
&& DECL_FUNCTION_MEMBER_P (value))
--- 117,123 ----
type = TREE_TYPE (value);
if (TREE_CODE (value) == FIELD_DECL)
! value = finish_non_static_data_member (value, current_class_ref,
/*qualifying_scope=*/NULL_TREE);
else if ((TREE_CODE (value) == FUNCTION_DECL
&& DECL_FUNCTION_MEMBER_P (value))
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.726
diff -c -3 -p -r1.726 pt.c
*** cp/pt.c 14 Jul 2003 21:32:25 -0000 1.726
--- cp/pt.c 16 Jul 2003 16:55:19 -0000
*************** tsubst_copy_and_build (tree t,
*** 8291,8296 ****
--- 8291,8298 ----
return error_mark_node;
}
}
+ else if (TREE_CODE (member) == FIELD_DECL)
+ return finish_non_static_data_member (member, object, NULL_TREE);
return finish_class_member_access_expr (object, member);
}
Index: cp/semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/semantics.c,v
retrieving revision 1.327
diff -c -3 -p -r1.327 semantics.c
*** cp/semantics.c 14 Jul 2003 19:05:02 -0000 1.327
--- cp/semantics.c 16 Jul 2003 16:55:25 -0000
*************** finish_parenthesized_expr (tree expr)
*** 1218,1228 ****
preceded by `.' or `->'. */
tree
! finish_non_static_data_member (tree decl, tree qualifying_scope)
{
my_friendly_assert (TREE_CODE (decl) == FIELD_DECL, 20020909);
! if (current_class_ptr == NULL_TREE)
{
if (current_function_decl
&& DECL_STATIC_FUNCTION_P (current_function_decl))
--- 1218,1228 ----
preceded by `.' or `->'. */
tree
! finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
{
my_friendly_assert (TREE_CODE (decl) == FIELD_DECL, 20020909);
! if (!object)
{
if (current_function_decl
&& DECL_STATIC_FUNCTION_P (current_function_decl))
*************** finish_non_static_data_member (tree decl
*** 1236,1262 ****
}
TREE_USED (current_class_ptr) = 1;
if (processing_template_decl)
- return build_min (COMPONENT_REF, TREE_TYPE (decl),
- current_class_ref, DECL_NAME (decl));
- else
{
! tree access_type = current_class_type;
! tree object = current_class_ref;
! while (access_type
! && !DERIVED_FROM_P (context_for_name_lookup (decl), access_type))
{
access_type = TYPE_CONTEXT (access_type);
while (access_type && DECL_P (access_type))
access_type = DECL_CONTEXT (access_type);
- }
! if (!access_type)
! {
! cp_error_at ("object missing in reference to `%D'",
! decl);
! error ("from this location");
! return error_mark_node;
}
perform_or_defer_access_check (TYPE_BINFO (access_type), decl);
--- 1236,1271 ----
}
TREE_USED (current_class_ptr) = 1;
if (processing_template_decl)
{
! tree type = TREE_TYPE (decl);
!
! if (TREE_CODE (type) == REFERENCE_TYPE)
! type = TREE_TYPE (type);
! else if (!DECL_MUTABLE_P (decl))
! /* Set the cv qualifiers */
! type = cp_build_qualified_type
! (type, (cp_type_quals (TREE_TYPE (current_class_ref))
! | cp_type_quals (TREE_TYPE (decl))));
! return build_min (COMPONENT_REF, type, object, decl);
! }
! else
! {
! tree access_type = TREE_TYPE (object);
! tree lookup_context = context_for_name_lookup (decl);
!
! while (!DERIVED_FROM_P (lookup_context, access_type))
{
access_type = TYPE_CONTEXT (access_type);
while (access_type && DECL_P (access_type))
access_type = DECL_CONTEXT (access_type);
! if (!access_type)
! {
! cp_error_at ("object missing in reference to `%D'", decl);
! error ("from this location");
! return error_mark_node;
! }
}
perform_or_defer_access_check (TYPE_BINFO (access_type), decl);
*************** finish_qualified_id_expr (tree qualifyin
*** 1357,1363 ****
}
if (TREE_CODE (expr) == FIELD_DECL)
! expr = finish_non_static_data_member (expr, qualifying_class);
else if (BASELINK_P (expr) && !processing_template_decl)
{
tree fn;
--- 1366,1373 ----
}
if (TREE_CODE (expr) == FIELD_DECL)
! expr = finish_non_static_data_member (expr, current_class_ref,
! qualifying_class);
else if (BASELINK_P (expr) && !processing_template_decl)
{
tree fn;
// { dg-do compile }
// Copyright (C) 2003 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 16 Jul 2003 <nathan@codesourcery.com>
// A non-dependent field_decl can bind at parse time.
template <class T>
struct Foo {
int j; // we never see this one.
int k; // { dg-error "" "" }
};
struct Baz
{
int j;
int k; // { dg-error "" "" }
};
template <class T>
struct Bar : public Foo<T>, Baz {
int baz () { return j; } // binds to Baz::j
int foo () { return this->k; } // { dg-error "request for member" "" }
};
int main()
{
Bar<int> bar;
bar.baz ();
bar.foo ();
return 0;
}