diff options
author | Jason Merrill <jason@redhat.com> | 2020-12-11 14:37:09 -0500 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2020-12-11 15:41:02 -0500 |
commit | 9324f7a25c7161a813bfae6cc2d180784b165740 (patch) | |
tree | 4301375bb12ac00dd881ca8429bf08be4a112a6f /gcc/cp | |
parent | 8bab7dce62e321e722346ba2db2d381bdf3fbe4b (diff) | |
download | gcc-9324f7a25c7161a813bfae6cc2d180784b165740.zip gcc-9324f7a25c7161a813bfae6cc2d180784b165740.tar.gz gcc-9324f7a25c7161a813bfae6cc2d180784b165740.tar.bz2 |
c++: Avoid considering some conversion ops [PR97600]
Patrick's earlier patch to check convertibility before constraints for
conversion ops wasn't suitable because checking convertibility can also lead
to unwanted instantiations, but it occurs to me that there's a smaller check
we can do to avoid doing normal consideration of the conversion ops in this
case: since we're in the middle of a user-defined conversion, we can exclude
from consideration any conversion ops that return a type that would need an
additional user-defined conversion to reach the desired type: namely, a type
that differs in class-ness from the desired type.
[temp.inst]/9 allows optimizations like this: "If the function selected by
overload resolution can be determined without instantiating a class template
definition, it is unspecified whether that instantiation actually takes
place."
gcc/cp/ChangeLog:
PR libstdc++/97600
* call.c (build_user_type_conversion_1): Avoid considering
conversion functions that return a clearly unsuitable type.
gcc/testsuite/ChangeLog:
* g++.dg/cpp2a/concepts-conv3.C: New test.
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/call.c | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 221e3de..c2d62e5 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -4025,9 +4025,9 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags, creating a garbage BASELINK; constructors can't be inherited. */ ctors = get_class_binding (totype, complete_ctor_identifier); + tree to_nonref = non_reference (totype); if (MAYBE_CLASS_TYPE_P (fromtype)) { - tree to_nonref = non_reference (totype); if (same_type_ignoring_top_level_qualifiers_p (to_nonref, fromtype) || (CLASS_TYPE_P (to_nonref) && CLASS_TYPE_P (fromtype) && DERIVED_FROM_P (to_nonref, fromtype))) @@ -4111,6 +4111,22 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags, tree conversion_path = TREE_PURPOSE (conv_fns); struct z_candidate *old_candidates; + /* If LOOKUP_NO_CONVERSION, don't consider a conversion function that + would need an addional user-defined conversion, i.e. if the return + type differs in class-ness from the desired type. So we avoid + considering operator bool when calling a copy constructor. + + This optimization avoids the failure in PR97600, and is allowed by + [temp.inst]/9: "If the function selected by overload resolution can be + determined without instantiating a class template definition, it is + unspecified whether that instantiation actually takes place." */ + tree convtype = non_reference (TREE_TYPE (conv_fns)); + if ((flags & LOOKUP_NO_CONVERSION) + && !WILDCARD_TYPE_P (convtype) + && (CLASS_TYPE_P (to_nonref) + != CLASS_TYPE_P (convtype))) + continue; + /* If we are called to convert to a reference type, we are trying to find a direct binding, so don't even consider temporaries. If we don't find a direct binding, the caller will try again to |