[llvm-branch-commits] [clang] [clang] remove unneeded template deduction canonicalizations (PR #101594)
Matheus Izvekov via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Aug 2 19:16:52 PDT 2024
https://github.com/mizvekov updated https://github.com/llvm/llvm-project/pull/101594
>From 86c6801ad60e867ab95051eb6e279a97aeefa4ce Mon Sep 17 00:00:00 2001
From: Matheus Izvekov <mizvekov at gmail.com>
Date: Thu, 1 Aug 2024 19:18:52 -0300
Subject: [PATCH] [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.
---
clang/lib/Sema/SemaTemplate.cpp | 4 +-
clang/lib/Sema/SemaTemplateDeduction.cpp | 86 +++++++------------
.../cxx1y-generic-lambdas-variadics.cpp | 8 +-
clang/test/SemaCXX/cxx1y-generic-lambdas.cpp | 4 +-
4 files changed, 39 insertions(+), 63 deletions(-)
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index c22e329bef2b9..cb16e8caa9a8a 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -4202,7 +4202,7 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
TemplateDeductionInfo Info(FailedCandidates.getLocation());
if (TemplateDeductionResult Result =
- DeduceTemplateArguments(Partial, CanonicalConverted, Info);
+ DeduceTemplateArguments(Partial, SugaredConverted, Info);
Result != TemplateDeductionResult::Success) {
// Store the failed-deduction information for use in diagnostics, later.
// TODO: Actually use the failed-deduction info?
@@ -4213,7 +4213,7 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
} else {
Matched.push_back(PartialSpecMatchResult());
Matched.back().Partial = Partial;
- Matched.back().Args = Info.takeCanonical();
+ Matched.back().Args = Info.takeSugared();
}
}
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index db7f233dcef73..eeeb780299e78 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -503,7 +503,6 @@ static TemplateDeductionResult DeduceNonTypeTemplateArgument(
const NonTypeTemplateParmDecl *NTTP, ValueDecl *D, QualType T,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
- D = D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
TemplateArgument New(D, T);
return DeduceNonTypeTemplateArgument(
S, TemplateParams, NTTP, DeducedTemplateArgument(New), T, Info, Deduced);
@@ -1380,11 +1379,6 @@ static bool isForwardingReference(QualType Param, unsigned FirstInnerIndex) {
return false;
}
-static CXXRecordDecl *getCanonicalRD(QualType T) {
- return cast<CXXRecordDecl>(
- T->castAs<RecordType>()->getDecl()->getCanonicalDecl());
-}
-
/// Attempt to deduce the template arguments by checking the base types
/// according to (C++20 [temp.deduct.call] p4b3.
///
@@ -1439,7 +1433,7 @@ DeduceTemplateBases(Sema &S, const CXXRecordDecl *RD,
for (const auto &Base : RD->bases()) {
QualType T = Base.getType();
assert(T->isRecordType() && "Base class that isn't a record?");
- if (Visited.insert(::getCanonicalRD(T)).second)
+ if (Visited.insert(T->getAsCXXRecordDecl()).second)
ToVisit.push_back(T);
}
};
@@ -1460,7 +1454,7 @@ DeduceTemplateBases(Sema &S, const CXXRecordDecl *RD,
// If this was a successful deduction, add it to the list of matches,
// otherwise we need to continue searching its bases.
- const CXXRecordDecl *RD = ::getCanonicalRD(NextT);
+ const CXXRecordDecl *RD = NextT->getAsCXXRecordDecl();
if (BaseResult == TemplateDeductionResult::Success)
Matches.insert({RD, DeducedCopy});
else
@@ -1481,7 +1475,7 @@ DeduceTemplateBases(Sema &S, const CXXRecordDecl *RD,
// We can give up once we have a single item (or have run out of things to
// search) since cyclical inheritance isn't valid.
while (Matches.size() > 1 && !ToVisit.empty()) {
- const CXXRecordDecl *RD = ::getCanonicalRD(ToVisit.pop_back_val());
+ const CXXRecordDecl *RD = ToVisit.pop_back_val()->getAsCXXRecordDecl();
Matches.erase(RD);
// Always add all bases, since the inheritance tree can contain
@@ -2030,15 +2024,16 @@ static TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch(
if (!S.isCompleteType(Info.getLocation(), A))
return Result;
- if (getCanonicalRD(A)->isInvalidDecl())
+ const CXXRecordDecl *RD = A->getAsCXXRecordDecl();
+ if (RD->isInvalidDecl())
return Result;
// Reset the incorrectly deduced argument from above.
Deduced = DeducedOrig;
// Check bases according to C++14 [temp.deduct.call] p4b3:
- auto BaseResult = DeduceTemplateBases(S, getCanonicalRD(A),
- TemplateParams, P, Info, Deduced);
+ auto BaseResult =
+ DeduceTemplateBases(S, RD, TemplateParams, P, Info, Deduced);
return BaseResult != TemplateDeductionResult::Invalid ? BaseResult
: Result;
}
@@ -3369,9 +3364,7 @@ Sema::DeduceTemplateArgumentsFromType(TemplateDecl *TD, QualType FromType,
// Use the InjectedClassNameType.
PType = Context.getTypeDeclType(CTD->getTemplatedDecl());
} else if (const auto *AliasTemplate = dyn_cast<TypeAliasTemplateDecl>(TD)) {
- PType = AliasTemplate->getTemplatedDecl()
- ->getUnderlyingType()
- .getCanonicalType();
+ PType = AliasTemplate->getTemplatedDecl()->getUnderlyingType();
} else {
assert(false && "Expected a class or alias template");
}
@@ -3505,15 +3498,15 @@ TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments(
// the explicit template arguments. They'll be used as part of deduction
// for this template parameter pack.
unsigned PartiallySubstitutedPackIndex = -1u;
- if (!CanonicalBuilder.empty()) {
- const TemplateArgument &Arg = CanonicalBuilder.back();
+ if (!SugaredBuilder.empty()) {
+ const TemplateArgument &Arg = SugaredBuilder.back();
if (Arg.getKind() == TemplateArgument::Pack) {
- auto *Param = TemplateParams->getParam(CanonicalBuilder.size() - 1);
+ auto *Param = TemplateParams->getParam(SugaredBuilder.size() - 1);
// If this is a fully-saturated fixed-size pack, it should be
// fully-substituted, not partially-substituted.
std::optional<unsigned> Expansions = getExpandedPackSize(Param);
if (!Expansions || Arg.pack_size() < *Expansions) {
- PartiallySubstitutedPackIndex = CanonicalBuilder.size() - 1;
+ PartiallySubstitutedPackIndex = SugaredBuilder.size() - 1;
CurrentInstantiationScope->SetPartiallySubstitutedPack(
Param, Arg.pack_begin(), Arg.pack_size());
}
@@ -3890,8 +3883,8 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
if (!Specialization || Specialization->isInvalidDecl())
return TemplateDeductionResult::SubstitutionFailure;
- assert(Specialization->getPrimaryTemplate()->getCanonicalDecl() ==
- FunctionTemplate->getCanonicalDecl());
+ assert(isSameDeclaration(Specialization->getPrimaryTemplate(),
+ FunctionTemplate));
// If the template argument list is owned by the function template
// specialization, release it.
@@ -4736,8 +4729,7 @@ TemplateDeductionResult Sema::DeduceTemplateArguments(
// types, template argument deduction fails.
if (!ArgFunctionType.isNull()) {
if (IsAddressOfFunction ? !isSameOrCompatibleFunctionType(
- Context.getCanonicalType(SpecializationType),
- Context.getCanonicalType(ArgFunctionType))
+ SpecializationType, ArgFunctionType)
: !Context.hasSameFunctionTypeIgnoringExceptionSpec(
SpecializationType, ArgFunctionType)) {
Info.FirstArg = TemplateArgument(SpecializationType);
@@ -4751,7 +4743,7 @@ TemplateDeductionResult Sema::DeduceTemplateArguments(
TemplateDeductionResult Sema::DeduceTemplateArguments(
FunctionTemplateDecl *ConversionTemplate, QualType ObjectType,
- Expr::Classification ObjectClassification, QualType ToType,
+ Expr::Classification ObjectClassification, QualType A,
CXXConversionDecl *&Specialization, TemplateDeductionInfo &Info) {
if (ConversionTemplate->isInvalidDecl())
return TemplateDeductionResult::Invalid;
@@ -4759,11 +4751,8 @@ TemplateDeductionResult Sema::DeduceTemplateArguments(
CXXConversionDecl *ConversionGeneric
= cast<CXXConversionDecl>(ConversionTemplate->getTemplatedDecl());
- QualType FromType = ConversionGeneric->getConversionType();
-
- // Canonicalize the types for deduction.
- QualType P = Context.getCanonicalType(FromType);
- QualType A = Context.getCanonicalType(ToType);
+ QualType P = ConversionGeneric->getConversionType();
+ bool IsReferenceP = P->isReferenceType(), IsReferenceA = A->isReferenceType();
// C++0x [temp.deduct.conv]p2:
// If P is a reference type, the type referred to by P is used for
@@ -4779,7 +4768,7 @@ TemplateDeductionResult Sema::DeduceTemplateArguments(
// We work around a defect in the standard here: cv-qualifiers are also
// removed from P and A in this case, unless P was a reference type. This
// seems to mostly match what other compilers are doing.
- if (!FromType->getAs<ReferenceType>()) {
+ if (!IsReferenceP) {
A = A.getUnqualifiedType();
P = P.getUnqualifiedType();
}
@@ -4835,7 +4824,7 @@ TemplateDeductionResult Sema::DeduceTemplateArguments(
// - If the original A is a reference type, A can be more
// cv-qualified than the deduced A (i.e., the type referred to
// by the reference)
- if (ToType->isReferenceType())
+ if (IsReferenceA)
TDF |= TDF_ArgWithReferenceType;
// - The deduced A can be another pointer or pointer to member
// type that can be converted to A via a qualification
@@ -5736,17 +5725,6 @@ FunctionTemplateDecl *Sema::getMoreSpecializedTemplate(
return AtLeastAsConstrained1 ? FT1 : FT2;
}
-/// Determine if the two templates are equivalent.
-static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) {
- if (T1 == T2)
- return true;
-
- if (!T1 || !T2)
- return false;
-
- return T1->getCanonicalDecl() == T2->getCanonicalDecl();
-}
-
UnresolvedSetIterator Sema::getMostSpecialized(
UnresolvedSetIterator SpecBegin, UnresolvedSetIterator SpecEnd,
TemplateSpecCandidateSet &FailedCandidates,
@@ -5774,9 +5752,9 @@ UnresolvedSetIterator Sema::getMostSpecialized(
FunctionTemplateDecl *Challenger
= cast<FunctionDecl>(*I)->getPrimaryTemplate();
assert(Challenger && "Not a function template specialization?");
- if (isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger, Loc,
- TPOC_Other, 0),
- Challenger)) {
+ if (declaresSameEntity(getMoreSpecializedTemplate(BestTemplate, Challenger,
+ Loc, TPOC_Other, 0),
+ Challenger)) {
Best = I;
BestTemplate = Challenger;
}
@@ -5789,9 +5767,9 @@ UnresolvedSetIterator Sema::getMostSpecialized(
FunctionTemplateDecl *Challenger
= cast<FunctionDecl>(*I)->getPrimaryTemplate();
if (I != Best &&
- !isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger,
- Loc, TPOC_Other, 0),
- BestTemplate)) {
+ !declaresSameEntity(getMoreSpecializedTemplate(BestTemplate, Challenger,
+ Loc, TPOC_Other, 0),
+ BestTemplate)) {
Ambiguous = true;
break;
}
@@ -6116,11 +6094,10 @@ Sema::getMoreSpecializedPartialSpecialization(
"the partial specializations being compared should specialize"
" the same template.");
TemplateName Name(PS1->getSpecializedTemplate());
- TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name);
QualType PT1 = Context.getTemplateSpecializationType(
- CanonTemplate, PS1->getTemplateArgs().asArray());
+ Name, PS1->getTemplateArgs().asArray());
QualType PT2 = Context.getTemplateSpecializationType(
- CanonTemplate, PS2->getTemplateArgs().asArray());
+ Name, PS2->getTemplateArgs().asArray());
TemplateDeductionInfo Info(Loc);
return getMoreSpecialized(*this, PT1, PT2, PS1, PS2, Info);
@@ -6129,12 +6106,11 @@ Sema::getMoreSpecializedPartialSpecialization(
bool Sema::isMoreSpecializedThanPrimary(
VarTemplatePartialSpecializationDecl *Spec, TemplateDeductionInfo &Info) {
VarTemplateDecl *Primary = Spec->getSpecializedTemplate();
- TemplateName CanonTemplate =
- Context.getCanonicalTemplateName(TemplateName(Primary));
+ TemplateName Name(Primary);
QualType PrimaryT = Context.getTemplateSpecializationType(
- CanonTemplate, Primary->getInjectedTemplateArgs());
+ Name, Primary->getInjectedTemplateArgs());
QualType PartialT = Context.getTemplateSpecializationType(
- CanonTemplate, Spec->getTemplateArgs().asArray());
+ Name, Spec->getTemplateArgs().asArray());
VarTemplatePartialSpecializationDecl *MaybeSpec =
getMoreSpecialized(*this, PartialT, PrimaryT, Spec, Primary, Info);
diff --git a/clang/test/SemaCXX/cxx1y-generic-lambdas-variadics.cpp b/clang/test/SemaCXX/cxx1y-generic-lambdas-variadics.cpp
index f38fb2c6d71e7..a3464d6668178 100644
--- a/clang/test/SemaCXX/cxx1y-generic-lambdas-variadics.cpp
+++ b/clang/test/SemaCXX/cxx1y-generic-lambdas-variadics.cpp
@@ -16,7 +16,7 @@ struct X { };
struct Y { };
struct Z { };
-int test() {
+int test() {
{
auto L = [](auto ... as) { };
L.operator()<bool>(true);
@@ -36,7 +36,7 @@ int test() {
{
auto L = [](auto a, auto b, auto ... cs) { };
L.operator()<bool, char>(false, 'a');
- L.operator()<bool, char, const char*>(false, 'a', "jim");
+ L.operator()<bool, char, const char*>(false, 'a', "jim");
}
{
@@ -77,7 +77,7 @@ int test() {
M(6.26, "jim", true);
M.operator()<X>(6.26, "jim", false, X{}, Y{}, Z{});
}
-
+
return 0;
}
int run = test();
@@ -106,7 +106,7 @@ namespace PR33082 {
template<int ...I> void a() {
int arr[] = { [](auto ...K) { (void)I; } ... };
// expected-error at -1 {{no viable conversion}}
- // expected-note-re at -2 {{candidate template ignored: could not match 'auto (*)(type-parameter-0-0...){{.*}}' against 'int'}}
+ // expected-note-re at -2 {{candidate template ignored: could not match 'auto (*)(auto...){{.*}}' against 'int'}}
}
template<typename ...T> struct Pack {};
diff --git a/clang/test/SemaCXX/cxx1y-generic-lambdas.cpp b/clang/test/SemaCXX/cxx1y-generic-lambdas.cpp
index 22765542b1aa0..3066bb0d0f0cc 100644
--- a/clang/test/SemaCXX/cxx1y-generic-lambdas.cpp
+++ b/clang/test/SemaCXX/cxx1y-generic-lambdas.cpp
@@ -217,7 +217,7 @@ namespace conversion_operator {
int (&fp2)(int) = [](auto a) { return a; }; // expected-error{{non-const lvalue}}
int (&&fp3)(int) = [](auto a) { return a; };
// expected-error at -1 {{no viable conversion}}
- // expected-note-re at -2 {{candidate template ignored: could not match 'auto (*)(type-parameter-0-0){{.*}}' against 'int (int)'}}
+ // expected-note-re at -2 {{candidate template ignored: could not match 'auto (*)(auto){{.*}}' against 'int (int)'}}
using F = int(int);
using G = int(void*);
@@ -293,7 +293,7 @@ int test() {
print("a = ", a, "\n");
return [](auto b) ->decltype(a) {
// expected-error at -1 {{no viable conversion}}
- // expected-note-re at -2 {{candidate template ignored: could not match 'int (*)(type-parameter-0-0){{.*}}' against 'int'}}
+ // expected-note-re at -2 {{candidate template ignored: could not match 'auto (*)(auto){{.*}}' ({{.*}}) against 'decltype(a)' (aka 'int')}}
print("b = ", b, "\n");
return b;
};
More information about the llvm-branch-commits
mailing list