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 <mizve...@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@-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; }; _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits