[clang] Improve deduction of reference typed NTTP (#110393)
This improves the existing workaround for a core issue introduced in CWG1770. When performing template argument deduction for an NTTP which the parameter side is a reference, instead of dropping the references for both sides, just make the argument be same reference typed as the parameter, in case the argument is not already a reference type. Fixes #73460
This commit is contained in:
@@ -465,6 +465,7 @@ Bug Fixes to C++ Support
|
||||
- Fixed an assertion failure in debug mode, and potential crashes in release mode, when
|
||||
diagnosing a failed cast caused indirectly by a failed implicit conversion to the type of the constructor parameter.
|
||||
- Fixed an assertion failure by adjusting integral to boolean vector conversions (#GH108326)
|
||||
- Fixed an issue deducing non-type template arguments of reference type. (#GH73460)
|
||||
- Mangle friend function templates with a constraint that depends on a template parameter from an enclosing template as members of the enclosing class. (#GH110247)
|
||||
- Fixed an issue in constraint evaluation, where type constraints on the lambda expression
|
||||
containing outer unexpanded parameters were not correctly expanded. (#GH101754)
|
||||
|
||||
@@ -442,18 +442,18 @@ DeduceNonTypeTemplateArgument(Sema &S, TemplateParameterList *TemplateParams,
|
||||
|
||||
// FIXME: It's not clear how deduction of a parameter of reference
|
||||
// type from an argument (of non-reference type) should be performed.
|
||||
// For now, we just remove reference types from both sides and let
|
||||
// the final check for matching types sort out the mess.
|
||||
ValueType = ValueType.getNonReferenceType();
|
||||
if (ParamType->isReferenceType())
|
||||
ParamType = ParamType.getNonReferenceType();
|
||||
else
|
||||
// Top-level cv-qualifiers are irrelevant for a non-reference type.
|
||||
ValueType = ValueType.getUnqualifiedType();
|
||||
// For now, we just make the argument have same reference type as the
|
||||
// parameter.
|
||||
if (ParamType->isReferenceType() && !ValueType->isReferenceType()) {
|
||||
if (ParamType->isRValueReferenceType())
|
||||
ValueType = S.Context.getRValueReferenceType(ValueType);
|
||||
else
|
||||
ValueType = S.Context.getLValueReferenceType(ValueType);
|
||||
}
|
||||
|
||||
return DeduceTemplateArgumentsByTypeMatch(
|
||||
S, TemplateParams, ParamType, ValueType, Info, Deduced,
|
||||
TDF_SkipNonDependent,
|
||||
TDF_SkipNonDependent | TDF_IgnoreQualifiers,
|
||||
PartialOrdering ? PartialOrderingKind::NonCall
|
||||
: PartialOrderingKind::None,
|
||||
/*ArrayBound=*/NewDeduced.wasDeducedFromArrayBound(), HasDeducedAnyParam);
|
||||
|
||||
@@ -613,3 +613,11 @@ struct {
|
||||
template<typename T>
|
||||
using a = s<f(T::x)>;
|
||||
}
|
||||
|
||||
namespace GH73460 {
|
||||
template <class T, T, T> struct A;
|
||||
template <class T, T n> struct A<T, n, n> {};
|
||||
|
||||
int j;
|
||||
template struct A<int&, j, j>;
|
||||
} // namespace GH73460
|
||||
|
||||
Reference in New Issue
Block a user