Commit 17b3c7a2 by Jason Merrill Committed by Jason Merrill

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
parent 7d7d50ba
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> 2011-07-28 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/49813 PR c++/49813
......
...@@ -5556,41 +5556,45 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain) ...@@ -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. function). We just strip everything and get to the arg.
See g++.old-deja/g++.oliva/template4.C and g++.dg/template/nontype9.C See g++.old-deja/g++.oliva/template4.C and g++.dg/template/nontype9.C
for examples. */ 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 /* ??? Maybe we could use convert_from_reference here, but we
would need to relax its constraints because the NOP_EXPR would need to relax its constraints because the NOP_EXPR
could actually change the type to something more cv-qualified, could actually change the type to something more cv-qualified,
and this is not folded by convert_from_reference. */ and this is not folded by convert_from_reference. */
tree addr = TREE_OPERAND (expr, 0); tree addr = TREE_OPERAND (probe, 0);
gcc_assert (TREE_CODE (expr_type) == REFERENCE_TYPE); gcc_assert (TREE_CODE (probe_type) == REFERENCE_TYPE);
gcc_assert (TREE_CODE (addr) == ADDR_EXPR); gcc_assert (TREE_CODE (addr) == ADDR_EXPR);
gcc_assert (TREE_CODE (TREE_TYPE (addr)) == POINTER_TYPE); gcc_assert (TREE_CODE (TREE_TYPE (addr)) == POINTER_TYPE);
gcc_assert (same_type_ignoring_top_level_qualifiers_p gcc_assert (same_type_ignoring_top_level_qualifiers_p
(TREE_TYPE (expr_type), (TREE_TYPE (probe_type),
TREE_TYPE (TREE_TYPE (addr)))); TREE_TYPE (TREE_TYPE (addr))));
expr = TREE_OPERAND (addr, 0); expr = TREE_OPERAND (addr, 0);
expr_type = TREE_TYPE (expr); expr_type = TREE_TYPE (expr);
} }
}
/* We could also generate a NOP_EXPR(ADDR_EXPR()) when the /* We could also generate a NOP_EXPR(ADDR_EXPR()) when the
parameter is a pointer to object, through decay and parameter is a pointer to object, through decay and
qualification conversion. Let's strip everything. */ qualification conversion. Let's strip everything. */
else if (TYPE_PTROBV_P (type)) else if (TREE_CODE (expr) == NOP_EXPR && TYPE_PTROBV_P (type))
{ {
STRIP_NOPS (expr); STRIP_NOPS (expr);
gcc_assert (TREE_CODE (expr) == ADDR_EXPR); gcc_assert (TREE_CODE (expr) == ADDR_EXPR);
gcc_assert (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE); gcc_assert (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE);
/* Skip the ADDR_EXPR only if it is part of the decay for /* Skip the ADDR_EXPR only if it is part of the decay for
an array. Otherwise, it is part of the original argument an array. Otherwise, it is part of the original argument
in the source code. */ in the source code. */
if (TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == ARRAY_TYPE) if (TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == ARRAY_TYPE)
expr = TREE_OPERAND (expr, 0); expr = TREE_OPERAND (expr, 0);
expr_type = TREE_TYPE (expr); expr_type = TREE_TYPE (expr);
}
} }
/* [temp.arg.nontype]/5, bullet 1 /* [temp.arg.nontype]/5, bullet 1
...@@ -8941,6 +8945,10 @@ tsubst_template_arg (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -8941,6 +8945,10 @@ tsubst_template_arg (tree t, tree args, tsubst_flags_t complain, tree in_decl)
/*integral_constant_expression_p=*/true); /*integral_constant_expression_p=*/true);
if (!(complain & tf_warning)) if (!(complain & tf_warning))
--c_inhibit_evaluation_warnings; --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; return r;
} }
...@@ -10981,7 +10989,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -10981,7 +10989,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
} }
else else
/* TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX. */ /* TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX. */
return unshare_expr (arg); return convert_from_reference (unshare_expr (arg));
} }
if (level == 1) if (level == 1)
......
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> 2011-07-28 H.J. Lu <hongjiu.lu@intel.com>
PR rtl-optimization/47958 PR rtl-optimization/47958
......
// 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;
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