Skip to content

Commit fd9bdcc

Browse files
committed
[clang] remove unneeded template deduction canonicalizations
This is mostly a cleanups patch, with some hard to observe sugar preservation improvements. Except for the function template deduction changes which improve some pre-existing diagnostics a little bit.
1 parent 9e9d98a commit fd9bdcc

File tree

4 files changed

+40
-63
lines changed

4 files changed

+40
-63
lines changed

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4202,7 +4202,7 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
42024202
TemplateDeductionInfo Info(FailedCandidates.getLocation());
42034203

42044204
if (TemplateDeductionResult Result =
4205-
DeduceTemplateArguments(Partial, CanonicalConverted, Info);
4205+
DeduceTemplateArguments(Partial, SugaredConverted, Info);
42064206
Result != TemplateDeductionResult::Success) {
42074207
// Store the failed-deduction information for use in diagnostics, later.
42084208
// TODO: Actually use the failed-deduction info?
@@ -4213,7 +4213,7 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
42134213
} else {
42144214
Matched.push_back(PartialSpecMatchResult());
42154215
Matched.back().Partial = Partial;
4216-
Matched.back().Args = Info.takeCanonical();
4216+
Matched.back().Args = Info.takeSugared();
42174217
}
42184218
}
42194219

clang/lib/Sema/SemaTemplateDeduction.cpp

Lines changed: 32 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,6 @@ static TemplateDeductionResult DeduceNonTypeTemplateArgument(
503503
const NonTypeTemplateParmDecl *NTTP, ValueDecl *D, QualType T,
504504
TemplateDeductionInfo &Info,
505505
SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
506-
D = D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
507506
TemplateArgument New(D, T);
508507
return DeduceNonTypeTemplateArgument(
509508
S, TemplateParams, NTTP, DeducedTemplateArgument(New), T, Info, Deduced);
@@ -1380,11 +1379,6 @@ static bool isForwardingReference(QualType Param, unsigned FirstInnerIndex) {
13801379
return false;
13811380
}
13821381

1383-
static CXXRecordDecl *getCanonicalRD(QualType T) {
1384-
return cast<CXXRecordDecl>(
1385-
T->castAs<RecordType>()->getDecl()->getCanonicalDecl());
1386-
}
1387-
13881382
/// Attempt to deduce the template arguments by checking the base types
13891383
/// according to (C++20 [temp.deduct.call] p4b3.
13901384
///
@@ -1439,7 +1433,7 @@ DeduceTemplateBases(Sema &S, const CXXRecordDecl *RD,
14391433
for (const auto &Base : RD->bases()) {
14401434
QualType T = Base.getType();
14411435
assert(T->isRecordType() && "Base class that isn't a record?");
1442-
if (Visited.insert(::getCanonicalRD(T)).second)
1436+
if (Visited.insert(T->getAsCXXRecordDecl()).second)
14431437
ToVisit.push_back(T);
14441438
}
14451439
};
@@ -1460,7 +1454,7 @@ DeduceTemplateBases(Sema &S, const CXXRecordDecl *RD,
14601454

14611455
// If this was a successful deduction, add it to the list of matches,
14621456
// otherwise we need to continue searching its bases.
1463-
const CXXRecordDecl *RD = ::getCanonicalRD(NextT);
1457+
const CXXRecordDecl *RD = NextT->getAsCXXRecordDecl();
14641458
if (BaseResult == TemplateDeductionResult::Success)
14651459
Matches.insert({RD, DeducedCopy});
14661460
else
@@ -1481,7 +1475,7 @@ DeduceTemplateBases(Sema &S, const CXXRecordDecl *RD,
14811475
// We can give up once we have a single item (or have run out of things to
14821476
// search) since cyclical inheritance isn't valid.
14831477
while (Matches.size() > 1 && !ToVisit.empty()) {
1484-
const CXXRecordDecl *RD = ::getCanonicalRD(ToVisit.pop_back_val());
1478+
const CXXRecordDecl *RD = ToVisit.pop_back_val()->getAsCXXRecordDecl();
14851479
Matches.erase(RD);
14861480

14871481
// Always add all bases, since the inheritance tree can contain
@@ -2030,15 +2024,16 @@ static TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch(
20302024
if (!S.isCompleteType(Info.getLocation(), A))
20312025
return Result;
20322026

2033-
if (getCanonicalRD(A)->isInvalidDecl())
2027+
const CXXRecordDecl *RD = A->getAsCXXRecordDecl();
2028+
if (RD->isInvalidDecl())
20342029
return Result;
20352030

20362031
// Reset the incorrectly deduced argument from above.
20372032
Deduced = DeducedOrig;
20382033

20392034
// Check bases according to C++14 [temp.deduct.call] p4b3:
2040-
auto BaseResult = DeduceTemplateBases(S, getCanonicalRD(A),
2041-
TemplateParams, P, Info, Deduced);
2035+
auto BaseResult =
2036+
DeduceTemplateBases(S, RD, TemplateParams, P, Info, Deduced);
20422037
return BaseResult != TemplateDeductionResult::Invalid ? BaseResult
20432038
: Result;
20442039
}
@@ -3369,9 +3364,7 @@ Sema::DeduceTemplateArgumentsFromType(TemplateDecl *TD, QualType FromType,
33693364
// Use the InjectedClassNameType.
33703365
PType = Context.getTypeDeclType(CTD->getTemplatedDecl());
33713366
} else if (const auto *AliasTemplate = dyn_cast<TypeAliasTemplateDecl>(TD)) {
3372-
PType = AliasTemplate->getTemplatedDecl()
3373-
->getUnderlyingType()
3374-
.getCanonicalType();
3367+
PType = AliasTemplate->getTemplatedDecl()->getUnderlyingType();
33753368
} else {
33763369
assert(false && "Expected a class or alias template");
33773370
}
@@ -3505,15 +3498,15 @@ TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments(
35053498
// the explicit template arguments. They'll be used as part of deduction
35063499
// for this template parameter pack.
35073500
unsigned PartiallySubstitutedPackIndex = -1u;
3508-
if (!CanonicalBuilder.empty()) {
3509-
const TemplateArgument &Arg = CanonicalBuilder.back();
3501+
if (!SugaredBuilder.empty()) {
3502+
const TemplateArgument &Arg = SugaredBuilder.back();
35103503
if (Arg.getKind() == TemplateArgument::Pack) {
3511-
auto *Param = TemplateParams->getParam(CanonicalBuilder.size() - 1);
3504+
auto *Param = TemplateParams->getParam(SugaredBuilder.size() - 1);
35123505
// If this is a fully-saturated fixed-size pack, it should be
35133506
// fully-substituted, not partially-substituted.
35143507
std::optional<unsigned> Expansions = getExpandedPackSize(Param);
35153508
if (!Expansions || Arg.pack_size() < *Expansions) {
3516-
PartiallySubstitutedPackIndex = CanonicalBuilder.size() - 1;
3509+
PartiallySubstitutedPackIndex = SugaredBuilder.size() - 1;
35173510
CurrentInstantiationScope->SetPartiallySubstitutedPack(
35183511
Param, Arg.pack_begin(), Arg.pack_size());
35193512
}
@@ -3890,8 +3883,8 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
38903883
if (!Specialization || Specialization->isInvalidDecl())
38913884
return TemplateDeductionResult::SubstitutionFailure;
38923885

3893-
assert(Specialization->getPrimaryTemplate()->getCanonicalDecl() ==
3894-
FunctionTemplate->getCanonicalDecl());
3886+
assert(isSameDeclaration(Specialization->getPrimaryTemplate(),
3887+
FunctionTemplate));
38953888

38963889
// If the template argument list is owned by the function template
38973890
// specialization, release it.
@@ -4736,8 +4729,7 @@ TemplateDeductionResult Sema::DeduceTemplateArguments(
47364729
// types, template argument deduction fails.
47374730
if (!ArgFunctionType.isNull()) {
47384731
if (IsAddressOfFunction ? !isSameOrCompatibleFunctionType(
4739-
Context.getCanonicalType(SpecializationType),
4740-
Context.getCanonicalType(ArgFunctionType))
4732+
SpecializationType, ArgFunctionType)
47414733
: !Context.hasSameFunctionTypeIgnoringExceptionSpec(
47424734
SpecializationType, ArgFunctionType)) {
47434735
Info.FirstArg = TemplateArgument(SpecializationType);
@@ -4751,19 +4743,17 @@ TemplateDeductionResult Sema::DeduceTemplateArguments(
47514743

47524744
TemplateDeductionResult Sema::DeduceTemplateArguments(
47534745
FunctionTemplateDecl *ConversionTemplate, QualType ObjectType,
4754-
Expr::Classification ObjectClassification, QualType ToType,
4746+
Expr::Classification ObjectClassification, QualType A,
47554747
CXXConversionDecl *&Specialization, TemplateDeductionInfo &Info) {
47564748
if (ConversionTemplate->isInvalidDecl())
47574749
return TemplateDeductionResult::Invalid;
47584750

47594751
CXXConversionDecl *ConversionGeneric
47604752
= cast<CXXConversionDecl>(ConversionTemplate->getTemplatedDecl());
47614753

4762-
QualType FromType = ConversionGeneric->getConversionType();
4763-
4764-
// Canonicalize the types for deduction.
4765-
QualType P = Context.getCanonicalType(FromType);
4766-
QualType A = Context.getCanonicalType(ToType);
4754+
QualType P = ConversionGeneric->getConversionType();
4755+
bool IsReferenceP = P->isReferenceType();
4756+
bool IsReferenceA = A->isReferenceType();
47674757

47684758
// C++0x [temp.deduct.conv]p2:
47694759
// If P is a reference type, the type referred to by P is used for
@@ -4779,7 +4769,7 @@ TemplateDeductionResult Sema::DeduceTemplateArguments(
47794769
// We work around a defect in the standard here: cv-qualifiers are also
47804770
// removed from P and A in this case, unless P was a reference type. This
47814771
// seems to mostly match what other compilers are doing.
4782-
if (!FromType->getAs<ReferenceType>()) {
4772+
if (!IsReferenceP) {
47834773
A = A.getUnqualifiedType();
47844774
P = P.getUnqualifiedType();
47854775
}
@@ -4835,7 +4825,7 @@ TemplateDeductionResult Sema::DeduceTemplateArguments(
48354825
// - If the original A is a reference type, A can be more
48364826
// cv-qualified than the deduced A (i.e., the type referred to
48374827
// by the reference)
4838-
if (ToType->isReferenceType())
4828+
if (IsReferenceA)
48394829
TDF |= TDF_ArgWithReferenceType;
48404830
// - The deduced A can be another pointer or pointer to member
48414831
// type that can be converted to A via a qualification
@@ -5736,17 +5726,6 @@ FunctionTemplateDecl *Sema::getMoreSpecializedTemplate(
57365726
return AtLeastAsConstrained1 ? FT1 : FT2;
57375727
}
57385728

5739-
/// Determine if the two templates are equivalent.
5740-
static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) {
5741-
if (T1 == T2)
5742-
return true;
5743-
5744-
if (!T1 || !T2)
5745-
return false;
5746-
5747-
return T1->getCanonicalDecl() == T2->getCanonicalDecl();
5748-
}
5749-
57505729
UnresolvedSetIterator Sema::getMostSpecialized(
57515730
UnresolvedSetIterator SpecBegin, UnresolvedSetIterator SpecEnd,
57525731
TemplateSpecCandidateSet &FailedCandidates,
@@ -5774,9 +5753,9 @@ UnresolvedSetIterator Sema::getMostSpecialized(
57745753
FunctionTemplateDecl *Challenger
57755754
= cast<FunctionDecl>(*I)->getPrimaryTemplate();
57765755
assert(Challenger && "Not a function template specialization?");
5777-
if (isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger, Loc,
5778-
TPOC_Other, 0),
5779-
Challenger)) {
5756+
if (declaresSameEntity(getMoreSpecializedTemplate(BestTemplate, Challenger,
5757+
Loc, TPOC_Other, 0),
5758+
Challenger)) {
57805759
Best = I;
57815760
BestTemplate = Challenger;
57825761
}
@@ -5789,9 +5768,9 @@ UnresolvedSetIterator Sema::getMostSpecialized(
57895768
FunctionTemplateDecl *Challenger
57905769
= cast<FunctionDecl>(*I)->getPrimaryTemplate();
57915770
if (I != Best &&
5792-
!isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger,
5793-
Loc, TPOC_Other, 0),
5794-
BestTemplate)) {
5771+
!declaresSameEntity(getMoreSpecializedTemplate(BestTemplate, Challenger,
5772+
Loc, TPOC_Other, 0),
5773+
BestTemplate)) {
57955774
Ambiguous = true;
57965775
break;
57975776
}
@@ -6116,11 +6095,10 @@ Sema::getMoreSpecializedPartialSpecialization(
61166095
"the partial specializations being compared should specialize"
61176096
" the same template.");
61186097
TemplateName Name(PS1->getSpecializedTemplate());
6119-
TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name);
61206098
QualType PT1 = Context.getTemplateSpecializationType(
6121-
CanonTemplate, PS1->getTemplateArgs().asArray());
6099+
Name, PS1->getTemplateArgs().asArray());
61226100
QualType PT2 = Context.getTemplateSpecializationType(
6123-
CanonTemplate, PS2->getTemplateArgs().asArray());
6101+
Name, PS2->getTemplateArgs().asArray());
61246102

61256103
TemplateDeductionInfo Info(Loc);
61266104
return getMoreSpecialized(*this, PT1, PT2, PS1, PS2, Info);
@@ -6129,12 +6107,11 @@ Sema::getMoreSpecializedPartialSpecialization(
61296107
bool Sema::isMoreSpecializedThanPrimary(
61306108
VarTemplatePartialSpecializationDecl *Spec, TemplateDeductionInfo &Info) {
61316109
VarTemplateDecl *Primary = Spec->getSpecializedTemplate();
6132-
TemplateName CanonTemplate =
6133-
Context.getCanonicalTemplateName(TemplateName(Primary));
6110+
TemplateName Name(Primary);
61346111
QualType PrimaryT = Context.getTemplateSpecializationType(
6135-
CanonTemplate, Primary->getInjectedTemplateArgs());
6112+
Name, Primary->getInjectedTemplateArgs());
61366113
QualType PartialT = Context.getTemplateSpecializationType(
6137-
CanonTemplate, Spec->getTemplateArgs().asArray());
6114+
Name, Spec->getTemplateArgs().asArray());
61386115

61396116
VarTemplatePartialSpecializationDecl *MaybeSpec =
61406117
getMoreSpecialized(*this, PartialT, PrimaryT, Spec, Primary, Info);

clang/test/SemaCXX/cxx1y-generic-lambdas-variadics.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ struct X { };
1616
struct Y { };
1717
struct Z { };
1818

19-
int test() {
19+
int test() {
2020
{
2121
auto L = [](auto ... as) { };
2222
L.operator()<bool>(true);
@@ -36,7 +36,7 @@ int test() {
3636
{
3737
auto L = [](auto a, auto b, auto ... cs) { };
3838
L.operator()<bool, char>(false, 'a');
39-
L.operator()<bool, char, const char*>(false, 'a', "jim");
39+
L.operator()<bool, char, const char*>(false, 'a', "jim");
4040
}
4141

4242
{
@@ -77,7 +77,7 @@ int test() {
7777
M(6.26, "jim", true);
7878
M.operator()<X>(6.26, "jim", false, X{}, Y{}, Z{});
7979
}
80-
80+
8181
return 0;
8282
}
8383
int run = test();
@@ -106,7 +106,7 @@ namespace PR33082 {
106106
template<int ...I> void a() {
107107
int arr[] = { [](auto ...K) { (void)I; } ... };
108108
// expected-error@-1 {{no viable conversion}}
109-
// expected-note-re@-2 {{candidate template ignored: could not match 'auto (*)(type-parameter-0-0...){{.*}}' against 'int'}}
109+
// expected-note-re@-2 {{candidate template ignored: could not match 'auto (*)(auto...){{.*}}' against 'int'}}
110110
}
111111

112112
template<typename ...T> struct Pack {};

clang/test/SemaCXX/cxx1y-generic-lambdas.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ namespace conversion_operator {
217217
int (&fp2)(int) = [](auto a) { return a; }; // expected-error{{non-const lvalue}}
218218
int (&&fp3)(int) = [](auto a) { return a; };
219219
// expected-error@-1 {{no viable conversion}}
220-
// expected-note-re@-2 {{candidate template ignored: could not match 'auto (*)(type-parameter-0-0){{.*}}' against 'int (int)'}}
220+
// expected-note-re@-2 {{candidate template ignored: could not match 'auto (*)(auto){{.*}}' against 'int (int)'}}
221221

222222
using F = int(int);
223223
using G = int(void*);
@@ -293,7 +293,7 @@ int test() {
293293
print("a = ", a, "\n");
294294
return [](auto b) ->decltype(a) {
295295
// expected-error@-1 {{no viable conversion}}
296-
// expected-note-re@-2 {{candidate template ignored: could not match 'int (*)(type-parameter-0-0){{.*}}' against 'int'}}
296+
// expected-note-re@-2 {{candidate template ignored: could not match 'auto (*)(auto){{.*}}' ({{.*}}) against 'decltype(a)' (aka 'int')}}
297297
print("b = ", b, "\n");
298298
return b;
299299
};

0 commit comments

Comments
 (0)