public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [C++] [PR84231] overload on cond_expr in template
@ 2018-02-09  2:09 Alexandre Oliva
  2018-02-15 19:20 ` Jason Merrill
  0 siblings, 1 reply; 9+ messages in thread
From: Alexandre Oliva @ 2018-02-09  2:09 UTC (permalink / raw)
  To: gcc-patches

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 verifies that, if a non-type-dependent COND_EXPRs is
recognized as an rvalues, so is the to-be-template-substituted one
created in its stead, so that overload resolution selects the correct
alternative.

Regstrapped on x86_64- and i686-linux-gnu.  Ok to install?

for  gcc/cp/ChangeLog

	PR c++/84231
	* typeck.c (build_x_conditional_expr): Make sure the
	to-be-tsubsted expr is an rvalue when it should.

for  gcc/testsuite/g++.dg/ChangeLog

	PR c++/84231
	* pr84231.C: New.
---
 gcc/cp/typeck.c                |   16 +++++++++++++++-
 gcc/testsuite/g++.dg/pr84231.C |   29 +++++++++++++++++++++++++++++
 2 files changed, 44 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/pr84231.C

diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 83e767829986..25ac44e57772 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -6560,12 +6560,26 @@ build_x_conditional_expr (location_t loc, tree ifexp, tree op1, tree op2,
   expr = build_conditional_expr (loc, ifexp, op1, op2, complain);
   if (processing_template_decl && expr != error_mark_node)
     {
+      bool rval = !glvalue_p (expr);
       tree min = build_min_non_dep (COND_EXPR, expr,
 				    orig_ifexp, orig_op1, orig_op2);
+      bool mrval = !glvalue_p (min);
       /* Remember that the result is an lvalue or xvalue.  */
-      if (glvalue_p (expr) && !glvalue_p (min))
+      if (!rval && mrval)
 	TREE_TYPE (min) = cp_build_reference_type (TREE_TYPE (min),
 						   !lvalue_p (expr));
+      else if (rval && !mrval)
+	{
+	  /* If it was supposed to be an rvalue but it's not, adjust
+	     one of the operands so that any overload resolution
+	     taking this COND_EXPR as an operand makes the correct
+	     decisions.  See c++/84231.  */
+	  TREE_OPERAND (min, 2) = build1_loc (loc, NON_LVALUE_EXPR,
+					      TREE_TYPE (min),
+					      TREE_OPERAND (min, 2));
+	  EXPR_LOCATION_WRAPPER_P (TREE_OPERAND (min, 2)) = 1;
+	  gcc_checking_assert (!glvalue_p (min));
+	}
       expr = convert_from_reference (min);
     }
   return expr;
diff --git a/gcc/testsuite/g++.dg/pr84231.C b/gcc/testsuite/g++.dg/pr84231.C
new file mode 100644
index 000000000000..de7c89a2ab69
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr84231.C
@@ -0,0 +1,29 @@
+// PR c++/84231 - overload resolution with cond_expr in a template
+
+// { dg-do compile }
+
+struct format {
+  template<typename T> format& operator%(const T&) { return *this; }
+  template<typename T> format& operator%(T&) { return *this; }
+};
+
+format f;
+
+template <typename>
+void function_template(bool b)
+{
+  // Compiles OK with array lvalue:
+  f % (b ? "x" : "x");
+
+  // Used to fails with pointer rvalue:
+  f % (b ? "" : "x");
+}
+
+void normal_function(bool b)
+{
+  // Both cases compile OK in non-template function:
+  f % (b ? "x" : "x");
+  f % (b ? "" : "x");
+
+  function_template<void>(b);
+}

-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2018-03-06  6:14 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-09  2:09 [C++] [PR84231] overload on cond_expr in template Alexandre Oliva
2018-02-15 19:20 ` Jason Merrill
2018-02-27 18:06   ` Alexandre Oliva
2018-02-27 18:22     ` Jason Merrill
2018-02-28  5:24       ` Alexandre Oliva
2018-02-28 16:51         ` Jason Merrill
2018-03-02  7:57           ` Alexandre Oliva
2018-03-02 17:14             ` Jason Merrill
2018-03-06  6:14               ` Alexandre Oliva

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).