aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@markmitchell.com>1998-06-12 09:47:04 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>1998-06-12 09:47:04 +0000
commit2a238a974bdff827ac0d0928ca9fe10ff59e683a (patch)
treee7672496825b85cd9dad0dd7a5fe954b17903b9d /gcc
parent77a45a2ea44010cabd700d777ac8b3557021bafa (diff)
downloadgcc-2a238a974bdff827ac0d0928ca9fe10ff59e683a.zip
gcc-2a238a974bdff827ac0d0928ca9fe10ff59e683a.tar.gz
gcc-2a238a974bdff827ac0d0928ca9fe10ff59e683a.tar.bz2
class.c (instantiate_type): Don't treat template-ids that don't specify any template arguments as...
* class.c (instantiate_type): Don't treat template-ids that don't specify any template arguments as equivalent to ordinary identifiers. Use OFFSET_REF instead of SCOPE_REF to refer to pointer-to-members for member templates. Tidy slightly. * cp-tree.def (TEMPLATE_ID_EXPR): Revise documentation. * init.c (build_offset_ref): Handle template-ids like ordinary identifiers, for the most part, but store a TEMPLATE_ID_EXPR in the offset part of the OFFSET_REF. * typeck.c (build_unary_op): Change check for unknown types to look for OFFSET_REFs, not SCOPE_REFs. From-SVN: r20442
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog13
-rw-r--r--gcc/cp/class.c83
-rw-r--r--gcc/cp/cp-tree.def2
-rw-r--r--gcc/cp/init.c38
-rw-r--r--gcc/cp/typeck.c2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/ptrmem1.C8
6 files changed, 94 insertions, 52 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 5539b4c..aced365 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,16 @@
+1998-06-12 Mark Mitchell <mark@markmitchell.com>
+
+ * class.c (instantiate_type): Don't treat template-ids that don't
+ specify any template arguments as equivalent to ordinary
+ identifiers. Use OFFSET_REF instead of SCOPE_REF to refer to
+ pointer-to-members for member templates. Tidy slightly.
+ * cp-tree.def (TEMPLATE_ID_EXPR): Revise documentation.
+ * init.c (build_offset_ref): Handle template-ids like ordinary
+ identifiers, for the most part, but store a TEMPLATE_ID_EXPR in the
+ offset part of the OFFSET_REF.
+ * typeck.c (build_unary_op): Change check for unknown types to
+ look for OFFSET_REFs, not SCOPE_REFs.
+
1998-06-11 Mark Mitchell <mark@markmitchell.com>
* pt.c (is_member_template_class): New function.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 0e1aa26..6e3942f 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -4961,6 +4961,7 @@ instantiate_type (lhstype, rhs, complain)
int complain;
{
tree explicit_targs = NULL_TREE;
+ int template_only = 0;
if (TREE_CODE (lhstype) == UNKNOWN_TYPE)
{
@@ -5090,38 +5091,28 @@ instantiate_type (lhstype, rhs, complain)
return rhs;
}
- case SCOPE_REF:
- {
- /* This can happen if we are forming a pointer-to-member for a
- member template. */
- tree template_id_expr = TREE_OPERAND (rhs, 1);
- tree name;
- my_friendly_assert (TREE_CODE (template_id_expr) == TEMPLATE_ID_EXPR,
- 0);
- explicit_targs = TREE_OPERAND (template_id_expr, 1);
- name = TREE_OPERAND (template_id_expr, 0);
- my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 0);
- rhs = lookup_fnfields (TYPE_BINFO (TREE_OPERAND (rhs, 0)), name, 1);
- goto overload;
- }
+ case OFFSET_REF:
+ /* This can happen if we are forming a pointer-to-member for a
+ member template. */
+ rhs = TREE_OPERAND (rhs, 1);
+ my_friendly_assert (TREE_CODE (rhs) == TEMPLATE_ID_EXPR, 0);
+
+ /* Fall through. */
case TEMPLATE_ID_EXPR:
{
explicit_targs = TREE_OPERAND (rhs, 1);
+ template_only = 1;
rhs = TREE_OPERAND (rhs, 0);
}
/* fall through */
my_friendly_assert (TREE_CODE (rhs) == OVERLOAD, 980401);
case OVERLOAD:
- overload:
{
tree elem, elems;
- /* First look for an exact match. Search overloaded
- functions. May have to undo what `default_conversion'
- might do to lhstype. */
-
+ /* Check that the LHSTYPE and the RHS are reasonable. */
lhstype = validate_lhs (lhstype, complain);
if (lhstype == error_mark_node)
return lhstype;
@@ -5129,30 +5120,32 @@ instantiate_type (lhstype, rhs, complain)
if (TREE_CODE (lhstype) != FUNCTION_TYPE
&& TREE_CODE (lhstype) != METHOD_TYPE)
{
- rhs = DECL_NAME (OVL_FUNCTION (rhs));
if (complain)
cp_error("cannot resolve overloaded function `%D' "
- "based on non-function type", rhs);
+ "based on non-function type",
+ DECL_NAME (OVL_FUNCTION (rhs)));
return error_mark_node;
}
- elems = rhs;
- /* If there are explicit_targs, only a template function
- can match. */
- if (explicit_targs == NULL_TREE)
- while (elems)
- {
- elem = OVL_FUNCTION (elems);
- if (! comptypes (lhstype, TREE_TYPE (elem), 1))
- elems = OVL_CHAIN (elems);
- else
- {
- mark_used (elem);
- return elem;
- }
- }
+ /* Look for an exact match, by searching through the
+ overloaded functions. */
+ if (template_only)
+ /* If we're processing a template-id, only a template
+ function can match, so we don't look through the
+ overloaded functions. */
+ ;
+ else for (elems = rhs; elems; elems = OVL_CHAIN (elems))
+ {
+ elem = OVL_FUNCTION (elems);
+ if (comptypes (lhstype, TREE_TYPE (elem), 1))
+ {
+ mark_used (elem);
+ return elem;
+ }
+ }
- /* No exact match found, look for a compatible template. */
+ /* No overloaded function was an exact match. See if we can
+ instantiate some template to match. */
{
tree save_elem = 0;
elems = rhs;
@@ -5189,14 +5182,14 @@ instantiate_type (lhstype, rhs, complain)
}
}
- /* If there are explicit_targs, only a template function
- can match. */
- if (explicit_targs == NULL_TREE)
+ /* There's no exact match, and no templates can be
+ instantiated to match. The last thing we try is to see if
+ some ordinary overloaded function is close enough. If
+ we're only looking for template functions, we don't do
+ this. */
+ if (!template_only)
{
- /* No match found, look for a compatible function. */
- tree elems = rhs;
- elems = rhs;
- for (; elems; elems = OVL_NEXT (elems))
+ for (elems = rhs; elems; elems = OVL_NEXT (elems))
{
elem = OVL_CURRENT (elems);
if (comp_target_types (lhstype, TREE_TYPE (elem), 1) > 0)
@@ -5228,6 +5221,8 @@ instantiate_type (lhstype, rhs, complain)
return save_elem;
}
}
+
+ /* We failed to find a match. */
if (complain)
{
cp_error ("cannot resolve overload to target type `%#T'", lhstype);
diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def
index cad0a59..dbbdb66 100644
--- a/gcc/cp/cp-tree.def
+++ b/gcc/cp/cp-tree.def
@@ -163,7 +163,7 @@ DEFTREECODE (DEFAULT_ARG, "default_arg", 'c', 2)
template will be a FUNCTION_DECL, TEMPLATE_DECL, or a list of
overloaded functions and templates if the template-id refers to
a global template. If the template-id refers to a member template,
- the template will be an IDENTIFIER_NODE. */
+ the template may be an IDENTIFIER_NODE. */
DEFTREECODE (TEMPLATE_ID_EXPR, "template_id_expr", 'e', 2)
/* An association between namespace and entity. Parameters are the
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 59491a7..cf6378b 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -1522,6 +1522,7 @@ build_offset_ref (type, name)
tree decl, fnfields, fields, t = error_mark_node;
tree basebinfo = NULL_TREE;
int dtor = 0;
+ tree orig_name = name;
/* class templates can come in as TEMPLATE_DECLs here. */
if (TREE_CODE (name) == TEMPLATE_DECL)
@@ -1532,8 +1533,6 @@ build_offset_ref (type, name)
if (processing_template_decl || uses_template_parms (type))
return build_min_nt (SCOPE_REF, type, name);
- else if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
- return build (SCOPE_REF, unknown_type_node, type, name);
/* Handle namespace names fully here. */
if (TREE_CODE (type) == NAMESPACE_DECL)
@@ -1542,6 +1541,16 @@ build_offset_ref (type, name)
if (type == NULL_TREE || ! is_aggr_type (type, 1))
return error_mark_node;
+ if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
+ {
+ /* If the NAME is a TEMPLATE_ID_EXPR, we are looking at
+ something like `a.template f<int>' or the like. For the most
+ part, we treat this just like a.f. We do remember, however,
+ the template-id that was used. */
+ name = TREE_OPERAND (orig_name, 0);
+ my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 0);
+ }
+
if (TREE_CODE (name) == BIT_NOT_EXPR)
{
dtor = 1;
@@ -1612,11 +1621,33 @@ build_offset_ref (type, name)
if (fnfields)
{
extern int flag_save_memoized_contexts;
- basebinfo = TREE_PURPOSE (fnfields);
/* Go from the TREE_BASELINK to the member function info. */
t = TREE_VALUE (fnfields);
+ if (TREE_CODE (orig_name) == TEMPLATE_ID_EXPR)
+ {
+ /* The FNFIELDS are going to contain functions that aren't
+ necessarily templates, and templates that don't
+ necessarily match the explicit template parameters. We
+ save all the functions, and the explicit parameters, and
+ then figure out exactly what to instantiate with what
+ arguments in instantiate_type. */
+
+ if (TREE_CODE (t) != OVERLOAD)
+ /* The code in instantiate_type which will process this
+ expects to encounter OVERLOADs, not raw functions. */
+ t = ovl_cons (t, NULL_TREE);
+
+ return build (OFFSET_REF,
+ build_offset_type (type, unknown_type_node),
+ decl,
+ build (TEMPLATE_ID_EXPR,
+ TREE_TYPE (t),
+ t,
+ TREE_OPERAND (orig_name, 1)));
+ }
+
if (!really_overloaded_fn (t))
{
tree access;
@@ -1625,6 +1656,7 @@ build_offset_ref (type, name)
t = OVL_CURRENT (t);
/* unique functions are handled easily. */
+ basebinfo = TREE_PURPOSE (fnfields);
access = compute_access (basebinfo, t);
if (access == access_protected_node)
{
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index d417afb..4b2e587 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -4527,7 +4527,7 @@ build_unary_op (code, xarg, noconvert)
}
if (TREE_CODE (arg) == OVERLOAD
- || (TREE_CODE (arg) == SCOPE_REF
+ || (TREE_CODE (arg) == OFFSET_REF
&& TREE_CODE (TREE_OPERAND (arg, 1)) == TEMPLATE_ID_EXPR))
return build1 (ADDR_EXPR, unknown_type_node, arg);
else if (TREE_CODE (arg) == TREE_LIST)
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/ptrmem1.C b/gcc/testsuite/g++.old-deja/g++.pt/ptrmem1.C
index 3cd9c2b..e14c726 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/ptrmem1.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/ptrmem1.C
@@ -1,10 +1,8 @@
-// Build don't run:
-
class foo
{
public:
template<class T>
- T bar() {}
+ T bar() { return 7; }
};
int
@@ -13,4 +11,8 @@ main()
foo f;
int (foo::*s)() = &foo::template bar<int>;
+ if ((f.*s)() == 7)
+ return 0;
+ else
+ return 1;
}