aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2011-07-29 03:10:21 -0400
committerJason Merrill <jason@gcc.gnu.org>2011-07-29 03:10:21 -0400
commit17b3c7a2dbccfb4dcb7d78e0c974a0ad212262a9 (patch)
tree0c7f40afebdcb16dd3bc1da94958d723f3244a58
parent7d7d50baf7dbd0d5cb6c16951007726b8cc7f66d (diff)
downloadgcc-17b3c7a2dbccfb4dcb7d78e0c974a0ad212262a9.zip
gcc-17b3c7a2dbccfb4dcb7d78e0c974a0ad212262a9.tar.gz
gcc-17b3c7a2dbccfb4dcb7d78e0c974a0ad212262a9.tar.bz2
re PR c++/49808 (GCC adds an address-of somewhere!)
PR c++/49808 * pt.c (tsubst) [TEMPLATE_PARM_INDEX]: Call convert_from_reference. (convert_nontype_argument, tsubst_template_arg): Handle its output. From-SVN: r176916
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/pt.c50
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/template/nontype24.C16
4 files changed, 56 insertions, 21 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index ccaba95..d6330bb 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2011-07-28 Jason Merrill <jason@redhat.com>
+
+ PR c++/49808
+ * pt.c (tsubst) [TEMPLATE_PARM_INDEX]: Call convert_from_reference.
+ (convert_nontype_argument, tsubst_template_arg): Handle its output.
+
2011-07-28 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/49813
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index b9e09af..a3cd956 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -5556,41 +5556,45 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
function). We just strip everything and get to the arg.
See g++.old-deja/g++.oliva/template4.C and g++.dg/template/nontype9.C
for examples. */
- if (TREE_CODE (expr) == NOP_EXPR)
+ if (TYPE_REF_OBJ_P (type) || TYPE_REFFN_P (type))
{
- if (TYPE_REF_OBJ_P (type) || TYPE_REFFN_P (type))
+ tree probe_type, probe = expr;
+ if (REFERENCE_REF_P (probe))
+ probe = TREE_OPERAND (probe, 0);
+ probe_type = TREE_TYPE (probe);
+ if (TREE_CODE (probe) == NOP_EXPR)
{
/* ??? Maybe we could use convert_from_reference here, but we
would need to relax its constraints because the NOP_EXPR
could actually change the type to something more cv-qualified,
and this is not folded by convert_from_reference. */
- tree addr = TREE_OPERAND (expr, 0);
- gcc_assert (TREE_CODE (expr_type) == REFERENCE_TYPE);
+ tree addr = TREE_OPERAND (probe, 0);
+ gcc_assert (TREE_CODE (probe_type) == REFERENCE_TYPE);
gcc_assert (TREE_CODE (addr) == ADDR_EXPR);
gcc_assert (TREE_CODE (TREE_TYPE (addr)) == POINTER_TYPE);
gcc_assert (same_type_ignoring_top_level_qualifiers_p
- (TREE_TYPE (expr_type),
+ (TREE_TYPE (probe_type),
TREE_TYPE (TREE_TYPE (addr))));
expr = TREE_OPERAND (addr, 0);
expr_type = TREE_TYPE (expr);
}
+ }
- /* We could also generate a NOP_EXPR(ADDR_EXPR()) when the
- parameter is a pointer to object, through decay and
- qualification conversion. Let's strip everything. */
- else if (TYPE_PTROBV_P (type))
- {
- STRIP_NOPS (expr);
- gcc_assert (TREE_CODE (expr) == ADDR_EXPR);
- gcc_assert (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE);
- /* Skip the ADDR_EXPR only if it is part of the decay for
- an array. Otherwise, it is part of the original argument
- in the source code. */
- if (TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == ARRAY_TYPE)
- expr = TREE_OPERAND (expr, 0);
- expr_type = TREE_TYPE (expr);
- }
+ /* We could also generate a NOP_EXPR(ADDR_EXPR()) when the
+ parameter is a pointer to object, through decay and
+ qualification conversion. Let's strip everything. */
+ else if (TREE_CODE (expr) == NOP_EXPR && TYPE_PTROBV_P (type))
+ {
+ STRIP_NOPS (expr);
+ gcc_assert (TREE_CODE (expr) == ADDR_EXPR);
+ gcc_assert (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE);
+ /* Skip the ADDR_EXPR only if it is part of the decay for
+ an array. Otherwise, it is part of the original argument
+ in the source code. */
+ if (TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == ARRAY_TYPE)
+ expr = TREE_OPERAND (expr, 0);
+ expr_type = TREE_TYPE (expr);
}
/* [temp.arg.nontype]/5, bullet 1
@@ -8941,6 +8945,10 @@ tsubst_template_arg (tree t, tree args, tsubst_flags_t complain, tree in_decl)
/*integral_constant_expression_p=*/true);
if (!(complain & tf_warning))
--c_inhibit_evaluation_warnings;
+ /* Preserve the raw-reference nature of T. */
+ if (TREE_TYPE (t) && TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE
+ && REFERENCE_REF_P (r))
+ r = TREE_OPERAND (r, 0);
}
return r;
}
@@ -10981,7 +10989,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
}
else
/* TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX. */
- return unshare_expr (arg);
+ return convert_from_reference (unshare_expr (arg));
}
if (level == 1)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index aebaf01..c825d3b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2011-07-28 Jason Merrill <jason@redhat.com>
+
+ PR c++/49808
+ * g++.dg/template/nontype24.C: New.
+
2011-07-28 H.J. Lu <hongjiu.lu@intel.com>
PR rtl-optimization/47958
diff --git a/gcc/testsuite/g++.dg/template/nontype24.C b/gcc/testsuite/g++.dg/template/nontype24.C
new file mode 100644
index 0000000..57fbe43
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/nontype24.C
@@ -0,0 +1,16 @@
+// PR c++/49808
+
+template <class X, X g>
+struct A
+{
+ A() { float r = g(0); }
+};
+
+struct f_t
+{
+ float operator() (float) const { return 1; }
+};
+
+f_t f;
+
+A<f_t&, f> x;