summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog10
-rw-r--r--gcc/cp/ir.texi2
-rw-r--r--gcc/cp/mangle.c9
-rw-r--r--gcc/cp/method.c3
-rw-r--r--gcc/cp/pt.c34
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/infinite1.C6
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/ref2.C12
7 files changed, 63 insertions, 13 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index ce7b48e6d43..87cea7059bc 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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>
diff --git a/gcc/cp/ir.texi b/gcc/cp/ir.texi
index 61165b7fa80..429c1554112 100644
--- a/gcc/cp/ir.texi
+++ b/gcc/cp/ir.texi
@@ -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
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index d4bd066cd09..2bba09f518b 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -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);
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index f6c006a0860..495c47b3d5d 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -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);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index f3c7989b13b..48df27f3815 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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))
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/infinite1.C b/gcc/testsuite/g++.old-deja/g++.pt/infinite1.C
index 90a2b75cc22..22f00739c87 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/infinite1.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/infinite1.C
@@ -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
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/ref2.C b/gcc/testsuite/g++.old-deja/g++.pt/ref2.C
new file mode 100644
index 00000000000..ee684981e70
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.pt/ref2.C
@@ -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;