Skip to content

Commit

Permalink
[clang] Improve deduction of reference typed NTTP (#110393)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
mizvekov authored Oct 1, 2024
1 parent 4bd81c5 commit d214bec
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 9 deletions.
1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
18 changes: 9 additions & 9 deletions clang/lib/Sema/SemaTemplateDeduction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
8 changes: 8 additions & 0 deletions clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit d214bec

Please sign in to comment.