ir.texi: Correct typo.

* ir.texi: Correct typo.
	* mangle.c (write_expression): Handle non-type template arguments
	with reference type.
	* method.c (build_overload_value): Likewise.
	* pt.c (convert_nontype_argument): Explicitly represent conversion
	to a reference with an ADDR_EXPR.
	(unify): Always unify arguments in left-to-right order.

From-SVN: r34396
This commit is contained in:
Mark Mitchell 2000-06-05 01:42:22 +00:00 committed by Mark Mitchell
parent f557989836
commit 0dc09a613b
7 changed files with 63 additions and 13 deletions

View file

@ -1,3 +1,13 @@
2000-06-04 Mark Mitchell <mark@codesourcery.com>
* ir.texi: Correct typo.
* mangle.c (write_expression): Handle non-type template arguments
with reference type.
* method.c (build_overload_value): Likewise.
* pt.c (convert_nontype_argument): Explicitly represent conversion
to a reference with an ADDR_EXPR.
(unify): Always unify arguments in left-to-right order.
2000-06-03 Alex Samuel <samuel@codesourcery.com>
Mark Mitchell <mark@codesourcery.com>

View file

@ -1675,7 +1675,7 @@ that of the result, will be either integral, boolean, or floating-point.
@item ADDR_EXPR
These nodes are used to represent the address of an object. (These
expression will always have pointer or reference type.) The operand may
expressions will always have pointer or reference type.) The operand may
be another expression, or it may be a declaration.
As an extension, G++ allows users to take the address of a label. In

View file

@ -1557,6 +1557,15 @@ write_expression (expr)
code = TREE_CODE (expr);
}
/* When we bind a variable or function to a non-type template
argument with reference type, we create an ADDR_EXPR to show
the fact that the entity's address has been taken. But, we
don't actually want to output a mangling code for the `&'. */
if (TREE_CODE (expr) == ADDR_EXPR
&& TREE_TYPE (expr)
&& TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE)
expr = TREE_OPERAND (expr, 0);
/* If it wasn't any of those, recursively expand the expression. */
write_string (operator_name_info[(int) code].mangled_name);

View file

@ -827,6 +827,9 @@ build_overload_value (type, value, flags)
/* Fall through. */
case REFERENCE_TYPE:
if (TREE_CODE (value) == ADDR_EXPR)
value = TREE_OPERAND (value, 0);
if (TREE_CODE (value) == VAR_DECL)
{
my_friendly_assert (DECL_NAME (value) != 0, 245);

View file

@ -2762,8 +2762,9 @@ convert_nontype_argument (type, expr)
tree e = expr;
STRIP_NOPS (e);
if (TREE_CODE (type) == REFERENCE_TYPE
|| TREE_CODE (expr_type) == ARRAY_TYPE)
if (TREE_CODE (expr_type) == ARRAY_TYPE
|| (TREE_CODE (type) == REFERENCE_TYPE
&& TREE_CODE (e) != ADDR_EXPR))
referent = e;
else
{
@ -2950,6 +2951,15 @@ convert_nontype_argument (type, expr)
{
tree type_referred_to = TREE_TYPE (type);
/* If this expression already has reference type, get the
underling object. */
if (TREE_CODE (expr_type) == REFERENCE_TYPE)
{
my_friendly_assert (TREE_CODE (expr) == ADDR_EXPR, 20000604);
expr = TREE_OPERAND (expr, 0);
expr_type = TREE_TYPE (expr);
}
if (TREE_CODE (type_referred_to) == FUNCTION_TYPE)
{
/* For a non-type template-parameter of type reference to
@ -2957,17 +2967,16 @@ convert_nontype_argument (type, expr)
template-argument represents a set of overloaded
functions, the matching function is selected from the
set (_over.over_). */
tree fns = expr;
tree fn;
fn = instantiate_type (type_referred_to, fns, 0);
fn = instantiate_type (type_referred_to, expr, 0);
if (fn == error_mark_node)
return error_mark_node;
if (!TREE_PUBLIC (fn))
{
if (really_overloaded_fn (fns))
if (really_overloaded_fn (expr))
/* Don't issue an error here; we might get a different
function if the overloading had worked out
differently. */
@ -2980,7 +2989,7 @@ convert_nontype_argument (type, expr)
TREE_TYPE (fn)),
0);
return fn;
expr = fn;
}
else
{
@ -2990,15 +2999,16 @@ convert_nontype_argument (type, expr)
identical) type of the template-argument. The
template-parameter is bound directly to the
template-argument, which must be an lvalue. */
if ((TYPE_MAIN_VARIANT (expr_type)
!= TYPE_MAIN_VARIANT (type_referred_to))
if (!same_type_p (TYPE_MAIN_VARIANT (expr_type),
TYPE_MAIN_VARIANT (type_referred_to))
|| !at_least_as_qualified_p (type_referred_to,
expr_type)
|| !real_lvalue_p (expr))
return error_mark_node;
else
return expr;
expr = error_mark_node;
}
mark_addressable (expr);
return build1 (ADDR_EXPR, type, expr);
}
break;
@ -8589,7 +8599,7 @@ unify (tparms, targs, parm, arg, strict)
return 1;
if (TREE_VEC_LENGTH (parm) != TREE_VEC_LENGTH (arg))
return 1;
for (i = TREE_VEC_LENGTH (parm) - 1; i >= 0; i--)
for (i = 0; i < TREE_VEC_LENGTH (parm); ++i)
if (unify (tparms, targs,
TREE_VEC_ELT (parm, i), TREE_VEC_ELT (arg, i),
UNIFY_ALLOW_NONE))

View file

@ -6,6 +6,12 @@ template <int i> void f()
f<i+1>(); // ERROR - excessive recursion
}
// We should never need this specialization because we should issue an
// error first about the recursive template instantions. But, in case
// the compiler fails to catch the error, this will keep it from
// running forever instantiating more and more templates.
template <> void f<100>();
int main()
{
f<0>(); // ERROR - starting here

View file

@ -0,0 +1,12 @@
// Build don't link:
// Origin: Mark Mitchell <mark@codesourcery.com>
template <class T, T&>
class C;
template <int& I>
class C<int, I> {};
int i;
C<int, i> c;