-
Notifications
You must be signed in to change notification settings - Fork 10.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Reland "[clang][Sema] Use original template pattern when declaring im…
…plicit deduction guides for nested template classes" (#73087) Reland of f418319 with proper handling of template constructors When a nested template is instantiated, the template pattern of the inner class is not copied into the outer class ClassTemplateSpecializationDecl. The specialization contains a ClassTemplateDecl with an empty record that points to the original template pattern instead. As a result, when looking up the constructors of the inner class, no results are returned. This patch finds the original template pattern and uses that for the lookup instead. Based on CWG2471 we must also substitute the known outer template arguments when creating deduction guides for the inner class. Changes from last iteration: 1. In template constructors, arguments are first rewritten to depth - 1 relative to the constructor as compared to depth 0 originally. These arguments are needed for substitution into constraint expressions. 2. Outer arguments are then applied with the template instantiator to produce a template argument at depth zero for use in the deduction guide. This substitution does not evaluate constraints, which preserves constraint arguments at the correct depth for later evaluation. 3. Tests are added that cover template constructors within nested deduction guides for all special substitution cases. 4. Computation of the template pattern and outer instantiation arguments are pulled into the constructor of `ConvertConstructorToDeductionGuideTransform`.
- Loading branch information
Showing
4 changed files
with
130 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
60 changes: 60 additions & 0 deletions
60
clang/test/SemaTemplate/nested-implicit-deduction-guides.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
// RUN: %clang_cc1 -std=c++20 -verify %s | ||
// expected-no-diagnostics | ||
|
||
template<class T> struct S { | ||
template<class U> struct N { | ||
N(T) {} | ||
N(T, U) {} | ||
template<class V> N(V, U) {} | ||
}; | ||
}; | ||
|
||
S<int>::N x{"a", 1}; | ||
using T = decltype(x); | ||
using T = S<int>::N<int>; | ||
|
||
template<class X> struct default_ftd_argument { | ||
template<class Y> struct B { | ||
template<class W = X, class Z = Y, class V = Z, int I = 0> B(Y); | ||
}; | ||
}; | ||
|
||
default_ftd_argument<int>::B default_arg("a"); | ||
using DefaultArg = decltype(default_arg); | ||
using DefaultArg = default_ftd_argument<int>::B<const char *>; | ||
|
||
template<bool> struct test; | ||
template<class X> struct non_type_param { | ||
template<class Y> struct B { | ||
B(Y); | ||
template<class Z, test<Z::value> = 0> B(Z); | ||
}; | ||
}; | ||
|
||
non_type_param<int>::B ntp = 5; | ||
using NonTypeParam = decltype(ntp); | ||
using NonTypeParam = non_type_param<int>::B<int>; | ||
|
||
template<typename A, typename T> | ||
concept C = (sizeof(T) == sizeof(A)); | ||
|
||
template<class X> struct concepts { | ||
template<class Y> struct B { | ||
template<class K = X, C<K> Z> B(Y, Z); | ||
}; | ||
}; | ||
|
||
concepts<int>::B cc(1, 3); | ||
using Concepts = decltype(cc); | ||
using Concepts = concepts<int>::B<int>; | ||
|
||
template<class X> struct requires_clause { | ||
template<class Y> struct B { | ||
template<class Z> requires (sizeof(Z) == sizeof(X)) | ||
B(Y, Z); | ||
}; | ||
}; | ||
|
||
requires_clause<int>::B req(1, 2); | ||
using RC = decltype(req); | ||
using RC = requires_clause<int>::B<int>; |