This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR c++/70610 (wrong overload resolution during template processing)


The gist of the issue is that with -std=c++03 or earlier a
NON_DEPENDENT_EXPR is considered to always be an lvalue according to
lvalue_kind().  This causes overload resolution to malfunction during
template processing because it sometimes chooses an overload that
expects an lvalue argument even though the expression underlying the
NON_DEPENDENT_EXPR is not an lvalue.  My patch for PR c++/21802
exacerbated this issue by having operator overload resolution get
performed only once, at template processing time (where we see
NON_DEPENDENT_EXPRs), instead of twice, at template processing time and
then at instantiation time (where we don't see NON_DEPENDENT_EXPRs).
The issue though is not restricted to operator overloads, it also
manifests itself in regular function overloads (see pr70610-3.C which
currently fails with an ambiguous overload error).

>From what I can tell the special casing done in lvalue_kind() for older
cxx_dialects is no longer necessary, so this patch removes it to have
lvalue_kind() unconditionally recurse into NON_DEPENDENT_EXPRs.  This
however caused a c++98 regression in g++.dg/template/lvalue2.C which is
fixed by removing the guard against cxx_dialect in
build_x_conditional_expr which also no longer seems necessary.  Although
I haven't looked too carefully...

Bootstrapped + regtested on x86_64-pc-linux-gnu, does this look OK to
commit?

gcc/cp/ChangeLog:

	PR c++/70610
	* tree.c (lvalue_kind) [NON_DEPENDENT_EXPR]: Unconditionally
	recurse into it.
	* typeck.c (build_x_conditional_expr): Unconditionally remember
	that the result is an lvalue or xvalue.

gcc/testsuite/ChangeLog:

	PR c++/70610
	* g++.dg/template/pr70610.C: New test.
	* g++.dg/template/pr70610-2.C: New test.
	* g++.dg/template/pr70610-3.C: New test.
	* g++.dg/template/pr70610-4.C: New test.
---
 gcc/cp/tree.c                             |  8 +-------
 gcc/cp/typeck.c                           |  6 ++----
 gcc/testsuite/g++.dg/template/pr70610-2.C | 21 +++++++++++++++++++++
 gcc/testsuite/g++.dg/template/pr70610-3.C | 21 +++++++++++++++++++++
 gcc/testsuite/g++.dg/template/pr70610-4.C | 19 +++++++++++++++++++
 gcc/testsuite/g++.dg/template/pr70610.C   | 21 +++++++++++++++++++++
 6 files changed, 85 insertions(+), 11 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/template/pr70610-2.C
 create mode 100644 gcc/testsuite/g++.dg/template/pr70610-3.C
 create mode 100644 gcc/testsuite/g++.dg/template/pr70610-4.C
 create mode 100644 gcc/testsuite/g++.dg/template/pr70610.C

diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 5d9de34..df2981f 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -224,13 +224,7 @@ lvalue_kind (const_tree ref)
       return lvalue_kind (BASELINK_FUNCTIONS (CONST_CAST_TREE (ref)));
 
     case NON_DEPENDENT_EXPR:
-      /* We just return clk_ordinary for NON_DEPENDENT_EXPR in C++98, but
-	 in C++11 lvalues don't bind to rvalue references, so we need to
-	 work harder to avoid bogus errors (c++/44870).  */
-      if (cxx_dialect < cxx11)
-	return clk_ordinary;
-      else
-	return lvalue_kind (TREE_OPERAND (ref, 0));
+      return lvalue_kind (TREE_OPERAND (ref, 0));
 
     default:
       if (!TREE_TYPE (ref))
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 4dc1b55..a62bae4 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -6275,10 +6275,8 @@ build_x_conditional_expr (location_t loc, tree ifexp, tree op1, tree op2,
     {
       tree min = build_min_non_dep (COND_EXPR, expr,
 				    orig_ifexp, orig_op1, orig_op2);
-      /* In C++11, remember that the result is an lvalue or xvalue.
-         In C++98, lvalue_kind can just assume lvalue in a template.  */
-      if (cxx_dialect >= cxx11
-	  && lvalue_or_rvalue_with_address_p (expr)
+      /* Remember that the result is an lvalue or xvalue.  */
+      if (lvalue_or_rvalue_with_address_p (expr)
 	  && !lvalue_or_rvalue_with_address_p (min))
 	TREE_TYPE (min) = cp_build_reference_type (TREE_TYPE (min),
 						   !real_lvalue_p (expr));
diff --git a/gcc/testsuite/g++.dg/template/pr70610-2.C b/gcc/testsuite/g++.dg/template/pr70610-2.C
new file mode 100644
index 0000000..3368a5e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/pr70610-2.C
@@ -0,0 +1,21 @@
+// PR c++/70610
+// { dg-do link }
+
+struct A { };
+
+void operator+ (const A &, A &);
+void operator+ (A &, const A &);
+void operator+ (const A &, const A &) { }
+
+template <typename T>
+void
+foo ()
+{
+  A () + A ();
+}
+
+int
+main ()
+{
+  foo<int> ();
+}
diff --git a/gcc/testsuite/g++.dg/template/pr70610-3.C b/gcc/testsuite/g++.dg/template/pr70610-3.C
new file mode 100644
index 0000000..4be458c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/pr70610-3.C
@@ -0,0 +1,21 @@
+// PR c++/70610
+// { dg-do link }
+
+void bar (const int &, int &);
+void bar (int &, const int &);
+void bar (const int &, const int &) { }
+
+int a, b;
+
+template <typename T>
+void
+foo ()
+{
+  bar (a + 1, b + 2);
+}
+
+int
+main ()
+{
+  foo<int> ();
+}
diff --git a/gcc/testsuite/g++.dg/template/pr70610-4.C b/gcc/testsuite/g++.dg/template/pr70610-4.C
new file mode 100644
index 0000000..127abdc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/pr70610-4.C
@@ -0,0 +1,19 @@
+// PR c++/70610
+// { dg-do link }
+
+struct A { void operator+ (const A &) { }; };
+
+void operator+ (const A &, A &);
+
+template <typename T>
+void
+foo ()
+{
+  A () + A ();
+}
+
+int
+main ()
+{
+  foo<int> ();
+}
diff --git a/gcc/testsuite/g++.dg/template/pr70610.C b/gcc/testsuite/g++.dg/template/pr70610.C
new file mode 100644
index 0000000..c7dde1c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/pr70610.C
@@ -0,0 +1,21 @@
+// PR c++/70610
+// { dg-do link }
+
+struct A { };
+
+void operator+ (A &);
+void operator+ (const A &) { }
+
+
+template <typename T>
+void
+foo ()
+{
+  +A ();
+}
+
+int
+main ()
+{
+  foo<int> ();
+}
-- 
2.8.1.135.ga04ac66


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]