+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.
int complain;
{
tree explicit_targs = NULL_TREE;
+ int template_only = 0;
if (TREE_CODE (lhstype) == UNKNOWN_TYPE)
{
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;
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;
}
}
- /* 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)
return save_elem;
}
}
+
+ /* We failed to find a match. */
if (complain)
{
cp_error ("cannot resolve overload to target type `%#T'", lhstype);
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
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)
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)
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;
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;
t = OVL_CURRENT (t);
/* unique functions are handled easily. */
+ basebinfo = TREE_PURPOSE (fnfields);
access = compute_access (basebinfo, t);
if (access == access_protected_node)
{
}
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)
-// Build don't run:
-
class foo
{
public:
template<class T>
- T bar() {}
+ T bar() { return 7; }
};
int
foo f;
int (foo::*s)() = &foo::template bar<int>;
+ if ((f.*s)() == 7)
+ return 0;
+ else
+ return 1;
}