aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/parser.c
diff options
context:
space:
mode:
authorAlexandre Oliva <aoliva@redhat.com>2018-03-06 06:25:12 +0000
committerAlexandre Oliva <aoliva@gcc.gnu.org>2018-03-06 06:25:12 +0000
commit23d63b459c032c41f99a7c735a33558e77d6baf7 (patch)
tree13f3e408fba20d613f4296a5ea55fd51999a632e /gcc/cp/parser.c
parent2e1a7ecb2d8f1ee3f88fd2906ab16eb30ab525f7 (diff)
downloadgcc-23d63b459c032c41f99a7c735a33558e77d6baf7.zip
gcc-23d63b459c032c41f99a7c735a33558e77d6baf7.tar.gz
gcc-23d63b459c032c41f99a7c735a33558e77d6baf7.tar.bz2
[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. From-SVN: r258271
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r--gcc/cp/parser.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 460b5ea..a19bbe1 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -4963,7 +4963,9 @@ cp_parser_fold_expression (cp_parser *parser, tree expr1)
else if (is_binary_op (TREE_CODE (expr1)))
error_at (location_of (expr1),
"binary expression in operand of fold-expression");
- else if (TREE_CODE (expr1) == COND_EXPR)
+ else if (TREE_CODE (expr1) == COND_EXPR
+ || (REFERENCE_REF_P (expr1)
+ && TREE_CODE (TREE_OPERAND (expr1, 0)) == COND_EXPR))
error_at (location_of (expr1),
"conditional expression in operand of fold-expression");