diff --git a/gcc/cp/call.c b/gcc/cp/call.c index a9323cc1f91d9517f6c83b7a079e7732e1325a76..6f677a5243b22674c6b94b2612d1fa8ad1ad226e 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -2651,7 +2651,7 @@ resolve_scoped_fn_name (tree scope, tree name) /* It might be the name of a function pointer member. */ if (fn && TREE_CODE (fn) == FIELD_DECL) - fn = finish_non_static_data_member (fn, scope); + fn = finish_non_static_data_member (fn, current_class_ref, scope); } if (!fn) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 1728b379353547b963ea148ff2ae5159fd832c1d..4f2a1432e4661761a1c6c63c2b0a61b244a6688a 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4129,7 +4129,7 @@ extern tree finish_label_stmt (tree); 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 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); diff --git a/gcc/cp/method.c b/gcc/cp/method.c index e1ffaad3769ae53aef72a6d4cc65689e8e4155cd..fdc026b3476f19f58284522a520bf2ea8728e28f 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -117,7 +117,7 @@ hack_identifier (tree value, tree name) type = TREE_TYPE (value); if (TREE_CODE (value) == FIELD_DECL) - value = finish_non_static_data_member (value, + 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)) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index bbce47e769aeb0c3f5b12d19bef589168f65e890..9d66c3c0addb66e8bce54069819db9a1e4a67f3d 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -8273,6 +8273,8 @@ tsubst_copy_and_build (tree t, 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); } diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 3d704ebe194258a5fd4c0c5a65e1f044f276a4d7..812ef6df2dc11277337a104dbc177fd0e54eed2a 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -1218,11 +1218,11 @@ finish_parenthesized_expr (tree expr) preceded by `.' or `->'. */ tree -finish_non_static_data_member (tree decl, tree qualifying_scope) +finish_non_static_data_member (tree decl, tree object, tree qualifying_scope) { my_friendly_assert (TREE_CODE (decl) == FIELD_DECL, 20020909); - if (current_class_ptr == NULL_TREE) + if (!object) { if (current_function_decl && DECL_STATIC_FUNCTION_P (current_function_decl)) @@ -1236,27 +1236,42 @@ finish_non_static_data_member (tree decl, tree qualifying_scope) } 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; + tree type = TREE_TYPE (decl); - while (access_type - && !DERIVED_FROM_P (context_for_name_lookup (decl), access_type)) + if (TREE_CODE (type) == REFERENCE_TYPE) + type = TREE_TYPE (type); + else + { + /* Set the cv qualifiers */ + int quals = cp_type_quals (TREE_TYPE (current_class_ref)); + + if (DECL_MUTABLE_P (decl)) + quals &= ~TYPE_QUAL_CONST; + + quals |= cp_type_quals (TREE_TYPE (decl)); + type = cp_build_qualified_type (type, quals); + } + + 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; + 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); @@ -1357,7 +1372,8 @@ finish_qualified_id_expr (tree qualifying_class, tree expr, bool done, } if (TREE_CODE (expr) == FIELD_DECL) - expr = finish_non_static_data_member (expr, qualifying_class); + expr = finish_non_static_data_member (expr, current_class_ref, + qualifying_class); else if (BASELINK_P (expr) && !processing_template_decl) { tree fn; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 60a68bb9b01fcb92d6f3428db357025ef737451e..4a3fcb97aca14f284268cd41cc1005d62bc4090b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2003-07-18 Nathan Sidwell <nathan@codesourcery.com> + + * g++.dg/parse/non-dependent2.C: New test. + 2003-07-18 Andrew Pinski <pinskia@physics.uc.edu> * g++.dg/init/init-ref4.C: xfail on targets without diff --git a/gcc/testsuite/g++.dg/parse/non-dependent2.C b/gcc/testsuite/g++.dg/parse/non-dependent2.C new file mode 100644 index 0000000000000000000000000000000000000000..46335c56bcce9c0abbebdf1864a1569a2d773920 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/non-dependent2.C @@ -0,0 +1,37 @@ +// { 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; +}