diff options
author | Mark Mitchell <mark@markmitchell.com> | 1998-06-12 09:47:04 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 1998-06-12 09:47:04 +0000 |
commit | 2a238a974bdff827ac0d0928ca9fe10ff59e683a (patch) | |
tree | e7672496825b85cd9dad0dd7a5fe954b17903b9d /gcc | |
parent | 77a45a2ea44010cabd700d777ac8b3557021bafa (diff) | |
download | gcc-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/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/cp/class.c | 83 | ||||
-rw-r--r-- | gcc/cp/cp-tree.def | 2 | ||||
-rw-r--r-- | gcc/cp/init.c | 38 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/ptrmem1.C | 8 |
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; } |