Commit d8f8dca1 by Mark Mitchell Committed by Mark Mitchell

class.c (pushclass): Tweak handling of class-level bindings.

	* class.c (pushclass): Tweak handling of class-level bindings.
	(resolve_address_of_overloaded_function): Update pointer-to-member
	handling.
	(instantiate_type): Likewise.
	* cvt.c (cp_convert_to_pointer): Likewise.
	* decl.c (pop_binding): Take the DECL to pop, not just the name.
	Deal with `struct stat' hack.
	(binding_level): Add to documentation.
	(push_binding): Clear BINDING_TYPE.
	(add_binding): New function.
	(push_local_binding): Use it.
	(push_class_binding): Likewise.
	(poplevel): Adjust calls to pop_binding.
	(poplevel_class): Likewise.
	(pushdecl): Adjust handling of TYPE_DECLs; add bindings for hidden
	declarations to current binding level.
	(push_class_level_binding): Likewise.
	(push_overloaded_decl): Adjust handling of OVERLOADs in local
	bindings.
	(lookup_namespace_name): Don't crash when confronted with a
	TEMPLATE_DECL.
	(lookup_name_real): Do `struct stat' hack in local binding
	contexts.
	(build_ptrmemfunc_type): Adjust documentation.
	(grokdeclarator): Don't avoid building real array types when
	processing templates unless really necessary.
	(finish_method): Adjust calls to pop_binding.
	* decl2.c (reparse_absdcl_as_expr): Recursively call ourselves,
	not reparse_decl_as_expr.
	(build_expr_from_tree): Deal with a template-id as the function to
	call in a METHOD_CALL_EXPR.
	* pt.c (convert_nontype_argument): Tweak pointer-to-member handling.
	(maybe_adjust_types_For_deduction): Don't do peculiar things with
	METHOD_TYPEs here.
	(resolve_overloaded_unification): Handle COMPONENT_REFs.  Build
	pointer-to-member types where necessary.
	* tree.c (build_cplus_array_type_1): Don't avoid building real
	array types when processing templates unless really necessary.
	(build_exception_variant): Compare the exception lists correctly.

From-SVN: r24314
parent 11b89622
1998-12-14 Mark Mitchell <mark@markmitchell.com>
* class.c (pushclass): Tweak handling of class-level bindings.
(resolve_address_of_overloaded_function): Update pointer-to-member
handling.
(instantiate_type): Likewise.
* cvt.c (cp_convert_to_pointer): Likewise.
* decl.c (pop_binding): Take the DECL to pop, not just the name.
Deal with `struct stat' hack.
(binding_level): Add to documentation.
(push_binding): Clear BINDING_TYPE.
(add_binding): New function.
(push_local_binding): Use it.
(push_class_binding): Likewise.
(poplevel): Adjust calls to pop_binding.
(poplevel_class): Likewise.
(pushdecl): Adjust handling of TYPE_DECLs; add bindings for hidden
declarations to current binding level.
(push_class_level_binding): Likewise.
(push_overloaded_decl): Adjust handling of OVERLOADs in local
bindings.
(lookup_namespace_name): Don't crash when confronted with a
TEMPLATE_DECL.
(lookup_name_real): Do `struct stat' hack in local binding
contexts.
(build_ptrmemfunc_type): Adjust documentation.
(grokdeclarator): Don't avoid building real array types when
processing templates unless really necessary.
(finish_method): Adjust calls to pop_binding.
* decl2.c (reparse_absdcl_as_expr): Recursively call ourselves,
not reparse_decl_as_expr.
(build_expr_from_tree): Deal with a template-id as the function to
call in a METHOD_CALL_EXPR.
* pt.c (convert_nontype_argument): Tweak pointer-to-member handling.
(maybe_adjust_types_For_deduction): Don't do peculiar things with
METHOD_TYPEs here.
(resolve_overloaded_unification): Handle COMPONENT_REFs. Build
pointer-to-member types where necessary.
* tree.c (build_cplus_array_type_1): Don't avoid building real
array types when processing templates unless really necessary.
(build_exception_variant): Compare the exception lists correctly.
1998-12-13 Mark Mitchell <mark@markmitchell.com>
* cp-tree.def (CPLUS_BINDING): Update documentation.
......
......@@ -4789,7 +4789,7 @@ pushclass (type, modify)
for (item = previous_class_values; item; item = TREE_CHAIN (item))
{
tree id = TREE_PURPOSE (item);
tree decl = IDENTIFIER_CLASS_VALUE (id);
tree decl = TREE_TYPE (item);
push_class_binding (id, decl);
if (TREE_CODE (decl) == TYPE_DECL)
......@@ -4808,8 +4808,6 @@ pushclass (type, modify)
if (! (IS_AGGR_TYPE_CODE (TREE_CODE (tag_type))
&& CLASSTYPE_IS_TEMPLATE (tag_type)))
pushtag (TREE_PURPOSE (tags), tag_type, 0);
else
pushdecl_class_level (CLASSTYPE_TI_TEMPLATE (tag_type));
}
current_function_decl = this_fndecl;
......@@ -5028,11 +5026,12 @@ resolve_address_of_overloaded_function (target_type,
interoperability with most_specialized_instantiation. */
tree matches = NULL_TREE;
/* If the TARGET_TYPE is a pointer-to-a-method, we convert it to
proper pointer-to-member type here. */
if (TREE_CODE (target_type) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (target_type)) == METHOD_TYPE)
target_type = build_ptrmemfunc_type (target_type);
/* By the time we get here, we should be seeing only real
pointer-to-member types, not the internal POINTER_TYPE to
METHOD_TYPE representation. */
my_friendly_assert (!(TREE_CODE (target_type) == POINTER_TYPE
&& (TREE_CODE (TREE_TYPE (target_type))
== METHOD_TYPE)), 0);
/* Check that the TARGET_TYPE is reasonable. */
if (TYPE_PTRFN_P (target_type))
......@@ -5475,15 +5474,20 @@ instantiate_type (lhstype, rhs, complain)
if (fn == error_mark_node)
return error_mark_node;
mark_addressable (fn);
TREE_TYPE (rhs) = lhstype;
TREE_OPERAND (rhs, 0) = fn;
TREE_CONSTANT (rhs) = staticp (fn);
if (TREE_CODE (lhstype) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (lhstype)) == METHOD_TYPE)
if (TYPE_PTRMEMFUNC_P (lhstype))
{
build_ptrmemfunc_type (lhstype);
rhs = build_ptrmemfunc (lhstype, rhs, 0);
/* We must use the POINTER_TYPE to METHOD_TYPE on RHS here
so that build_ptrmemfunc knows that RHS we have is not
already a pointer-to-member constant. Instead, it is
just a ADDR_EXPR over a FUNCTION_DECL. */
TREE_TYPE (rhs) = TYPE_PTRMEMFUNC_FN_TYPE (lhstype);
rhs = build_ptrmemfunc (TREE_TYPE (rhs), rhs, 0);
}
else
/* Here, things our simple; we have exactly what we need. */
TREE_TYPE (rhs) = lhstype;
}
return rhs;
......
......@@ -95,9 +95,6 @@ cp_convert_to_pointer (type, expr)
}
}
if (TYPE_PTRMEMFUNC_P (type))
type = TYPE_PTRMEMFUNC_FN_TYPE (type);
/* Handle anachronistic conversions from (::*)() to cv void* or (*)(). */
if (TREE_CODE (type) == POINTER_TYPE
&& (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
......@@ -128,16 +125,14 @@ cp_convert_to_pointer (type, expr)
intype = TREE_TYPE (expr);
}
if (TYPE_PTRMEMFUNC_P (intype))
intype = TYPE_PTRMEMFUNC_FN_TYPE (intype);
form = TREE_CODE (intype);
if (form == POINTER_TYPE || form == REFERENCE_TYPE)
if (POINTER_TYPE_P (intype))
{
intype = TYPE_MAIN_VARIANT (intype);
if (TYPE_MAIN_VARIANT (type) != intype
&& TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE
&& IS_AGGR_TYPE (TREE_TYPE (type))
&& IS_AGGR_TYPE (TREE_TYPE (intype))
......@@ -181,12 +176,9 @@ cp_convert_to_pointer (type, expr)
}
}
}
if (TREE_CODE (TREE_TYPE (intype)) == METHOD_TYPE
&& TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
return build_ptrmemfunc (type, expr, 1);
if (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE
if (TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE
&& TREE_CODE (TREE_TYPE (intype)) == OFFSET_TYPE)
{
tree b1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (type));
......@@ -205,10 +197,7 @@ cp_convert_to_pointer (type, expr)
if (binfo && ! TREE_VIA_VIRTUAL (binfo))
expr = size_binop (code, expr, BINFO_OFFSET (binfo));
}
if (TREE_CODE (TREE_TYPE (intype)) == METHOD_TYPE
|| (TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE))
else if (TYPE_PTRMEMFUNC_P (type))
{
cp_error ("cannot convert `%E' from type `%T' to type `%T'",
expr, intype, type);
......@@ -219,6 +208,14 @@ cp_convert_to_pointer (type, expr)
TREE_CONSTANT (rval) = TREE_CONSTANT (expr);
return rval;
}
else if (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype))
return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 1);
else if (TYPE_PTRMEMFUNC_P (intype))
{
cp_error ("cannot convert `%E' from type `%T' to type `%T'",
expr, intype, type);
return error_mark_node;
}
my_friendly_assert (form != OFFSET_TYPE, 186);
......@@ -228,7 +225,7 @@ cp_convert_to_pointer (type, expr)
if (integer_zerop (expr))
{
if (TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
if (TYPE_PTRMEMFUNC_P (type))
return build_ptrmemfunc (type, expr, 0);
expr = build_int_2 (0, 0);
TREE_TYPE (expr) = type;
......
......@@ -180,7 +180,8 @@ static void check_for_uninitialized_const_var PROTO((tree));
static unsigned long typename_hash PROTO((hash_table_key));
static boolean typename_compare PROTO((hash_table_key, hash_table_key));
static void push_binding PROTO((tree, tree, struct binding_level*));
static void pop_binding PROTO((tree));
static void add_binding PROTO((tree, tree));
static void pop_binding PROTO((tree, tree));
#if defined (DEBUG_CP_BINDING_LEVELS)
static void indent PROTO((void));
......@@ -602,7 +603,10 @@ push_decl_level (stack, obstack)
to catch class-local declarations. It is otherwise nonexistent.
Also there may be binding levels that catch cleanups that must be
run when exceptions occur. */
run when exceptions occur. Thus, to see whether a name is bound in
the current scope, it is not enough to look in the
CURRENT_BINDING_LEVEL. You should use lookup_name_current_level
instead. */
/* Note that the information in the `names' component of the global contour
is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */
......@@ -637,7 +641,8 @@ struct binding_level
is the name of an entity bound in the class; the TREE_VALUE is
the IDENTIFIER_CLASS_VALUE before we entered the class. Thus,
when leaving class scope, we can restore the
IDENTIFIER_CLASS_VALUE by walking this list. */
IDENTIFIER_CLASS_VALUE by walking this list. The TREE_TYPE is
the DECL bound by this name in the class. */
tree class_shadowed;
/* Similar to class_shadowed, but for IDENTIFIER_TYPE_VALUE, and
......@@ -1072,6 +1077,7 @@ push_binding (id, decl, level)
/* Now, fill in the binding information. */
BINDING_VALUE (binding) = decl;
BINDING_TYPE (binding) = NULL_TREE;
BINDING_LEVEL (binding) = level;
LOCAL_BINDING_P (binding) = (level != class_binding_level);
......@@ -1080,6 +1086,38 @@ push_binding (id, decl, level)
IDENTIFIER_BINDING (id) = binding;
}
/* ID is already bound in the current scope. But, DECL is an
additional binding for ID in the same scope. This is the `struct
stat' hack whereby a non-typedef class-name or enum-name can be
bound at the same level as some other kind of entity. It's the
responsibility of the caller to check that inserting this name is
legal here. */
static void
add_binding (id, decl)
tree id;
tree decl;
{
tree binding = IDENTIFIER_BINDING (id);
if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
/* The new name is the type name. */
BINDING_TYPE (binding) = decl;
else
{
/* The old name must be the type name. It was placed in
IDENTIFIER_VALUE because it was thought, at the point it
was declared, to be the only entity with such a name. */
my_friendly_assert (TREE_CODE (BINDING_VALUE (binding)) == TYPE_DECL
&& DECL_ARTIFICIAL (BINDING_VALUE (binding)),
0);
/* Move the type name into the type slot; it is now hidden by
the new binding. */
BINDING_TYPE (binding) = BINDING_VALUE (binding);
BINDING_VALUE (binding) = decl;
}
}
/* Bind DECL to ID in the current_binding_level. */
void
......@@ -1087,14 +1125,18 @@ push_local_binding (id, decl)
tree id;
tree decl;
{
tree d = decl;;
tree d = decl;
if (TREE_CODE (decl) == OVERLOAD)
/* We must put the OVERLOAD into a TREE_LIST since the
TREE_CHAIN of an OVERLOAD is already used. */
decl = build_tree_list (NULL_TREE, decl);
/* Create a binding, hanging off of ID. */
if (lookup_name_current_level (id))
/* Supplement the existing binding. */
add_binding (id, decl);
else
/* Create a new binding. */
push_binding (id, d, current_binding_level);
/* And put DECL on the list of things declared by the current
......@@ -1110,14 +1152,29 @@ push_class_binding (id, decl)
tree id;
tree decl;
{
if (IDENTIFIER_BINDING (id)
&& BINDING_LEVEL (IDENTIFIER_BINDING (id)) == class_binding_level)
/* Supplement the existing binding. */
add_binding (id, decl);
else
/* Create a new binding. */
push_binding (id, decl, class_binding_level);
/* Update the IDENTIFIER_CLASS_VALUE for this ID to be the
class-level declaration. Note that we do not use DECL here
because of the possibility of the `struct stat' hack; if DECL is
a class-name or enum-name we might prefer a field-name, or some
such. */
IDENTIFIER_CLASS_VALUE (id) = BINDING_VALUE (IDENTIFIER_BINDING (id));
}
/* Remove the innermost binding for ID; it has gone out of scope. */
/* Remove the binding for DECL which should be the innermost binding
for ID. */
static void
pop_binding (id)
pop_binding (id, decl)
tree id;
tree decl;
{
tree binding;
......@@ -1127,15 +1184,31 @@ pop_binding (id)
get here for such an entity. */
return;
my_friendly_assert (IDENTIFIER_BINDING (id) != NULL_TREE, 0);
/* Unhook the innermost binding from the list of bindings. */
/* Get the innermost binding for ID. */
binding = IDENTIFIER_BINDING (id);
/* The name should be bound. */
my_friendly_assert (binding != NULL_TREE, 0);
/* The DECL will be either the ordinary binding or the type
binding for this identifier. Remove that binding. */
if (BINDING_VALUE (binding) == decl)
BINDING_VALUE (binding) = NULL_TREE;
else if (BINDING_TYPE (binding) == decl)
BINDING_TYPE (binding) = NULL_TREE;
else
my_friendly_abort (0);
if (!BINDING_VALUE (binding) && !BINDING_TYPE (binding))
{
/* We're completely done with the innermost binding for this
identifier. Unhook it from the list of bindings. */
IDENTIFIER_BINDING (id) = TREE_CHAIN (binding);
/* And place this list node on the free list. */
/* And place it on the free list. */
TREE_CHAIN (binding) = free_binding_nodes;
free_binding_nodes = binding;
}
}
/* Exit a binding level.
......@@ -1303,7 +1376,7 @@ poplevel (keep, reverse, functionbody)
and we are leaving the `for' scope. There's no reason to
keep the binding of the inner `i' in this case. */
pop_binding (DECL_NAME (link));
pop_binding (DECL_NAME (link), link);
else if ((outer_binding
&& (TREE_CODE (BINDING_VALUE (outer_binding))
== TYPE_DECL))
......@@ -1319,7 +1392,7 @@ poplevel (keep, reverse, functionbody)
We must pop the for-scope binding so we know what's a
type and what isn't. */
pop_binding (DECL_NAME (link));
pop_binding (DECL_NAME (link), link);
else
{
/* Mark this VAR_DECL as dead so that we can tell we left it
......@@ -1350,9 +1423,10 @@ poplevel (keep, reverse, functionbody)
{
/* Remove the binding. */
if (TREE_CODE_CLASS (TREE_CODE (link)) == 'd')
pop_binding (DECL_NAME (link));
pop_binding (DECL_NAME (link), link);
else if (TREE_CODE (link) == TREE_LIST)
pop_binding (DECL_NAME (OVL_FUNCTION (TREE_VALUE (link))));
pop_binding (DECL_NAME (OVL_FUNCTION (TREE_VALUE (link))),
TREE_VALUE (link));
else
my_friendly_abort (0);
}
......@@ -1362,7 +1436,7 @@ poplevel (keep, reverse, functionbody)
that we kept around. */
for (link = current_binding_level->dead_vars_from_for;
link; link = TREE_CHAIN (link))
pop_binding (DECL_NAME (TREE_VALUE (link)));
pop_binding (DECL_NAME (TREE_VALUE (link)), TREE_VALUE (link));
/* Restore the IDENTIFIER_TYPE_VALUEs. */
for (link = current_binding_level->type_shadowed;
......@@ -1607,7 +1681,7 @@ poplevel_class (force)
for (shadowed = level->class_shadowed;
shadowed;
shadowed = TREE_CHAIN (shadowed))
pop_binding (TREE_PURPOSE (shadowed));
pop_binding (TREE_PURPOSE (shadowed), TREE_TYPE (shadowed));
GNU_xref_end_scope ((HOST_WIDE_INT) class_binding_level,
(HOST_WIDE_INT) class_binding_level->level_chain,
......@@ -3617,12 +3691,6 @@ pushdecl (x)
set_identifier_type_value_with_scope (DECL_NAME (x), type,
current_binding_level);
if (TREE_CODE (x) == TYPE_DECL
&& DECL_ARTIFICIAL (x)
&& t != NULL_TREE)
/* We don't want an artificial TYPE_DECL is we already
have another DECL with the same name. */
need_new_binding = 0;
}
/* Multiple external decls of the same identifier ought to match.
......@@ -3663,7 +3731,8 @@ pushdecl (x)
if (IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE && TREE_PUBLIC (x))
TREE_PUBLIC (name) = 1;
if (need_new_binding)
if (!(TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)
&& t != NULL_TREE))
{
if (TREE_CODE (x) == FUNCTION_DECL)
my_friendly_assert
......@@ -3999,10 +4068,6 @@ push_class_level_binding (name, x)
if (!class_binding_level)
return;
if (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)
&& purpose_member (name, class_binding_level->class_shadowed))
return;
/* If this declaration shadows a declaration from an enclosing
class, then we will need to restore IDENTIFIER_CLASS_VALUE when
we leave this class. Record the shadowed declaration here. */
......@@ -4010,12 +4075,13 @@ push_class_level_binding (name, x)
class_binding_level->class_shadowed
= tree_cons (name, IDENTIFIER_CLASS_VALUE (name),
class_binding_level->class_shadowed);
TREE_TYPE (class_binding_level->class_shadowed)
= x;
pop_obstacks ();
/* Put the binding on the stack of bindings for the identifier, and
update IDENTIFIER_CLASS_VALUE. */
push_class_binding (name, x);
IDENTIFIER_CLASS_VALUE (name) = x;
obstack_ptr_grow (&decl_obstack, x);
}
......@@ -4155,8 +4221,8 @@ push_overloaded_decl (decl, forgettable)
/* We only create an OVERLOAD if there was a previous binding at
this level. In that case, we need to remove the old binding
and replace it with the new binding. We must also run
through the NAMES on the current binding level to update the
chain. */
through the NAMES on the binding level where the name was
bound to update the chain. */
if (TREE_CODE (new_binding) == OVERLOAD)
{
tree *d;
......@@ -4168,11 +4234,21 @@ push_overloaded_decl (decl, forgettable)
|| (TREE_CODE (*d) == TREE_LIST
&& TREE_VALUE (*d) == old))
{
*d = TREE_CHAIN (*d);
break;
if (TREE_CODE (*d) == TREE_LIST)
/* Just replace the old binding with the new. */
TREE_VALUE (*d) = new_binding;
else
/* Build a TREE_LIST to wrap the OVERLOAD. */
*d = build_tree_list (NULL_TREE, new_binding);
/* And update the CPLUS_BINDING node. */
BINDING_VALUE (IDENTIFIER_BINDING (name))
= new_binding;
return decl;
}
pop_binding (name);
/* We should always find a previous binding in this case. */
my_friendly_abort (0);
}
/* Install the new binding. */
......@@ -4887,9 +4963,16 @@ lookup_namespace_name (namespace, name)
my_friendly_assert (TREE_CODE (namespace) == NAMESPACE_DECL, 370);
/* This happens for A::B<int> when B is a namespace. */
if (TREE_CODE (name) == NAMESPACE_DECL)
/* This happens for A::B<int> when B is a namespace. */
return name;
else if (TREE_CODE (name) == TEMPLATE_DECL)
{
/* This happens for A::B where B is a template, and there are no
template arguments. */
cp_error ("invalid use of `%D'", name);
return error_mark_node;
}
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 373);
......@@ -5321,15 +5404,27 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
else
flags = lookup_flags (prefer_type, namespaces_only);
/* First, look in a non-global scope, carefully avoiding any
class-scope bindings if required. */
/* First, look in non-namespace scopes. */
val = IDENTIFIER_BINDING (name);
while (val && nonclass && !LOCAL_BINDING_P (val))
val = TREE_CHAIN (val);
for (val = IDENTIFIER_BINDING (name); val; val = TREE_CHAIN (val))
{
if (!LOCAL_BINDING_P (val) && nonclass)
/* We're not looking for class-scoped bindings, so keep going. */
continue;
/* Get the DECL actually bound. */
if (val)
/* If this is the kind of thing we're looking for, we're done. */
if (qualify_lookup (BINDING_VALUE (val), flags))
{
val = BINDING_VALUE (val);
break;
}
else if ((flags & LOOKUP_PREFER_TYPES)
&& qualify_lookup (BINDING_TYPE (val), flags))
{
val = BINDING_TYPE (val);
break;
}
}
/* If VAL is a type from a dependent base, we're not really supposed
to be able to see it; the fact that we can is the "implicit
......@@ -5342,10 +5437,6 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
&& uses_template_parms (current_class_type))
val = lookup_field (current_class_type, name, 0, 1);
/* Make sure that this binding is the sort of thing we're looking
for. */
val = qualify_lookup (val, flags);
/* We don't put names from baseclasses onto the IDENTIFIER_BINDING
list when we're defining a type. It would probably be simpler to
do this, but we don't. So, we must lookup names from base
......@@ -5361,8 +5452,8 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
}
/* If we found a type from a dependent base class (using the
implicit typename extension), turn it into the TYPE_DECL for a
TYPENAME_TYPE here. */
implicit typename extension) make sure that there's not some
global name which should be chosen instead. */
if (val && TREE_CODE (val) == TYPE_DECL
&& IMPLICIT_TYPENAME_P (TREE_TYPE (val)))
{
......@@ -8575,7 +8666,8 @@ grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace)
return decl;
}
/* Create a canonical pointer to member function type. */
/* Create and return a canonical pointer to member function type, for
TYPE, which is a POINTER_TYPE to a METHOD_TYPE. */
tree
build_ptrmemfunc_type (type)
......@@ -9790,7 +9882,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
/* If this involves a template parameter, it'll be
constant, but we don't know what the value is yet. */
if (processing_template_decl)
if (uses_template_parms (size))
{
/* Resolve a qualified reference to an enumerator or
static const data member of ours. */
......@@ -10141,9 +10233,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
type = build_reference_type (type);
}
else if (TREE_CODE (type) == METHOD_TYPE)
{
type = build_ptrmemfunc_type (build_pointer_type (type));
}
else
type = build_pointer_type (type);
......@@ -13976,7 +14066,7 @@ finish_method (decl)
for (link = current_binding_level->names; link; link = TREE_CHAIN (link))
{
if (DECL_NAME (link) != NULL_TREE)
pop_binding (DECL_NAME (link));
pop_binding (DECL_NAME (link), link);
my_friendly_assert (TREE_CODE (link) != FUNCTION_DECL, 163);
DECL_CONTEXT (link) = NULL_TREE;
}
......
......@@ -3547,7 +3547,7 @@ reparse_absdcl_as_expr (type, decl)
return build_functional_cast (type, NULL_TREE);
/* recurse */
decl = reparse_decl_as_expr (type, TREE_OPERAND (decl, 0));
decl = reparse_absdcl_as_expr (type, TREE_OPERAND (decl, 0));
decl = build_x_function_call (decl, NULL_TREE, current_class_ref);
......@@ -3770,11 +3770,28 @@ build_expr_from_tree (t)
TREE_OPERAND (ref, 1),
build_expr_from_tree (TREE_OPERAND (t, 2)));
}
else
{
tree fn = TREE_OPERAND (t, 0);
/* We can get a TEMPLATE_ID_EXPR here on code like:
x->f<2>();
so we must resolve that. However, we can also get things
like a BIT_NOT_EXPR here, when referring to a destructor,
and things like that are not correctly resolved by
build_expr_from_tree. So, just use build_expr_from_tree
when we really need it. */
if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
fn = build_expr_from_tree (fn);
return build_method_call
(build_expr_from_tree (TREE_OPERAND (t, 1)),
TREE_OPERAND (t, 0),
fn,
build_expr_from_tree (TREE_OPERAND (t, 2)),
NULL_TREE, LOOKUP_NORMAL);
}
case CALL_EXPR:
if (TREE_CODE (TREE_OPERAND (t, 0)) == SCOPE_REF)
......
......@@ -2710,9 +2710,6 @@ convert_nontype_argument (type, expr)
case RECORD_TYPE:
{
tree fns;
tree fn;
if (!TYPE_PTRMEMFUNC_P (type))
/* This handles templates like
template<class T, T t> void f();
......@@ -2743,16 +2740,11 @@ convert_nontype_argument (type, expr)
if (TREE_CODE (expr) != ADDR_EXPR)
return error_mark_node;
fns = TREE_OPERAND (expr, 0);
expr = instantiate_type (type, expr, 0);
fn = instantiate_type (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (type)),
fns, 0);
if (fn == error_mark_node)
if (expr == error_mark_node)
return error_mark_node;
expr = build_unary_op (ADDR_EXPR, fn, 0);
my_friendly_assert (same_type_p (type, TREE_TYPE (expr)),
0);
return expr;
......@@ -6972,8 +6964,7 @@ maybe_adjust_types_for_deduction (strict, parm, arg)
deduction. */
if (TREE_CODE (*arg) == ARRAY_TYPE)
*arg = build_pointer_type (TREE_TYPE (*arg));
else if (TREE_CODE (*arg) == FUNCTION_TYPE
|| TREE_CODE (*arg) == METHOD_TYPE)
else if (TREE_CODE (*arg) == FUNCTION_TYPE)
*arg = build_pointer_type (*arg);
else
*arg = TYPE_MAIN_VARIANT (*arg);
......@@ -7163,6 +7154,11 @@ resolve_overloaded_unification (tparms, targs, parm, arg, strict,
if (TREE_CODE (arg) == ADDR_EXPR)
arg = TREE_OPERAND (arg, 0);
if (TREE_CODE (arg) == COMPONENT_REF)
/* Handle `&x' where `x' is some static or non-static member
function name. */
arg = TREE_OPERAND (arg, 1);
/* Strip baselink information. */
while (TREE_CODE (arg) == TREE_LIST)
arg = TREE_VALUE (arg);
......@@ -7188,6 +7184,8 @@ resolve_overloaded_unification (tparms, targs, parm, arg, strict,
if (subargs)
{
elem = tsubst (TREE_TYPE (fn), subargs, NULL_TREE);
if (TREE_CODE (elem) == METHOD_TYPE)
elem = build_ptrmemfunc_type (build_pointer_type (elem));
good += try_one_overload (tparms, targs, tempargs, parm, elem,
strict, sub_strict, explicit_mask);
}
......@@ -7196,10 +7194,15 @@ resolve_overloaded_unification (tparms, targs, parm, arg, strict,
else if (TREE_CODE (arg) == OVERLOAD)
{
for (; arg; arg = OVL_NEXT (arg))
{
tree type = TREE_TYPE (OVL_CURRENT (arg));
if (TREE_CODE (type) == METHOD_TYPE)
type = build_ptrmemfunc_type (build_pointer_type (type));
good += try_one_overload (tparms, targs, tempargs, parm,
TREE_TYPE (OVL_CURRENT (arg)),
type,
strict, sub_strict, explicit_mask);
}
}
else
my_friendly_abort (981006);
......
......@@ -416,7 +416,7 @@ build_cplus_array_type_1 (elt_type, index_type)
saveable_obstack = &permanent_obstack;
}
if (processing_template_decl
if (uses_template_parms (elt_type)
|| uses_template_parms (index_type))
{
t = make_node (ARRAY_TYPE);
......@@ -1467,15 +1467,20 @@ build_exception_variant (type, raises)
for (; v; v = TYPE_NEXT_VARIANT (v))
{
tree t;
tree u;
if (TYPE_QUALS (v) != type_quals)
continue;
/* @@ This should do set equality, not exact match. */
if (simple_cst_list_equal (TYPE_RAISES_EXCEPTIONS (v), raises))
/* List of exceptions raised matches previously found list.
for (t = TYPE_RAISES_EXCEPTIONS (v), u = raises;
t != NULL_TREE && u != NULL_TREE;
t = TREE_CHAIN (t), u = TREE_CHAIN (v))
if (!same_type_p (TREE_VALUE (t), TREE_VALUE (u)))
break;
@@ Nice to free up storage used in consing up the
@@ list of exceptions raised. */
if (!t && !u)
/* There's a memory leak here; RAISES is not freed. */
return v;
}
......
......@@ -3,9 +3,9 @@
// Posted by Trevor Taylor <ttaylor@powerup.com.au>
template<class T> struct A {
void X() throw(T); // gets bogus error - previous decl - XFAIL *-*-*
void X() throw(T);
};
template<class T>
inline void A<T>::X()
throw(T) { } // gets bogus error - different throws - XFAIL *-*-*
throw(T) { }
// Build don't link:
namespace N {
template <class T> struct S;
};
void f()
{
N::S(); // ERROR - invalid use of template
}
// Build don't link:
// crash test - XFAIL *-*-*
// Simplified from bug report by Trevor Taylor <ttaylor@powerup.com.au>
struct T {
int operator()(int) { }
int operator()(int) { } // ERROR - candidate
};
int main() {
......
// Build don't link:
struct S {
int A;
struct A {
enum { a = 0 };
};
void f();
};
void S::f() {
A = A::a;
}
// Build don't link:
template<int N, class C>
class Bar {};
template<class C>
class Huh {};
template<int N>
void foo(const Bar<N,Huh<float[1]> > &x) {}
int main() {
foo(Bar<3,Huh<float[1]> >());
}
// Build don't link:
template <int i> class a
{
public :
int k;
template <int j> int f() const { return this->f<j-1>(); }
int g() const { return f<i>(); };
};
template <>
template <>
int a<2>::f<0>() const {
return 0;
}
int main()
{
a<2> x;
return x.g();
}
// Build don't run:
template <class T>
int f(int (*fn)(T))
{
return (*fn)(3);
}
struct S {
static int g(int) { return 1; }
static void g();
int h();
};
int S::h()
{
return f(&g);
}
int main()
{
S s;
if (s.h () != 1)
return 1;
}
// Build don't run:
template<class T,class T1>
int connect_to_method(T* receiver,
int (T1::*method)())
{
return (receiver->*method)();
}
class Gtk_Container
{
public:
int remove_callback() { return 1; }
void remove_callback(int);
int f();
};
int Gtk_Container::f()
{
return connect_to_method(this, &Gtk_Container::remove_callback);
}
int main()
{
Gtk_Container gc;
if (gc.f () != 1)
return 1;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment