When performing template argument deduction for a non-reference

conversion function when we're binding the result to a reference, drop
cv-qualifiers on the type we're referring to, since we should be
deducing a type that can be adjusted (via cv-qualification) to the
requested type. Fixes PR9336, and the remaining Boost.Assign failure.

llvm-svn: 127117
This commit is contained in:
Douglas Gregor 2011-03-06 09:03:20 +00:00
parent 92db8e8e39
commit d99609ae48
2 changed files with 33 additions and 7 deletions

View File

@ -2845,18 +2845,18 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
QualType P = Context.getCanonicalType(FromType);
QualType A = Context.getCanonicalType(ToType);
// C++0x [temp.deduct.conv]p3:
// C++0x [temp.deduct.conv]p2:
// If P is a reference type, the type referred to by P is used for
// type deduction.
if (const ReferenceType *PRef = P->getAs<ReferenceType>())
P = PRef->getPointeeType();
// C++0x [temp.deduct.conv]p3:
// If A is a reference type, the type referred to by A is used
// C++0x [temp.deduct.conv]p4:
// [...] If A is a reference type, the type referred to by A is used
// for type deduction.
if (const ReferenceType *ARef = A->getAs<ReferenceType>())
A = ARef->getPointeeType();
// C++ [temp.deduct.conv]p2:
A = ARef->getPointeeType().getUnqualifiedType();
// C++ [temp.deduct.conv]p3:
//
// If A is not a reference type:
else {
@ -2877,9 +2877,10 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
else
P = P.getUnqualifiedType();
// C++0x [temp.deduct.conv]p3:
// C++0x [temp.deduct.conv]p4:
// If A is a cv-qualified type, the top level cv-qualifiers of A's
// type are ignored for type deduction.
// type are ignored for type deduction. If A is a reference type, the type
// referred to by A is used for type deduction.
A = A.getUnqualifiedType();
}

View File

@ -353,3 +353,28 @@ namespace PR8034 {
};
int x = C().operator int();
}
namespace PR9336 {
template<class T>
struct generic_list
{
template<class Container>
operator Container()
{
Container ar;
T* i;
ar[0]=*i;
return ar;
}
};
template<class T>
struct array
{
T& operator[](int);
const T& operator[](int)const;
};
generic_list<generic_list<int> > l;
array<array<int> > a = l;
}