Skip to content

Commit c7bfc41

Browse files
authored
[Clang][NFCI] Prefer non-canonical template arguments for synthesized CTAD guides (llvm#99840)
This seems to be low-hanging fruit: We could remove all calls to `Context.getCanonicalTemplateArgument()` and gain a better diagnostic/AST. The non-canonical template arguments shouldn't make a difference when synthesizing a CTAD guide, so this is intended to be an NFC. Closes llvm#79798
1 parent 56ad7cc commit c7bfc41

File tree

5 files changed

+79
-80
lines changed

5 files changed

+79
-80
lines changed

clang/lib/Sema/SemaTemplateDeductionGuide.cpp

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -363,8 +363,7 @@ struct ConvertConstructorToDeductionGuideTransform {
363363
return nullptr;
364364
// Constraints require that we substitute depth-1 arguments
365365
// to match depths when substituted for evaluation later
366-
Depth1Args.push_back(SemaRef.Context.getCanonicalTemplateArgument(
367-
SemaRef.Context.getInjectedTemplateArg(NewParam)));
366+
Depth1Args.push_back(SemaRef.Context.getInjectedTemplateArg(NewParam));
368367

369368
if (NestedPattern) {
370369
TemplateDeclInstantiator Instantiator(SemaRef, DC,
@@ -379,8 +378,7 @@ struct ConvertConstructorToDeductionGuideTransform {
379378
"Unexpected template parameter depth");
380379

381380
AllParams.push_back(NewParam);
382-
SubstArgs.push_back(SemaRef.Context.getCanonicalTemplateArgument(
383-
SemaRef.Context.getInjectedTemplateArg(NewParam)));
381+
SubstArgs.push_back(SemaRef.Context.getInjectedTemplateArg(NewParam));
384382
}
385383

386384
// Substitute new template parameters into requires-clause if present.
@@ -795,8 +793,8 @@ buildAssociatedConstraints(Sema &SemaRef, FunctionTemplateDecl *F,
795793
/*NewIndex=*/AdjustedAliasTemplateArgs.size(),
796794
getTemplateParameterDepth(TP) + AdjustDepth);
797795

798-
auto NewTemplateArgument = Context.getCanonicalTemplateArgument(
799-
Context.getInjectedTemplateArg(NewParam));
796+
TemplateArgument NewTemplateArgument =
797+
Context.getInjectedTemplateArg(NewParam);
800798
AdjustedAliasTemplateArgs.push_back(NewTemplateArgument);
801799
}
802800
// Template arguments used to transform the template arguments in
@@ -822,8 +820,8 @@ buildAssociatedConstraints(Sema &SemaRef, FunctionTemplateDecl *F,
822820
getTemplateParameterDepth(TP) + AdjustDepth);
823821
FirstUndeducedParamIdx += 1;
824822
assert(TemplateArgsForBuildingRC[Index].isNull());
825-
TemplateArgsForBuildingRC[Index] = Context.getCanonicalTemplateArgument(
826-
Context.getInjectedTemplateArg(NewParam));
823+
TemplateArgsForBuildingRC[Index] =
824+
Context.getInjectedTemplateArg(NewParam);
827825
continue;
828826
}
829827
TemplateArgumentLoc Input =
@@ -923,8 +921,8 @@ Expr *buildIsDeducibleConstraint(Sema &SemaRef,
923921
/*NewIndex=*/TransformedTemplateArgs.size(),
924922
getTemplateParameterDepth(TP) + AdjustDepth);
925923

926-
auto NewTemplateArgument = Context.getCanonicalTemplateArgument(
927-
Context.getInjectedTemplateArg(NewParam));
924+
TemplateArgument NewTemplateArgument =
925+
Context.getInjectedTemplateArg(NewParam);
928926
TransformedTemplateArgs.push_back(NewTemplateArgument);
929927
}
930928
// Transformed the ReturnType to restore the uninstantiated depth.
@@ -1087,8 +1085,8 @@ BuildDeductionGuideForTypeAlias(Sema &SemaRef,
10871085
getTemplateParameterDepth(TP));
10881086
FPrimeTemplateParams.push_back(NewParam);
10891087

1090-
auto NewTemplateArgument = Context.getCanonicalTemplateArgument(
1091-
Context.getInjectedTemplateArg(NewParam));
1088+
TemplateArgument NewTemplateArgument =
1089+
Context.getInjectedTemplateArg(NewParam);
10921090
TransformedDeducedAliasArgs[AliasTemplateParamIdx] = NewTemplateArgument;
10931091
}
10941092
unsigned FirstUndeducedParamIdx = FPrimeTemplateParams.size();
@@ -1109,8 +1107,7 @@ BuildDeductionGuideForTypeAlias(Sema &SemaRef,
11091107
assert(TemplateArgsForBuildingFPrime[FTemplateParamIdx].isNull() &&
11101108
"The argument must be null before setting");
11111109
TemplateArgsForBuildingFPrime[FTemplateParamIdx] =
1112-
Context.getCanonicalTemplateArgument(
1113-
Context.getInjectedTemplateArg(NewParam));
1110+
Context.getInjectedTemplateArg(NewParam);
11141111
}
11151112

11161113
// To form a deduction guide f' from f, we leverage clang's instantiation

clang/test/AST/ast-dump-ctad-alias.cpp

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,22 +32,24 @@ Out2<double>::AInner t(1.0);
3232
// CHECK-NEXT: | | |-UnresolvedLookupExpr {{.*}} '<dependent type>' lvalue (no ADL) = 'Concept'
3333
// CHECK-NEXT: | | | |-TemplateArgument type 'int'
3434
// CHECK-NEXT: | | | | `-BuiltinType {{.*}} 'int'
35-
// CHECK-NEXT: | | | `-TemplateArgument type 'type-parameter-1-0'
36-
// CHECK-NEXT: | | | `-TemplateTypeParmType {{.*}} 'type-parameter-1-0' dependent depth 1 index 0
35+
// CHECK-NEXT: | | | `-TemplateArgument type 'Y':'type-parameter-1-0'
36+
// CHECK-NEXT: | | | `-TemplateTypeParmType {{.*}} 'Y' dependent depth 1 index 0
37+
// CHECK-NEXT: | | | `-TemplateTypeParm {{.*}} 'Y'
3738
// CHECK-NEXT: | | `-TypeTraitExpr {{.*}} 'bool' __is_deducible
3839
// CHECK-NEXT: | | |-DeducedTemplateSpecializationType {{.*}} 'Out2<double>::AInner' dependent
3940
// CHECK-NEXT: | | | `-name: 'Out2<double>::AInner'
4041
// CHECK-NEXT: | | | `-TypeAliasTemplateDecl {{.+}} AInner{{$}}
41-
// CHECK-NEXT: | | `-ElaboratedType {{.*}} 'Inner<type-parameter-1-0>' sugar dependent
42-
// CHECK-NEXT: | | `-TemplateSpecializationType {{.*}} 'Inner<type-parameter-1-0>' dependent
42+
// CHECK-NEXT: | | `-ElaboratedType {{.*}} 'Inner<Y>' sugar dependent
43+
// CHECK-NEXT: | | `-TemplateSpecializationType {{.*}} 'Inner<Y>' dependent
4344
// CHECK-NEXT: | | |-name: 'Inner':'Out<int>::Inner' qualified
4445
// CHECK-NEXT: | | | `-ClassTemplateDecl {{.+}} Inner{{$}}
45-
// CHECK-NEXT: | | `-TemplateArgument type 'type-parameter-1-0'
46-
// CHECK-NEXT: | | `-SubstTemplateTypeParmType {{.*}} 'type-parameter-1-0'
46+
// CHECK-NEXT: | | `-TemplateArgument type 'Y'
47+
// CHECK-NEXT: | | `-SubstTemplateTypeParmType {{.*}} 'Y'
4748
// CHECK-NEXT: | | |-FunctionTemplate {{.*}} '<deduction guide for Inner>'
48-
// CHECK-NEXT: | | `-TemplateTypeParmType {{.*}} 'type-parameter-1-0' dependent depth 1 index 0
49-
// CHECK-NEXT: | |-CXXDeductionGuideDecl {{.*}} <deduction guide for AInner> 'auto (type-parameter-0-0) -> Inner<type-parameter-0-0>'
50-
// CHECK-NEXT: | | `-ParmVarDecl {{.*}} 'type-parameter-0-0'
49+
// CHECK-NEXT: | | `-TemplateTypeParmType {{.*}} 'Y' dependent depth 1 index 0
50+
// CHECK-NEXT: | | `-TemplateTypeParm {{.*}} 'Y'
51+
// CHECK-NEXT: | |-CXXDeductionGuideDecl {{.*}} <deduction guide for AInner> 'auto (Y) -> Inner<Y>'
52+
// CHECK-NEXT: | | `-ParmVarDecl {{.*}} 'Y'
5153
// CHECK-NEXT: | `-CXXDeductionGuideDecl {{.*}} used <deduction guide for AInner> 'auto (double) -> Inner<double>' implicit_instantiation
5254
// CHECK-NEXT: | |-TemplateArgument type 'double'
5355
// CHECK-NEXT: | | `-BuiltinType {{.*}} 'double'
@@ -77,8 +79,8 @@ AFoo3 afoo3{0, 1};
7779
// CHECK-NEXT: | |-UnresolvedLookupExpr {{.*}} '<dependent type>' lvalue (no ADL) = 'Concept'
7880
// CHECK-NEXT: | | |-TemplateArgument type 'int'
7981
// CHECK-NEXT: | | | `-BuiltinType {{.*}} 'int'
80-
// CHECK-NEXT: | | `-TemplateArgument type 'type-parameter-0-1'
81-
// CHECK-NEXT: | | `-TemplateTypeParmType {{.*}} 'type-parameter-0-1' dependent depth 0 index 1
82+
// CHECK-NEXT: | | `-TemplateArgument type 'V'
83+
// CHECK-NEXT: | | `-TemplateTypeParmType {{.*}} 'V' dependent depth 0 index 1
8284

8385
template <typename... T1>
8486
struct Foo {
@@ -88,16 +90,16 @@ struct Foo {
8890
template <typename...T2>
8991
using AFoo = Foo<T2...>;
9092
AFoo a(1, 2);
91-
// CHECK: |-CXXDeductionGuideDecl {{.*}} implicit <deduction guide for AFoo> 'auto (type-parameter-0-0...) -> Foo<type-parameter-0-0...>'
92-
// CHECK-NEXT: | | `-ParmVarDecl {{.*}} 'type-parameter-0-0...' pack
93+
// CHECK: |-CXXDeductionGuideDecl {{.*}} implicit <deduction guide for AFoo> 'auto (T2...) -> Foo<T2...>'
94+
// CHECK-NEXT: | | `-ParmVarDecl {{.*}} 'T2...' pack
9395
// CHECK-NEXT: | `-CXXDeductionGuideDecl {{.*}} implicit used <deduction guide for AFoo> 'auto (int, int) -> Foo<int, int>' implicit_instantiation
9496

9597
template <typename T>
9698
using BFoo = Foo<T, T>;
9799
BFoo b2(1.0, 2.0);
98-
// CHECK: |-CXXDeductionGuideDecl {{.*}} implicit <deduction guide for BFoo> 'auto (type-parameter-0-0, type-parameter-0-0) -> Foo<type-parameter-0-0, type-parameter-0-0>'
99-
// CHECK-NEXT: | | |-ParmVarDecl {{.*}} 'type-parameter-0-0'
100-
// CHECK-NEXT: | | `-ParmVarDecl {{.*}} 'type-parameter-0-0'
100+
// CHECK: |-CXXDeductionGuideDecl {{.*}} implicit <deduction guide for BFoo> 'auto (T, T) -> Foo<T, T>'
101+
// CHECK-NEXT: | | |-ParmVarDecl {{.*}} 'T'
102+
// CHECK-NEXT: | | `-ParmVarDecl {{.*}} 'T'
101103
// CHECK-NEXT: | `-CXXDeductionGuideDecl {{.*}} implicit used <deduction guide for BFoo> 'auto (double, double) -> Foo<double, double>' implicit_instantiation
102104

103105
namespace GH90209 {

clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ namespace std_example {
7878
template<class T> struct A { // expected-note {{candidate}} expected-note {{implicit deduction guide}}
7979
template<class U>
8080
A(T &&, U &&, int *); // expected-note {{[with T = int, U = int] not viable: expects an rvalue}} \
81-
// expected-note {{implicit deduction guide declared as 'template <class T, class U> A(T &&, type-parameter-0-1 &&, int *) -> A<T>'}}
81+
// expected-note {{implicit deduction guide declared as 'template <class T, class U> A(T &&, U &&, int *) -> A<T>'}}
8282
A(T &&, int *); // expected-note {{requires 2}} \
8383
// expected-note {{implicit deduction guide declared as 'template <class T> A(T &&, int *) -> A<T>'}}
8484
};

clang/test/SemaCXX/cxx20-ctad-type-alias.cpp

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,8 @@ struct Foo {
110110

111111
template <typename X, int Y>
112112
using Bar = Foo<X, sizeof(X)>; // expected-note {{candidate template ignored: couldn't infer template argument 'X'}} \
113-
// expected-note {{implicit deduction guide declared as 'template <typename X> requires __is_deducible(test9::Bar, Foo<type-parameter-0-0, sizeof(type-parameter-0-0)>) Bar(Foo<type-parameter-0-0, sizeof(type-parameter-0-0)>) -> Foo<type-parameter-0-0, sizeof(type-parameter-0-0)>'}} \
114-
// expected-note {{implicit deduction guide declared as 'template <typename X> requires __is_deducible(test9::Bar, Foo<type-parameter-0-0, sizeof(type-parameter-0-0)>) Bar(const type-parameter-0-0 (&)[sizeof(type-parameter-0-0)]) -> Foo<type-parameter-0-0, sizeof(type-parameter-0-0)>'}} \
113+
// expected-note {{implicit deduction guide declared as 'template <typename X> requires __is_deducible(test9::Bar, Foo<X, sizeof(X)>) Bar(Foo<X, sizeof(X)>) -> Foo<X, sizeof(X)>'}} \
114+
// expected-note {{implicit deduction guide declared as 'template <typename X> requires __is_deducible(test9::Bar, Foo<X, sizeof(X)>) Bar(const X (&)[sizeof(X)]) -> Foo<X, sizeof(X)>'}} \
115115
// expected-note {{candidate template ignored: constraints not satisfied [with X = int]}} \
116116
// expected-note {{cannot deduce template arguments for 'Bar' from 'Foo<int, 4UL>'}}
117117

@@ -138,13 +138,13 @@ namespace test11 {
138138
struct A {};
139139
template<class T> struct Foo { T c; };
140140
template<class X, class Y=A>
141-
using AFoo = Foo<Y>; // expected-note {{candidate template ignored: could not match 'Foo<type-parameter-0-0>' against 'int'}} \
142-
// expected-note {{implicit deduction guide declared as 'template <class Y = A> requires __is_deducible(test11::AFoo, Foo<type-parameter-0-0>) AFoo(Foo<type-parameter-0-0>) -> Foo<type-parameter-0-0>'}} \
141+
using AFoo = Foo<Y>; // expected-note {{candidate template ignored: could not match 'Foo<Y>' against 'int'}} \
142+
// expected-note {{implicit deduction guide declared as 'template <class Y = A> requires __is_deducible(test11::AFoo, Foo<Y>) AFoo(Foo<Y>) -> Foo<Y>'}} \
143143
// expected-note {{candidate template ignored: constraints not satisfied [with Y = int]}} \
144144
// expected-note {{cannot deduce template arguments for 'AFoo' from 'Foo<int>'}} \
145-
// expected-note {{implicit deduction guide declared as 'template <class Y = A> requires __is_deducible(test11::AFoo, Foo<type-parameter-0-0>) AFoo(type-parameter-0-0) -> Foo<type-parameter-0-0>'}} \
145+
// expected-note {{implicit deduction guide declared as 'template <class Y = A> requires __is_deducible(test11::AFoo, Foo<Y>) AFoo(Y) -> Foo<Y>'}} \
146146
// expected-note {{candidate function template not viable: requires 0 arguments, but 1 was provided}} \
147-
// expected-note {{implicit deduction guide declared as 'template <class Y = A> requires __is_deducible(test11::AFoo, Foo<type-parameter-0-0>) AFoo() -> Foo<type-parameter-0-0>'}}
147+
// expected-note {{implicit deduction guide declared as 'template <class Y = A> requires __is_deducible(test11::AFoo, Foo<Y>) AFoo() -> Foo<Y>'}}
148148

149149
AFoo s = {1}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'AFoo'}}
150150
} // namespace test11
@@ -211,9 +211,9 @@ template<typename> concept False = false;
211211
template<False W>
212212
using BFoo = AFoo<W>; // expected-note {{candidate template ignored: constraints not satisfied [with V = int]}} \
213213
// expected-note {{cannot deduce template arguments for 'BFoo' from 'Foo<int *>'}} \
214-
// expected-note {{implicit deduction guide declared as 'template <class V> requires __is_deducible(AFoo, Foo<type-parameter-0-0 *>) && __is_deducible(test15::BFoo, Foo<type-parameter-0-0 *>) BFoo(type-parameter-0-0 *) -> Foo<type-parameter-0-0 *>}} \
215-
// expected-note {{candidate template ignored: could not match 'Foo<type-parameter-0-0 *>' against 'int *'}} \
216-
// expected-note {{template <class V> requires __is_deducible(AFoo, Foo<type-parameter-0-0 *>) && __is_deducible(test15::BFoo, Foo<type-parameter-0-0 *>) BFoo(Foo<type-parameter-0-0 *>) -> Foo<type-parameter-0-0 *>}}
214+
// expected-note {{implicit deduction guide declared as 'template <class V> requires __is_deducible(AFoo, Foo<V *>) && __is_deducible(test15::BFoo, Foo<V *>) BFoo(V *) -> Foo<V *>}} \
215+
// expected-note {{candidate template ignored: could not match 'Foo<V *>' against 'int *'}} \
216+
// expected-note {{template <class V> requires __is_deducible(AFoo, Foo<V *>) && __is_deducible(test15::BFoo, Foo<V *>) BFoo(Foo<V *>) -> Foo<V *>}}
217217
int i = 0;
218218
AFoo a1(&i); // OK, deduce Foo<int *>
219219

@@ -263,12 +263,12 @@ template<typename T> requires False<T> // expected-note {{because 'int' does not
263263
Foo(T) -> Foo<int>;
264264

265265
template <typename U>
266-
using Bar = Foo<U>; // expected-note {{could not match 'Foo<type-parameter-0-0>' against 'int'}} \
267-
// expected-note {{implicit deduction guide declared as 'template <typename U> requires __is_deducible(test18::Bar, Foo<type-parameter-0-0>) Bar(Foo<type-parameter-0-0>) -> Foo<type-parameter-0-0>'}} \
266+
using Bar = Foo<U>; // expected-note {{could not match 'Foo<U>' against 'int'}} \
267+
// expected-note {{implicit deduction guide declared as 'template <typename U> requires __is_deducible(test18::Bar, Foo<U>) Bar(Foo<U>) -> Foo<U>'}} \
268268
// expected-note {{candidate template ignored: constraints not satisfied}} \
269-
// expected-note {{implicit deduction guide declared as 'template <typename T> requires False<type-parameter-0-0> && __is_deducible(test18::Bar, Foo<int>) Bar(type-parameter-0-0) -> Foo<int>'}} \
269+
// expected-note {{implicit deduction guide declared as 'template <typename T> requires False<T> && __is_deducible(test18::Bar, Foo<int>) Bar(T) -> Foo<int>'}} \
270270
// expected-note {{candidate function template not viable}} \
271-
// expected-note {{implicit deduction guide declared as 'template <typename U> requires __is_deducible(test18::Bar, Foo<type-parameter-0-0>) Bar() -> Foo<type-parameter-0-0>'}}
271+
// expected-note {{implicit deduction guide declared as 'template <typename U> requires __is_deducible(test18::Bar, Foo<U>) Bar() -> Foo<U>'}}
272272

273273
Bar s = {1}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments}}
274274
} // namespace test18
@@ -296,8 +296,8 @@ class Foo {};
296296
// Verify that template template type parameter TTP is referenced/used in the
297297
// template arguments of the RHS.
298298
template <template<typename> typename TTP>
299-
using Bar = Foo<K<TTP>>; // expected-note {{candidate template ignored: could not match 'Foo<K<template-parameter-0-0>>' against 'int'}} \
300-
// expected-note {{implicit deduction guide declared as 'template <template <typename> typename TTP> requires __is_deducible(test20::Bar, Foo<K<template-parameter-0-0>>) Bar(Foo<K<template-parameter-0-0>>) -> Foo<K<template-parameter-0-0>>'}}
299+
using Bar = Foo<K<TTP>>; // expected-note {{candidate template ignored: could not match 'Foo<K<TTP>>' against 'int'}} \
300+
// expected-note {{implicit deduction guide declared as 'template <template <typename> typename TTP> requires __is_deducible(test20::Bar, Foo<K<TTP>>) Bar(Foo<K<TTP>>) -> Foo<K<TTP>>'}}
301301

302302
template <class T>
303303
class Container {};

0 commit comments

Comments
 (0)