summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/call.c63
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl2.c12
-rw-r--r--gcc/cp/parse.y61
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/lookup/scoped3.C23
7 files changed, 110 insertions, 62 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 921550ed4b2..3f4c1d0319b 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 f1d46ba06bf..088cc1e46e5 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 121aabac9e4..b805f976419 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 afb8693a6b7..3d717e8475b 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 bdbee018e5a..d1f9f4d68b4 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 b40420e24c3..8196168626b 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 00000000000..992f1d12809
--- /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>;