From: Jason Merrill Date: Fri, 29 Jul 2011 07:10:21 +0000 (-0400) Subject: re PR c++/49808 (GCC adds an address-of somewhere!) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=17b3c7a2dbccfb4dcb7d78e0c974a0ad212262a9;p=gcc.git 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 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ccaba95e880..d6330bb5a61 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2011-07-28 Jason Merrill + + 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 PR c++/49813 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index b9e09af7e26..a3cd9568d23 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 aebaf018f75..c825d3bade0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2011-07-28 Jason Merrill + + PR c++/49808 + * g++.dg/template/nontype24.C: New. + 2011-07-28 H.J. Lu 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 00000000000..57fbe430e1c --- /dev/null +++ b/gcc/testsuite/g++.dg/template/nontype24.C @@ -0,0 +1,16 @@ +// PR c++/49808 + +template +struct A +{ + A() { float r = g(0); } +}; + +struct f_t +{ + float operator() (float) const { return 1; } +}; + +f_t f; + +A x;