c++: Adjust conversion deduction [PR61663][DR976]

Drop the return type's reference before doing cvqual and related decays.

	gcc/cp/
	PR c++/61663
	* pt.cc (maybe_adjust_types_for_deduction): Implement DR976.
	gcc/testsuite/
	* g++.dg/template/pr61663.C: New.
This commit is contained in:
Nathan Sidwell 2023-06-10 12:42:17 -04:00
parent 30a8771c0f
commit 80f075b410
2 changed files with 69 additions and 5 deletions

View file

@ -22725,10 +22725,16 @@ maybe_adjust_types_for_deduction (tree tparms,
break;
case DEDUCE_CONV:
/* [temp.deduct.conv] First remove a reference type on parm.
DRs 322 & 976 affected this. */
if (TYPE_REF_P (*parm))
*parm = TREE_TYPE (*parm);
/* Swap PARM and ARG throughout the remainder of this
function; the handling is precisely symmetric since PARM
will initialize ARG rather than vice versa. */
std::swap (parm, arg);
break;
case DEDUCE_EXACT:
@ -22795,11 +22801,6 @@ maybe_adjust_types_for_deduction (tree tparms,
result |= UNIFY_ALLOW_OUTER_MORE_CV_QUAL;
}
/* DR 322. For conversion deduction, remove a reference type on parm
too (which has been swapped into ARG). */
if (strict == DEDUCE_CONV && TYPE_REF_P (*arg))
*arg = TREE_TYPE (*arg);
return result;
}

View file

@ -0,0 +1,63 @@
// { dg-do compile { target c++11 } }
// PR c++/61663
// DR 976, strip ref from conv op return type before doing
// fn and ary decay or CV qual removal
struct F
{
template<class T>
operator const T&();
};
void Foo ()
{
F f;
int i = f;
}
template<typename T> struct X {};
struct Y
{
template<typename T> operator X<T> () &&; // #3
template<typename T> operator X<T> const & () const &; // #4
};
void Use (X<void>);
Y Val ();
Y const &Ref ();
// { dg-final { scan-assembler "_Z5Frob3v:.*_ZNO1Ycv1XIT_EIvEEv.*_Z3Use1XIvE" } }
void Frob3 ()
{
Use (Val ()); // #3
}
// { dg-final { scan-assembler "_Z5Frob4v:.*_ZNKR1YcvRK1XIT_EIvEEv.*_Z3Use1XIvE" } }
void Frob4 ()
{
Use (Ref ()); // #4
}
struct Z
{
template<typename T> using FnRef = void (&) (T);
template<typename T> using AryRef = T (&)[];
template<typename T> operator FnRef<T> ();
template<typename T> operator AryRef<T> ();
};
// { dg-final { scan-assembler "_Z5Frob5R1Z:.*_ZN1ZcvRFvT_EIiEEv.*_ZN1ZcvRA_T_IiEEv" } }
void Frob5 (Z &z)
{
void (*fnptr)(int) = z;
int *iptr = z;
}
// { dg-final { scan-assembler "_Z5Frob6R1Z:.*_ZN1ZcvRFvT_EIfEEv.*_ZN1ZcvRA_T_IfEEv" } }
void Frob6 (Z &z)
{
void (&fnref)(float) = z;
float (&aryref)[] = z;
}