From 3c4e06c27a886a2b5a2f46d197a2476c8baa46ce Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 30 Jan 2014 00:28:52 -0500 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 3 +++ gcc/cp/call.c | 29 ++++++++++++++++++---- gcc/testsuite/g++.dg/template/operator12.C | 9 +++++++ 3 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/operator12.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 858272ffc8d..59f2b7ec91d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,8 @@ 2014-01-29 Jason Merrill + 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 f6566cff1a2..f572bc1fc88 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 00000000000..bc8e91de4cd --- /dev/null +++ b/gcc/testsuite/g++.dg/template/operator12.C @@ -0,0 +1,9 @@ +// PR c++/59707 + +struct T { + template operator D*() const; +}; + +void f(T x) { + x < x; // { dg-error "no match" } +}