Author: Younan Zhang Date: 2025-03-24T16:46:48+08:00 New Revision: 38d71c9bdcf6b10c6fe02d5bd74fc8e6efb50a4d
URL: https://github.com/llvm/llvm-project/commit/38d71c9bdcf6b10c6fe02d5bd74fc8e6efb50a4d DIFF: https://github.com/llvm/llvm-project/commit/38d71c9bdcf6b10c6fe02d5bd74fc8e6efb50a4d.diff LOG: [Clang] Fix the assertion condition after b8d1f3d6 (#132669) Thanks to the example provided by MagentaTreehouse, I realized the assertion I added in b8d1f3d6 didn't cover all valid cases like, when inheriting from a class template specialization, the source of a synthesized template parameter might be an implicit specialization, whose inner function template is thus living at depth 0, for which we don’t want it to overflow too. I've decided to remove that assertion because I don't think it's particularly useful: we're checking whether Depth = 0 parameters come from function templates whose parents contribute no template parameters to the depth, which is redundant given what the template depth already means. This also incorporates a drive-by fix for https://github.com/llvm/llvm-project/pull/132061#discussion_r2008756718, which I somehow missed. Added: Modified: clang/lib/Sema/SemaTemplateDeductionGuide.cpp clang/test/SemaTemplate/deduction-guide.cpp Removed: ################################################################################ diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp index 9cfdb7596b660..3b2129e0df815 100644 --- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp +++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp @@ -376,12 +376,10 @@ struct ConvertConstructorToDeductionGuideTransform { if (NestedPattern) Args.addOuterRetainedLevels(NestedPattern->getTemplateDepth()); auto [Depth, Index] = getDepthAndIndex(Param); - // Depth can still be 0 if FTD belongs to an explicit class template - // specialization with an empty template parameter list. In that case, - // we don't want the NewDepth to overflow, and it should remain 0. - assert(Depth || - cast<ClassTemplateSpecializationDecl>(FTD->getDeclContext()) - ->isExplicitSpecialization()); + // Depth can be 0 if FTD belongs to a non-template class/a class + // template specialization with an empty template parameter list. In + // that case, we don't want the NewDepth to overflow, and it should + // remain 0. NamedDecl *NewParam = transformTemplateParameter( SemaRef, DC, Param, Args, Index + Depth1IndexAdjustment, Depth ? Depth - 1 : 0); @@ -970,6 +968,19 @@ getRHSTemplateDeclAndArgs(Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate) { return {Template, AliasRhsTemplateArgs}; } +bool IsNonDeducedArgument(const TemplateArgument &TA) { + // The following cases indicate the template argument is non-deducible: + // 1. The result is null. E.g. When it comes from a default template + // argument that doesn't appear in the alias declaration. + // 2. The template parameter is a pack and that cannot be deduced from + // the arguments within the alias declaration. + // Non-deducible template parameters will persist in the transformed + // deduction guide. + return TA.isNull() || + (TA.getKind() == TemplateArgument::Pack && + llvm::any_of(TA.pack_elements(), IsNonDeducedArgument)); +} + // Build deduction guides for a type alias template from the given underlying // deduction guide F. FunctionTemplateDecl * @@ -1033,20 +1044,6 @@ BuildDeductionGuideForTypeAlias(Sema &SemaRef, AliasRhsTemplateArgs, TDeduceInfo, DeduceResults, /*NumberOfArgumentsMustMatch=*/false); - static std::function<bool(const TemplateArgument &TA)> IsNonDeducedArgument = - [](const TemplateArgument &TA) { - // The following cases indicate the template argument is non-deducible: - // 1. The result is null. E.g. When it comes from a default template - // argument that doesn't appear in the alias declaration. - // 2. The template parameter is a pack and that cannot be deduced from - // the arguments within the alias declaration. - // Non-deducible template parameters will persist in the transformed - // deduction guide. - return TA.isNull() || - (TA.getKind() == TemplateArgument::Pack && - llvm::any_of(TA.pack_elements(), IsNonDeducedArgument)); - }; - SmallVector<TemplateArgument> DeducedArgs; SmallVector<unsigned> NonDeducedTemplateParamsInFIndex; // !!NOTE: DeduceResults respects the sequence of template parameters of diff --git a/clang/test/SemaTemplate/deduction-guide.cpp b/clang/test/SemaTemplate/deduction-guide.cpp index ecd152abebd74..6db132ca37c7e 100644 --- a/clang/test/SemaTemplate/deduction-guide.cpp +++ b/clang/test/SemaTemplate/deduction-guide.cpp @@ -723,3 +723,51 @@ void test() { NewDeleteAllocator abc(42); } // expected-error {{no viable constr // CHECK-NEXT: `-ParmVarDecl {{.+}} 'T' } // namespace GH128691 + +namespace GH132616_DeductionGuide { + +template <class T> struct A { + template <class U> + A(U); +}; + +template <typename> +struct B : A<int> { + using A::A; +}; + +template <class T> +B(T) -> B<T>; + +B b(24); + +// CHECK-LABEL: Dumping GH132616_DeductionGuide::<deduction guide for B>: +// CHECK-NEXT: FunctionTemplateDecl {{.+}} implicit <deduction guide for B> +// CHECK-NEXT: |-TemplateTypeParmDecl {{.+}} typename depth 0 index 0 +// CHECK-NEXT: |-TemplateTypeParmDecl {{.+}} class depth 0 index 1 U +// CHECK-NEXT: `-CXXDeductionGuideDecl {{.+}} implicit <deduction guide for B> 'auto (U) -> B<type-parameter-0-0>' +// CHECK-NEXT: `-ParmVarDecl {{.+}} 'U' + +struct C { + template <class U> + C(U); +}; + +template <typename> +struct D : C { + using C::C; +}; + +template <class T> +D(T) -> D<T>; + +D d(24); + +// CHECK-LABEL: Dumping GH132616_DeductionGuide::<deduction guide for D>: +// CHECK-NEXT: FunctionTemplateDecl {{.+}} implicit <deduction guide for D> +// CHECK-NEXT: |-TemplateTypeParmDecl {{.+}} typename depth 0 index 0 +// CHECK-NEXT: |-TemplateTypeParmDecl {{.+}} class depth 0 index 1 U +// CHECK-NEXT: `-CXXDeductionGuideDecl {{.+}} implicit <deduction guide for D> 'auto (U) -> D<type-parameter-0-0>' +// CHECK-NEXT: `-ParmVarDecl {{.+}} 'U' + +} // namespace GH132616_DeductionGuide _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits