Skip to content

Commit d214bec

Browse files
authored
[clang] Improve deduction of reference typed NTTP (llvm#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 llvm#73460
1 parent 4bd81c5 commit d214bec

File tree

3 files changed

+18
-9
lines changed

3 files changed

+18
-9
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,7 @@ Bug Fixes to C++ Support
465465
- Fixed an assertion failure in debug mode, and potential crashes in release mode, when
466466
diagnosing a failed cast caused indirectly by a failed implicit conversion to the type of the constructor parameter.
467467
- Fixed an assertion failure by adjusting integral to boolean vector conversions (#GH108326)
468+
- Fixed an issue deducing non-type template arguments of reference type. (#GH73460)
468469
- Mangle friend function templates with a constraint that depends on a template parameter from an enclosing template as members of the enclosing class. (#GH110247)
469470
- Fixed an issue in constraint evaluation, where type constraints on the lambda expression
470471
containing outer unexpanded parameters were not correctly expanded. (#GH101754)

clang/lib/Sema/SemaTemplateDeduction.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -442,18 +442,18 @@ DeduceNonTypeTemplateArgument(Sema &S, TemplateParameterList *TemplateParams,
442442

443443
// FIXME: It's not clear how deduction of a parameter of reference
444444
// type from an argument (of non-reference type) should be performed.
445-
// For now, we just remove reference types from both sides and let
446-
// the final check for matching types sort out the mess.
447-
ValueType = ValueType.getNonReferenceType();
448-
if (ParamType->isReferenceType())
449-
ParamType = ParamType.getNonReferenceType();
450-
else
451-
// Top-level cv-qualifiers are irrelevant for a non-reference type.
452-
ValueType = ValueType.getUnqualifiedType();
445+
// For now, we just make the argument have same reference type as the
446+
// parameter.
447+
if (ParamType->isReferenceType() && !ValueType->isReferenceType()) {
448+
if (ParamType->isRValueReferenceType())
449+
ValueType = S.Context.getRValueReferenceType(ValueType);
450+
else
451+
ValueType = S.Context.getLValueReferenceType(ValueType);
452+
}
453453

454454
return DeduceTemplateArgumentsByTypeMatch(
455455
S, TemplateParams, ParamType, ValueType, Info, Deduced,
456-
TDF_SkipNonDependent,
456+
TDF_SkipNonDependent | TDF_IgnoreQualifiers,
457457
PartialOrdering ? PartialOrderingKind::NonCall
458458
: PartialOrderingKind::None,
459459
/*ArrayBound=*/NewDeduced.wasDeducedFromArrayBound(), HasDeducedAnyParam);

clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,3 +613,11 @@ struct {
613613
template<typename T>
614614
using a = s<f(T::x)>;
615615
}
616+
617+
namespace GH73460 {
618+
template <class T, T, T> struct A;
619+
template <class T, T n> struct A<T, n, n> {};
620+
621+
int j;
622+
template struct A<int&, j, j>;
623+
} // namespace GH73460

0 commit comments

Comments
 (0)