aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2014-01-30 00:28:52 -0500
committerJason Merrill <jason@gcc.gnu.org>2014-01-30 00:28:52 -0500
commit3c4e06c27a886a2b5a2f46d197a2476c8baa46ce (patch)
tree0eb018ba052dc4372a048baf50937c95dd617962 /gcc
parent3b16363e1aa7ff2a614290db89f853b995807601 (diff)
downloadgcc-3c4e06c27a886a2b5a2f46d197a2476c8baa46ce.zip
gcc-3c4e06c27a886a2b5a2f46d197a2476c8baa46ce.tar.gz
gcc-3c4e06c27a886a2b5a2f46d197a2476c8baa46ce.tar.bz2
re PR c++/59707 (Crash when using std::map with template class)
PR c++/59707 * call.c (add_builtin_candidate): Catch dependent types. From-SVN: r207295
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog3
-rw-r--r--gcc/cp/call.c29
-rw-r--r--gcc/testsuite/g++.dg/template/operator12.C9
3 files changed, 36 insertions, 5 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 858272f..59f2b7e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,8 @@
2014-01-29 Jason Merrill <jason@redhat.com>
+ PR c++/59707
+ * call.c (add_builtin_candidate): Catch dependent types.
+
PR c++/59989
* pt.c (expand_template_argument_pack): Correct
non_default_args_count calculation.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index f6566cf..f572bc1 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -2329,7 +2329,6 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
case INDIRECT_REF:
if (TYPE_PTR_P (type1)
- && !uses_template_parms (TREE_TYPE (type1))
&& (TYPE_PTROB_P (type1)
|| TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE))
break;
@@ -2467,15 +2466,13 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
&& TREE_CODE (type2) == ENUMERAL_TYPE)
break;
if (TYPE_PTR_P (type1)
- && null_ptr_cst_p (args[1])
- && !uses_template_parms (type1))
+ && null_ptr_cst_p (args[1]))
{
type2 = type1;
break;
}
if (null_ptr_cst_p (args[0])
- && TYPE_PTR_P (type2)
- && !uses_template_parms (type2))
+ && TYPE_PTR_P (type2))
{
type1 = type2;
break;
@@ -2642,6 +2639,28 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
gcc_unreachable ();
}
+ /* Make sure we don't create builtin candidates with dependent types. */
+ bool u1 = uses_template_parms (type1);
+ bool u2 = type2 ? uses_template_parms (type2) : false;
+ if (u1 || u2)
+ {
+ /* Try to recover if one of the types is non-dependent. But if
+ there's only one type, there's nothing we can do. */
+ if (!type2)
+ return;
+ /* And we lose if both are dependent. */
+ if (u1 && u2)
+ return;
+ /* Or if they have different forms. */
+ if (TREE_CODE (type1) != TREE_CODE (type2))
+ return;
+
+ if (u1 && !u2)
+ type1 = type2;
+ else if (u2 && !u1)
+ type2 = type1;
+ }
+
/* If we're dealing with two pointer types or two enumeral types,
we need candidates for both of them. */
if (type2 && !same_type_p (type1, type2)
diff --git a/gcc/testsuite/g++.dg/template/operator12.C b/gcc/testsuite/g++.dg/template/operator12.C
new file mode 100644
index 0000000..bc8e91d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/operator12.C
@@ -0,0 +1,9 @@
+// PR c++/59707
+
+struct T {
+ template<class D> operator D*() const;
+};
+
+void f(T x) {
+ x < x; // { dg-error "no match" }
+}