[C++] [PR84231] overload on cond_expr in template
commit11a93d7a09b871b3b9a2eb108eb91ad83d94e070
authoraoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 6 Mar 2018 06:25:12 +0000 (6 06:25 +0000)
committeraoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 6 Mar 2018 06:25:12 +0000 (6 06:25 +0000)
tree13f3e408fba20d613f4296a5ea55fd51999a632e
parent47608302d0de4e394f30ac92fef32047220d037f
[C++] [PR84231] overload on cond_expr in template

A non-type-dependent COND_EXPR within a template is reconstructed with
the original operands, after one with non-dependent proxies is built to
determine its result type.  This is problematic because the operands of
a COND_EXPR determined to be an rvalue may have been converted to denote
their rvalue nature.  The reconstructed one, however, won't have such
conversions, so lvalue_kind may not recognize it as an rvalue, which may
lead to e.g. incorrect overload resolution decisions.

If we mistake such a COND_EXPR for an lvalue, overload resolution might
regard a conversion sequence that binds it to a non-const reference as
viable, and then select that over one that binds it to a const
reference.  Only after template substitution would we rebuild the
COND_EXPR, realize it is an rvalue, and conclude the reference binding
is ill-formed, but at that point we'd have long discarded any alternate
candidates we could have used.

This patch modifies the logic that determines whether a
(non-type-dependent) COND_EXPR in a template is an lvalue, to rely on
its type, more specifically, on the presence of a REFERENCE_TYPE
wrapper.  In order to avoid a type bootstrapping problem, the
REFERENCE_TYPE that wraps the type of some such COND_EXPRs is
introduced earlier, so that we don't have to test for lvalueness of
the expression using the very code that we wish to change.

for  gcc/cp/ChangeLog

PR c++/84231
* tree.c (lvalue_kind): Use presence/absence of REFERENCE_TYPE
only while processing template decls.
* typeck.c (build_x_conditional_expr): Move wrapping of
reference type around type...
* call.c (build_conditional_expr_1): ... here.  Rename
is_lvalue to is_glvalue.
* parser.c (cp_parser_fold_expression): Catch REFERENCE_REF_P
INDIRECT_REF of COND_EXPR too.

for  gcc/testsuite/ChangeLog

PR c++/84231
* g++.dg/pr84231.C: New.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@258271 138bc75d-0d04-0410-961f-82ee72b054a4
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/parser.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/pr84231.C [new file with mode: 0644]