-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[clang] remove unneeded template deduction canonicalizations #101594
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-clang Author: Matheus Izvekov (mizvekov) ChangesThis 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. Full diff: https://github.com/llvm/llvm-project/pull/101594.diff 4 Files Affected:
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@-1 {{no viable conversion}}
- // expected-note-re@-2 {{candidate template ignored: could not match 'auto (*)(type-parameter-0-0...){{.*}}' against 'int'}}
+ // expected-note-re@-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@-1 {{no viable conversion}}
- // expected-note-re@-2 {{candidate template ignored: could not match 'auto (*)(type-parameter-0-0){{.*}}' against 'int (int)'}}
+ // expected-note-re@-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@-1 {{no viable conversion}}
- // expected-note-re@-2 {{candidate template ignored: could not match 'int (*)(type-parameter-0-0){{.*}}' against 'int'}}
+ // expected-note-re@-2 {{candidate template ignored: could not match 'auto (*)(auto){{.*}}' ({{.*}}) against 'decltype(a)' (aka 'int')}}
print("b = ", b, "\n");
return b;
};
|
074e6fa
to
86c6801
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM modulo nit
5fa1cc6
to
56c022e
Compare
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.
86c6801
to
fd9bdcc
Compare
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.