diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 921550ed4b2f9cec3f3e0364be9389c77554ceaa..3f4c1d0319bb848b93b8b587a8ca5d049bbfd8b4 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,13 @@ 2002-12-24 Nathan Sidwell <nathan@codesourcery.com> + PR C++/7964 + * cp-tree.h (resolve_scoped_fn_name): Prototype. + * call.c (resolve_scoped_fn_name): New function. Deal with + more template expansion. Broken out of ... + * parse.y (parse_finish_call_expr): ... here. Call it. + * decl2.c (build_expr_from_tree, CALL_EXPR): Use + resolve_scoped_fn_name and build_call_from_tree. + PR c++/9053 * decl.c (duplicate_decls): Templates may be disambiguated by return type. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index f1d46ba06bf8be4b189d67c8c5408755f6c22e61..088cc1e46e5ff08116457d56e30d06f0444bad28 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -2597,6 +2597,69 @@ build_user_type_conversion (tree totype, tree expr, int flags) return NULL_TREE; } +/* Find the possibly overloaded set of functions corresponding to a + call of the form SCOPE::NAME (...). NAME might be a + TEMPLATE_ID_EXPR, OVERLOAD, _DECL, IDENTIFIER_NODE or LOOKUP_EXPR. */ + +tree +resolve_scoped_fn_name (tree scope, tree name) +{ + tree fn; + tree template_args = NULL_TREE; + bool is_template_id = TREE_CODE (name) == TEMPLATE_ID_EXPR; + + if (is_template_id) + { + template_args = TREE_OPERAND (name, 1); + name = TREE_OPERAND (name, 0); + } + if (TREE_CODE (name) == OVERLOAD) + name = DECL_NAME (get_first_fn (name)); + else if (TREE_CODE (name) == LOOKUP_EXPR) + name = TREE_OPERAND (name, 0); + + if (TREE_CODE (scope) == NAMESPACE_DECL) + fn = lookup_namespace_name (scope, name); + else + { + if (!TYPE_BEING_DEFINED (scope) + && !COMPLETE_TYPE_P (complete_type (scope))) + { + error ("incomplete type '%T' cannot be used to name a scope", + scope); + return error_mark_node; + } + + if (BASELINK_P (name)) + fn = name; + else + fn = lookup_member (scope, name, /*protect=*/1, /*prefer_type=*/0); + if (fn && current_class_type) + fn = (adjust_result_of_qualified_name_lookup + (fn, scope, current_class_type)); + } + + if (!fn) + { + error ("'%D' has no member named '%E'", scope, name); + return error_mark_node; + } + if (is_template_id) + { + tree fns = fn; + + if (BASELINK_P (fn)) + fns = BASELINK_FUNCTIONS (fns); + fns = build_nt (TEMPLATE_ID_EXPR, fns, template_args); + if (BASELINK_P (fn)) + BASELINK_FUNCTIONS (fn) = fns; + else + fn = fns; + } + + return fn; +} + /* Do any initial processing on the arguments to a function call. */ static tree diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 121aabac9e41ed55bd7271cfc9ca88514436e0f6..b805f976419d73f7a3372ac156eae0866e1c562e 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -3547,6 +3547,7 @@ extern tree build_method_call (tree, tree, tree, tree, int); extern bool null_ptr_cst_p (tree); extern bool sufficient_parms_p (tree); extern tree type_decays_to (tree); +extern tree resolve_scoped_fn_name (tree, tree); extern tree build_user_type_conversion (tree, tree, int); extern tree build_new_function_call (tree, tree); extern tree build_new_method_call (tree, tree, tree, tree, int); diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index afb8693a6b730643285377b96e6318ca008cd848..3d717e8475b94cbea1e70eb03a0ec0be0085d012 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -3241,16 +3241,18 @@ build_expr_from_tree (t) { tree ref = TREE_OPERAND (t, 0); tree name = TREE_OPERAND (ref, 1); + tree fn, scope, args; if (TREE_CODE (name) == TEMPLATE_ID_EXPR) name = build_nt (TEMPLATE_ID_EXPR, TREE_OPERAND (name, 0), build_expr_from_tree (TREE_OPERAND (name, 1))); - - return build_member_call - (build_expr_from_tree (TREE_OPERAND (ref, 0)), - name, - build_expr_from_tree (TREE_OPERAND (t, 1))); + + scope = build_expr_from_tree (TREE_OPERAND (ref, 0)); + args = build_expr_from_tree (TREE_OPERAND (t, 1)); + fn = resolve_scoped_fn_name (scope, name); + + return build_call_from_tree (fn, args, 1); } else { diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index bdbee018e5ab9672137abbb4820de259d0cf43c5..d1f9f4d68b4725e17521a9d2974edc4851bcab5b 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -4115,72 +4115,19 @@ static tree parse_finish_call_expr (tree fn, tree args, int koenig) { bool disallow_virtual; - tree template_args; - tree template_id; - tree f; if (TREE_CODE (fn) == OFFSET_REF) return build_offset_ref_call_from_tree (fn, args); if (TREE_CODE (fn) == SCOPE_REF) { - tree scope; - tree name; - - scope = TREE_OPERAND (fn, 0); - name = TREE_OPERAND (fn, 1); + tree scope = TREE_OPERAND (fn, 0); + tree name = TREE_OPERAND (fn, 1); if (scope == error_mark_node || name == error_mark_node) return error_mark_node; if (!processing_template_decl) - { - if (TREE_CODE (scope) == NAMESPACE_DECL) - fn = lookup_namespace_name (scope, name); - else - { - if (!COMPLETE_TYPE_P (scope) && !TYPE_BEING_DEFINED (scope)) - { - error ("incomplete type '%T' cannot be used to name a scope", - scope); - return error_mark_node; - } - else if (TREE_CODE (name) == TEMPLATE_ID_EXPR) - { - template_id = name; - template_args = TREE_OPERAND (name, 1); - name = TREE_OPERAND (name, 0); - } - else - { - template_id = NULL_TREE; - template_args = NULL_TREE; - } - - if (BASELINK_P (name)) - fn = name; - else - { - if (TREE_CODE (name) == OVERLOAD) - name = DECL_NAME (get_first_fn (name)); - fn = lookup_member (scope, name, /*protect=*/1, - /*prefer_type=*/0); - if (!fn) - { - error ("'%D' has no member named '%E'", scope, name); - return error_mark_node; - } - - if (BASELINK_P (fn) && template_id) - BASELINK_FUNCTIONS (fn) - = build_nt (TEMPLATE_ID_EXPR, - BASELINK_FUNCTIONS (fn), - template_args); - } - if (current_class_type) - fn = (adjust_result_of_qualified_name_lookup - (fn, scope, current_class_type)); - } - } + fn = resolve_scoped_fn_name (scope, name); disallow_virtual = true; } else @@ -4188,6 +4135,8 @@ parse_finish_call_expr (tree fn, tree args, int koenig) if (koenig && TREE_CODE (fn) == IDENTIFIER_NODE) { + tree f; + /* Do the Koenig lookup. */ fn = do_identifier (fn, 2, args); /* If name lookup didn't find any matching declarations, we've diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b40420e24c3d490229a6f7d56c903872ba78d254..8196168626b8bc36083b2c0e573f16e186463e56 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,7 @@ 2002-12-24 Nathan Sidwell <nathan@codesourcery.com> - + + * g++.dg/lookup/scoped3.C: New test. + * g++.dg/lookup/decl1.C: New test. * g++.dg/lookup/decl2.C: New test. diff --git a/gcc/testsuite/g++.dg/lookup/scoped3.C b/gcc/testsuite/g++.dg/lookup/scoped3.C new file mode 100644 index 0000000000000000000000000000000000000000..992f1d1280939da35959ac314dcad448c964380e --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/scoped3.C @@ -0,0 +1,23 @@ + +// { dg-do compile } + +// Copyright (C) 2002 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 24 Dec 2002 <nathan@codesourcery.com> + +// PR 7964. ICE with scoped method call + +struct A { + virtual void ostr() const; +}; + +class B : public virtual A {}; + +template<typename T> +struct C : public B +{ + void ostr() const + { B::ostr(); } +}; + + +template C<int>;