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:
parent
30a8771c0f
commit
80f075b410
2 changed files with 69 additions and 5 deletions
11
gcc/cp/pt.cc
11
gcc/cp/pt.cc
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
63
gcc/testsuite/g++.dg/template/pr61663.C
Normal file
63
gcc/testsuite/g++.dg/template/pr61663.C
Normal 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;
|
||||
}
|
Loading…
Add table
Reference in a new issue